Announcements

Starting in December, we will archive content from the community that is 10 years and older. This FAQ provides more information.

Use of Align function programatically to change the alignment of Tiles for floor

MehtaRajesh
Advocate
Advocate

Use of Align function programatically to change the alignment of Tiles for floor

MehtaRajesh
Advocate
Advocate

Hello All,

(Revit Arch)

I have used Ceiling Tile 600 x 600 as a material for  Structure for Floor.

We can change the alignment by using Revit Command (Modify | Floors -> Align option

Is there any way to do this activity programatically ?

Where is the alignement property for floor stored?

Is there any way to extract the present value of alignment and change it programatically (GET and SET property)

Thanks in advance for your kind support

Regards,
Rajesh







Reply
8,213 Views
20 Replies
Replies (20)

Aaron.Lu
Autodesk
Autodesk
Dear MehtaRajesh,

do you mean you want to align floor with some level or grid?
you can do that via API:
1. first move the floor to the correct position (exact position after alignment IMPORTANT!) by calling ElementTransformUtils.MoveElement(s)
2. align the floor with the target by calling Document.Create.NewAlignment method


Aaron Lu
Developer Technical Services
Autodesk Developer Network

MehtaRajesh
Advocate
Advocate

Hi Aaron,

We need to align surface Pattern (At present it is 600 x 600 square) of floor such a way to minimize the wastage of tiles and need to make sure that the size of each tile area should be more than 50 % of the complete tile as far as possible.

At presently we are able to do it by using  "Revit Command (Modify | Floors -> Align option"

We are in process to automate this task.

Regards,
Rajesh

0 Likes

Aaron.Lu
Autodesk
Autodesk
Sorry, I'm not Revit experts, would you please give me more context on this?
like how to accomplish your task in UI: select floor > click Align > then ....

and also would you please provide some example rvt file?


Aaron Lu
Developer Technical Services
Autodesk Developer Network
0 Likes

MehtaRajesh
Advocate
Advocate

Hi,

The manual process is as under,
Data - Square floor family having (Property - Construction -> Structure - >  Finish1 -> Material (Ceiling Tile 600 x 600 ))

Input

 

___________________ A
|                |                |      300

|________ |_________| B

|                |                |

|                |                |      600

|                |                |

|_________|________ |

|                |                |  

|________ |_________|     300

Step 1: Select Floor
Step 2:  Under menu Modify | Floor --> Select Align (AL) Button

Step 2.1:

Prompt: Please select line or point reference for alignment:
Select A horizontal line

Step 2.2:

Prompt: Please select an entity to align (it will move into alignment with)
Select B horizontal line

Output: Tiles are properly aligned

__________________

|                |                |                

|                |                |      600

|                |                |

| ________|_________|         

|                |                |

|                |                |      600

|                |                |

|_________|________|


Regards,

 

0 Likes

Anonymous
Not applicable

Dear Mehta rajesh

 

 

you can functionally align two elements in revit through API programming.  if and only if these are geometrically aligned. API function not forced to Align . For more details you can view this post.

 

http://adndevblog.typepad.com/aec/2014/12/revitapi-align-2-pipes-through-center-lines.html

 

This is an example of alignment of two pipes. You can view.

 

As i know, you can chose NewfamilyInstance option for better placement. for more detail if you share me an example rvt file then i will look on this once.

0 Likes

Dale.Bartlett
Collaborator
Collaborator

Hi Manish,

Rajesh is not looking to align elements. He wants to align the floor surface pattern (hatch) such that one of the hatch lines is aligned with the edge of the floor object. Imagine large floor tiles in you bathroom; the pattern starts (aligns) with at least one, probably two walls. This is manually possible in Revit by selecting the align tool, then one of the hatch cross lines, and aligning with the edge of the floor slab object. I cannot find anything in Snoop to indicate the geometry/location/origin of the surface pattern. This is a very good question. Regards, Dale.




______________
Yes, I'm Satoshi.

Anonymous
Not applicable

Tnx Dale,

 

You are absolutely right.

 

but i try to give information about Document.Create.NewAlignment() method in API. 

 

Regards 

Manish

0 Likes

Aaron.Lu
Autodesk
Autodesk
Thanks, unfortunately the is no such API yet, so I've logged a wish:
CF-3928 - case 11459435: API ability to align floor hatch line with floor's edge


Aaron Lu
Developer Technical Services
Autodesk Developer Network
0 Likes

Anonymous
Not applicable

Any word on when this API access will be added? 

0 Likes

jeremytammik
Autodesk
Autodesk

Dear Chris,

 

Thank you for your query, both here and in your own subsequent thread

 

http://forums.autodesk.com/t5/revit-api/api-access-to-surface-pattern-alignment/m-p/6344811

 

I cannot say when the wish list item CF-3928 [case 11459435: API ability to align floor hatch line with floor's edge] will be addressed.

 

Please submit a business case to help underline its importance, as I suggested in my answer to your new thread.

 

Thank you!

 

Best regards,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes

mehdi.blanchard
Enthusiast
Enthusiast

Hi,

 

Is there any update on this wish? 

 

We work on large floor plans and automating the Ceiling Tile set out would be of great benefit to us.

 

Kind Regards,

Mehdi

FAIR59
Advisor
Advisor

The references to the hatch-lines are available via the API, see https://forums.autodesk.com/t5/revit-api-forum/dimension-on-hatch-pattern-slab/m-p/7078368#M22785

 

With those references you can move the lines indirectly, by aligning them to a reference plane and moving that plane.

 

here's my test-code:

 

			Element elem = doc.GetElement(sel.GetElementIds().FirstOrDefault());
			Floor floor = elem as Floor;
		    Reference r = HostObjectUtils.GetTopFaces(floor).FirstOrDefault();
		    PlanarFace face = elem.GetGeometryObjectFromReference(r) as PlanarFace;
		    XYZ corner = null;
		    foreach( Curve cv in face.GetEdgesAsCurveLoops().FirstOrDefault())
		    {
		    	corner = cv.GetEndPoint(0);
		    	break;
		    }
		    var HatchLines = AnalyzeHatch(elem,r);
			sb.AppendLine ("elem  "+ elem.Id);
			sb.AppendLine();
			using (TransactionGroup tg = new TransactionGroup(doc,"align2RefPlane"))
			{
				tg.Start();
				foreach (var HLine in HatchLines)
			    {
					ReferencePlane pl = null;
					using (Transaction t = new Transaction(doc,"CreateRefPlane"))
					{
						t.Start();
						pl = doc.Create.NewReferencePlane(HLine.Item3.Add(HLine.Item4.Multiply(3)),HLine.Item3,face.FaceNormal.Multiply(3),doc.ActiveView);
						pl.Name = string.Format("{0}_{1}","ref", Guid.NewGuid());
						t.Commit();
					}
					string stableRef = string.Format("{0}:0:{1}",pl.UniqueId,"SURFACE");
					Reference ref2Plane = Reference.ParseFromStableRepresentation(doc,stableRef);
					using (Transaction t = new Transaction(doc,"align2RefPlane"))
					{
						t.Start();
						doc.Create.NewAlignment(doc.ActiveView,ref2Plane,HLine.Item2);
						t.Commit();
					}
					using (Transaction t = new Transaction(doc,"MovePlane"))
					{
						t.Start();
						XYZ translation = HLine.Item3.Subtract(corner);
						ElementTransformUtils.MoveElement(doc,pl.Id,translation);
						t.Commit();
					}
			    }
				tg.Assimilate();
			}

 

with the helpermethod:

	/// <summary>
	/// Analyse the hatch
	/// </summary>
	/// <param name="elem">An element with surface hatch.</param>
	/// <param name="hatchface">The reference to the face to analyse.</param>
	/// <returns>Returns:
	///  foreach hatchline in hatchpattern	
	///  item1 = index of hatchline in hatchpattern
	///  item2 = reference to the hatchline
	///  item3 = point on hatchline
	///  item4 = direction of hatchline.</returns>
		List<Tuple<int,Reference,XYZ,XYZ>> AnalyzeHatch(Element elem, Reference hatchface)
		{
			//check for model surfacepattern
			List<Tuple<int,Reference,XYZ,XYZ>> res = new List<Tuple<int,Reference,XYZ,XYZ>>();
			Document doc = elem.Document;
			PlanarFace face = elem.GetGeometryObjectFromReference(hatchface) as PlanarFace;
            Material mat = doc.GetElement(face.MaterialElementId) as Material;
            FillPatternElement patterntype = doc.GetElement(mat.SurfacePatternId) as FillPatternElement;
            if (patterntype== null)    return  res;
            FillPattern pattern =  patterntype.GetFillPattern();
            if (pattern.IsSolidFill || pattern.Target == FillPatternTarget.Drafting) return res;            

            
			// get number of gridLines in pattern                
			int _gridCount = pattern.GridCount;

			// construct StableRepresentations and find the Reference to HatchLines
            string StableRef = hatchface.ConvertToStableRepresentation(doc);
            using ( Transaction t = new Transaction(doc,"analyse hatch"))
			{
            	if (!doc.IsModifiable)
            	{
            		t.Start();
            	}
            	
            	for (int hatchindex =0; hatchindex<_gridCount; hatchindex++)
            	{
            		ReferenceArray _resArr = new ReferenceArray();
            		for (int ip = 0; ip < 2; ip++)
                	{
            			int index = (hatchindex+1) + (ip * _gridCount *2);
                	    string StableHatchString = StableRef + string.Format("/{0}", index);
                	    Reference HatchRef = null;
                	    try
                	    {
                	        HatchRef = Reference.ParseFromStableRepresentation(doc, StableHatchString);
                	    }
                	    catch
                	    { }
                	    if (HatchRef == null) continue;
                	    _resArr.Append(HatchRef);
                	}
					// 2 or more References => create dimension
                	if (_resArr.Size>1)
                	{
                	    using (SubTransaction st = new SubTransaction(doc))
                	    {
                	        st.Start();
                	        Dimension _dimension = doc.Create.NewDimension(doc.ActiveView, Line.CreateBound(XYZ.Zero, new XYZ(10, 0, 0)), _resArr);
							// move dimension a tiny amount to orient the dimension perpendicular to the hatchlines
							// I can't say why it works, but it does.
                	        ElementTransformUtils.MoveElement(doc, _dimension.Id, new XYZ(.1, 0, 0));

                	        Reference r1 = _dimension.References.get_Item(0);
                	        XYZ direction =( _dimension.Curve as Line).Direction;
                	        XYZ hatchDirection = direction.CrossProduct(face.FaceNormal).Normalize();
                	        XYZ origin = _dimension.Origin.Subtract(direction.Multiply((double) _dimension.Value/2)) ;
                	        res.Add ( new Tuple<int,Reference,XYZ,XYZ>(hatchindex,r1,origin,hatchDirection));
                	        st.RollBack();
                	    }
                	}
            	}
			}
            return res;
		}

Dale.Bartlett
Collaborator
Collaborator

Hi Fair59, That is significant work to publish, thank you very much. I haven't tested yet but will endeavour to do so over the next while. Kind regards, Dale




______________
Yes, I'm Satoshi.
0 Likes

Mark.Ackerley
Advocate
Advocate

Hey,

 

I needed to do alignments on a series of walls, so created a Python solution in Dynamo with the help of Alban de 

Chasteigner the link is here:

 

https://forum.dynamobim.com/t/align-surface-patterns-to-wall-edge/44646/5?u=mark.ackerley

 

The bulk of (Alban's) work is this...

 

#thanks to Alban de Chasteigner (Genius Loci) and Fair59
import clr
import sys

pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)

import string

# Import Element wrapper extension methods
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
# toProtoType etc.
clr.ImportExtensions(Revit.GeometryConversion)

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
import System
from System import Guid

walls = UnwrapElement(IN[0])
refPlanesWall = UnwrapElement(IN[1])
indexRefs = IN[2]

refDimensions = []
for wall, refPlanes, indexes in zip(walls, refPlanesWall, indexRefs ):
	#get the external face reference of the wall as an array
	extFaceRefList = HostObjectUtils.GetSideFaces(wall,ShellLayerType.Exterior)
	#for (the array containing) the external face reference, get it's geometry
	for extFaceRef in extFaceRefList:
		extFace = wall.GetGeometryObjectFromReference(extFaceRef)
		#get the external face surface edges as lines, get the first line (the bottom)
		for	bottomEdgeCurve in extFace.GetEdgesAsCurveLoops()[0]:
			#get the finish point of the line
			corner = bottomEdgeCurve.GetEndPoint(1)
		#Check for model surfacepattern
		material = doc.GetElement(extFace.MaterialElementId)
		patterntype = doc.GetElement(material.SurfacePatternId)
		pattern = patterntype.GetFillPattern()
		#Get number of gridLines in pattern                
		gridCount = pattern.GridCount		
		#Construct StableRepresentation to top face reference
		stableRef = extFaceRef.ConvertToStableRepresentation(doc)
		
		#we want horizontal and vertical refs so we want 2 arrays
		refList = []
		refAll = []
		for hatchindex in range(0, gridCount):
			refAr = ReferenceArray()
			ip=0
			while ip<2:
				#generate an index for each hatch reference
				index = (hatchindex+1) + (ip * gridCount *2)
				#create a string for each hatch reference using the face reference and hatch index
				stableHatchString = stableRef + str.Format("/{0}", index)
				#generate a new reference for each hatch reference using the string
				HatchRef = Reference.ParseFromStableRepresentation(doc, stableHatchString)
				#the hatch reference is both 
				refAr.Append(HatchRef)
				ip += 1
			#refList contains arrays, each containing a pair of references
			#we only want 2 arrays, a horizontal and a vertical
			refAll.append(refAr)
		#we use the index we returned from the reference plane to
		#determine the index we need of the references... there aren't
		#any properties or methods of the reference to determine orientation
		for i in indexes:	
			refList.append(refAll[i])

	#for each wall, we run each refPlane against each reference, 1 hor, 1 vert
	for refAr, refPlane in zip(refList, refPlanes):
		#start a transaction
		TransactionManager.Instance.EnsureInTransaction(doc)
		refDim = doc.Create.NewDimension(doc.ActiveView, Line.CreateBound(XYZ.Zero, XYZ(10, 0, 0)), refAr)		
		ElementTransformUtils.MoveElement(doc, refDim.Id, XYZ(.1, 0, 0))			
		r1 = refDim.References.get_Item(0)
		direction = refDim.Curve.Direction
		hatchDirection = direction.CrossProduct(extFace.FaceNormal).Normalize()
		origin = refDim.Origin.Subtract(direction.Multiply(refDim.Value/2))
		#end transaction
		TransactionManager.Instance.TransactionTaskDone()
		
		stableRef = str.Format("{0}:0:{1}",refPlane.UniqueId,"SURFACE")
		ref2Plane = Reference.ParseFromStableRepresentation(doc,stableRef)
		
		#start a transaction
		TransactionManager.Instance.EnsureInTransaction(doc)
		doc.Create.NewAlignment(doc.ActiveView,ref2Plane,r1)
		#end transaction
		TransactionManager.Instance.TransactionTaskDone()
		
		#start a transaction
		TransactionManager.Instance.EnsureInTransaction(doc)
		translation = origin.Subtract(corner)
		ElementTransformUtils.MoveElement(doc,refPlane.Id,-translation)
		#end transaction
		TransactionManager.Instance.TransactionTaskDone()
		
		refDimensions.append(refDim)

#we don't need the dimensions or reference planes any more
#start a transaction		 
TransactionManager.Instance.EnsureInTransaction(doc)
for refDim in refDimensions:
	doc.Delete(refDim.Id)
for refPlanes in refPlanesWall:
	for refPlanes in refPlanes:
		doc.Delete(refPlanes.Id)
#finish transaction
TransactionManager.Instance.TransactionTaskDone()

OUT = walls

Align Wall Material.gif

 

 

Hopefully that's of interest,

 

Mark

 

noamgatCXBC7
Participant
Participant

Hello,

Thanks for the amazing work here!

I'm trying to use it in the context of ceilings, and it is not working.

This is what my ceiling looks like in Revit:

noamgatCXBC7_0-1609146760817.png

 

I am able to

1) Get a pointer to the ceiling object

2) Get the top face of it and try to analyse:

 

var topFaces = HostObjectUtils.GetTopFaces(c);
var top = topFaces[0];
var analysis = AnalyzeHatch(c, top);

 

However, the line 

            FillPatternElement patterntype = doc.GetElement(mat.SurfaceForegroundPatternId) as FillPatternElement;

 

of AnalyseHatch() returns null, and therefore an empty result is returned. What can I do to use this with ceilings?

0 Likes

Anonymous
Not applicable

For ceilings, I found I had to get the hatch pattern from the bottom face. You can check out my Python code that is used to align ceiling grids with light fixtures at the link below, but here's a brief excerpt that might help you.

 

[ceiling_down_face] = HostObjectUtils.GetBottomFaces(ceiling)
face = ceiling.GetGeometryObjectFromReference(ceiling_down_face)

// ...

try:
    material = doc.GetElement(face.MaterialElementId)
    pattern = doc.GetElement(material.SurfacePatternId).GetFillPattern()
except (AttributeError, InvalidOperationException):
    failed.append(ceiling)

 

https://github.com/zachcmathews/pyRevitBoost/blob/f89bd147eb8eafa81601304e0251c6c4627817d9/pyRevitBo... 

 

Zachary Mathews

Maintainer of pyRevitBoost 

Electrical Designer I & BIM Manager Intern

Southern A&E, LLC

0 Likes

konradzaremba
Explorer
Explorer

Hi all,

I have been playing around with Fair59 hack for a while but got stuck. What I  am trying to achieve is:

- make method possible to use in 3d and for wall different wall orientation

- adjust hatches on side faces of the wall especially on openings

 

The first objective seems to be accomplished. I am able to create ref planes from 3d view. The other however seems more tricky. 

 

First of all, when I got the face from the opening even if it is painted it is returning Category Material (id 24) obviously no hatch pattern so no further action. I did a small workaround and set the category parameter to be one with hatch. In this case, I am able to create ref planes for those faces. Unfortunately, I can't align those references with hatch ref down the road. Please help I run out of ideas on how to approach it.

 

The snippet got quite long but it should work pasted into command. All utilities included in the region.

 

 

 

    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]

    public class WallHatch : IExternalCommand
    {
        #region Command
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements
        )
        {
            var uiapp = commandData?.Application;
            var uidoc = uiapp?.ActiveUIDocument;
            var app = uiapp?.Application;
            var doc = uidoc?.Document;

            List<Tuple<int, Reference, XYZ, XYZ>> res = new List<Tuple<int, Reference, XYZ, XYZ>>();

            Selection _selection = uidoc.Selection;
            ICollection<ElementId> selIds = _selection.GetElementIds();
            List<Element> elems = new List<Element>();
            foreach (var id in selIds)
            {
                elems.Add(doc.GetElement(id));
            }

            List<PlanarFace> wallFaces = GetSideFaces(elems[0] as Wall);
            var WallHatchLine = AnalyzeWallHatch(doc,wallFaces);
            List<PlanarFace> WallFront = GetWallMainFaces(elems[0], ShellLayerType.Exterior);                  
            XYZ corner = GetPointAtCorner(WallFront.FirstOrDefault());

            try
            {
                using (TransactionGroup tg = new TransactionGroup(doc, "align2RefPlane"))
                {
                    tg.Start();
                    foreach (var HLine in WallHatchLine)
                    {
                      ReferencePlane pl = null;
                        //Ctreate Ref Plane from Hatch
                        using (Transaction t = new Transaction(doc, "CreateRefPlane"))
                        {
                            t.Start();
                            pl = doc.Create.NewReferencePlane(HLine.Item3.Add(HLine.Item4.Multiply(3)), HLine.Item3, HLine.Item5.Multiply(3), doc.ActiveView);
                            pl.Name = string.Format("{0}_{1}", "ref", Guid.NewGuid());
                            t.Commit();
                        }
                        
                        //Align Ref Plane to Hatch Ref
                        string stableRef = string.Format("{0}:0:{1}", pl.UniqueId, "SURFACE");
                        Reference ref2Plane = Reference.ParseFromStableRepresentation(doc, stableRef);
                        using (Transaction t = new Transaction(doc, "align2RefPlane"))
                        {
                            t.Start();
                            doc.Create.NewAlignment(doc.ActiveView, ref2Plane, HLine.Item2);
                            t.Commit();
                        }

                        //Move Hatch
                        using (Transaction t = new Transaction(doc, "MovePlane"))
                        {
                            t.Start();
                            XYZ translation = HLine.Item3.Subtract(corner);
                           ElementTransformUtils.MoveElement(doc, pl.Id, translation);
                            t.Commit();
                        }               
                    }
                    tg.Assimilate();
                }
                    return Result.Succeeded;
                }
                catch (System.Exception e)
                    return Result.Failed;
                }
         }

        #endregion Command


        #region Utils

        /// <summary>
        /// Get Side  Faces of the wall
        /// </summary>
        /// <param name="wall"></param>
        /// <returns></returns>

        /// <summary>
        /// Analyse the hatch
        /// </summary>
        /// <param name="elem">An element with surface hatch.</param>
        /// <param name="hatchface">The reference to the face to analyse.</param>
        /// <returns>Returns:
        ///  foreach hatchline in hatchpattern	
        ///  item1 = index of hatchline in hatchpattern
        ///  item2 = reference to the hatchline
        ///  item3 = point on hatchline
        ///  item4 = direction of hatchline.</returns>
        ///  item5 = face normal
		
		//added item5 for debug reasons
        List<Tuple<int, Reference, XYZ, XYZ, XYZ>> AnalyzeWallHatch(Document doc, List<PlanarFace> wallFaces) {
            List<Tuple<int, Reference, XYZ, XYZ, XYZ>> res = new List<Tuple<int, Reference, XYZ, XYZ, XYZ>>();
            List<XYZ> faceCorners = new List<XYZ>();

            foreach (PlanarFace face in wallFaces)
            {
                Material mat = doc.GetElement(face.MaterialElementId) as Material;

                    //In no hatch pattern assgined
                    FillPatternElement patterntype = doc.GetElement(mat.SurfaceForegroundPatternId) as FillPatternElement;
                    if (patterntype == null) continue;
                    FillPattern pattern = patterntype.GetFillPattern();
               //     if (pattern.IsSolidFill || pattern.Target == FillPatternTarget.Drafting) continue;
                 
                    // get number of gridLines in pattern    
                    // grid count indicated no of direction in hatch pattern
                    // null - no hatch, 1 one direction (vertical or horizontal), 2 two directions , 3 directions
                    int _gridCount = pattern.GridCount;
                    // construct StableRepresentations and find the Reference to face - info for further hack
                    string StableRef = face.Reference.ConvertToStableRepresentation(doc);

                using (var transaction = new Transaction(doc, "Wall align hatch"))
                {
                    if (!doc.IsModifiable)
                    {
                        transaction.Start();
                    }
                        //Get Reff arrays from hatch directions indicates line of the hatch
                        for (int hatchDirectionIndex = 0; hatchDirectionIndex < _gridCount; hatchDirectionIndex++)
                        {
                            ReferenceArray _resArr = new ReferenceArray();
                            for (int ip = 0; ip < 2; ip++)
                            {
                                int index = (hatchDirectionIndex + 1) + (ip * _gridCount * 2);
                                //Merege string reperenetation of hatch to get hatch line reference from face hatch
                                string StableHatchString = StableRef + string.Format("/{0}", index);
                                Reference HatchRef = null;
                                try
                                {
                                    HatchRef = Reference.ParseFromStableRepresentation(doc, StableHatchString);
                                }
                                catch
                                { }
                                if (HatchRef == null) continue;
                                _resArr.Append(HatchRef);
                            }
                            // 2 or more References => create dimension
                            if (_resArr.Size > 1)
                            {
                                using (SubTransaction st = new SubTransaction(doc))
                                {
                                    //setup sketch plane to be face
                                    st.Start();

                                    SketchPlane skpPln = SketchPlane.Create(doc, face.Reference);
                                    doc.ActiveView.SketchPlane = skpPln;
                                    XYZ othercorner = GetPointAtOpositeCorner(face);

                                    Curve LowestEdge = GetLowestEdge(face);

XYZ dirvec = LowestEdge.GetEndPoint(1).Subtract(LowestEdge.GetEndPoint(0));

//Modified dimension line to be lower edge of the face
                                      Dimension _dimension = doc.Create.NewDimension(doc.ActiveView, Line.CreateBound(LowestEdge.GetEndPoint(0), LowestEdge.GetEndPoint(1)), _resArr);


//seems not working in 3d view
// move dimension a tiny amount to orient the dimension perpendicular to the hatchlines
// I can't say why it works, but it does.
//ElementTransformUtils.MoveElement(doc, _dimension.Id, new XYZ(.1, 0, 0));
// ElementTransformUtils.MoveElement(doc, _dimension.Id, dirvec.Normalize()*20);

                                Reference r1 = _dimension.References.get_Item(0);
                                    XYZ direction = (_dimension.Curve as Line).Direction;
                                    XYZ hatchDirection = direction.CrossProduct(face.FaceNormal).Normalize();
                                    XYZ origin = _dimension.Origin.Subtract(direction.Multiply((double)_dimension.Value / 2));
                                    res.Add(new Tuple<int, Reference, XYZ, XYZ, XYZ>(hatchDirectionIndex, r1, origin, hatchDirection, face.FaceNormal));
                                    //st.RollBack();
                                    st.Commit();
                                }
                        }
                    }
                   transaction.Commit();
                }
            }
            return res;
        }

        public static List<PlanarFace> GetWallMainFaces(Element elem, ShellLayerType faceside = ShellLayerType.Exterior)
        {
            List<PlanarFace> wallFaces = new List<PlanarFace>();
            Wall wall = elem as Wall;
            IList<Reference> rs = HostObjectUtils.GetSideFaces(wall, faceside);
            foreach (Reference r in rs)
            {
                wallFaces.Add(elem.GetGeometryObjectFromReference(r) as PlanarFace);

            }
            return wallFaces;
        }

        public static List<PlanarFace> GetSideFaces(Wall wall)
        {

            List<PlanarFace> lineAngl = new List<PlanarFace>();
            LocationCurve locationCurve = wall.Location as LocationCurve;
            Line line = locationCurve.Curve as Line;

            XYZ locVector = line.Direction;
            List<PlanarFace> wallfaces = GetFaces(wall);

            foreach (PlanarFace f in wallfaces)
            {
                XYZ faceNorm = f.ComputeNormal(new UV(0.5, 0.5));
                if (IsParallel(locVector, faceNorm) == true)
                {
                    lineAngl.Add(f);
                }
            }
            return lineAngl;
        }

        public static List<PlanarFace> GetFaces(Wall wall)
        {
            List<PlanarFace> faclst = new List<PlanarFace>();
            Options opt = new Options();
            opt.ComputeReferences = true;
            opt.DetailLevel = ViewDetailLevel.Fine;
            opt.IncludeNonVisibleObjects = true;
            GeometryElement geomElem = wall.get_Geometry(opt);
            foreach (GeometryObject geomObj in geomElem)
            {
                Solid geomSolid = geomObj as Solid;
                if (null != geomSolid)
                {
                    int faces = 0;
                    double totalArea = 0;
                    foreach (PlanarFace geomFace in geomSolid.Faces)
                    {
                        faclst.Add(geomFace);
                    }
                }
            }
            return faclst;
        }

        const double _eps = 1.0e-9;
        public static bool IsParallel(XYZ a, XYZ b)
        {
            double angle = a.AngleTo(b);
            return _eps > angle || System.Math.Abs(angle - System.Math.PI) < _eps;
        }

        public static XYZ GetPointAtCorner(PlanarFace face)
        {
            XYZ corner = null;
            foreach (Curve cv in face.GetEdgesAsCurveLoops().FirstOrDefault())
            {
                corner = cv.GetEndPoint(0);
                break;
            }
            return corner;
        }

        public static XYZ GetPointAtOpositeCorner(PlanarFace face)
        {
            XYZ corner = null;
            foreach (Curve cv in face.GetEdgesAsCurveLoops().FirstOrDefault())
            {
                corner = cv.GetEndPoint(1);
                break;
            }
            return corner;
        }

        public static Curve GetLowestEdge(PlanarFace face)
        {
            XYZ corner = null;
            double midmin = xxx-xxxxxxxx;
            Curve lowEdge = null;
            foreach (Curve cv in face.GetEdgesAsCurveLoops().FirstOrDefault())
            {
                XYZ midpoint = (cv.GetEndPoint(0) + cv.GetEndPoint(1)) / 2;
                if (midpoint.Z < midmin)
                {
                    midmin = midpoint.Z;
                    lowEdge = cv;
                }
            }
            return lowEdge;
        }
    }
}

 

 

 

 

0 Likes

gls_whdev8
Explorer
Explorer

 

1.dim, create referencePlane can work fine in 3d view

but!

 XYZ direction = (_dimension.Curve as Line).Direction;

this direction may not first gridLine to his offset gridLine, it may also the oppside.if it happend,item2 and item3 are not couple! the referencePlane is not aligned with reference of hatch line! 

 

2.NewAlignment() in 3d view don't work well,Create a section view for the wall.

Ning_Zhou
Advocate
Advocate

no official API yet for model hatch pattern?

we have similar case -> align model hatch pattern lines in 2 curtain panels in same curtain wall, ideally in different curtain walls too, i believe it's doable using Fair59's workaround even though not yet tried, any thought?

0 Likes