Remove unnecessary points in curveloop

Remove unnecessary points in curveloop

desdinova
Advocate Advocate
1,100 Views
2 Replies
Message 1 of 3

Remove unnecessary points in curveloop

desdinova
Advocate
Advocate
 public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument uidoc = uiapp.ActiveUIDocument;
            Application app = uiapp.Application;
            Document doc = uidoc.Document;

            Reference reference = uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);

            Room room = doc.GetElement(reference) as Room;

            List<CurveLoop> curveLoops = GetRoomBoundry(room);

            List<XYZ> points = new List<XYZ>();
            List<XYZ> pointsToRemove = new List<XYZ>();
            double threshold = 0.1;

            foreach (Curve curve in curveLoops[0])
            {
                points.Add(curve.GetEndPoint(0));
            }

            for (int i = 1; i < points.Count-1; i++)
            {
                XYZ previous = points[i - 1];
                XYZ current = points[i];
                XYZ next = points[i + 1];

                double nextToPrevious = DistanceBetweenPoints(previous, next);
                double ordinal = DistanceBetweenPoints(previous, current) + DistanceBetweenPoints(current, next);

                if (Math.Abs(nextToPrevious - ordinal) < threshold)
                {
                    pointsToRemove.Add(points[i]);
                }

            }

            if(pointsToRemove.Count>0)
            {
                foreach (XYZ point in pointsToRemove)
                {
                    LineUtils.DrawMarker(doc, point);
                }
            }

            return Result.Succeeded;
        }

        public double DistanceBetweenPoints(XYZ firstPoint,XYZ secondPoint)
        {
            Line line = Line.CreateBound(firstPoint, secondPoint);
            return line.ApproximateLength;
        }

        public static List<CurveLoop> GetRoomBoundry(Room room)
        {
            Document doc = room.Document;

            List<CurveLoop> curveLoops = new List<CurveLoop>();

            CurveLoop curveLoop = null;

            IList<IList<Autodesk.Revit.DB.BoundarySegment>> loops = room.GetBoundarySegments(new SpatialElementBoundaryOptions());

            foreach (IList<Autodesk.Revit.DB.BoundarySegment> loop in loops)
            {
                IList<Curve> curveList = new List<Curve>();

                foreach (Autodesk.Revit.DB.BoundarySegment seg in loop)
                {
                    Curve curve = seg.GetCurve();
                    XYZ p = curve.GetEndPoint(0);
                    XYZ q = curve.GetEndPoint(1);
                    Line line = Line.CreateBound(p, q);
                    curveList.Add(Line.CreateBound(p, q));
                }

                curveLoop = CurveLoop.Create(curveList);
                curveLoops.Add(curveLoop);
            }

            return curveLoops;

        }

Hello friends

I want to remove unnecessery point from my curveloop 

ın image below i mark the points i dont need.

But some curveloops i cant find the all unnecessery points

How can i solve this?

Is there any smarter algorithm?

Thanks in advance....

 

2017-10-27_13-24-47 (2).png

 

 

 

 

0 Likes
1,101 Views
2 Replies
Replies (2)
Message 2 of 3

RPTHOMAS108
Mentor
Mentor

I believe the problem in your code is that as you iterate the list of points the first point is never the next point. i.e. you start at a point, find the distance to the next point and continue this pattern until all points have been iterated over. However, the last point is close to the first point where you started but this isn’t considered (since iteration has now ended). Are you always finding one point missing?

 

I would instead create two empty collections (A & B), iterate the points and add to collection ‘A’ if the point isn’t already in that list (in terms of distance comparison), otherwise add to collection ‘B’. Then I’d know that all items in collection B are the ones I’d want to get rid of. I would then iterate the items in ‘B’ find the curve with matching end point according to distance nearest to 0. For that curve end I’d look in collection ‘A’ for the nearest point and that will be the point I adjust the end to.

 

XXY class has a distance to other XYZ function so there is no need to draw a line and measure its length. Distance between points can also be found by an adaption of Pythagoras theorem:

 

Distance = Sqrt((X1-X2)^2 + (Y1-Y2)^2 + (Z1-Z2)^2)

 

I assume all of your rooms are square? If you are going to recreate these loops later then you are only currently allowing for point to point straight lines. If a wall is at a room corner then it appears (from the logic shown in your output) the line will be thrown off position by the elimination of one of the points.

0 Likes
Message 3 of 3

desdinova
Advocate
Advocate

Thank you for your reply.

In my case 

public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument uidoc = uiapp.ActiveUIDocument;
            Application app = uiapp.Application;
            Document doc = uidoc.Document;

            Reference reference = uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element,new ElementSelectionFilter<Room>());

            Room room = doc.GetElement(reference) as Room;

            List<CurveLoop> curveLoops = GetRoomBoundry(room);

            List<XYZ> points = new List<XYZ>();
            List<XYZ> pointsToRemove = new List<XYZ>();

            foreach (Curve curve in curveLoops[0])
            {
                points.Add(curve.GetEndPoint(0));
            }

            for (int i = 0; i < points.Count; i++)
            {
                XYZ firstPoint = points[i];

                for (int j = 0; j < points.Count; j++)
                {
                    if (firstPoint.ToString() != points[j].ToString())
                    {
                        Line line = Line.CreateBound(firstPoint, points[j]);
                        XYZ startPoint = line.GetEndPoint(0);
                        XYZ endPoint = line.GetEndPoint(1);

                        foreach (XYZ xyz in points)
                        {
                            if(xyz.ToString()!=startPoint.ToString()&&xyz.ToString()!=endPoint.ToString())
                            {
                                if(line.Contains(xyz))
                                {
                                    if (!pointsToRemove.Contains(xyz))
                                    {
                                        pointsToRemove.Add(xyz);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (pointsToRemove.Count>0)
            {
                foreach (XYZ point in pointsToRemove)
                {
                    points.Remove(point);
                    LineUtils.DrawMarker(doc, point);
                }
            }

            return Result.Succeeded;
        }

The code above is working fine.

I will try your suggessions.

Thanks a lot.

0 Likes