Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Create dimensions for Filled Region Boundary

10 REPLIES 10
SOLVED
Reply
Message 1 of 11
Anonymous
1748 Views, 10 Replies

Create dimensions for Filled Region Boundary

Hi All,

 

I've been working with dimensions for a while for multiple objects. The method needs a ReferenceArray to work. Now, I need to create dimensions for a filled region and I can't get the reference for the curves contained in the boundary.

 

Filled RegionFilled RegionDimensions for the FIlled Region.Dimensions for the FIlled Region.

Any tip of advice will be very well received.

 

Thanks in advance!

10 REPLIES 10
Message 2 of 11
jeremytammik
in reply to: Anonymous

Dear Jorge,

 

Thank you for your query.

 

How did you create the dimensions in your second image?

 

Hove you used RevitLookup to explore in depth the filled region geometry and the dimension object with their respective references?

 

I have passed on your question to the development team for advice for you.

 

Best regards,

 

Jeremy

 



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

Message 3 of 11
Anonymous
in reply to: jeremytammik

Hi @jeremytammik , Thanks for your reply.

 

The dimensions in the second image were created using native commands (no API, just clicking using "Align Dimension").

 

Indeed, I used Revit Lookup searching for some "Reference" in the Filled Region sub-elements with no results. Already tried to get the references from the CUrveLoop curves, but again, with no results. All I get is "Reference = null".

 

Any tip of advice will be very well received.

 

Thanks for escalating the query to the development team.

 

Regards

Message 4 of 11
aignatovich
in reply to: Anonymous

Hi! Try this code:

[Transaction(TransactionMode.Manual)]
public class CreateFillledRegionDimensionsCommand : IExternalCommand
{
	public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
	{
		var uiapp = commandData.Application;
		var uidoc = uiapp.ActiveUIDocument;
		var doc = uidoc.Document;

		var view = uidoc.ActiveGraphicalView;

		var filledRegions = FindFilledRegions(doc, view.Id).ToList();

		using (var transaction = new Transaction(doc, "filled regions dimensions"))
		{
			transaction.Start();

			foreach (var filledRegion in filledRegions)
			{
				CreateDimensions(filledRegion, -1*view.RightDirection);

				CreateDimensions(filledRegion, view.UpDirection);
			}

			transaction.Commit();
		}

		return Result.Succeeded;
	}

	private static void CreateDimensions(FilledRegion filledRegion, XYZ dimensionDirection)
	{
		var document = filledRegion.Document;

		var view = (View) document.GetElement(filledRegion.OwnerViewId);

		var edgesDirection = dimensionDirection.CrossProduct(view.ViewDirection);

		var edges = FindRegionEdges(filledRegion)
			.Where(x => IsEdgeDirectionSatisfied(x, edgesDirection))
			.ToList();

		if (edges.Count < 2)
			return;

		var shift = UnitUtils.ConvertToInternalUnits(-10*view.Scale, DisplayUnitType.DUT_MILLIMETERS)*edgesDirection;

		var dimensionLine = Line.CreateUnbound(filledRegion.get_BoundingBox(view).Min + shift, dimensionDirection);

		var references = new ReferenceArray();

		foreach (var edge in edges)
			references.Append(edge.Reference);

		document.Create.NewDimension(view, dimensionLine, references);
	}

	private static bool IsEdgeDirectionSatisfied(Edge edge, XYZ edgeDirection)
	{
		var edgeCurve = edge.AsCurve() as Line;

		if (edgeCurve == null)
			return false;

		return edgeCurve.Direction.CrossProduct(edgeDirection).IsAlmostEqualTo(XYZ.Zero);
	}

	private static IEnumerable<Edge> FindRegionEdges(FilledRegion filledRegion)
	{
		var view = (View)filledRegion.Document.GetElement(filledRegion.OwnerViewId);

		var options = new Options
			{
				View = view,
				ComputeReferences = true
			};

		return filledRegion
			.get_Geometry(options)
			.OfType<Solid>()
			.SelectMany(x => x.Edges.Cast<Edge>());
	}

	private static IEnumerable<FilledRegion> FindFilledRegions(Document document, ElementId viewId)
	{
		var collector = new FilteredElementCollector(document, viewId);

		return collector
			.OfClass(typeof (FilledRegion))
			.Cast<FilledRegion>();
	}
}

It produces something like this:

 

dimensioned-filled-region.PNG

Message 5 of 11
Anonymous
in reply to: aignatovich

Thanks, @aignatovich. I really appreciate it.

 

I'll give it a try with my script and I'll post here how it turned!.

 

Regards

Message 6 of 11
aignatovich
in reply to: Anonymous

Dimensioning in Revit is one of my favorite topics Robot Happy


Message 7 of 11
Anonymous
in reply to: aignatovich

Glad to hear! Now I know where to focus my questions! 😄

Message 8 of 11
Anonymous
in reply to: aignatovich

Hi @aignatovich . Your suggestion was the solution to my problem!. I took (if you don't mind) the liberty to extend the approach, so the method asks for the type name (string) of the dimension you want to assign:

 

private void CreateDimensions(
            FilledRegion filledRegion,
            XYZ dimensionDirection,
            string typeName)
        {
            var document = filledRegion.Document;

            var view = (View)document.GetElement(filledRegion.OwnerViewId);

            var edgesDirection = dimensionDirection.CrossProduct(view.ViewDirection);

            var edges = FindRegionEdges(filledRegion)
                .Where(x => IsEdgeDirectionSatisfied(x, edgesDirection))
                .ToList();

            if (edges.Count < 2)
                return;

            // Se hace este ajuste para que la distancia no depende de la escala. <<<<<< evaluar para información de acotado y etiquetado!!!
            var shift = UnitUtils.ConvertToInternalUnits(5 * view.Scale, DisplayUnitType.DUT_MILLIMETERS) * edgesDirection;

            var dimensionLine = Line.CreateUnbound(
                filledRegion.get_BoundingBox(view).Min + shift,
                dimensionDirection);

            var references = new ReferenceArray();

            foreach (var edge in edges)
                references.Append(edge.Reference);

            Dimension dim = document.Create.NewDimension(view, dimensionLine, references);

            ElementId dr_id = DimensionTypeId(
                        document, typeName);

            if (dr_id != null)
            {
                dim.ChangeTypeId(dr_id);
            }
        }

        private static bool IsEdgeDirectionSatisfied(Edge edge, XYZ edgeDirection)
        {
            var edgeCurve = edge.AsCurve() as Line;

            if (edgeCurve == null)
                return false;

            return edgeCurve.Direction.CrossProduct(edgeDirection).IsAlmostEqualTo(XYZ.Zero);
        }

        private static IEnumerable<FilledRegion> FindFilledRegions(Document document, ElementId viewId)
        {
            var collector = new FilteredElementCollector(document, viewId);

            return collector
                .OfClass(typeof(FilledRegion))
                .Cast<FilledRegion>();
        }

        private static IEnumerable<Edge> FindRegionEdges(FilledRegion filledRegion)
        {
            var view = (View)filledRegion.Document.GetElement(filledRegion.OwnerViewId);

            var options = new Options
            {
                View = view,
                ComputeReferences = true
            };

            return filledRegion
                .get_Geometry(options)
                .OfType<Solid>()
                .SelectMany(x => x.Edges.Cast<Edge>());
        }

        private static ElementId DimensionTypeId(
            Document doc,
            string typeName)
        {
            List<Element> mt_coll = new FilteredElementCollector(doc)
                .OfClass(typeof(DimensionType))
                .WhereElementIsElementType()
                .ToList();

            DimensionType dimType = null;

            foreach (Element type in mt_coll)
            {
                if (type is DimensionType)
                {
                    if (type.Name == typeName)
                    {
                        dimType = type as DimensionType;
                        break;
                    }
                }

            }

            return dimType.Id;
        }

Hope this helps someone else!

 

Regards!

 

Message 9 of 11
Anonymous
in reply to: aignatovich

Hi @aignatovich . Your suggestion was the solution to my problem!. I took (if you don't mind) the liberty to extend the approach, so the method asks for the type name (string) of the dimension you want to assign:

 

private void CreateDimensions(
            FilledRegion filledRegion,
            XYZ dimensionDirection,
            string typeName)
        {
            var document = filledRegion.Document;

            var view = (View)document.GetElement(filledRegion.OwnerViewId);

            var edgesDirection = dimensionDirection.CrossProduct(view.ViewDirection);

            var edges = FindRegionEdges(filledRegion)
                .Where(x => IsEdgeDirectionSatisfied(x, edgesDirection))
                .ToList();

            if (edges.Count < 2)
                return;

            // Se hace este ajuste para que la distancia no depende de la escala. <<<<<< evaluar para información de acotado y etiquetado!!!
            var shift = UnitUtils.ConvertToInternalUnits(5 * view.Scale, DisplayUnitType.DUT_MILLIMETERS) * edgesDirection;

            var dimensionLine = Line.CreateUnbound(
                filledRegion.get_BoundingBox(view).Min + shift,
                dimensionDirection);

            var references = new ReferenceArray();

            foreach (var edge in edges)
                references.Append(edge.Reference);

            Dimension dim = document.Create.NewDimension(view, dimensionLine, references);

            ElementId dr_id = DimensionTypeId(
                        document, typeName);

            if (dr_id != null)
            {
                dim.ChangeTypeId(dr_id);
            }
        }

        private static bool IsEdgeDirectionSatisfied(Edge edge, XYZ edgeDirection)
        {
            var edgeCurve = edge.AsCurve() as Line;

            if (edgeCurve == null)
                return false;

            return edgeCurve.Direction.CrossProduct(edgeDirection).IsAlmostEqualTo(XYZ.Zero);
        }

        private static IEnumerable<FilledRegion> FindFilledRegions(Document document, ElementId viewId)
        {
            var collector = new FilteredElementCollector(document, viewId);

            return collector
                .OfClass(typeof(FilledRegion))
                .Cast<FilledRegion>();
        }

        private static IEnumerable<Edge> FindRegionEdges(FilledRegion filledRegion)
        {
            var view = (View)filledRegion.Document.GetElement(filledRegion.OwnerViewId);

            var options = new Options
            {
                View = view,
                ComputeReferences = true
            };

            return filledRegion
                .get_Geometry(options)
                .OfType<Solid>()
                .SelectMany(x => x.Edges.Cast<Edge>());
        }

        private static ElementId DimensionTypeId(
            Document doc,
            string typeName)
        {
            List<Element> mt_coll = new FilteredElementCollector(doc)
                .OfClass(typeof(DimensionType))
                .WhereElementIsElementType()
                .ToList();

            DimensionType dimType = null;

            foreach (Element type in mt_coll)
            {
                if (type is DimensionType)
                {
                    if (type.Name == typeName)
                    {
                        dimType = type as DimensionType;
                        break;
                    }
                }

            }

            return dimType.Id;
        }

 

image.png

 

Hope this helps someone else!

 

Regards!

Message 10 of 11
jeremytammik
in reply to: Anonymous

Thank you very much, both, for the nice solution!

 

Edited and preserved for posterity by The Building Coder:

 

https://thebuildingcoder.typepad.com/blog/2019/08/auto-dimension-filled-region-boundary.html

 

Cheers,

 

Jeremy

 



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

Message 11 of 11
Anonymous
in reply to: jeremytammik

Hi @jeremytammik, It is an honor to be mentioned on The Building Coder.

 

All the credits must go to @aignatovich, who's a solution was outstanding! I just tweaked it a little bit.

 

Thanks again on helping with the solution!

 

Regards! 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Rail Community


Autodesk Design & Make Report