Create dimensions for Filled Region Boundary

Anonymous

Create dimensions for Filled Region Boundary

Anonymous
Not applicable

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!

0 Likes
Reply
Accepted solutions (1)
1,814 Views
10 Replies
Replies (10)

jeremytammik
Autodesk
Autodesk

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

0 Likes

Anonymous
Not applicable

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

0 Likes

aignatovich
Advisor
Advisor
Accepted solution

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

Anonymous
Not applicable

Thanks, @aignatovich. I really appreciate it.

 

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

 

Regards

0 Likes

aignatovich
Advisor
Advisor

Dimensioning in Revit is one of my favorite topics Robot Happy


0 Likes

Anonymous
Not applicable

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

0 Likes

Anonymous
Not applicable

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!

 

0 Likes

Anonymous
Not applicable

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!

0 Likes

jeremytammik
Autodesk
Autodesk

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

0 Likes

Anonymous
Not applicable

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! 

0 Likes