Closed CurveLoop causes intersection error due to curve overlap

Closed CurveLoop causes intersection error due to curve overlap

MustaeenUrRehmann.Qazi
Contributor Contributor
724 Views
8 Replies
Message 1 of 9

Closed CurveLoop causes intersection error due to curve overlap

MustaeenUrRehmann.Qazi
Contributor
Contributor

Hi,

I am trying to generate curve loops from boundary points of TopoSurfaces.

I am using for loop that runs through the points and creates curves for each pair and then adds to a List of curves, which is then used to create curveloop.

My end purpose is to generate loft geometry from these curve loops.

 

The problem is that the last curve of my curveloop intersects with the first curve which the API doesnt allow for loft creation, and if i remove this last curve, then the loft geometry created is not a solid but rather an open shell. 

So how can i achieve these closed curveloops without creating any intersection. Any help would be appreciated

Here is my code that explains my description further:

 

IList<XYZ> bounding_pts1 = topo1.GetBoundaryPoints();
                    
                    List<Curve> curves1 = new List<Curve>();
               // Implement a For loop to create curves from the boundary 
               //points of topography
                    for (int i = 0; i < bounding_pts1.Count; ++i)
                    {
                        if (i < bounding_pts1.Count - 1)
                        { 
                            // Create lines and add to curves list
                            Line line = Line.CreateBound(bounding_pts1[i], bounding_pts1[i + 1]);
                            //Append points to CurveLoop
                            curves1.Add(line);
                        }

                        else if (i == bounding_pts1.Count - 1)
                        {
                            // Create lines and add to curves list
                            Line line = Line.CreateBound(bounding_pts1[i], bounding_pts1[0]);
                            //Append points to CurveLoop
                            curves1.Add(line);
                        }

                    }
                    //Create line connecting start and end point of topography bound points and adding it to curves collection
                    
                    // check intersection/ Overlap b/w first and last curve in curves list
                    IntersectionResultArray resultArray1 = new IntersectionResultArray();
                    int lastcurveidx1 = curves1.Count - 1;
                    var check_intersect1 = curves1[0].Intersect(curves1[lastcurveidx1], out resultArray1);
                    XYZ intersection_point1 = new XYZ();
                    if (check_intersect1 == SetComparisonResult.Overlap)
                    {
                        //remove the last curve from curves2 list and get XYZ position of the intersection/overlap
                        curves1.RemoveAt(lastcurveidx1);
                        intersection_point1 = resultArray1.get_Item(0).XYZPoint;
                        //Now create a new curve which ends at the intersection point and add it to curves2 list
                        int lastpointidx1 = bounding_pts1.Count - 1;
                        Line last_line1 = Line.CreateBound(bounding_pts1[lastpointidx1], intersection_point1);
                        curves1.Add(last_line1);
                    }

                    // create First curve loop from list of curves i.e a polygon
                    CurveLoop curveLoop1 = CurveLoop.Create(curves1);

                    // now get second topography and perform the same procedure as above

                    Selection sel2 = uiapp.ActiveUIDocument.Selection;
                    TopographySurface topo2 = doc.GetElement(sel2.PickObject(ObjectType.Element)) as TopographySurface;
                    IList<XYZ> bounding_pts2 = topo2.GetBoundaryPoints();

                    List<Curve> curves2 = new List<Curve>();

                    for (int i = 0; i < bounding_pts2.Count ; ++i)
                    {
                       if(i < bounding_pts2.Count - 1)
                       {
                            // Create lines and add to curves list
                            Line line = Line.CreateBound(bounding_pts2[i], bounding_pts2[i + 1]);
                            //Append points to CurveLoop
                            curves2.Add(line);
                       }
                       else if (i == bounding_pts2.Count - 1)
                       {
                            Line line = Line.CreateBound(bounding_pts2[i], bounding_pts2[0]);
                            //Append points to CurveLoop
                            curves2.Add(line);
                       }
                            

                    }

                    //Create line connecting start and end point of topography bound points and adding it to curves collec
                    
                    // check intersection/ Overlap b/w first and last curve in curves list
                    IntersectionResultArray resultArray = new IntersectionResultArray();
                    int lastcurveidx2 = curves2.Count - 1;
                    var check_intersect = curves2[0].Intersect(curves2[lastcurveidx2], out resultArray);
                    XYZ intersection_point = new XYZ();
                    if (check_intersect == SetComparisonResult.Overlap) 
                    {
                        //remove the last curve from curves2 list and get XYZ position of the intersection/overlap
                        curves2.RemoveAt(lastcurveidx2);
                        intersection_point = resultArray.get_Item(0).XYZPoint;
                        //Now create a new curve which ends at the intersection point and add it to curves2 list
                        int lastpointidx2 = bounding_pts2.Count - 1;
                        Line last_line2 = Line.CreateBound(bounding_pts2[lastpointidx2], intersection_point);
                        curves2.Add(last_line2);
                    }

                    // create curve loop from list of curves i.e a polygon
                    CurveLoop curveLoop2 = CurveLoop.Create(curves2);

                    List<CurveLoop> curve_profiles = new List<CurveLoop>();
                    curve_profiles.Add(curveLoop1);
                    curve_profiles.Add(curveLoop2);

Update:

i tried taking the start point of the first curve and used it as the endpoint of the final curve to get the CurveLoop closed but i am still getting the same error

Here the code snippet:

// First check if there is an overlap/ intersection in the curveloop
 if (check_intersect1 == SetComparisonResult.Overlap)
                    {
                        //remove the last curve from curves2 list and get XYZ position of the intersection/overlap
                        curves1.RemoveAt(lastcurveidx1);
                        intersection_point1 = resultArray1.get_Item(0).XYZPoint;
                        //Now create a new curve which ends at the intersection point and add it to curves2 list
                        int lastpointidx1 = bounding_pts1.Count - 1;
                        // get start point of first curve from the curve list
                        var start_pt_first_curve = curves1[0].GetEndPoint(0);
                        Line last_line1 = Line.CreateBound(bounding_pts1[lastpointidx1], start_pt_first_curve);
                        curves1.Add(last_line1);
                    }

                    // create curve loop from list of curves i.e a polygon
                    CurveLoop curveLoop1 = CurveLoop.Create(curves1);

 

0 Likes
Accepted solutions (3)
725 Views
8 Replies
Replies (8)
Message 2 of 9

mhannonQ65N2
Advocate
Advocate
Accepted solution

Are you sure that GetBoundaryPoints is giving you the points in the order that you want? It could be giving them in the order they were added or some other order. I suggest that you use your list of lines to create some model lines so you can see what is going on by looking at the model.

Message 3 of 9

RPTHOMAS108
Mentor
Mentor

You need to check the profiles are not intersecting by elevation also.

 

You are essentially creating a solid between two surfaces. All the points of the top surface need to be separated in elevation from all the points of the bottom surface or the side walls will cross. However you have inconsistent logs where layers only feature in certain logs. The missing information you don't have would probably eliminate the intersections you are currently getting.

 

 

Message 4 of 9

MustaeenUrRehmann.Qazi
Contributor
Contributor

Hi,

A bit of further information to explain the Error:

The algorithm that creates the TopoSurfaces is designed such that it doesnt create any intersecting toposurfaces. i.e  if connecting two or more stratas causes  an intersection into other soil stratas the algorithm skips that and keeps tha layer sequence intact. Thus, its a simple layer structure with one layer below another and no intersections in z -direction.  

Second, The loft is created by user selection of two toposurfaces after the toposurfaces for all the soil layers are formed.

In current situation i have all the toposurfaces of all horizons, now:

1. First Toposurface is selected and its boundary points are extracted

2. A list of curves is formed using these boundary points(using a for loop which creates a Line for each consecutive pair of boundary points )

3. A curve loop from the curves created using the above for loop

4. Second toposurfaces is selected by user (Topos surfaces are not intersecting in z direction)

5. The same procedure as above from points 2 to 3.

6. Loft is created.

Problem: If i do not connect (i.e create a line/curve) the last point in my Boundary points list  to the first point then every thing is fine Loft is created as an open shell. But as soon as i connect the last point in boundary points list to the first point i.e try to close the curveloop, The API gives me the intersection Error.

**  code example in the post

0 Likes
Message 5 of 9

MustaeenUrRehmann.Qazi
Contributor
Contributor

Hi,
Thank you, yes i got your point. I have no intersections in Z direction, I posted some more detail above to explain the problem further. Any help would be appreciated,
Cheers,

0 Likes
Message 6 of 9

MustaeenUrRehmann.Qazi
Contributor
Contributor

Hi,

I have checked again the open shell that is created. Yes it seems to be that, the problem lies in the order of the Boundary points, So the method GetBoundaryPoints() doesnt extract boundary points in a specific order. This causes the problem when i connect the points using my for loop technique (that connects each consecutive pair of points). 

Since I am doing it programatically how would I be able to order the list of points? Any help in this direction would be appreciated.

Cheers,

Update:

Here seems to be a solution to this problem.

Does TopographySurface.GetBoundaryPoints guarantee point ordering? - Autodesk Community - Revit Prod...

0 Likes
Message 7 of 9

RPTHOMAS108
Mentor
Mentor
Accepted solution

Probably easier to either compare the points with the Mesh in the geometry or just use the Mesh geometry to find the points alone.

 

In the mesh the exterior points will be those associated with edges that appear in only one triangle. The exterior edges then also define the order of the points around the topo.

 

How are you ensuring the topo surface only has exterior points when created from the logs? Your top and bottom loft surfaces will not feature level changes due to the internal points of the topo. 

Message 8 of 9

MustaeenUrRehmann.Qazi
Contributor
Contributor
Hi,
Thank you!!. Great Idea. I get your point. So i Used a ConvexHull algorithm(Jarvis March Algorithm ) to get out the boundary points(Points that form the hull). So all the points constituting the Toposurface (Interior plus exterior) are provided to the algorithm which then takes out the outermost points based on Left most orientation. Ill share it below as Solution.
I also get your point regarding the final loft created, as it wont represent the level changes. Yes thats an issue which i need to solve in the next step, either i will try Tesselated shape or something similar e.g a Nurbs surface that envelops the whole layer. I would appreciate some help in this regard as well. Thanks again!!
0 Likes
Message 9 of 9

MustaeenUrRehmann.Qazi
Contributor
Contributor
Accepted solution

Hi all,

So after some research i came up with another solution to getting the boundary points, Since we can Imagine the Toposurface as a Polygon that has inner points as well as exterior points. So,  this issue can then be considered as a convexhull problem. I have used a ConvexHull algorithm called "Jarvis March" algorithm to extract the Boundary points of the toposurfaces. A list of all points that constitute the Toposurface is provided to the Algorithm which then takes out the boundary points or the points which constitute convex hull.

Code:

 

 

 

public class GeometryMethods 
    {
        public static List<XYZ> ConvexHull(List<XYZ> points)
        {
            if (points.Count < 3)
            {
                throw new ArgumentException("At least 3 points reqired", "points");
            }

            List<XYZ> hull = new List<XYZ>();

            // get leftmost point
            XYZ vPointOnHull = points.Where(p => p.X == points.Min(min => min.X)).First();

            XYZ vEndpoint;
            do
            {
                hull.Add(vPointOnHull);
                vEndpoint = points[0];

                for (int i = 1; i < points.Count; i++)
                {
                    if ((vPointOnHull == vEndpoint)
                        || (Orientation(vPointOnHull, vEndpoint, points[i]) == -1))
                    {
                        vEndpoint = points[i];
                    }
                }

                vPointOnHull = vEndpoint;

            }
            while (vEndpoint != hull[0]);

            return hull;
        }

        private static int Orientation(XYZ point1, XYZ point2, XYZ point)
        {
            // Calculate the determinant
            int Orin = (int)((point2.X - point1.X) * 
(point.Y - point1.Y) - (point.X - point1.X) * (point2.Y - point1.Y));
// Left oriented
            if (Orin > 0)
                return -1; 
 // Right Oriented 
            if (Orin < 0)
                return 1;
 // Colinear 
            return 0;
        }
    }

 

 

 

 

0 Likes