Dimensioning elements - Error: dimension are no longer parallel. Plot twist: they are parallel

Dimensioning elements - Error: dimension are no longer parallel. Plot twist: they are parallel

_marcin
Participant Participant
886 Views
3 Replies
Message 1 of 4

Dimensioning elements - Error: dimension are no longer parallel. Plot twist: they are parallel

_marcin
Participant
Participant

Hello,

 

I'm currently working on script that will add new elements (of categories Structural Framing, and Parts) to assembly and will update dimension lines and tags in views from that assembly.

Mostly I've finished this tool however in some special cases I'm getting warning that "dimension are no longer parallel". Depending on assembly it occurs on 3-4 dimension lines (structural framng elements) out of 20. 

When I've tried to recreate those dimensions with getting dimensioned faces instead of references the same error got posted, (it works that it gets Stable Representation from reference then cycles through element geometry/faces until it finds face that has the same Stable Representation and adds that Reference to new ReferenceArray). Only after adding UniqueId of element, adding information that it's instance, then parsing reference form stable representation I would be able to recreate those dimensions. On the other hand I can't add it to every reference as the error appears on different assembly. I'm thinking of using Failure Api but I'm afraid this issue may occur to only few of the newly added elements so adding "INSTANCE" to each element is asking for troubles.

 

Now I'd like to ask if someone know how to get information when those references should have added information ifthey are coming from instance


And my code to recreate problematic dimension line:

# -*- coding: utf-8 -*-
"""
"""
from pyrevit import revit, DB
from Autodesk.Revit.UI.Selection import ObjectType, ISelectionFilter
from Autodesk.Revit.Exceptions import OperationCanceledException

#from System import Windows
from System.Collections.Generic import List

doc = revit.doc
uidoc = revit.uidoc
ops = DB.Options()
ops.ComputeReferences = True
ops.IncludeNonVisibleObjects = True


def SolidFromBeam(beam):
    """returns solid from StructuralFraming element"""
    cat_solid = DB.Solid
    beam_geom = beam.get_Geometry(ops)
		
    if beam.HasModifiedGeometry():
        for geom in beam_geom:
            if geom.GetType() == cat_solid:
                if geom.Volume > 0:
                    return geom

    else:
        for geom in beam_geom:
            if geom.GetType() == DB.GeometryInstance:
                ig = DB.GeometryInstance.GetInstanceGeometry(geom)
                for element in ig:
                    if element.Volume > 0:
                        return element

class EverythingISelectionFilter(ISelectionFilter):
    def AllowElement(self, elem):
        return True

def SelectModelElement():
    try:
        reference = uidoc.Selection.PickObject(ObjectType.Element, EverythingISelectionFilter(), "Select Element")
    except OperationCanceledException:
        pass
    else:
        element = doc.GetElement(reference)
        return element


with revit.Transaction("WTF"):

    dim = SelectModelElement()

    if dim != None:

        dim_view = dim.View
        dim_type = DB.Document.GetElement(doc, dim.GetTypeId())
        dim_style = dim_type.get_Parameter(DB.BuiltInParameter.LINEAR_DIM_TYPE).AsInteger()

        ops.View = dim_view
        if dim_style == 1:
            style = "continous"
        if dim_style == 3:
            style = "cummulative"
        
        location_line = dim.Curve.Clone()



        list_of_new_stable_representation = []
        list_of_original_stable_representations = []

        original_reference_array = dim.References
        original_stable_representations = ""
        list_of_elements =[]
        n = 1
        for reference in original_reference_array:
            element_id = reference.ElementId
            element = DB.Document.GetElement(doc, element_id)
            list_of_elements.append(element)
            stable_representation = reference.ConvertToStableRepresentation(doc)
            list_of_original_stable_representations.append(stable_representation)
            original_stable_representations += str(n) + '\t' + str(element_id) + '\t' + stable_representation + ';\n'

            n += 1

        new_stable_representations = ''


        new_reference_array = DB.ReferenceArray()
        n = 1

        for item, representation in zip(list_of_elements, list_of_original_stable_representations):

            solid = SolidFromBeam(item)
            faces = solid.Faces
            for face in faces:
                reference = face.Reference
                sr = reference.ConvertToStableRepresentation(doc)
                if "INSTANCE" in representation:
                    if sr in original_stable_representations:# and sr not in new_stable_representations:
                        list_of_new_stable_representation.append(sr)
                        #https://thebuildingcoder.typepad.com/blog/2016/04/stable-reference-string-magic-voodoo.html
                        unique_id = item.UniqueId
                        new_stable_reference = str(unique_id) + ':0:INSTANCE:' + sr
                        new_reference = DB.Reference.ParseFromStableRepresentation(doc, new_stable_reference)
                        new_reference_array.Append(new_reference)
                        new_stable_representations += str(n) + '\t' + str(item.Id) + ';\t'+ new_stable_reference + ';\t' + str(face.FaceNormal) + ';\t'+ str(face.Origin) +  '\n'
                        n += 1
                else:
                    new_reference_array.Append(reference)
                                    
        """
        print("Verified number of element: \t%s" %len(list_of_elements))
        print("Original ReferenceArray size: \t%s" %original_reference_array.Size)
        print(original_stable_representations)
        print("New ReferenceArray size: \t%s" %len(list_of_new_stable_representation))
        print(new_stable_representations)
        #"""

        new_dimension = doc.Create.NewDimension(dim_view, location_line, new_reference_array, dim_type)

 

Notes:

GetSymbolGeometry() and GetInstanceGeometry() retrieves only Line elements from "INSTANCE" items.

In case of one element solid and it faces did not have stable representation used in dimension

 

Solution prepared with:

0 Likes
Accepted solutions (1)
887 Views
3 Replies
Replies (3)
Message 2 of 4

Moustafa_K
Advisor
Advisor

Not sure this might help, worth a try any way, there is an Id property for edges and Faces, that might come handy for this case. I mean to over run the hurdle of switches between Stable Reference tokens, you can do the same and extract the Face.Id, or Edge.Id , depending on what dimension line is connected to. Then after from this Id you can try to get the same from the new Beam, which eventually you can bring out the true references out of the new beam. then create the new dimension to these references.

 

Not sure this is the perfect solution or addresses the why you have 4 out of 20 that didn't work. Will be glad if you can share your findings. 

 

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
0 Likes
Message 3 of 4

_marcin
Participant
Participant

Thank you for response. I've thought that you can only get References from dimension line, I'll check this aproach in optymalization stage, however the main issue is that I can't get correct reference from those Faces. When I use:

new_reference_array = DB.ReferenceArray()
for face in solid:
    face_normal = face.FaceNormal
    if face_normal.IsAlmostEqualTo(dimension_direction.Negate(), 1e-5):
        reference = face_normal.Reference
        new_reference_array.Append(reference)

I receive error and those references are removed from dimension. Only after modyfying stable representation:

structural_framing_element.UniqueId + ":0:INSTANCE:" + stable_reference

and parsing it from document dimension line is created correctly

0 Likes
Message 4 of 4

_marcin
Participant
Participant
Accepted solution

Looks like I have solved this issue. The cause was that in order to dimension element/get correct references you need get symbol geometry. I had to take few steps:

 

First I needed to get information if geometry of family instance element is modified. If it is, then job is easy as you can get direct access to geometry and retrieve faces/edges references to add to reference array of your dimension.

If element has not modified geometry, then you need to get dimensioned element transformation. With this you transform symbol geometry and find elements you wish to dimension. Alternatively you can go through instance geometry and retrieve its equivalent from symbol geometry using PlanarFace id number, then pass those references to reference array.

 

 

0 Likes