def isIntersectingLoopPathList(loopList, otherPaths, pointBegin, pointEnd): "Determine if the segment between the first and second point is intersecting the loop list." normalizedSegment = pointEnd.dropAxis(2) - pointBegin.dropAxis(2) normalizedSegmentLength = abs(normalizedSegment) if normalizedSegmentLength == 0.0: return False normalizedSegment /= normalizedSegmentLength segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) pointBeginRotated = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pointBegin) pointEndRotated = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pointEnd) if euclidean.isLoopListIntersectingInsideXSegment(loopList, pointBeginRotated.x, pointEndRotated.x, segmentYMirror, pointBeginRotated.y): return True for path in otherPaths: rotatedPath = euclidean.getPathRoundZAxisByPlaneAngle( segmentYMirror, path) for pointIndex in range(len(rotatedPath) - 1): pointFirst = rotatedPath[pointIndex] pointSecond = rotatedPath[pointIndex + 1] if euclidean.isLineIntersectingInsideXSegment( pointBeginRotated.x, pointEndRotated.x, pointFirst, pointSecond, pointBeginRotated.y): return True return False
def insertPathsBetween( self, nextBeginning, pathEnd ): "Insert paths between the perimeter and the fill." betweenX = [] switchX = [] segment = nextBeginning.minus( pathEnd ) segment.normalize() segmentXY = segment.dropAxis( 2 ) segmentYMirror = complex( segment.x, - segment.y ) pathEndRotated = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pathEnd ) nextBeginningRotated = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, nextBeginning ) y = pathEndRotated.y z = pathEndRotated.z for betweenIndex in range( len( self.getBetweens() ) ): between = self.getBetweens()[ betweenIndex ] betweenRotated = euclidean.getPathRoundZAxisByPlaneAngle( segmentYMirror, between ) euclidean.addXIntersections( betweenRotated, betweenIndex, switchX, y ) switchX.sort( euclidean.compareSolidXByX ) maximumX = max( pathEndRotated.x, nextBeginningRotated.x ) minimumX = min( pathEndRotated.x, nextBeginningRotated.x ) for xIntersection in switchX: if xIntersection.real > minimumX and xIntersection.real < maximumX: betweenX.append( xIntersection ) betweenXIndex = 0 while betweenXIndex < len( betweenX ) - 1: betweenXFirst = betweenX[ betweenXIndex ] betweenXSecond = betweenX[ betweenXIndex + 1 ] if betweenXSecond.imag == betweenXFirst.imag: betweenXIndex += 1 betweenFirst = euclidean.getRoundZAxisByPlaneAngle( segmentXY, Vec3( betweenXFirst.real, y, z ) ) betweenSecond = euclidean.getRoundZAxisByPlaneAngle( segmentXY, Vec3( betweenXSecond.real, y, z ) ) loopFirst = self.getBetweens()[ int( betweenXFirst.imag ) ] self.addPathBetween( betweenFirst, betweenSecond, loopFirst ) betweenXIndex += 1
def isLoopIntersectingLoop( anotherLoop, loop ): "Determine if the a loop is intersecting another loop." for pointIndex in range( len( loop ) ): pointFirst = loop[ pointIndex ] pointSecond = loop[ ( pointIndex + 1 ) % len( loop ) ] segment = pointFirst.minus( pointSecond ) normalizedSegment = segment.dropAxis( 2 ) normalizedSegment /= abs( normalizedSegment ) segmentYMirror = complex( normalizedSegment.real, - normalizedSegment.imag ) segmentFirstPoint = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pointFirst ) segmentSecondPoint = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pointSecond ) if euclidean.isLoopIntersectingInsideXSegment( anotherLoop, segmentFirstPoint.x, segmentSecondPoint.x, segmentYMirror, segmentFirstPoint.y ): return True return False
def getInsetFromClockwiseTriple( aheadAbsolute, behindAbsolute, center, radius ): "Get loop inset from clockwise triple, out from widdershins loop." originalCenterMinusBehind = center.minus( behindAbsolute ) originalCenterMinusBehind.normalize() centerRoundZAngle = originalCenterMinusBehind.dropAxis( 2 ) reverseRoundZAngle = complex( centerRoundZAngle.real, - centerRoundZAngle.imag ) aheadAbsolute = euclidean.getRoundZAxisByPlaneAngle( reverseRoundZAngle, aheadAbsolute ) behindAbsolute = euclidean.getRoundZAxisByPlaneAngle( reverseRoundZAngle, behindAbsolute ) center = euclidean.getRoundZAxisByPlaneAngle( reverseRoundZAngle, center ) aheadIntersection = getIntersectionAtInset( aheadAbsolute, center, radius ) behindIntersection = getIntersectionAtInset( center, behindAbsolute, radius ) centerMinusAhead = center.minus( aheadAbsolute ) if abs( centerMinusAhead.y ) < abs( 0.000001 * centerMinusAhead.x ): between = aheadIntersection.plus( behindIntersection ) between.scale( 0.5 ) return euclidean.getRoundZAxisByPlaneAngle( centerRoundZAngle, between ) yMinusAhead = behindIntersection.y - aheadIntersection.y x = aheadIntersection.x + yMinusAhead * centerMinusAhead.x / centerMinusAhead.y between = Vec3( x, behindIntersection.y, behindIntersection.z ) return euclidean.getRoundZAxisByPlaneAngle( centerRoundZAngle, between )
def isIntersectingLoopPathList( loopList, otherPaths, pointBegin, pointEnd ): "Determine if the segment between the first and second point is intersecting the loop list." normalizedSegment = pointEnd.dropAxis( 2 ) - pointBegin.dropAxis( 2 ) normalizedSegmentLength = abs( normalizedSegment ) if normalizedSegmentLength == 0.0: return False normalizedSegment /= normalizedSegmentLength segmentYMirror = complex( normalizedSegment.real, - normalizedSegment.imag ) pointBeginRotated = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pointBegin ) pointEndRotated = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pointEnd ) if euclidean.isLoopListIntersectingInsideXSegment( loopList, pointBeginRotated.x, pointEndRotated.x, segmentYMirror, pointBeginRotated.y ): return True for path in otherPaths: rotatedPath = euclidean.getPathRoundZAxisByPlaneAngle( segmentYMirror, path ) for pointIndex in range( len( rotatedPath ) - 1 ): pointFirst = rotatedPath[ pointIndex ] pointSecond = rotatedPath[ pointIndex + 1 ] if euclidean.isLineIntersectingInsideXSegment( pointBeginRotated.x, pointEndRotated.x, pointFirst, pointSecond, pointBeginRotated.y ): return True return False
def addArc( self, afterCenterDifferenceAngle, afterPoint, beforeCenterSegment, beforePoint, center ): "Add arc segments to the filleted skein." curveSection = 0.5 absoluteDifferenceAngle = abs( afterCenterDifferenceAngle ) steps = int( math.ceil( max( absoluteDifferenceAngle * 2.4, absoluteDifferenceAngle * beforeCenterSegment.length() / curveSection ) ) ) stepPlaneAngle = euclidean.getPolar( afterCenterDifferenceAngle / steps, 1.0 ) for step in range( 1, steps ): beforeCenterSegment = euclidean.getRoundZAxisByPlaneAngle( stepPlaneAngle, beforeCenterSegment ) arcPoint = center.plus( beforeCenterSegment ) self.addLinearMovePoint( arcPoint ) self.addLinearMovePoint( afterPoint )
def isLoopIntersectingLoop(anotherLoop, loop): "Determine if the a loop is intersecting another loop." for pointIndex in range(len(loop)): pointFirst = loop[pointIndex] pointSecond = loop[(pointIndex + 1) % len(loop)] segment = pointFirst.minus(pointSecond) normalizedSegment = segment.dropAxis(2) normalizedSegment /= abs(normalizedSegment) segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) segmentFirstPoint = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pointFirst) segmentSecondPoint = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pointSecond) if euclidean.isLoopIntersectingInsideXSegment(anotherLoop, segmentFirstPoint.x, segmentSecondPoint.x, segmentYMirror, segmentFirstPoint.y): return True return False
def getOverhangDirection( belowOutsetLoops, segmentBegin, segmentEnd ): "Add to span direction from the endpoint segments which overhang the layer below." segment = segmentEnd.minus( segmentBegin ) normalizedSegment = complex( segment.x, segment.y ) normalizedSegment /= abs( normalizedSegment ) segmentYMirror = complex( normalizedSegment.real, - normalizedSegment.imag ) segmentBegin = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, segmentBegin ) segmentEnd = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, segmentEnd ) solidXIntersectionList = [] y = segmentBegin.y solidXIntersectionList.append( complex( segmentBegin.x, - 1.0 ) ) solidXIntersectionList.append( complex( segmentEnd.x, - 1.0 ) ) for belowLoopIndex in range( len( belowOutsetLoops ) ): belowLoop = belowOutsetLoops[ belowLoopIndex ] rotatedOutset = euclidean.getPathRoundZAxisByPlaneAngle( segmentYMirror, belowLoop ) euclidean.addXIntersections( rotatedOutset, belowLoopIndex, solidXIntersectionList, y ) overhangingSegments = euclidean.getSegmentsFromIntersections( solidXIntersectionList, y, segmentBegin.z ) overhangDirection = complex() for overhangingSegment in overhangingSegments: overhangDirection += getDoubledRoundZ( overhangingSegment, normalizedSegment ) return overhangDirection
def helicalMove(self, isCounterclockwise, splitLine): "Get statistics for a helical move." if self.oldLocation == None: return location = self.getLocationSetFeedrateToSplitLine(splitLine) location.add(self.oldLocation) center = Vec3().getFromVec3(self.oldLocation) indexOfR = gcodec.indexOfStartingWithSecond("R", splitLine) if indexOfR > 0: radius = gcodec.getDoubleAfterFirstLetter(splitLine[indexOfR]) halfLocationMinusOld = location.minus(self.oldLocation) halfLocationMinusOld.scale(0.5) halfLocationMinusOldLength = halfLocationMinusOld.length() centerMidpointDistance = math.sqrt(radius * radius - halfLocationMinusOldLength * halfLocationMinusOldLength) centerMinusMidpoint = euclidean.getRotatedWiddershinsQuarterAroundZAxis( halfLocationMinusOld) centerMinusMidpoint.normalize() centerMinusMidpoint.scale(centerMidpointDistance) if isCounterclockwise: center.setToVec3( halfLocationMinusOld.plus(centerMinusMidpoint)) else: center.setToVec3( halfLocationMinusOld.minus(centerMinusMidpoint)) else: center.x = gcodec.getDoubleForLetter("I", splitLine) center.y = gcodec.getDoubleForLetter("J", splitLine) curveSection = 0.5 center.add(self.oldLocation) afterCenterSegment = location.minus(center) beforeCenterSegment = self.oldLocation.minus(center) afterCenterDifferenceAngle = euclidean.getAngleAroundZAxisDifference( afterCenterSegment, beforeCenterSegment) absoluteDifferenceAngle = abs(afterCenterDifferenceAngle) steps = int( round(0.5 + max( absoluteDifferenceAngle * 2.4, absoluteDifferenceAngle * beforeCenterSegment.length() / curveSection))) stepPlaneAngle = euclidean.getPolar(afterCenterDifferenceAngle / steps, 1.0) zIncrement = (afterCenterSegment.z - beforeCenterSegment.z) / float(steps) for step in range(1, steps): beforeCenterSegment = euclidean.getRoundZAxisByPlaneAngle( stepPlaneAngle, beforeCenterSegment) beforeCenterSegment.z += zIncrement arcPoint = center.plus(beforeCenterSegment) self.addToPath(arcPoint) self.addToPath(location)
def insertPathsBetween(self, nextBeginning, pathEnd): "Insert paths between the perimeter and the fill." betweenX = [] switchX = [] segment = nextBeginning.minus(pathEnd) segment.normalize() segmentXY = segment.dropAxis(2) segmentYMirror = complex(segment.x, -segment.y) pathEndRotated = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pathEnd) nextBeginningRotated = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, nextBeginning) y = pathEndRotated.y z = pathEndRotated.z for betweenIndex in range(len(self.getBetweens())): between = self.getBetweens()[betweenIndex] betweenRotated = euclidean.getPathRoundZAxisByPlaneAngle( segmentYMirror, between) euclidean.addXIntersections(betweenRotated, betweenIndex, switchX, y) switchX.sort(euclidean.compareSolidXByX) maximumX = max(pathEndRotated.x, nextBeginningRotated.x) minimumX = min(pathEndRotated.x, nextBeginningRotated.x) for xIntersection in switchX: if xIntersection.real > minimumX and xIntersection.real < maximumX: betweenX.append(xIntersection) betweenXIndex = 0 while betweenXIndex < len(betweenX) - 1: betweenXFirst = betweenX[betweenXIndex] betweenXSecond = betweenX[betweenXIndex + 1] if betweenXSecond.imag == betweenXFirst.imag: betweenXIndex += 1 betweenFirst = euclidean.getRoundZAxisByPlaneAngle( segmentXY, Vec3(betweenXFirst.real, y, z)) betweenSecond = euclidean.getRoundZAxisByPlaneAngle( segmentXY, Vec3(betweenXSecond.real, y, z)) loopFirst = self.getBetweens()[int(betweenXFirst.imag)] self.addPathBetween(betweenFirst, betweenSecond, loopFirst) betweenXIndex += 1
def getInsetFromClockwiseTriple(aheadAbsolute, behindAbsolute, center, radius): "Get loop inset from clockwise triple, out from widdershins loop." originalCenterMinusBehind = center.minus(behindAbsolute) originalCenterMinusBehind.normalize() centerRoundZAngle = originalCenterMinusBehind.dropAxis(2) reverseRoundZAngle = complex(centerRoundZAngle.real, -centerRoundZAngle.imag) aheadAbsolute = euclidean.getRoundZAxisByPlaneAngle( reverseRoundZAngle, aheadAbsolute) behindAbsolute = euclidean.getRoundZAxisByPlaneAngle( reverseRoundZAngle, behindAbsolute) center = euclidean.getRoundZAxisByPlaneAngle(reverseRoundZAngle, center) aheadIntersection = getIntersectionAtInset(aheadAbsolute, center, radius) behindIntersection = getIntersectionAtInset(center, behindAbsolute, radius) centerMinusAhead = center.minus(aheadAbsolute) if abs(centerMinusAhead.y) < abs(0.000001 * centerMinusAhead.x): between = aheadIntersection.plus(behindIntersection) between.scale(0.5) return euclidean.getRoundZAxisByPlaneAngle(centerRoundZAngle, between) yMinusAhead = behindIntersection.y - aheadIntersection.y x = aheadIntersection.x + yMinusAhead * centerMinusAhead.x / centerMinusAhead.y between = Vec3(x, behindIntersection.y, behindIntersection.z) return euclidean.getRoundZAxisByPlaneAngle(centerRoundZAngle, between)
def addArc(self, afterCenterDifferenceAngle, afterPoint, beforeCenterSegment, beforePoint, center): "Add arc segments to the filleted skein." curveSection = 0.5 absoluteDifferenceAngle = abs(afterCenterDifferenceAngle) steps = int( math.ceil( max( absoluteDifferenceAngle * 2.4, absoluteDifferenceAngle * beforeCenterSegment.length() / curveSection))) stepPlaneAngle = euclidean.getPolar(afterCenterDifferenceAngle / steps, 1.0) for step in range(1, steps): beforeCenterSegment = euclidean.getRoundZAxisByPlaneAngle( stepPlaneAngle, beforeCenterSegment) arcPoint = center.plus(beforeCenterSegment) self.addLinearMovePoint(arcPoint) self.addLinearMovePoint(afterPoint)
def helicalMove( self, isCounterclockwise, splitLine ): "Get statistics for a helical move." if self.oldLocation == None: return location = self.getLocationSetFeedrateToSplitLine( splitLine ) location.add( self.oldLocation ) center = Vec3().getFromVec3( self.oldLocation ) indexOfR = gcodec.indexOfStartingWithSecond( "R", splitLine ) if indexOfR > 0: radius = gcodec.getDoubleAfterFirstLetter( splitLine[ indexOfR ] ) halfLocationMinusOld = location.minus( self.oldLocation ) halfLocationMinusOld.scale( 0.5 ) halfLocationMinusOldLength = halfLocationMinusOld.length() centerMidpointDistance = math.sqrt( radius * radius - halfLocationMinusOldLength * halfLocationMinusOldLength ) centerMinusMidpoint = euclidean.getRotatedWiddershinsQuarterAroundZAxis( halfLocationMinusOld ) centerMinusMidpoint.normalize() centerMinusMidpoint.scale( centerMidpointDistance ) if isCounterclockwise: center.setToVec3( halfLocationMinusOld.plus( centerMinusMidpoint ) ) else: center.setToVec3( halfLocationMinusOld.minus( centerMinusMidpoint ) ) else: center.x = gcodec.getDoubleForLetter( "I", splitLine ) center.y = gcodec.getDoubleForLetter( "J", splitLine ) curveSection = 0.5 center.add( self.oldLocation ) afterCenterSegment = location.minus( center ) beforeCenterSegment = self.oldLocation.minus( center ) afterCenterDifferenceAngle = euclidean.getAngleAroundZAxisDifference( afterCenterSegment, beforeCenterSegment ) absoluteDifferenceAngle = abs( afterCenterDifferenceAngle ) steps = int( round( 0.5 + max( absoluteDifferenceAngle * 2.4, absoluteDifferenceAngle * beforeCenterSegment.length() / curveSection ) ) ) stepPlaneAngle = euclidean.getPolar( afterCenterDifferenceAngle / steps, 1.0 ) zIncrement = ( afterCenterSegment.z - beforeCenterSegment.z ) / float( steps ) for step in range( 1, steps ): beforeCenterSegment = euclidean.getRoundZAxisByPlaneAngle( stepPlaneAngle, beforeCenterSegment ) beforeCenterSegment.z += zIncrement arcPoint = center.plus( beforeCenterSegment ) self.addToPath( arcPoint ) self.addToPath( location )