@@ -77,29 +77,8 @@ public static BoundingBox BooleanIntersection(this List<BoundingBox> boxes, doub
77
77
[ Output ( "intersection" , "The line corresponding to the overlap of the two provided lines or null if no overlap could be found." ) ]
78
78
public static Line BooleanIntersection ( this Line line , Line refLine , double tolerance = Tolerance . Distance )
79
79
{
80
- if ( line == null || line . Length ( ) <= tolerance || refLine . Length ( ) <= tolerance )
81
- return null ;
82
-
83
- if ( line . IsCollinear ( refLine , tolerance ) )
84
- {
85
- List < Line > splitLine = line . SplitAtPoints ( refLine . ControlPoints ( ) , tolerance ) ;
86
- if ( splitLine . Count == 3 )
87
- return splitLine [ 1 ] ;
88
- else if ( splitLine . Count == 2 )
89
- {
90
- Point aPt = refLine . ControlPoints ( ) . Average ( ) ;
91
- return line . Start . SquareDistance ( aPt ) < line . End . SquareDistance ( aPt ) ? splitLine [ 0 ] : splitLine [ 1 ] ;
92
- }
93
- else
94
- {
95
- double sqTol = tolerance * tolerance ;
96
- Point aPt = splitLine [ 0 ] . ControlPoints ( ) . Average ( ) ;
97
- Point aRPt = refLine . ControlPoints ( ) . Average ( ) ;
98
- return aRPt . SquareDistance ( splitLine [ 0 ] ) > sqTol && aPt . SquareDistance ( refLine ) > sqTol ? null : line ;
99
- }
100
- }
101
-
102
- return null ;
80
+ List < Line > result = new List < Line > { line } . BooleanIntersection ( new List < Line > { refLine } , tolerance ) ;
81
+ return result . Count == 0 ? null : result [ 0 ] ;
103
82
}
104
83
105
84
/***************************************************/
@@ -111,15 +90,38 @@ public static Line BooleanIntersection(this Line line, Line refLine, double tole
111
90
[ Output ( "intersection" , "The collection of lines corresponding to the overlaps of the first line and any of the reference lines." ) ]
112
91
public static List < Line > BooleanIntersection ( this Line line , List < Line > refLines , double tolerance = Tolerance . Distance )
113
92
{
114
- List < Line > result = new List < Line > ( ) ;
115
- if ( line . Length ( ) <= tolerance )
116
- return result ;
93
+ return new List < Line > { line } . BooleanIntersection ( refLines , tolerance ) ;
94
+ }
95
+
96
+ /***************************************************/
97
+
117
98
118
- foreach ( Line l in refLines . BooleanUnion ( tolerance ) )
99
+ [ Description ( "Computes the boolean intersection of two collections of lines, e.g. all overlaps of the first set of lines with the reference lines and returns a new collection of lines matching the overlap." ) ]
100
+ [ Input ( "lines" , "First list of lines to intersect." ) ]
101
+ [ Input ( "refLines" , "A list of reference lines to intersect with the first list of lines." ) ]
102
+ [ Input ( "tolerance" , "Tolerance to be used in the method." , typeof ( Length ) ) ]
103
+ [ Output ( "intersection" , "The list of lines corresponding to the overlaps of the first list of lines and any of the reference lines." ) ]
104
+ public static List < Line > BooleanIntersection ( this List < Line > lines , List < Line > refLines , double tolerance = Tolerance . Distance )
105
+ {
106
+ double sqTol = tolerance * tolerance ;
107
+ lines = lines . Where ( x => x != null && x . SquareLength ( ) > sqTol ) . ToList ( ) ;
108
+ List < Line > refLeft = refLines . Where ( x => x != null && x . SquareLength ( ) > sqTol ) . ToList ( ) ;
109
+
110
+ List < Line > result = new List < Line > ( ) ;
111
+ foreach ( var cluster in lines . ClusterCollinear ( tolerance ) )
119
112
{
120
- Line intersection = line . BooleanIntersection ( l , tolerance ) ;
121
- if ( intersection != null )
122
- result . Add ( intersection ) ;
113
+ List < Line > toIntersect = new List < Line > ( ) ;
114
+ for ( int i = refLines . Count - 1 ; i >= 0 ; i -- )
115
+ {
116
+ if ( refLines [ i ] . IsCollinear ( cluster [ 0 ] ) )
117
+ {
118
+ toIntersect . Add ( refLines [ i ] ) ;
119
+ refLines . RemoveAt ( i ) ;
120
+ }
121
+ }
122
+
123
+ if ( toIntersect . Count != 0 )
124
+ result . AddRange ( cluster . BooleanIntersectionCollinear ( toIntersect , tolerance ) ) ;
123
125
}
124
126
125
127
return result ;
@@ -128,24 +130,19 @@ public static List<Line> BooleanIntersection(this Line line, List<Line> refLines
128
130
/***************************************************/
129
131
130
132
[ Description ( "Computes the boolean intersection of a collection of lines, e.g. the overlap of all the provided lines and returns this overlap as a new line." ) ]
131
- [ Input ( "lines" , "The collection of lines to intersect." ) ]
133
+ [ Input ( "lines" , "The list of lines to intersect." ) ]
132
134
[ Input ( "tolerance" , "Tolerance to be used in the method." , typeof ( Length ) ) ]
133
135
[ Output ( "intersection" , "The line corresponding to the overlap all of the provided lines." ) ]
134
136
public static Line BooleanIntersection ( this List < Line > lines , double tolerance = Tolerance . Distance )
135
137
{
136
- if ( lines [ 0 ] . Length ( ) <= tolerance )
138
+ if ( lines . IsCollinear ( tolerance ) )
139
+ return lines . BooleanIntersectionCollinear ( tolerance ) ;
140
+ else
137
141
return null ;
138
-
139
- Line result = lines [ 0 ] ;
140
- for ( int i = 1 ; i < lines . Count ; i ++ )
141
- {
142
- result = result . BooleanIntersection ( lines [ i ] , tolerance ) ;
143
- }
144
-
145
- return result ;
146
142
}
147
143
148
144
145
+
149
146
/***************************************************/
150
147
/**** public Methods - Regions ****/
151
148
/***************************************************/
@@ -410,7 +407,8 @@ public static List<PolyCurve> BooleanIntersection(this IEnumerable<ICurve> regio
410
407
return result ;
411
408
}
412
409
413
- /**************************************************
410
+
411
+ /***************************************************/
414
412
/*** Private methods ***/
415
413
/***************************************************/
416
414
@@ -432,7 +430,58 @@ private static bool IsSimilarSegment(this ICurve curve, ICurve refCurve, double
432
430
return false ;
433
431
}
434
432
435
- /***************************************************/
433
+ /***************************************************/
434
+
435
+ private static List < Line > BooleanIntersectionCollinear ( this List < Line > lines , List < Line > lines2 , double tolerance )
436
+ {
437
+ Vector dir = lines [ 0 ] . Direction ( ) ;
438
+ ( Point , Point ) extents1 = lines . Extents ( dir , tolerance ) ;
439
+ ( Point , Point ) extents2 = lines2 . Extents ( dir , tolerance ) ;
440
+ Point min = ( extents1 . Item1 - extents2 . Item1 ) . DotProduct ( dir ) < 0 ? extents1 . Item1 : extents2 . Item1 ;
441
+
442
+ List < ( double , double ) > ranges1 = lines . SortedDomains ( min , tolerance ) ;
443
+ List < ( double , double ) > ranges2 = lines2 . SortedDomains ( min , tolerance ) ;
444
+
445
+ List < ( double , double ) > mergedRanges1 = ranges1 . MergeRanges ( tolerance ) ;
446
+ List < ( double , double ) > mergedRanges2 = ranges2 . MergeRanges ( tolerance ) ;
447
+
448
+ List < ( double , double ) > intersectedRanges = new List < ( double , double ) > ( ) ;
449
+ int i = 0 ;
450
+ foreach ( ( double , double ) range in mergedRanges1 )
451
+ {
452
+ for ( ; i < mergedRanges2 . Count ; i ++ )
453
+ {
454
+ if ( range . Item1 - mergedRanges2 [ i ] . Item2 < - tolerance && range . Item2 - mergedRanges2 [ i ] . Item1 > tolerance )
455
+ intersectedRanges . Add ( ( Math . Max ( range . Item1 , mergedRanges2 [ i ] . Item1 ) , Math . Min ( range . Item2 , mergedRanges2 [ i ] . Item2 ) ) ) ;
456
+
457
+ if ( range . Item2 - mergedRanges2 [ i ] . Item2 < tolerance )
458
+ break ;
459
+ }
460
+ }
461
+
462
+ return intersectedRanges . Select ( x => new Line { Start = min + dir * x . Item1 , End = min + dir * x . Item2 } ) . ToList ( ) ;
463
+ }
464
+
465
+ /***************************************************/
466
+
467
+ private static Line BooleanIntersectionCollinear ( this List < Line > lines , double tolerance )
468
+ {
469
+ Line dirLine = lines . Select ( x => x . Start ) . Union ( lines . Select ( x => x . End ) ) . FitLine ( tolerance ) ;
470
+ Vector dir = dirLine . Direction ( tolerance ) ;
471
+ ( Point , Point ) extents = lines . Extents ( dir , tolerance ) ;
472
+ Point min = dirLine . ClosestPoint ( extents . Item1 , true ) ;
473
+
474
+ List < ( double , double ) > ranges = lines . SortedDomains ( min , tolerance ) ;
475
+ double maxStart = ranges . Select ( x => x . Item1 ) . OrderByDescending ( x => x ) . First ( ) ;
476
+ double minEnd = ranges . Select ( x => x . Item2 ) . OrderBy ( x => x ) . First ( ) ;
477
+
478
+ if ( minEnd - maxStart > tolerance )
479
+ return new Line { Start = min + dir * maxStart , End = min + dir * minEnd } ;
480
+ else
481
+ return null ;
482
+ }
483
+
484
+ /***************************************************/
436
485
437
486
}
438
487
}
0 commit comments