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


Digital Integration Manager, DuPod
Facebook |
Twitter |
LinkedIn