Create dimension to wall centerline, center of core, faces of core

Create dimension to wall centerline, center of core, faces of core

boostyourbim
Advocate Advocate
11,891 Views
53 Replies
Message 1 of 54

Create dimension to wall centerline, center of core, faces of core

boostyourbim
Advocate
Advocate

I'm trying to create dimensions to walls via the API. It is possible to get a reference to a wall's centerline, center of core, and faces of core? These options are avaiable when creating dimensions in the Revit UI.

0 Likes
11,892 Views
53 Replies
Replies (53)
Message 41 of 54

l_malyshev
Explorer
Explorer

Hello @jeremy_tammik,  @FAIR59 and everyone. How can I get the correct stable representation for the pipe?

7ad0349e-ace2-4a15-b604-c796c492579c-0025b218:0:LINEAR/0
7ad0349e-ace2-4a15-b604-c796c492579c-0025b218:0:LINEAR/1

Pipe with a slopePipe with a slope

 

0 Likes
Message 42 of 54

jeremy_tammik
Alumni
Alumni

Not sure, but guessing: pipe has a LocationCurve; the curve has endpoints; the end points have references; the references can be converted to their stable representations; please check and confirm; may be wrong.

  

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

andrzej_m
Participant
Participant

Hi All ,

 

As far as I investigated, there is a rule that determines how indexed references are ordered. (It's a program, so there must be some logic to it.)

 

For multi-layer wall I think the order is:

1: Center axis
2: 1-2 layers face
3: 2-3 layers face
4: 3-4 layers face

***

N: Core Center axis
N+1: Last face
N+2: First face

Where N is the count of wall layers

 

Aricke59 has right but I think that the missing point is that when we change the wall instance type then already created references had to remain unchanged and probably new references are appended. 

 

In the end we have no sure that we will reference to proper face by manually created stable representation unless we've just created the wall ourselves.

 

Best regards

Andrzej

0 Likes
Message 44 of 54

andrzej_m
Participant
Participant

Code to create alignment to wall core center axis: (works as described above)

        private void CreateWallCoreAxisToGridAlignment(Grid newGrid, Wall wall)
        {
            var layersCount = wall.WallType.GetCompoundStructure().GetLayers().Count();

            try
            {
                var stableRep = CreateStableRepresentation(wall, layersCount);

                var ref0 = Reference.ParseFromStableRepresentation(Doc, stableRep);

                Doc.Create.NewAlignment(View, newGrid.Curve.Reference, ref0);

                Debug.WriteLine("NewAlignment to standard stable representation created!");
            }
            catch (Exception ex)
            {
                var stableRefs = GetStableRepresentations(wall, layersCount + 7);

                foreach (var stRefStr in stableRefs)
                {
                    try
                    {
                        var stRef = Reference.ParseFromStableRepresentation(Doc, stRefStr);

                        if (stRef != null)
                        {
                            Doc.Create.NewAlignment(View, newGrid.Curve.Reference, stRef);
                            Debug.WriteLine("NewAlignment to random stable representation created!!!");
                            break;
                        }
                    }
                    catch (Exception) { }
                }
            }
        }


        internal static string CreateStableRepresentation(Element element, int stRefIndex)
        {
            string uniqueID = element.UniqueId;

            return $"{uniqueID}:{stRefIndex}:SURFACE";
        }

        internal static List<string> GetStableRepresentations(Element element, int count)
        {
            var result = new List<string>();    

            string uniqueID = element.UniqueId;

            for (int i = 0; i < count; i++)
            {
                result.Add($"{uniqueID}:{i}:SURFACE");
            }

            return result;
        }

 

Best regards

Andrzej

0 Likes
Message 45 of 54

Annonymous24
Explorer
Explorer

 is there any working solution for this?

 

0 Likes
Message 46 of 54

dvargas7EMYQ
Explorer
Explorer

Hi @andrzej_m to reference to faces, specifically how should the reference string be formatted? Can you provide an example of a valid reference string?

0 Likes
Message 47 of 54

ctm_mka
Collaborator
Collaborator

Going back to the topic of walls, and workarounds, (note i have not read every response, no idea if anyone came up with this yet) id like to propose this "hack-y" solution:

Why use wall references at all? Why not create detail lines where you need them, and get references from the them instead (presuming that is relatively easy)?

  • Assuming the the view you want to dimension in is cut perpendicular to the wall, the bounding box of the wall in the active view will actually represent the outside faces of the wall.
  • the bounding box min point is the bottom left of the wall, relative to the view.
  • using this point, create your first detail curve.
  • iterate through the wall layers to get their thicknesses using WallType.GetCompoundStructure().GetLayers();
    • note the order of the wall layers when listed seems to be top to bottom, as you would read them in the edit assembly screen, can someone confirm this is consistent with variable layered compound walls?
  • create offsets of the original detail curve using the wall layer thicknesses and the view direction.
  • get references of detail curves.
0 Likes
Message 48 of 54

ctm_mka
Collaborator
Collaborator

So i was a bit bored this morning, and coded up a working solution to my workaround, enjoy:

 UIDocument _uidoc = commandData.Application.ActiveUIDocument;
 Document _doc = _uidoc.Document;
 View _active = _uidoc.ActiveView;
 ICollection<ElementId> _selectionIdList = _uidoc.Selection.GetElementIds();
 ICollection<GraphicsStyle> gscoll = new FilteredElementCollector(_doc).OfClass(typeof(GraphicsStyle)).Cast<GraphicsStyle>().ToList();
 ICollection<DimensionType> dimscoll = new FilteredElementCollector(_doc).OfClass(typeof(DimensionType)).Cast<DimensionType>().ToList();
 GraphicsStyle linestyle = gscoll.Where(x => x.Name.Equals("Your Line Style here")).FirstOrDefault();
 DimensionType dimstyle = dimscoll.Where(x => x.Name.Equals("Your Dimension Sytle here")).FirstOrDefault();
 Wall elem = _doc.GetElement(_selectionIdList.First()) as Wall;
 BoundingBoxXYZ bbox = elem.get_BoundingBox(_active);
 XYZ start = bbox.Min;
 WallType wtype = elem.WallType;
 var structure = wtype.GetCompoundStructure().GetLayers();
 List<double> thickies = structure.Select(layer => layer.Width).ToList();
 List<Curve> linecoll = new List<Curve>();
 Curve startline = Line.CreateBound(start, new XYZ(start.X, start.Y, start.Z + 2)); //adjust z value as needed for end point
 linecoll.Add(startline);
 
 double thkprevious = 0;
 for (int i = 0; i < thickies.Count; i++)
 {
     double thk = thickies[i] + thkprevious;
     thkprevious = thk;
     Curve temp = startline.CreateOffset(thk, _active.ViewDirection);
     linecoll.Add(temp);
 }
 Line dimline = Line.CreateBound(startline.GetEndPoint(1), linecoll.Last().GetEndPoint(1));
 ReferenceArray refarray = new ReferenceArray();
 using (Transaction tr = new Transaction(_doc))
 {
     tr.Start("Wall Dims in Section");
     foreach (Curve curve in linecoll)
     {
         DetailCurve test = _doc.Create.NewDetailCurve(_active, curve);
         refarray.Append(test.GeometryCurve.Reference);
         test.LineStyle = linestyle;
     }
     
     Dimension newdim = _doc.Create.NewDimension(_active, dimline, refarray);
     newdim.DimensionType = dimstyle;
     tr.Commit();
0 Likes
Message 49 of 54

andrzej_m
Participant
Participant

Hi All.

 

@Annonymous24 for me this is the only working solution to guess a stable representation of specific layer face to create a dimension.

 

@dvargas7EMYQ in my code You can see the stable representation string formatting for element surface: 

$"{uniqueID}:{stRefIndex}:SURFACE";

 

@ctm_mkafor me the main problem with Your solution is that references created this way are not attached to that wall, so when that wall changes its position Your lines will remain in the old location.

 

0 Likes
Message 50 of 54

Annonymous24
Explorer
Explorer

@andrzej_m , can you elaborate how to guess a stable representation of specific layer face. coz not able to understand its logic . I want to dimension core boundary . 

0 Likes
Message 51 of 54

andrzej_m
Participant
Participant

@Annonymous24 The code I posted assumes that I know the exact position of my layer face. However, if I try to create a dimension referencing the wrong stable representation, the dimension creation will throw an error.

As I mentioned earlier, there is an algorithm that Revit uses to assign stable representation indexes to newly created walls. However, when a wall type is changed, new indexes may be appended.

 

My approach is as follows:

I first attempt to create a dimension using the index I expect for the new wall.

If that fails, I try each available index one by one until the correct one is found.

 

In the vast majority of cases, the wall type will either remain unchanged or change to another type with the same number of layers. In those situations, my logic typically “guesses” the correct index on the first attempt.

0 Likes
Message 52 of 54

TripleM-Dev.net
Advisor
Advisor

Hi@Annonymous24 ,

 

Certain wall faces/planes have fixed indexes (not documented by Autodesk, but used this for a decade), like the exterior, center and interior face.

And there are some more I think, like Core and some depending on how many layers and it's structure.

 

There's a list somewhere floating around about these (similar when you want to dimension to certain family planes, like top, bottom, right etc)

 

Dimension a wall manually and use RevitLoopup addin to id how the stable reference is build and what Surface index is used for common wall faces.

(haven't got a simple sample on hand, there should be a lot of samples here, i've posted several myself, look for revit stable reference voodomagic)

 

For instance dimensioning to the exterior wall face index won't break if another wall type is selected.

 

- Michel

0 Likes
Message 53 of 54

dvargas7EMYQ
Explorer
Explorer

@andrzej_m Thank you for you response! The reason I asked was because I tried your method but consistently got invalid references. I assumed maybe I was formatting the reference string improperly, however I used the exact format you presented above. 

 

This is what I tested and the results :

8-layer wall

1 - wall center line
2 - invalid reference
3 - invalid reference
4 - invalid reference
5 - exterior finish face
6 - interior finish face
7 - invalid reference
8 - invalid reference
9 - invalid reference
10 - invalid reference

 

5-layer wall

1 - wall center line
2 - invalid reference
3 - invalid reference
4 - invalid reference
5 - exterior finish face
6 - interior finish face
7 - invalid reference

 

Through my testing the only indices that produce any valid references is 1,5 and 6 to the wall center, exterior face and interior face respectively. However, I've been unable to replicate the behavior you outlined in your earlier post. 

 

0 Likes
Message 54 of 54

andrzej_m
Participant
Participant

@dvargas7EMYQ 

I would recommend checking the following:

  1. The geometry you're trying to reference may not have generated references. In that case, try retrieving the geometry using the Options.ComputeReferences = true setting to ensure references are created.

  2. If your wall is from an older model or has undergone many modifications, the stable representation indexes might have been overridden and set to unusually high values.

  3. Try manually creating a dimension to the specific layer in Revit, and then inspect its reference string using a tool like RevitLookup. This will also show you the exact format of the reference string.

0 Likes