import bpy from . import mathematics from . import curves from . import util from mathutils import Vector algoPOV = None algoDIR = None class BezierSegmentIntersectionPoint: def __init__(self, segment, parameter, intersectionPoint): self.segment = segment self.parameter = parameter self.intersectionPoint = intersectionPoint class BezierSegmentsIntersector: def __init__(self, segment1, segment2, worldMatrix1, worldMatrix2): self.segment1 = segment1 self.segment2 = segment2 self.worldMatrix1 = worldMatrix1 self.worldMatrix2 = worldMatrix2 def CalcFirstIntersection(self, nrSamples1, nrSamples2): algorithm = bpy.context.scene.curvetools.IntersectCurvesAlgorithm if algorithm == '3D': return self.CalcFirstRealIntersection3D(nrSamples1, nrSamples2) if algorithm == 'From_View': global algoDIR if algoDIR is not None: return self.CalcFirstRealIntersectionFromViewDIR(nrSamples1, nrSamples2) global algoPOV if algoPOV is not None: return self.CalcFirstRealIntersectionFromViewPOV(nrSamples1, nrSamples2) return None def CalcFirstIntersection3D(self, nrSamples1, nrSamples2): fltNrSamples1 = float(nrSamples1) fltNrSamples2 = float(nrSamples2) limitDistance = bpy.context.scene.curvetools.LimitDistance for iSample1 in range(nrSamples1): segPar10 = float(iSample1) / fltNrSamples1 segPar11 = float(iSample1 + 1) / fltNrSamples1 P0 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar10) P1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar11) for iSample2 in range(nrSamples2): segPar20 = float(iSample2) / fltNrSamples2 segPar21 = float(iSample2 + 1) / fltNrSamples2 Q0 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar20) Q1 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar21) intersectionPointData = mathematics.CalcIntersectionPointLineSegments(P0, P1, Q0, Q1, limitDistance) if intersectionPointData is None: continue intersectionSegment1Parameter = segPar10 + (intersectionPointData[0] / fltNrSamples1) intersectionPoint1 = BezierSegmentIntersectionPoint(self.segment1, intersectionSegment1Parameter, intersectionPointData[2]) intersectionSegment2Parameter = segPar20 + (intersectionPointData[1] / fltNrSamples2) intersectionPoint2 = BezierSegmentIntersectionPoint(self.segment2, intersectionSegment2Parameter, intersectionPointData[3]) return [intersectionPoint1, intersectionPoint2] return None def CalcFirstRealIntersection3D(self, nrSamples1, nrSamples2): fltNrSamples1 = float(nrSamples1) fltNrSamples2 = float(nrSamples2) limitDistance = bpy.context.scene.curvetools.LimitDistance for iSample1 in range(nrSamples1): segPar10 = float(iSample1) / fltNrSamples1 segPar11 = float(iSample1 + 1) / fltNrSamples1 P0 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar10) P1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar11) for iSample2 in range(nrSamples2): segPar20 = float(iSample2) / fltNrSamples2 segPar21 = float(iSample2 + 1) / fltNrSamples2 Q0 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar20) Q1 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar21) intersectionPointData = mathematics.CalcIntersectionPointLineSegments(P0, P1, Q0, Q1, limitDistance) if intersectionPointData is None: continue # intersection point can't be an existing point intersectionSegment1Parameter = segPar10 + (intersectionPointData[0] / (fltNrSamples1)) worldPoint1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=intersectionSegment1Parameter) if (mathematics.IsSamePoint(P0, worldPoint1, limitDistance)) or \ (mathematics.IsSamePoint(P1, worldPoint1, limitDistance)): intersectionPoint1 = None else: intersectionPoint1 = BezierSegmentIntersectionPoint(self.segment1, intersectionSegment1Parameter, worldPoint1) intersectionSegment2Parameter = segPar20 + (intersectionPointData[1] / (fltNrSamples2)) worldPoint2 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=intersectionSegment2Parameter) if (mathematics.IsSamePoint(Q0, worldPoint2, limitDistance)) or \ (mathematics.IsSamePoint(Q1, worldPoint2, limitDistance)): intersectionPoint2 = None else: intersectionPoint2 = BezierSegmentIntersectionPoint(self.segment2, intersectionSegment2Parameter, worldPoint2) return [intersectionPoint1, intersectionPoint2] return None def CalcFirstIntersectionFromViewDIR(self, nrSamples1, nrSamples2): global algoDIR fltNrSamples1 = float(nrSamples1) fltNrSamples2 = float(nrSamples2) for iSample1 in range(nrSamples1): segPar10 = float(iSample1) / fltNrSamples1 segPar11 = float(iSample1 + 1) / fltNrSamples1 P0 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar10) P1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar11) for iSample2 in range(nrSamples2): segPar20 = float(iSample2) / fltNrSamples2 segPar21 = float(iSample2 + 1) / fltNrSamples2 Q0 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar20) Q1 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar21) intersectionPointData = mathematics.CalcIntersectionPointsLineSegmentsDIR(P0, P1, Q0, Q1, algoDIR) if intersectionPointData is None: continue intersectionSegment1Parameter = segPar10 + (intersectionPointData[0] / fltNrSamples1) worldPoint1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=intersectionSegment1Parameter) intersectionPoint1 = BezierSegmentIntersectionPoint(self.segment1, intersectionSegment1Parameter, worldPoint1) intersectionSegment2Parameter = segPar20 + (intersectionPointData[1] / fltNrSamples2) worldPoint2 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=intersectionSegment2Parameter) intersectionPoint2 = BezierSegmentIntersectionPoint(self.segment2, intersectionSegment2Parameter, worldPoint2) return [intersectionPoint1, intersectionPoint2] return None def CalcFirstRealIntersectionFromViewDIR(self, nrSamples1, nrSamples2): global algoDIR fltNrSamples1 = float(nrSamples1) fltNrSamples2 = float(nrSamples2) limitDistance = bpy.context.scene.curvetools.LimitDistance for iSample1 in range(nrSamples1): segPar10 = float(iSample1) / fltNrSamples1 segPar11 = float(iSample1 + 1) / fltNrSamples1 P0 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar10) P1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar11) for iSample2 in range(nrSamples2): segPar20 = float(iSample2) / fltNrSamples2 segPar21 = float(iSample2 + 1) / fltNrSamples2 Q0 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar20) Q1 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar21) intersectionPointData = mathematics.CalcIntersectionPointsLineSegmentsDIR(P0, P1, Q0, Q1, algoDIR) if intersectionPointData is None: continue # intersection point can't be an existing point intersectionSegment1Parameter = segPar10 + (intersectionPointData[0] / (fltNrSamples1)) worldPoint1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=intersectionSegment1Parameter) if (mathematics.IsSamePoint(P0, worldPoint1, limitDistance)) or \ (mathematics.IsSamePoint(P1, worldPoint1, limitDistance)): intersectionPoint1 = None else: intersectionPoint1 = BezierSegmentIntersectionPoint(self.segment1, intersectionSegment1Parameter, worldPoint1) intersectionSegment2Parameter = segPar20 + (intersectionPointData[1] / (fltNrSamples2)) worldPoint2 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=intersectionSegment2Parameter) if (mathematics.IsSamePoint(Q0, worldPoint2, limitDistance)) or \ (mathematics.IsSamePoint(Q1, worldPoint2, limitDistance)): intersectionPoint2 = None else: intersectionPoint2 = BezierSegmentIntersectionPoint(self.segment2, intersectionSegment2Parameter, worldPoint2) return [intersectionPoint1, intersectionPoint2] return None def CalcFirstIntersectionFromViewPOV(self, nrSamples1, nrSamples2): global algoPOV fltNrSamples1 = float(nrSamples1) fltNrSamples2 = float(nrSamples2) for iSample1 in range(nrSamples1): segPar10 = float(iSample1) / fltNrSamples1 segPar11 = float(iSample1 + 1) / fltNrSamples1 P0 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar10) P1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar11) for iSample2 in range(nrSamples2): segPar20 = float(iSample2) / fltNrSamples2 segPar21 = float(iSample2 + 1) / fltNrSamples2 Q0 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar20) Q1 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar21) intersectionPointData = mathematics.CalcIntersectionPointsLineSegmentsPOV(P0, P1, Q0, Q1, algoPOV) if intersectionPointData is None: continue intersectionSegment1Parameter = segPar10 + (intersectionPointData[0] / fltNrSamples1) worldPoint1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=intersectionSegment1Parameter) intersectionPoint1 = BezierSegmentIntersectionPoint(self.segment1, intersectionSegment1Parameter, worldPoint1) intersectionSegment2Parameter = segPar20 + (intersectionPointData[1] / fltNrSamples2) worldPoint2 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=intersectionSegment2Parameter) intersectionPoint2 = BezierSegmentIntersectionPoint(self.segment2, intersectionSegment2Parameter, worldPoint2) return [intersectionPoint1, intersectionPoint2] return None def CalcFirstRealIntersectionFromViewPOV(self, nrSamples1, nrSamples2): global algoPOV fltNrSamples1 = float(nrSamples1) fltNrSamples2 = float(nrSamples2) limitDistance = bpy.context.scene.curvetools.LimitDistance for iSample1 in range(nrSamples1): segPar10 = float(iSample1) / fltNrSamples1 segPar11 = float(iSample1 + 1) / fltNrSamples1 P0 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar10) P1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar11) for iSample2 in range(nrSamples2): segPar20 = float(iSample2) / fltNrSamples2 segPar21 = float(iSample2 + 1) / fltNrSamples2 Q0 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar20) Q1 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar21) intersectionPointData = mathematics.CalcIntersectionPointsLineSegmentsPOV(P0, P1, Q0, Q1, algoPOV) if intersectionPointData is None: continue # intersection point can't be an existing point intersectionSegment1Parameter = segPar10 + (intersectionPointData[0] / fltNrSamples1) worldPoint1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=intersectionSegment1Parameter) if (mathematics.IsSamePoint(P0, worldPoint1, limitDistance)) or \ (mathematics.IsSamePoint(P1, worldPoint1, limitDistance)): intersectionPoint1 = None else: intersectionPoint1 = BezierSegmentIntersectionPoint(self.segment1, intersectionSegment1Parameter, worldPoint1) intersectionSegment2Parameter = segPar20 + (intersectionPointData[1] / fltNrSamples2) worldPoint2 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=intersectionSegment2Parameter) if (mathematics.IsSamePoint(Q0, worldPoint2, limitDistance)) or \ (mathematics.IsSamePoint(Q1, worldPoint2, limitDistance)): intersectionPoint2 = None else: intersectionPoint2 = BezierSegmentIntersectionPoint(self.segment2, intersectionSegment2Parameter, worldPoint2) return [intersectionPoint1, intersectionPoint2] return None def CalcIntersections(self, nrSamples1, nrSamples2): algorithm = bpy.context.scene.curvetools.IntersectCurvesAlgorithm if algorithm == '3D': return self.CalcIntersections3D(nrSamples1, nrSamples2) if algorithm == 'From_View': global algoDIR if algoDIR is not None: return self.CalcIntersectionsFromViewDIR(nrSamples1, nrSamples2) global algoPOV if algoPOV is not None: return self.CalcIntersectionsFromViewPOV(nrSamples1, nrSamples2) return [[], []] def CalcIntersections3D(self, nrSamples1, nrSamples2): rvIntersections1 = [] rvIntersections2 = [] fltNrSamples1 = float(nrSamples1) fltNrSamples2 = float(nrSamples2) limitDistance = bpy.context.scene.curvetools.LimitDistance for iSample1 in range(nrSamples1): segPar10 = float(iSample1) / fltNrSamples1 segPar11 = float(iSample1 + 1) / fltNrSamples1 P0 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar10) P1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar11) for iSample2 in range(nrSamples2): segPar20 = float(iSample2) / fltNrSamples2 segPar21 = float(iSample2 + 1) / fltNrSamples2 Q0 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar20) Q1 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar21) intersectionPointData = mathematics.CalcIntersectionPointLineSegments(P0, P1, Q0, Q1, limitDistance) if intersectionPointData is None: continue intersectionSegment1Parameter = segPar10 + (intersectionPointData[0] / fltNrSamples1) worldPoint1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=intersectionSegment1Parameter) intersectionPoint1 = BezierSegmentIntersectionPoint(self.segment1, intersectionSegment1Parameter, worldPoint1) rvIntersections1.append(intersectionPoint1) intersectionSegment2Parameter = segPar20 + (intersectionPointData[1] / fltNrSamples2) worldPoint2 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=intersectionSegment2Parameter) intersectionPoint2 = BezierSegmentIntersectionPoint(self.segment2, intersectionSegment2Parameter, worldPoint2) rvIntersections2.append(intersectionPoint2) return [rvIntersections1, rvIntersections2] def CalcIntersectionsFromViewDIR(self, nrSamples1, nrSamples2): global algoDIR rvIntersections1 = [] rvIntersections2 = [] fltNrSamples1 = float(nrSamples1) fltNrSamples2 = float(nrSamples2) for iSample1 in range(nrSamples1): segPar10 = float(iSample1) / fltNrSamples1 segPar11 = float(iSample1 + 1) / fltNrSamples1 P0 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar10) P1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar11) for iSample2 in range(nrSamples2): segPar20 = float(iSample2) / fltNrSamples2 segPar21 = float(iSample2 + 1) / fltNrSamples2 Q0 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar20) Q1 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar21) intersectionPointData = mathematics.CalcIntersectionPointsLineSegmentsDIR(P0, P1, Q0, Q1, algoDIR) if intersectionPointData is None: continue intersectionSegment1Parameter = segPar10 + (intersectionPointData[0] / fltNrSamples1) worldPoint1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=intersectionSegment1Parameter) intersectionPoint1 = BezierSegmentIntersectionPoint(self.segment1, intersectionSegment1Parameter, worldPoint1) rvIntersections1.append(intersectionPoint1) intersectionSegment2Parameter = segPar20 + (intersectionPointData[1] / fltNrSamples2) worldPoint2 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=intersectionSegment2Parameter) intersectionPoint2 = BezierSegmentIntersectionPoint(self.segment2, intersectionSegment2Parameter, worldPoint2) rvIntersections2.append(intersectionPoint2) return [rvIntersections1, rvIntersections2] def CalcIntersectionsFromViewPOV(self, nrSamples1, nrSamples2): global algoPOV rvIntersections1 = [] rvIntersections2 = [] fltNrSamples1 = float(nrSamples1) fltNrSamples2 = float(nrSamples2) for iSample1 in range(nrSamples1): segPar10 = float(iSample1) / fltNrSamples1 segPar11 = float(iSample1 + 1) / fltNrSamples1 P0 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar10) P1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=segPar11) for iSample2 in range(nrSamples2): segPar20 = float(iSample2) / fltNrSamples2 segPar21 = float(iSample2 + 1) / fltNrSamples2 Q0 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar20) Q1 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=segPar21) intersectionPointData = mathematics.CalcIntersectionPointsLineSegmentsPOV(P0, P1, Q0, Q1, algoPOV) if intersectionPointData is None: continue intersectionSegment1Parameter = segPar10 + (intersectionPointData[0] / fltNrSamples1) worldPoint1 = self.worldMatrix1 @ self.segment1.CalcPoint(parameter=intersectionSegment1Parameter) intersectionPoint1 = BezierSegmentIntersectionPoint(self.segment1, intersectionSegment1Parameter, worldPoint1) rvIntersections1.append(intersectionPoint1) intersectionSegment2Parameter = segPar20 + (intersectionPointData[1] / fltNrSamples2) worldPoint2 = self.worldMatrix2 @ self.segment2.CalcPoint(parameter=intersectionSegment2Parameter) intersectionPoint2 = BezierSegmentIntersectionPoint(self.segment2, intersectionSegment2Parameter, worldPoint2) rvIntersections2.append(intersectionPoint2) return [rvIntersections1, rvIntersections2] class BezierSplineIntersectionPoint: def __init__(self, spline, bezierSegmentIntersectionPoint): self.spline = spline self.bezierSegmentIntersectionPoint = bezierSegmentIntersectionPoint class BezierSplinesIntersector: def __init__(self, spline1, spline2, worldMatrix1, worldMatrix2): self.spline1 = spline1 self.spline2 = spline2 self.worldMatrix1 = worldMatrix1 self.worldMatrix2 = worldMatrix2 def CalcIntersections(self): rvIntersections1 = [] rvIntersections2 = [] try: nrSamplesPerSegment1 = int(self.spline1.resolution / self.spline1.nrSegments) except: nrSamplesPerSegment1 = 2 if nrSamplesPerSegment1 < 2: nrSamplesPerSegment1 = 2 try: nrSamplesPerSegment2 = int(self.spline2.resolution / self.spline2.nrSegments) except: nrSamplesPerSegment2 = 2 if nrSamplesPerSegment2 < 2: nrSamplesPerSegment2 = 2 for segment1 in self.spline1.segments: for segment2 in self.spline2.segments: segmentsIntersector = BezierSegmentsIntersector(segment1, segment2, self.worldMatrix1, self.worldMatrix2) segmentIntersections = segmentsIntersector.CalcIntersections(nrSamplesPerSegment1, nrSamplesPerSegment2) if segmentIntersections is None: continue segment1Intersections = segmentIntersections[0] for segmentIntersection in segment1Intersections: splineIntersection = BezierSplineIntersectionPoint(self.spline1, segmentIntersection) rvIntersections1.append(splineIntersection) segment2Intersections = segmentIntersections[1] for segmentIntersection in segment2Intersections: splineIntersection = BezierSplineIntersectionPoint(self.spline2, segmentIntersection) rvIntersections2.append(splineIntersection) return [rvIntersections1, rvIntersections2] class CurvesIntersector: @staticmethod def FromSelection(): selObjects = bpy.context.selected_objects if len(selObjects) != 2: raise Exception("len(selObjects) != 2") # shouldn't be possible blenderActiveCurve = bpy.context.active_object blenderOtherCurve = selObjects[0] if blenderActiveCurve == blenderOtherCurve: blenderOtherCurve = selObjects[1] aCurve = curves.Curve(blenderActiveCurve) oCurve = curves.Curve(blenderOtherCurve) return CurvesIntersector(aCurve, oCurve) @staticmethod def ResetGlobals(): global algoPOV algoPOV = None global algoDIR algoDIR = None @staticmethod def InitGlobals(): CurvesIntersector.ResetGlobals() global algoPOV global algoDIR algo = bpy.context.scene.curvetools.IntersectCurvesAlgorithm if algo == 'From_View': regionView3D = util.GetFirstRegionView3D() if regionView3D is None: print("### ERROR: regionView3D is None. Stopping.") return viewPerspective = regionView3D.view_perspective print("--", "viewPerspective:", viewPerspective) if viewPerspective == 'ORTHO': viewMatrix = regionView3D.view_matrix print("--", "viewMatrix:") print(viewMatrix) algoDIR = Vector((viewMatrix[2][0], viewMatrix[2][1], viewMatrix[2][2])) print("--", "algoDIR:", algoDIR) # ## TODO: doesn't work properly if viewPerspective == 'PERSP': viewMatrix = regionView3D.view_matrix print("--", "viewMatrix:") print(viewMatrix) algoPOV = regionView3D.view_location.copy() print("--", "algoPOV:", algoPOV) otherPOV = Vector((viewMatrix[0][3], viewMatrix[1][3], viewMatrix[2][3])) print("--", "otherPOV:", otherPOV) localPOV = Vector((0, 0, 0)) globalPOV = viewMatrix * localPOV print("--", "globalPOV:", globalPOV) perspMatrix = regionView3D.perspective_matrix print("--", "perspMatrix:") print(perspMatrix) globalPOVPersp = perspMatrix * localPOV print("--", "globalPOVPersp:", globalPOVPersp) if viewPerspective == 'CAMERA': camera = bpy.context.scene.camera if camera is None: print("### ERROR: camera is None. Stopping.") return print("--", "camera:", camera) cameraData = camera.data print("--", "cameraData.type:", cameraData.type) cameraMatrix = camera.matrix_world print("--", "cameraMatrix:") print(cameraMatrix) if cameraData.type == 'ORTHO': cameraMatrix = camera.matrix_world # algoDIR = Vector((cameraMatrix[2][0], cameraMatrix[2][1], cameraMatrix[2][2])) algoDIR = Vector((- cameraMatrix[0][2], - cameraMatrix[1][2], - cameraMatrix[2][2])) print("--", "algoDIR:", algoDIR) if cameraData.type == 'PERSP': algoPOV = camera.location.copy() print("--", "algoPOV:", algoPOV) def __init__(self, activeCurve, otherCurve): self.activeCurve = activeCurve self.otherCurve = otherCurve CurvesIntersector.InitGlobals() def CalcIntersections(self): rvIntersections1 = [] rvIntersections2 = [] worldMatrix1 = self.activeCurve.curve.matrix_world worldMatrix2 = self.otherCurve.curve.matrix_world for spline1 in self.activeCurve.splines: for spline2 in self.otherCurve.splines: splineIntersector = BezierSplinesIntersector(spline1, spline2, worldMatrix1, worldMatrix2) splineIntersections = splineIntersector.CalcIntersections() if splineIntersections is None: continue spline1Intersections = splineIntersections[0] for splineIntersection in spline1Intersections: rvIntersections1.append(splineIntersection) spline2Intersections = splineIntersections[1] for splineIntersection in spline2Intersections: rvIntersections2.append(splineIntersection) return [rvIntersections1, rvIntersections2] def CalcAndApplyIntersections(self): mode = bpy.context.scene.curvetools.IntersectCurvesMode if mode == 'Empty': return self.CalcAndApplyEmptyAtIntersections() if mode == 'Insert': return self.CalcAndApplyInsertAtIntersections() if mode == 'Split': return self.CalcAndApplySplitAtIntersections() return [0, 0] def CalcAndApplyEmptyAtIntersections(self): intersections = self.CalcIntersections() intersectionsActive = intersections[0] intersectionsOther = intersections[1] nrActive = 0 nrOther = 0 affect = bpy.context.scene.curvetools.IntersectCurvesAffect if (affect == 'Both') or (affect == 'Active'): for splineIntersection in intersectionsActive: iPoint = splineIntersection.bezierSegmentIntersectionPoint.intersectionPoint bpy.ops.object.empty_add(type='PLAIN_AXES', align='WORLD', location=(iPoint.x, iPoint.y, iPoint.z), rotation=(0, 0, 0)) nrActive += 1 if (affect == 'Both') or (affect == 'Other'): for splineIntersection in intersectionsOther: iPoint = splineIntersection.bezierSegmentIntersectionPoint.intersectionPoint bpy.ops.object.empty_add(type='PLAIN_AXES', align='WORLD', location=(iPoint.x, iPoint.y, iPoint.z), rotation=(0, 0, 0)) nrOther += 1 return [nrActive, nrOther] def CalcAndApplyInsertAtIntersections(self): nrActive = 0 nrOther = 0 affect = bpy.context.scene.curvetools.IntersectCurvesAffect affectA = (affect == 'Both') or (affect == 'Active') affectO = (affect == 'Both') or (affect == 'Other') for iSplineA in range(len(self.activeCurve.splines)): splineA = self.activeCurve.splines[iSplineA] nrSegmentsA = len(splineA.segments) resPerSegA = splineA.resolutionPerSegment for iSplineO in range(len(self.otherCurve.splines)): splineO = self.otherCurve.splines[iSplineO] nrSegmentsO = len(splineO.segments) resPerSegO = splineO.resolutionPerSegment iSegA = 0 while True: segA = splineA.segments[iSegA] iSegO = 0 while True: segO = splineO.segments[iSegO] segIntersector = BezierSegmentsIntersector(segA, segO, self.activeCurve.worldMatrix, self.otherCurve.worldMatrix) segFirstIntersection = segIntersector.CalcFirstIntersection(resPerSegA, resPerSegO) if segFirstIntersection is not None: intPointA = segFirstIntersection[0] intPointO = segFirstIntersection[1] # else does something weird if 1 of them is None.. if (intPointA is not None) and (intPointO is not None): if affectA: if intPointA is not None: splineA.InsertPoint(segA, intPointA.parameter) nrActive += 1 nrSegmentsA += 1 if affectO: if intPointO is not None: splineO.InsertPoint(segO, intPointO.parameter) nrOther += 1 nrSegmentsO += 1 iSegO += 1 if not (iSegO < nrSegmentsO): break iSegA += 1 if not (iSegA < nrSegmentsA): break if affectO: splineO.RefreshInScene() if affectA: splineA.RefreshInScene() return [nrActive, nrOther] def CalcAndApplySplitAtIntersections(self): nrActive = 0 nrOther = 0 affect = bpy.context.scene.curvetools.IntersectCurvesAffect affectA = (affect == 'Both') or (affect == 'Active') affectO = (affect == 'Both') or (affect == 'Other') nrSplinesA = len(self.activeCurve.splines) nrSplinesO = len(self.otherCurve.splines) iSplineA = 0 while True: splineA = self.activeCurve.splines[iSplineA] nrSegmentsA = len(splineA.segments) resPerSegA = splineA.resolutionPerSegment iSplineO = 0 while True: splineO = self.otherCurve.splines[iSplineO] nrSegmentsO = len(splineO.segments) resPerSegO = splineO.resolutionPerSegment iSegA = 0 while True: segA = splineA.segments[iSegA] iSegO = 0 while True: segO = splineO.segments[iSegO] segIntersector = BezierSegmentsIntersector(segA, segO, self.activeCurve.worldMatrix, self.otherCurve.worldMatrix) segFirstIntersection = segIntersector.CalcFirstIntersection(resPerSegA, resPerSegO) if segFirstIntersection is not None: intPointA = segFirstIntersection[0] intPointO = segFirstIntersection[1] # else does something weird if 1 of them is None.. if (intPointA is not None) and (intPointO is not None): if affectA: if intPointA is not None: print("--", "splineA.Split():") newSplinesA = splineA.Split(segA, intPointA.parameter) if newSplinesA is not None: newResolutions = splineA.CalcDivideResolution(segA, intPointA.parameter) newSplinesA[0].resolution = newResolutions[0] newSplinesA[1].resolution = newResolutions[1] splineA = newSplinesA[0] self.activeCurve.splines[iSplineA] = splineA self.activeCurve.splines.insert(iSplineA + 1, newSplinesA[1]) nrActive += 1 if affectO: if intPointO is not None: print("--", "splineO.Split():") newSplinesO = splineO.Split(segO, intPointO.parameter) if newSplinesO is not None: newResolutions = splineO.CalcDivideResolution(segO, intPointO.parameter) newSplinesO[0].resolution = newResolutions[0] newSplinesO[1].resolution = newResolutions[1] splineO = newSplinesO[0] self.otherCurve.splines[iSplineO] = splineO self.otherCurve.splines.insert(iSplineO + 1, newSplinesO[1]) nrOther += 1 nrSegmentsO = len(splineO.segments) iSegO += 1 if not (iSegO < nrSegmentsO): break nrSegmentsA = len(splineA.segments) iSegA += 1 if not (iSegA < nrSegmentsA): break nrSplinesO = len(self.otherCurve.splines) iSplineO += 1 if not (iSplineO < nrSplinesO): break nrSplinesA = len(self.activeCurve.splines) iSplineA += 1 if not (iSplineA < nrSplinesA): break if affectA: print("") print("--", "self.activeCurve.RebuildInScene():") self.activeCurve.RebuildInScene() if affectO: print("") print("--", "self.otherCurve.RebuildInScene():") self.otherCurve.RebuildInScene() return [nrActive, nrOther]