CurveLoop inside another CurveLoop

CurveLoop inside another CurveLoop

AndrewButenko
Advocate Advocate
3,010 Views
7 Replies
Message 1 of 8

CurveLoop inside another CurveLoop

AndrewButenko
Advocate
Advocate

Hello1

I have 2 curveloop (cl1 and cl2). How  to determine cl1 inside cl2 or not?

Безымянный.png

0 Likes
3,011 Views
7 Replies
Replies (7)
Message 2 of 8

aignatovich
Advisor
Advisor

Hi!

 

There is a simple answer, if your curveloops are edges of the face, for example top floor face or side wall face. In such cases outerLoop.IsCounterclockwise(floorFace.ComputeNormal(UV.Zero)) is True.

 

Otherwise, you should analyze your polygons, there are some free libraries, such as NetTopologySuite.

Message 3 of 8

AndrewButenko
Advocate
Advocate

Thank you!

 

Do you have any  example of using NetTopologySuite?

0 Likes
Message 4 of 8

aignatovich
Advisor
Advisor

Please refer to the documentation http://nettopologysuite.github.io/html/index.html

 

This library is simple and powerful. Simple example of use:

 

var factory = new GeometryFactory();

var p1 = factory.CreatePolygon(new[]
	{
		new Coordinate(0, 0),

		new Coordinate(10, 0),

		new Coordinate(10, 10),

		new Coordinate(0, 10),

		new Coordinate(0, 0)
	});

var p2 = factory.CreatePolygon(new[]
	{
		new Coordinate(3, 3),

		new Coordinate(6, 3),

		new Coordinate(7, 4),

		new Coordinate(4.5, 5),

		new Coordinate(2, 4),

		new Coordinate(3, 3)
	});

Console.WriteLine(p2.Within(p1));

Console.WriteLine(p1.Difference(p2).Area);
0 Likes
Message 5 of 8

AndrewButenko
Advocate
Advocate

Thank you! I will try

0 Likes
Message 6 of 8

Mustafa.Salaheldin
Collaborator
Collaborator

Here is the cure for all your pain. I've written a sample code for any generic nested curves/loops. Thanks to @jeremy_tammik and @aignatovich because most of the solution was inspired by them.

 

First please note that I use the Meter as unit in my project. Second I created a function to create 2 nested loop of model curves. The logic behind is always and forever the inner loop(s) will always have a smaller area(s) than the outer one.

So first I listed all the curve arrays as a key value pair then calculate for each one of them the area then select the grater one as it is the outer loop.

 

I hope I helped and please don't forget to mark this reply as an answer.

 

 

 

#region Namespaces

using System;
using System.Collections.Generic;
using Autodesk.Revit.Attributes;

using Autodesk.Revit.DB;

using Autodesk.Revit.UI;

//using Autodesk.Revit.Collections;

using RvtApplication = Autodesk.Revit.ApplicationServices.Application;
using RvtDocument = Autodesk.Revit.DB.Document;

#endregion

namespace test
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    public class NestedCurvesLoops : IExternalCommand
    {
        #region Cached Variables

        private static ExternalCommandData _cachedCmdData;

        public static UIApplication CachedUiApp
        {
            get
            {
                return _cachedCmdData.Application;
            }
        }

        public static RvtApplication CachedApp
        {
            get
            {
                return CachedUiApp.Application;
            }
        }

        public static RvtDocument CachedDoc
        {
            get
            {
                return CachedUiApp.ActiveUIDocument.Document;
            }
        }

        #endregion

        #region IExternalCommand Members         

        public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elemSet)
        {
            _cachedCmdData = cmdData;

            try
            {
                //TODO: add your code below.

                Dictionary<int, CurveArray> cd = CreateNestedLoops();

                double area = 0;
                int theOuterLoopIndex = -1;

                foreach (var ca in cd)
                {
                    List<XYZ> pts = new List<XYZ>();

                    foreach (Curve c in ca.Value)
                    {
                        pts.Add(c.GetEndPoint(0));
                        pts.Add(c.GetEndPoint(1));
                    }

                    double newArea = CalculateArea(pts);

                    if (newArea > area)
                    {
                        area = newArea;
                        theOuterLoopIndex = ca.Key;
                    }
                }

                TaskDialog.Show("Revit", string.Format("The outer loop index is {0}, with area of: {1}.", theOuterLoopIndex, area));

                return Result.Succeeded;
            }
            catch (Exception ex)
            {
                msg = ex.ToString();
                return Result.Failed;
            }
        }

        private double CalculateArea(List<XYZ> p)
        {
            int n = p.Count;

            double sum = p[0].X * (p[1].Y - p[n - 1].Y);
            for (int i = 1; i < n - 1; ++i)
            {
                sum += p[i].X * (p[i + 1].Y - p[i - 1].Y);
            }
            sum += p[n - 1].X * (p[0].Y - p[n - 2].Y);

            return UnitUtils.Convert(0.5 * sum, DisplayUnitType.DUT_SQUARE_FEET, DisplayUnitType.DUT_SQUARE_METERS);
        }

        private Dictionary<int, CurveArray> CreateNestedLoops()
        {
            Dictionary<int, CurveArray> ca = new Dictionary<int, CurveArray>();

            CurveArray theMostOuterLoop = new CurveArray();

            SketchPlane sp = CachedDoc.ActiveView.SketchPlane;

            using (Transaction t = new Transaction(CachedDoc, "Create Curve loops"))
            {
                t.Start();

                XYZ po1 = new XYZ(0, 0, 0);
                XYZ po2 = new XYZ(10, 0, 0);
                XYZ po3 = new XYZ(10, 10, 0);
                XYZ po4 = new XYZ(0, 10, 0);

                ModelCurve co1 = CachedDoc.Create.NewModelCurve(Line.CreateBound(po1, po2), sp);
                ModelCurve co2 = CachedDoc.Create.NewModelCurve(Line.CreateBound(po2, po3), sp);
                ModelCurve co3 = CachedDoc.Create.NewModelCurve(Line.CreateBound(po3, po4), sp);
                ModelCurve co4 = CachedDoc.Create.NewModelCurve(Line.CreateBound(po4, po1), sp);

                theMostOuterLoop.Append(co1.GeometryCurve);
                theMostOuterLoop.Append(co2.GeometryCurve);
                theMostOuterLoop.Append(co3.GeometryCurve);
                theMostOuterLoop.Append(co4.GeometryCurve);

                ca.Add(0, theMostOuterLoop);

                XYZ pi1 = new XYZ(3, 3, 0);
                XYZ pi2 = new XYZ(6, 3, 0);
                XYZ pi3 = new XYZ(7, 4, 0);
                XYZ pi4 = new XYZ(4.5, 5, 0);
                XYZ pi5 = new XYZ(2, 4, 0);

                ModelCurve ci1 = CachedDoc.Create.NewModelCurve(Line.CreateBound(pi1, pi2), sp);
                ModelCurve ci2 = CachedDoc.Create.NewModelCurve(Line.CreateBound(pi2, pi3), sp);
                ModelCurve ci3 = CachedDoc.Create.NewModelCurve(Line.CreateBound(pi3, pi4), sp);
                ModelCurve ci4 = CachedDoc.Create.NewModelCurve(Line.CreateBound(pi4, pi5), sp);
                ModelCurve ci5 = CachedDoc.Create.NewModelCurve(Line.CreateBound(pi5, pi1), sp);

                CurveArray theInsiderLoop = new CurveArray();
                theInsiderLoop.Append(ci1.GeometryCurve);
                theInsiderLoop.Append(ci2.GeometryCurve);
                theInsiderLoop.Append(ci3.GeometryCurve);
                theInsiderLoop.Append(ci4.GeometryCurve);
                theInsiderLoop.Append(ci5.GeometryCurve);

                ca.Add(1, theInsiderLoop);

                t.Commit();
            }


            return ca;
        }

        #endregion
    }
}

¯\_(ツ)_/¯
Let it work like a charm.

Mustafa Salaheldin


EESignature




Digital Integration Manager, DuPod

Facebook | Twitter | LinkedIn

Message 7 of 8

jeremytammik
Autodesk
Autodesk

Dear Mustafa,

 

Thank you for your code sample.

 

The area comparison is indeed useful.

 

It requires that you are sure of two things:

 

  • The inner loop is contained within the outer one.
  • The inner and outer loops do not intersect.

 

Here is my first attempt at delving into this topic:

 

 

Here are some other recent related discussions:

 

 

Cheers,

 

Jeremy



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

0 Likes
Message 8 of 8

Anonymous
Not applicable

if have a Curve is Arc, how do I do?