How to create correct referenceArray for further use while creating Dimensions?

How to create correct referenceArray for further use while creating Dimensions?

theknownsilhouette
Enthusiast Enthusiast
704 Views
6 Replies
Message 1 of 7

How to create correct referenceArray for further use while creating Dimensions?

theknownsilhouette
Enthusiast
Enthusiast

I'm facing issues while creating dimension for a window (refer attached family).

 

Syntax required: 

Dimension dim = doc.Create.NewDimension(View view, Line line, ReferenceArray refArray);

 

Issue: 

Not getting any valid references from the geometry. When trying to iterate through the geometry.

  1. The instance doesn't return any edges that are horizontal, and the length is equal to width of the window. If I remove the conditions for edge length == window width, undesired lines are being returned. Hence throwing exceptions for "invalid number of references" or "invalid direction for dimension".
  2. Faces returned from the geometry can't be used as reference as no face returns a valid reference. All faces return the reference as null. (refer "Code snippet B")


I spent lot of time but didn't get it. Then I tried to put dimension for a wall using below code (refer "Code snippet A") to validate if I'm implementing the basics correctly. It didn't work. So, I believe that my understanding about the reference and it's uses isn't clear. Can anyone of you explain why it didn't work? Identifying the issue in "code snippet A" would be much easier as it's a small piece of code.

 

("Code snippet A")

 

 

 Document doc = commandData.Application.ActiveUIDocument.Document;

            Wall wall = new FilteredElementCollector(doc).OfClass(typeof(Wall)).WhereElementIsNotElementType().Cast<Wall>().ToList().FirstOrDefault();


            using (Transaction t = new Transaction(doc, "Dimension for Wall"))
            {
                t.Start();

                Line line = (wall.Location as LocationCurve).Curve as Line;

                ReferenceArray refArray = new ReferenceArray();
                refArray.Append(line.GetEndPointReference(0));
                refArray.Append(line.GetEndPointReference(1));

                Dimension dim = doc.Create.NewDimension(doc.ActiveView, line, refArray);

                t.Commit();
            }



            return Result.Succeeded;

 

 


Most probably once I'm able to put the dimension for wall, I should be able to execute the same for window. Though I've put the code for easy reference.  In case, there's something more I should consider while putting dimension for a custom window (family). 

 

 

"Code snippet B"

 

 

 FilteredElementCollector _fec = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).WhereElementIsNotElementType();
                    Options opt = new Options();

                    List<Curve> lineList = new List<Curve>();
                    List<Curve> edgeList = new List<Curve>();
                    List<Face> face_List = new List<Face>();
                    List<Curve> allLines = new List<Curve>();
                    ReferenceArray refArray = new ReferenceArray();


                    foreach (var famInst in _fec.WhereElementIsNotElementType().WhereElementIsNotElementType().Cast<FamilyInstance>().ToList())
                    {
                        GeometryElement geoElement = famInst.get_Geometry(opt);
                        if (geoElement != null)
                        {
                            foreach (GeometryObject item in geoElement)
                            {
                                if (item is Solid)
                                {
                                    Solid solid = (item as Solid);
                                    EdgeArray edgeArray = solid.Edges;
                                    foreach (Edge f in edgeArray)
                                    {
                                        edgeList.Add(f.AsCurve());

                                    }
                                    FaceArray faceArray = solid.Faces;
                                    foreach (Face f in faceArray)
                                    {
                                        XYZ faceNormal = f.ComputeNormal(new UV(0, 0));

                                        if ((f is PlanarFace) && (f.Reference != null) && (faceNormal.DotProduct(XYZ.BasisX) == 1 || faceNormal.DotProduct(XYZ.BasisX) == -1))
                                        {
                                            face_List.Add(f);
                                        }
                                    }
                                    edgeList = edgeList.Where(x => x.Length == Width)
                                                        .Where(x => x.GetEndPoint(0).Y == x.GetEndPoint(1).Y)
                                                        .Where(x => x.GetEndPoint(0).Z == x.GetEndPoint(1).Z).ToList();

                                    allLines.AddRange(edgeList);
                                }
                                else if (item is GeometryInstance)
                                {
                                    GeometryInstance geometryInstance = item as GeometryInstance;
                                    GeometryElement instanceGeoElement = geometryInstance.GetInstanceGeometry();


                                    foreach (GeometryObject geometryObjectInstance in instanceGeoElement)
                                    {
                                        if (geometryObjectInstance is Solid)
                                        {
                                            Solid isolid = (geometryObjectInstance as Solid);

                                            double sa = isolid.SurfaceArea;

                                            if (sa != 0)
                                            {
                                                try
                                                {
                                                    EdgeArray edgeArray = new EdgeArray();

                                                    edgeArray = isolid.Edges;
                                                    foreach (Edge f in edgeArray)
                                                    {
                                                        if (f.AsCurve() is Line)
                                                        {
                                                            edgeList.Add(f.AsCurve());
                                                        }
                                                    }
                                                    FaceArray faceArray = isolid.Faces;
                                                    foreach (Face f in faceArray)
                                                    {
                                                        XYZ faceNormal = f.ComputeNormal(new UV(0, 0));

                                                        if ((f is PlanarFace) && (f.Reference != null) && (faceNormal.DotProduct(XYZ.BasisX) == 1 || faceNormal.DotProduct(XYZ.BasisX) == -1))
                                                        {
                                                            face_List.Add(f);
                                                        }
                                                    }

                                                    edgeList = edgeList
                                                        .Where(x => x.Length == Width)
                                                        .Where(x => x.GetEndPoint(0).Y == x.GetEndPoint(1).Y)
                                                        .Where(x => x.GetEndPoint(0).Z == x.GetEndPoint(1).Z).ToList();

                                                    allLines.AddRange(edgeList);


                                                }
                                                catch (Exception e)
                                                {
                                                    throw;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            try
                                            {
                                                allLines.AddRange(geometryInstance.SymbolGeometry.Where(x => x is Curve).Cast<Curve>().Where(x => x.Length == Width)
                                                    .Where(x => (x as Curve).GetEndPoint(0).Y == (x as Curve).GetEndPoint(1).Y)
                                                    .Where(x => (x as Curve).GetEndPoint(0).Z == (x as Curve).GetEndPoint(1).Z).ToList());



                                                foreach (Face face in geometryInstance.SymbolGeometry.Where(x => x is Face).Cast<Face>().ToList())
                                                {
                                                    XYZ fNormal = face.ComputeNormal(new UV(0, 0));
                                                    if ((face is PlanarFace) && (face.Reference != null) && (fNormal.DotProduct(XYZ.BasisX) == 1 || fNormal.DotProduct(XYZ.BasisX) == -1))
                                                    {
                                                        face_List.Add(face);
                                                    }
                                                }

                                            }
                                            catch (Exception)
                                            {

                                                throw;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }


                    lineList = allLines.ToList();

                    if (face_List.Count > 2)
                    {
                        refArray.Append(face_List.FirstOrDefault().Reference);
                        refArray.Append(face_List.LastOrDefault().Reference);

                        Line lineforDim = Line.CreateBound(face_List.FirstOrDefault().Reference.GlobalPoint, face_List.LastOrDefault().Reference.GlobalPoint);
                        Dimension dim = doc.Create.NewDimension(Elevation, lineforDim, refArray);
                    }

                    if (lineList.Count > 0)
                    {
                        Curve TopLine = lineList.FirstOrDefault();
                        Curve BottomLine = lineList.LastOrDefault();

                        face_List = face_List.Where(x => x.Reference != null).OrderByDescending(x => x.Reference.UVPoint.U).ToList();
                        refArray.Append(TopLine.Reference);
                        refArray.Append(BottomLine.Reference);
                        XYZ pt1 = (TopLine.GetEndPoint(0).X > TopLine.GetEndPoint(1).X) ? TopLine.GetEndPoint(0) : TopLine.GetEndPoint(1);
                        XYZ pt2 = (BottomLine.GetEndPoint(0).X > TopLine.GetEndPoint(1).X) ? BottomLine.GetEndPoint(0) : BottomLine.GetEndPoint(1);

                        Line lineforDim = Line.CreateBound(pt1, pt2);
                        Dimension dim = doc.Create.NewDimension(Elevation, lineforDim, refArray);


                    }

 

 

 
Thanks for your valuable time!

0 Likes
705 Views
6 Replies
Replies (6)
Message 2 of 7

jeremy_tammik
Alumni
Alumni

edge length == window width

 

Sorry, this expression is completely useless in a digital computer working with real numbers.  That would explain why you were not able to retrieve the desired edges. Please inform yourself about the need for fuzz:

 

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 7

theknownsilhouette
Enthusiast
Enthusiast

1. Thanks @jeremy_tammik, for sharing the need for fuzz. It's really a good lesson to implement further.

2. Though the reason I was not able to get the references, is that I missed setting the computeReference property true for option class object.

 

 

Options opt = new Options();
opt.ComputeReferences = true;

 

 


3. Now when I've placed the dimensions using required faces, the dimensions are being created (I can select them in Revit using the ID), but the dimensions aren't visible in Revit. When I tried to diagnose the issue, I found that the property AreReferencesAvailable is found to be false, and it seems to be the root cause.

 

 

bool validDim = dim.IsValid; //true
bool oneSegment = dim.HasOneSegment(); //true
bool refAvailable = dim.AreReferencesAvailable; //false

 

 

 Any suggestions to consider?

0 Likes
Message 4 of 7

jeremy_tammik
Alumni
Alumni

Thank you for the update and appreciation. Yes, sorry about not mentioning ComputeReferences... that is one of the (many?) obvious first things to check. Interesting observation with IsValid, HasOneSegment and AreReferencesAvailable. Can you try to create a similar dimension manually in the UI? Is there any way to make that visible? Do those settings affect the UI-generated dimensioning on the same way?

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 5 of 7

theknownsilhouette
Enthusiast
Enthusiast

Yes. I've created the dimensions manually. It's always visible until unless, either I hide the object or it's associated dimension deliberately using the visibility graphics or Hide element command.

0 Likes
Message 6 of 7

jeremy_tammik
Alumni
Alumni

OK, good. If the UI-generated dimensioning is visible, it ought to be possible to see the API-generated as well. Similar issues have been discussed and solved here in the past. Can you search the forum for something like "dimension visible" and see whether any of the solutions help in your case as well?

  

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 7 of 7

jeremy_tammik
Alumni
Alumni

So, I now have two simultaneous forum threads struggling to *create visible dimensioning*. They have valid geometry references and can create valid dimensioning from those, but the resulting dimension object reports `AreReferencesAvailable` as false:

  

  

Are you the same person raising these two? Can we please settle on one of them for further discussion? 

  

I suggest we pick the latter to continue, OK?

  

Thank you.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes