2 from . import mathematics
6 from mathutils
import Vector
12 class BezierSegmentIntersectionPoint
:
13 def __init__(self
, segment
, parameter
, intersectionPoint
):
14 self
.segment
= segment
15 self
.parameter
= parameter
16 self
.intersectionPoint
= intersectionPoint
19 class BezierSegmentsIntersector
:
20 def __init__(self
, segment1
, segment2
, worldMatrix1
, worldMatrix2
):
21 self
.segment1
= segment1
22 self
.segment2
= segment2
23 self
.worldMatrix1
= worldMatrix1
24 self
.worldMatrix2
= worldMatrix2
26 def CalcFirstIntersection(self
, nrSamples1
, nrSamples2
):
27 algorithm
= bpy
.context
.scene
.curvetools
.IntersectCurvesAlgorithm
30 return self
.CalcFirstRealIntersection3D(nrSamples1
, nrSamples2
)
32 if algorithm
== 'From_View':
34 if algoDIR
is not None:
35 return self
.CalcFirstRealIntersectionFromViewDIR(nrSamples1
, nrSamples2
)
38 if algoPOV
is not None:
39 return self
.CalcFirstRealIntersectionFromViewPOV(nrSamples1
, nrSamples2
)
43 def CalcFirstIntersection3D(self
, nrSamples1
, nrSamples2
):
44 fltNrSamples1
= float(nrSamples1
)
45 fltNrSamples2
= float(nrSamples2
)
47 limitDistance
= bpy
.context
.scene
.curvetools
.LimitDistance
49 for iSample1
in range(nrSamples1
):
50 segPar10
= float(iSample1
) / fltNrSamples1
51 segPar11
= float(iSample1
+ 1) / fltNrSamples1
52 P0
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar10
)
53 P1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar11
)
55 for iSample2
in range(nrSamples2
):
56 segPar20
= float(iSample2
) / fltNrSamples2
57 segPar21
= float(iSample2
+ 1) / fltNrSamples2
58 Q0
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar20
)
59 Q1
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar21
)
61 intersectionPointData
= mathematics
.CalcIntersectionPointLineSegments(P0
, P1
, Q0
, Q1
, limitDistance
)
62 if intersectionPointData
is None:
65 intersectionSegment1Parameter
= segPar10
+ (intersectionPointData
[0] / fltNrSamples1
)
66 intersectionPoint1
= BezierSegmentIntersectionPoint(self
.segment1
,
67 intersectionSegment1Parameter
,
68 intersectionPointData
[2])
70 intersectionSegment2Parameter
= segPar20
+ (intersectionPointData
[1] / fltNrSamples2
)
71 intersectionPoint2
= BezierSegmentIntersectionPoint(self
.segment2
,
72 intersectionSegment2Parameter
,
73 intersectionPointData
[3])
75 return [intersectionPoint1
, intersectionPoint2
]
79 def CalcFirstRealIntersection3D(self
, nrSamples1
, nrSamples2
):
80 fltNrSamples1
= float(nrSamples1
)
81 fltNrSamples2
= float(nrSamples2
)
83 limitDistance
= bpy
.context
.scene
.curvetools
.LimitDistance
85 for iSample1
in range(nrSamples1
):
86 segPar10
= float(iSample1
) / fltNrSamples1
87 segPar11
= float(iSample1
+ 1) / fltNrSamples1
88 P0
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar10
)
89 P1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar11
)
91 for iSample2
in range(nrSamples2
):
92 segPar20
= float(iSample2
) / fltNrSamples2
93 segPar21
= float(iSample2
+ 1) / fltNrSamples2
94 Q0
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar20
)
95 Q1
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar21
)
97 intersectionPointData
= mathematics
.CalcIntersectionPointLineSegments(P0
, P1
, Q0
, Q1
, limitDistance
)
98 if intersectionPointData
is None:
101 # intersection point can't be an existing point
102 intersectionSegment1Parameter
= segPar10
+ (intersectionPointData
[0] / (fltNrSamples1
))
103 worldPoint1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=intersectionSegment1Parameter
)
104 if (mathematics
.IsSamePoint(P0
, worldPoint1
, limitDistance
)) or \
105 (mathematics
.IsSamePoint(P1
, worldPoint1
, limitDistance
)):
107 intersectionPoint1
= None
109 intersectionPoint1
= BezierSegmentIntersectionPoint(self
.segment1
,
110 intersectionSegment1Parameter
,
113 intersectionSegment2Parameter
= segPar20
+ (intersectionPointData
[1] / (fltNrSamples2
))
114 worldPoint2
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=intersectionSegment2Parameter
)
115 if (mathematics
.IsSamePoint(Q0
, worldPoint2
, limitDistance
)) or \
116 (mathematics
.IsSamePoint(Q1
, worldPoint2
, limitDistance
)):
118 intersectionPoint2
= None
120 intersectionPoint2
= BezierSegmentIntersectionPoint(self
.segment2
,
121 intersectionSegment2Parameter
,
124 return [intersectionPoint1
, intersectionPoint2
]
128 def CalcFirstIntersectionFromViewDIR(self
, nrSamples1
, nrSamples2
):
131 fltNrSamples1
= float(nrSamples1
)
132 fltNrSamples2
= float(nrSamples2
)
134 for iSample1
in range(nrSamples1
):
135 segPar10
= float(iSample1
) / fltNrSamples1
136 segPar11
= float(iSample1
+ 1) / fltNrSamples1
137 P0
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar10
)
138 P1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar11
)
140 for iSample2
in range(nrSamples2
):
141 segPar20
= float(iSample2
) / fltNrSamples2
142 segPar21
= float(iSample2
+ 1) / fltNrSamples2
143 Q0
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar20
)
144 Q1
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar21
)
146 intersectionPointData
= mathematics
.CalcIntersectionPointsLineSegmentsDIR(P0
, P1
, Q0
, Q1
, algoDIR
)
147 if intersectionPointData
is None:
150 intersectionSegment1Parameter
= segPar10
+ (intersectionPointData
[0] / fltNrSamples1
)
151 worldPoint1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=intersectionSegment1Parameter
)
152 intersectionPoint1
= BezierSegmentIntersectionPoint(self
.segment1
,
153 intersectionSegment1Parameter
,
156 intersectionSegment2Parameter
= segPar20
+ (intersectionPointData
[1] / fltNrSamples2
)
157 worldPoint2
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=intersectionSegment2Parameter
)
158 intersectionPoint2
= BezierSegmentIntersectionPoint(self
.segment2
,
159 intersectionSegment2Parameter
,
162 return [intersectionPoint1
, intersectionPoint2
]
166 def CalcFirstRealIntersectionFromViewDIR(self
, nrSamples1
, nrSamples2
):
169 fltNrSamples1
= float(nrSamples1
)
170 fltNrSamples2
= float(nrSamples2
)
172 limitDistance
= bpy
.context
.scene
.curvetools
.LimitDistance
174 for iSample1
in range(nrSamples1
):
175 segPar10
= float(iSample1
) / fltNrSamples1
176 segPar11
= float(iSample1
+ 1) / fltNrSamples1
177 P0
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar10
)
178 P1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar11
)
180 for iSample2
in range(nrSamples2
):
181 segPar20
= float(iSample2
) / fltNrSamples2
182 segPar21
= float(iSample2
+ 1) / fltNrSamples2
183 Q0
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar20
)
184 Q1
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar21
)
186 intersectionPointData
= mathematics
.CalcIntersectionPointsLineSegmentsDIR(P0
, P1
, Q0
, Q1
, algoDIR
)
187 if intersectionPointData
is None:
190 # intersection point can't be an existing point
191 intersectionSegment1Parameter
= segPar10
+ (intersectionPointData
[0] / (fltNrSamples1
))
192 worldPoint1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=intersectionSegment1Parameter
)
193 if (mathematics
.IsSamePoint(P0
, worldPoint1
, limitDistance
)) or \
194 (mathematics
.IsSamePoint(P1
, worldPoint1
, limitDistance
)):
196 intersectionPoint1
= None
198 intersectionPoint1
= BezierSegmentIntersectionPoint(self
.segment1
,
199 intersectionSegment1Parameter
,
202 intersectionSegment2Parameter
= segPar20
+ (intersectionPointData
[1] / (fltNrSamples2
))
203 worldPoint2
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=intersectionSegment2Parameter
)
204 if (mathematics
.IsSamePoint(Q0
, worldPoint2
, limitDistance
)) or \
205 (mathematics
.IsSamePoint(Q1
, worldPoint2
, limitDistance
)):
207 intersectionPoint2
= None
209 intersectionPoint2
= BezierSegmentIntersectionPoint(self
.segment2
,
210 intersectionSegment2Parameter
,
213 return [intersectionPoint1
, intersectionPoint2
]
217 def CalcFirstIntersectionFromViewPOV(self
, nrSamples1
, nrSamples2
):
220 fltNrSamples1
= float(nrSamples1
)
221 fltNrSamples2
= float(nrSamples2
)
223 for iSample1
in range(nrSamples1
):
224 segPar10
= float(iSample1
) / fltNrSamples1
225 segPar11
= float(iSample1
+ 1) / fltNrSamples1
226 P0
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar10
)
227 P1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar11
)
229 for iSample2
in range(nrSamples2
):
230 segPar20
= float(iSample2
) / fltNrSamples2
231 segPar21
= float(iSample2
+ 1) / fltNrSamples2
232 Q0
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar20
)
233 Q1
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar21
)
235 intersectionPointData
= mathematics
.CalcIntersectionPointsLineSegmentsPOV(P0
, P1
, Q0
, Q1
, algoPOV
)
236 if intersectionPointData
is None:
239 intersectionSegment1Parameter
= segPar10
+ (intersectionPointData
[0] / fltNrSamples1
)
240 worldPoint1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=intersectionSegment1Parameter
)
241 intersectionPoint1
= BezierSegmentIntersectionPoint(self
.segment1
,
242 intersectionSegment1Parameter
,
245 intersectionSegment2Parameter
= segPar20
+ (intersectionPointData
[1] / fltNrSamples2
)
246 worldPoint2
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=intersectionSegment2Parameter
)
247 intersectionPoint2
= BezierSegmentIntersectionPoint(self
.segment2
,
248 intersectionSegment2Parameter
,
251 return [intersectionPoint1
, intersectionPoint2
]
255 def CalcFirstRealIntersectionFromViewPOV(self
, nrSamples1
, nrSamples2
):
258 fltNrSamples1
= float(nrSamples1
)
259 fltNrSamples2
= float(nrSamples2
)
261 limitDistance
= bpy
.context
.scene
.curvetools
.LimitDistance
263 for iSample1
in range(nrSamples1
):
264 segPar10
= float(iSample1
) / fltNrSamples1
265 segPar11
= float(iSample1
+ 1) / fltNrSamples1
266 P0
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar10
)
267 P1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar11
)
269 for iSample2
in range(nrSamples2
):
270 segPar20
= float(iSample2
) / fltNrSamples2
271 segPar21
= float(iSample2
+ 1) / fltNrSamples2
272 Q0
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar20
)
273 Q1
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar21
)
275 intersectionPointData
= mathematics
.CalcIntersectionPointsLineSegmentsPOV(P0
, P1
, Q0
, Q1
, algoPOV
)
276 if intersectionPointData
is None:
279 # intersection point can't be an existing point
280 intersectionSegment1Parameter
= segPar10
+ (intersectionPointData
[0] / fltNrSamples1
)
281 worldPoint1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=intersectionSegment1Parameter
)
282 if (mathematics
.IsSamePoint(P0
, worldPoint1
, limitDistance
)) or \
283 (mathematics
.IsSamePoint(P1
, worldPoint1
, limitDistance
)):
285 intersectionPoint1
= None
287 intersectionPoint1
= BezierSegmentIntersectionPoint(self
.segment1
,
288 intersectionSegment1Parameter
,
291 intersectionSegment2Parameter
= segPar20
+ (intersectionPointData
[1] / fltNrSamples2
)
292 worldPoint2
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=intersectionSegment2Parameter
)
293 if (mathematics
.IsSamePoint(Q0
, worldPoint2
, limitDistance
)) or \
294 (mathematics
.IsSamePoint(Q1
, worldPoint2
, limitDistance
)):
296 intersectionPoint2
= None
298 intersectionPoint2
= BezierSegmentIntersectionPoint(self
.segment2
,
299 intersectionSegment2Parameter
,
302 return [intersectionPoint1
, intersectionPoint2
]
306 def CalcIntersections(self
, nrSamples1
, nrSamples2
):
307 algorithm
= bpy
.context
.scene
.curvetools
.IntersectCurvesAlgorithm
309 if algorithm
== '3D':
310 return self
.CalcIntersections3D(nrSamples1
, nrSamples2
)
312 if algorithm
== 'From_View':
314 if algoDIR
is not None:
315 return self
.CalcIntersectionsFromViewDIR(nrSamples1
, nrSamples2
)
318 if algoPOV
is not None:
319 return self
.CalcIntersectionsFromViewPOV(nrSamples1
, nrSamples2
)
323 def CalcIntersections3D(self
, nrSamples1
, nrSamples2
):
324 rvIntersections1
= []
325 rvIntersections2
= []
327 fltNrSamples1
= float(nrSamples1
)
328 fltNrSamples2
= float(nrSamples2
)
330 limitDistance
= bpy
.context
.scene
.curvetools
.LimitDistance
332 for iSample1
in range(nrSamples1
):
333 segPar10
= float(iSample1
) / fltNrSamples1
334 segPar11
= float(iSample1
+ 1) / fltNrSamples1
335 P0
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar10
)
336 P1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar11
)
338 for iSample2
in range(nrSamples2
):
339 segPar20
= float(iSample2
) / fltNrSamples2
340 segPar21
= float(iSample2
+ 1) / fltNrSamples2
341 Q0
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar20
)
342 Q1
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar21
)
344 intersectionPointData
= mathematics
.CalcIntersectionPointLineSegments(P0
, P1
, Q0
, Q1
, limitDistance
)
345 if intersectionPointData
is None:
348 intersectionSegment1Parameter
= segPar10
+ (intersectionPointData
[0] / fltNrSamples1
)
349 worldPoint1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=intersectionSegment1Parameter
)
350 intersectionPoint1
= BezierSegmentIntersectionPoint(self
.segment1
,
351 intersectionSegment1Parameter
,
353 rvIntersections1
.append(intersectionPoint1
)
355 intersectionSegment2Parameter
= segPar20
+ (intersectionPointData
[1] / fltNrSamples2
)
356 worldPoint2
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=intersectionSegment2Parameter
)
357 intersectionPoint2
= BezierSegmentIntersectionPoint(self
.segment2
,
358 intersectionSegment2Parameter
,
360 rvIntersections2
.append(intersectionPoint2
)
362 return [rvIntersections1
, rvIntersections2
]
364 def CalcIntersectionsFromViewDIR(self
, nrSamples1
, nrSamples2
):
367 rvIntersections1
= []
368 rvIntersections2
= []
370 fltNrSamples1
= float(nrSamples1
)
371 fltNrSamples2
= float(nrSamples2
)
373 for iSample1
in range(nrSamples1
):
374 segPar10
= float(iSample1
) / fltNrSamples1
375 segPar11
= float(iSample1
+ 1) / fltNrSamples1
376 P0
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar10
)
377 P1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar11
)
379 for iSample2
in range(nrSamples2
):
380 segPar20
= float(iSample2
) / fltNrSamples2
381 segPar21
= float(iSample2
+ 1) / fltNrSamples2
382 Q0
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar20
)
383 Q1
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar21
)
385 intersectionPointData
= mathematics
.CalcIntersectionPointsLineSegmentsDIR(P0
, P1
, Q0
, Q1
, algoDIR
)
386 if intersectionPointData
is None:
389 intersectionSegment1Parameter
= segPar10
+ (intersectionPointData
[0] / fltNrSamples1
)
390 worldPoint1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=intersectionSegment1Parameter
)
391 intersectionPoint1
= BezierSegmentIntersectionPoint(self
.segment1
,
392 intersectionSegment1Parameter
,
394 rvIntersections1
.append(intersectionPoint1
)
396 intersectionSegment2Parameter
= segPar20
+ (intersectionPointData
[1] / fltNrSamples2
)
397 worldPoint2
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=intersectionSegment2Parameter
)
398 intersectionPoint2
= BezierSegmentIntersectionPoint(self
.segment2
,
399 intersectionSegment2Parameter
,
401 rvIntersections2
.append(intersectionPoint2
)
403 return [rvIntersections1
, rvIntersections2
]
405 def CalcIntersectionsFromViewPOV(self
, nrSamples1
, nrSamples2
):
408 rvIntersections1
= []
409 rvIntersections2
= []
411 fltNrSamples1
= float(nrSamples1
)
412 fltNrSamples2
= float(nrSamples2
)
414 for iSample1
in range(nrSamples1
):
415 segPar10
= float(iSample1
) / fltNrSamples1
416 segPar11
= float(iSample1
+ 1) / fltNrSamples1
417 P0
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar10
)
418 P1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=segPar11
)
420 for iSample2
in range(nrSamples2
):
421 segPar20
= float(iSample2
) / fltNrSamples2
422 segPar21
= float(iSample2
+ 1) / fltNrSamples2
423 Q0
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar20
)
424 Q1
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=segPar21
)
426 intersectionPointData
= mathematics
.CalcIntersectionPointsLineSegmentsPOV(P0
, P1
, Q0
, Q1
, algoPOV
)
427 if intersectionPointData
is None:
430 intersectionSegment1Parameter
= segPar10
+ (intersectionPointData
[0] / fltNrSamples1
)
431 worldPoint1
= self
.worldMatrix1
@ self
.segment1
.CalcPoint(parameter
=intersectionSegment1Parameter
)
432 intersectionPoint1
= BezierSegmentIntersectionPoint(self
.segment1
,
433 intersectionSegment1Parameter
,
435 rvIntersections1
.append(intersectionPoint1
)
437 intersectionSegment2Parameter
= segPar20
+ (intersectionPointData
[1] / fltNrSamples2
)
438 worldPoint2
= self
.worldMatrix2
@ self
.segment2
.CalcPoint(parameter
=intersectionSegment2Parameter
)
439 intersectionPoint2
= BezierSegmentIntersectionPoint(self
.segment2
,
440 intersectionSegment2Parameter
,
442 rvIntersections2
.append(intersectionPoint2
)
444 return [rvIntersections1
, rvIntersections2
]
447 class BezierSplineIntersectionPoint
:
448 def __init__(self
, spline
, bezierSegmentIntersectionPoint
):
450 self
.bezierSegmentIntersectionPoint
= bezierSegmentIntersectionPoint
453 class BezierSplinesIntersector
:
454 def __init__(self
, spline1
, spline2
, worldMatrix1
, worldMatrix2
):
455 self
.spline1
= spline1
456 self
.spline2
= spline2
457 self
.worldMatrix1
= worldMatrix1
458 self
.worldMatrix2
= worldMatrix2
460 def CalcIntersections(self
):
461 rvIntersections1
= []
462 rvIntersections2
= []
465 nrSamplesPerSegment1
= int(self
.spline1
.resolution
/ self
.spline1
.nrSegments
)
467 nrSamplesPerSegment1
= 2
468 if nrSamplesPerSegment1
< 2:
469 nrSamplesPerSegment1
= 2
472 nrSamplesPerSegment2
= int(self
.spline2
.resolution
/ self
.spline2
.nrSegments
)
474 nrSamplesPerSegment2
= 2
475 if nrSamplesPerSegment2
< 2:
476 nrSamplesPerSegment2
= 2
478 for segment1
in self
.spline1
.segments
:
479 for segment2
in self
.spline2
.segments
:
480 segmentsIntersector
= BezierSegmentsIntersector(segment1
, segment2
,
481 self
.worldMatrix1
, self
.worldMatrix2
)
482 segmentIntersections
= segmentsIntersector
.CalcIntersections(nrSamplesPerSegment1
, nrSamplesPerSegment2
)
483 if segmentIntersections
is None:
486 segment1Intersections
= segmentIntersections
[0]
487 for segmentIntersection
in segment1Intersections
:
488 splineIntersection
= BezierSplineIntersectionPoint(self
.spline1
, segmentIntersection
)
489 rvIntersections1
.append(splineIntersection
)
491 segment2Intersections
= segmentIntersections
[1]
492 for segmentIntersection
in segment2Intersections
:
493 splineIntersection
= BezierSplineIntersectionPoint(self
.spline2
, segmentIntersection
)
494 rvIntersections2
.append(splineIntersection
)
496 return [rvIntersections1
, rvIntersections2
]
499 class CurvesIntersector
:
502 selObjects
= bpy
.context
.selected_objects
503 if len(selObjects
) != 2:
504 raise Exception("len(selObjects) != 2") # shouldn't be possible
506 blenderActiveCurve
= bpy
.context
.active_object
507 blenderOtherCurve
= selObjects
[0]
508 if blenderActiveCurve
== blenderOtherCurve
:
509 blenderOtherCurve
= selObjects
[1]
511 aCurve
= curves
.Curve(blenderActiveCurve
)
512 oCurve
= curves
.Curve(blenderOtherCurve
)
514 return CurvesIntersector(aCurve
, oCurve
)
525 CurvesIntersector
.ResetGlobals()
529 algo
= bpy
.context
.scene
.curvetools
.IntersectCurvesAlgorithm
530 if algo
== 'From_View':
531 regionView3D
= util
.GetFirstRegionView3D()
532 if regionView3D
is None:
533 print("### ERROR: regionView3D is None. Stopping.")
536 viewPerspective
= regionView3D
.view_perspective
537 print("--", "viewPerspective:", viewPerspective
)
539 if viewPerspective
== 'ORTHO':
540 viewMatrix
= regionView3D
.view_matrix
541 print("--", "viewMatrix:")
544 algoDIR
= Vector((viewMatrix
[2][0], viewMatrix
[2][1], viewMatrix
[2][2]))
545 print("--", "algoDIR:", algoDIR
)
547 # ## TODO: doesn't work properly
548 if viewPerspective
== 'PERSP':
549 viewMatrix
= regionView3D
.view_matrix
550 print("--", "viewMatrix:")
553 algoPOV
= regionView3D
.view_location
.copy()
554 print("--", "algoPOV:", algoPOV
)
556 otherPOV
= Vector((viewMatrix
[0][3], viewMatrix
[1][3], viewMatrix
[2][3]))
557 print("--", "otherPOV:", otherPOV
)
559 localPOV
= Vector((0, 0, 0))
560 globalPOV
= viewMatrix
* localPOV
561 print("--", "globalPOV:", globalPOV
)
563 perspMatrix
= regionView3D
.perspective_matrix
564 print("--", "perspMatrix:")
567 globalPOVPersp
= perspMatrix
* localPOV
568 print("--", "globalPOVPersp:", globalPOVPersp
)
570 if viewPerspective
== 'CAMERA':
571 camera
= bpy
.context
.scene
.camera
573 print("### ERROR: camera is None. Stopping.")
576 print("--", "camera:", camera
)
577 cameraData
= camera
.data
578 print("--", "cameraData.type:", cameraData
.type)
580 cameraMatrix
= camera
.matrix_world
581 print("--", "cameraMatrix:")
584 if cameraData
.type == 'ORTHO':
585 cameraMatrix
= camera
.matrix_world
586 # algoDIR = Vector((cameraMatrix[2][0], cameraMatrix[2][1], cameraMatrix[2][2]))
587 algoDIR
= Vector((- cameraMatrix
[0][2], - cameraMatrix
[1][2], - cameraMatrix
[2][2]))
588 print("--", "algoDIR:", algoDIR
)
590 if cameraData
.type == 'PERSP':
591 algoPOV
= camera
.location
.copy()
592 print("--", "algoPOV:", algoPOV
)
594 def __init__(self
, activeCurve
, otherCurve
):
595 self
.activeCurve
= activeCurve
596 self
.otherCurve
= otherCurve
598 CurvesIntersector
.InitGlobals()
600 def CalcIntersections(self
):
601 rvIntersections1
= []
602 rvIntersections2
= []
604 worldMatrix1
= self
.activeCurve
.curve
.matrix_world
605 worldMatrix2
= self
.otherCurve
.curve
.matrix_world
607 for spline1
in self
.activeCurve
.splines
:
608 for spline2
in self
.otherCurve
.splines
:
609 splineIntersector
= BezierSplinesIntersector(spline1
, spline2
, worldMatrix1
, worldMatrix2
)
610 splineIntersections
= splineIntersector
.CalcIntersections()
611 if splineIntersections
is None:
614 spline1Intersections
= splineIntersections
[0]
615 for splineIntersection
in spline1Intersections
:
616 rvIntersections1
.append(splineIntersection
)
618 spline2Intersections
= splineIntersections
[1]
619 for splineIntersection
in spline2Intersections
:
620 rvIntersections2
.append(splineIntersection
)
622 return [rvIntersections1
, rvIntersections2
]
624 def CalcAndApplyIntersections(self
):
625 mode
= bpy
.context
.scene
.curvetools
.IntersectCurvesMode
628 return self
.CalcAndApplyEmptyAtIntersections()
630 return self
.CalcAndApplyInsertAtIntersections()
632 return self
.CalcAndApplySplitAtIntersections()
636 def CalcAndApplyEmptyAtIntersections(self
):
637 intersections
= self
.CalcIntersections()
638 intersectionsActive
= intersections
[0]
639 intersectionsOther
= intersections
[1]
644 affect
= bpy
.context
.scene
.curvetools
.IntersectCurvesAffect
646 if (affect
== 'Both') or (affect
== 'Active'):
647 for splineIntersection
in intersectionsActive
:
648 iPoint
= splineIntersection
.bezierSegmentIntersectionPoint
.intersectionPoint
649 bpy
.ops
.object.empty_add(type='PLAIN_AXES',
651 location
=(iPoint
.x
, iPoint
.y
, iPoint
.z
), rotation
=(0, 0, 0))
654 if (affect
== 'Both') or (affect
== 'Other'):
655 for splineIntersection
in intersectionsOther
:
656 iPoint
= splineIntersection
.bezierSegmentIntersectionPoint
.intersectionPoint
657 bpy
.ops
.object.empty_add(type='PLAIN_AXES',
659 location
=(iPoint
.x
, iPoint
.y
, iPoint
.z
), rotation
=(0, 0, 0))
662 return [nrActive
, nrOther
]
664 def CalcAndApplyInsertAtIntersections(self
):
668 affect
= bpy
.context
.scene
.curvetools
.IntersectCurvesAffect
669 affectA
= (affect
== 'Both') or (affect
== 'Active')
670 affectO
= (affect
== 'Both') or (affect
== 'Other')
672 for iSplineA
in range(len(self
.activeCurve
.splines
)):
673 splineA
= self
.activeCurve
.splines
[iSplineA
]
674 nrSegmentsA
= len(splineA
.segments
)
675 resPerSegA
= splineA
.resolutionPerSegment
677 for iSplineO
in range(len(self
.otherCurve
.splines
)):
678 splineO
= self
.otherCurve
.splines
[iSplineO
]
679 nrSegmentsO
= len(splineO
.segments
)
680 resPerSegO
= splineO
.resolutionPerSegment
684 segA
= splineA
.segments
[iSegA
]
688 segO
= splineO
.segments
[iSegO
]
690 segIntersector
= BezierSegmentsIntersector(segA
, segO
,
691 self
.activeCurve
.worldMatrix
,
692 self
.otherCurve
.worldMatrix
)
693 segFirstIntersection
= segIntersector
.CalcFirstIntersection(resPerSegA
, resPerSegO
)
695 if segFirstIntersection
is not None:
696 intPointA
= segFirstIntersection
[0]
697 intPointO
= segFirstIntersection
[1]
698 # else does something weird if 1 of them is None..
699 if (intPointA
is not None) and (intPointO
is not None):
701 if intPointA
is not None:
702 splineA
.InsertPoint(segA
, intPointA
.parameter
)
708 if intPointO
is not None:
709 splineO
.InsertPoint(segO
, intPointO
.parameter
)
715 if not (iSegO
< nrSegmentsO
):
719 if not (iSegA
< nrSegmentsA
):
723 splineO
.RefreshInScene()
726 splineA
.RefreshInScene()
728 return [nrActive
, nrOther
]
730 def CalcAndApplySplitAtIntersections(self
):
734 affect
= bpy
.context
.scene
.curvetools
.IntersectCurvesAffect
735 affectA
= (affect
== 'Both') or (affect
== 'Active')
736 affectO
= (affect
== 'Both') or (affect
== 'Other')
738 nrSplinesA
= len(self
.activeCurve
.splines
)
739 nrSplinesO
= len(self
.otherCurve
.splines
)
743 splineA
= self
.activeCurve
.splines
[iSplineA
]
744 nrSegmentsA
= len(splineA
.segments
)
745 resPerSegA
= splineA
.resolutionPerSegment
749 splineO
= self
.otherCurve
.splines
[iSplineO
]
750 nrSegmentsO
= len(splineO
.segments
)
751 resPerSegO
= splineO
.resolutionPerSegment
755 segA
= splineA
.segments
[iSegA
]
759 segO
= splineO
.segments
[iSegO
]
761 segIntersector
= BezierSegmentsIntersector(segA
, segO
,
762 self
.activeCurve
.worldMatrix
,
763 self
.otherCurve
.worldMatrix
)
764 segFirstIntersection
= segIntersector
.CalcFirstIntersection(resPerSegA
, resPerSegO
)
766 if segFirstIntersection
is not None:
767 intPointA
= segFirstIntersection
[0]
768 intPointO
= segFirstIntersection
[1]
769 # else does something weird if 1 of them is None..
770 if (intPointA
is not None) and (intPointO
is not None):
772 if intPointA
is not None:
773 print("--", "splineA.Split():")
774 newSplinesA
= splineA
.Split(segA
, intPointA
.parameter
)
775 if newSplinesA
is not None:
776 newResolutions
= splineA
.CalcDivideResolution(segA
, intPointA
.parameter
)
777 newSplinesA
[0].resolution
= newResolutions
[0]
778 newSplinesA
[1].resolution
= newResolutions
[1]
780 splineA
= newSplinesA
[0]
781 self
.activeCurve
.splines
[iSplineA
] = splineA
782 self
.activeCurve
.splines
.insert(iSplineA
+ 1, newSplinesA
[1])
787 if intPointO
is not None:
788 print("--", "splineO.Split():")
789 newSplinesO
= splineO
.Split(segO
, intPointO
.parameter
)
790 if newSplinesO
is not None:
791 newResolutions
= splineO
.CalcDivideResolution(segO
, intPointO
.parameter
)
792 newSplinesO
[0].resolution
= newResolutions
[0]
793 newSplinesO
[1].resolution
= newResolutions
[1]
795 splineO
= newSplinesO
[0]
796 self
.otherCurve
.splines
[iSplineO
] = splineO
797 self
.otherCurve
.splines
.insert(iSplineO
+ 1, newSplinesO
[1])
801 nrSegmentsO
= len(splineO
.segments
)
803 if not (iSegO
< nrSegmentsO
):
806 nrSegmentsA
= len(splineA
.segments
)
808 if not (iSegA
< nrSegmentsA
):
811 nrSplinesO
= len(self
.otherCurve
.splines
)
813 if not (iSplineO
< nrSplinesO
):
816 nrSplinesA
= len(self
.activeCurve
.splines
)
818 if not (iSplineA
< nrSplinesA
):
823 print("--", "self.activeCurve.RebuildInScene():")
824 self
.activeCurve
.RebuildInScene()
827 print("--", "self.otherCurve.RebuildInScene():")
828 self
.otherCurve
.RebuildInScene()
830 return [nrActive
, nrOther
]