-- CIRCLES AND LINES -- -- © OpenSpark Interactive -- -- ---------------------------------------------------------------------- -- RayCutsSphere(aRayPoint1, aRayPoint2, aCenter, aRadius) -- ReflectPointInLine(aPoint, aPointOnLine, anAngle) -- GetPerpendicular(aPoint, aPointOnLine, anAngle) -- GetDistanceToLine(aPoint, aPointOnLine, anAngle) -- CircleCutsCircle(aCentre1, aRadius1, aCentre2, aRadius2) -- LineCutsCircle(aCenter, aRadius, aLine) -- LineCutsLine(aLine1, aLine2) -- LineEquation(aPoint1, aPoint2) -- SegmentIntersection(aSegment1, aSegment2, isRecursive) -- IsASegment(aSegment) ---------------------------------------------------------------------- on RayCutsSphere(aRayPoint1, aRayPoint2, aCenter, aRadius) ------------ -- INPUT: , and should all be -- position vectors. aRayPoint1 and aRayPoint2 represent -- points on a line, aCenter is the center of a sphere with -- radius aRadius. -- should be a number -- ACTION: Calculates the shortest vector from aCenter to the given -- ray, and thus determines the center point of a circle -- which can be inscribed on the sphere. The given ray -- intersects the sphere and the circle at the same points, -- so we can simplify the rest of the calculation to the -- intersection of a line with a circle. -- OUTPUT: Returns a list of zero, one or two vectors, representing -- the points at which the ray defined by aRayPoint1 and -- aRayPoint2 intersect the surface of the sphere defined -- by aCenter and aRadius. If the input values are unusable -- then an error symbol is returned instead. -------------------------------------------------------------------- vIntersections = [] -- one or two vectors may be added if ilk(aRayPoint1) <> #vector then return #vectorExpected else if ilk(aRayPoint2) <> #vector then return #vectorExpected else if ilk(aCenter) <> #vector then return #centerPointExpected else if not ilk(aRadius, #number) then return #numberExpected end if -- Determine the direction vector between the two line points vDirection = (aRayPoint1 - aRayPoint2).getNormalized() -- Create a vector from aRayPoint to aCenter vDelta = aRayPoint1 - aCenter -- Find the perpendicular to the line that passes through aCenter. -- To do this, we first find a vector which is perpendicular to both -- vDelta and vDirection vOrthogonal = vDelta.cross(vDirection) if vOrthogonal.magnitude = 0 then -- vDelta and vDirection are parallel. aCenter is on the line. -- There is no perpendicular, so we can use a shortcut. vPointOnLine = aCenter vSegmentLength = aRadius else vPerpendicular = vOrthogonal.cross(vDirection).getNormalized() -- The point where the perpendicular crosses the line can be -- defined either as: -- * a displacement from aRayPoint1 to aCenter followed by a -- displacement back along vPerpendicular from aCenter -- towards the line. (Let's call the length of this -- displacement vDistance). -- or as -- * a displacement along the vDirection from aRayPoint1. -- -- The magnitude of the displacements along vDirection and -- vPerpendicular are both unknown. -- -- K * vDirection = vDelta - vDistance * vPerpendicular -- -- Taking the dot product of both sides by the perpendicular, we -- get... -- -- 0 = vDelta.vPerpendicular - vDistance * 1 -- -- ... since vPerpendicular is a unit vector and so its dot -- product with itself will be 1 vDistance = vDelta * vPerpendicular if abs(aRadius) < abs(vDistance) then -- The line does not cut the sphere return vIntersections end if vVectorToLine = vPerpendicular * vDistance -- The points where the line crosses the sphere will be either side -- of the point which is vVectorToLine from aCenter. We can use -- Pythagoras to determine how far forward and back along the line -- these points will be. vPointOnLine = aCenter + vVectorToLine vSegmentLength = sqrt(aRadius * aRadius - vDistance * vDistance) end if if vSegmentLength = 0 then -- The line cuts the sphere at a tangent: there is only one -- intersection point vIntersections.append(vPointOnLine) else -- We need to calculate two intersection points vVector = vDirection * vSegmentLength vIntersections.append(vPointOnLine + vVector) vIntersections.append(vPointOnLine - vVector) end if return vIntersections end RayCutsSphere on ReflectPointInLine(aPoint, aPointOnLine, anAngle) ----------------- -- INPUT: should be a point in 2D space -- should be a point in 2D space on the line -- should be the angle in radians that the line -- makes with the horizontal. -- ACTION: Calculates the perpendicular from to the line -- defined by and to , and -- adds this twice from to give its reflection in -- the line. -- OUTPUT: Returns a the reflection of point in the line. -------------------------------------------------------------------- -- Create a vector from the point on the line to the other point tDeltaH = aPoint.locH - aPointOnLine.locH tDeltaV = aPoint.locV - aPointOnLine.locV -- Create a unit vector, tVector, along the line: tCosAngle = cos(anAngle) tSinAngle = sin(anAngle) -- tVector = [tCosAngle, tSinAngle] -- We need to find the point where the perpendicular to the line -- that passes through aPoint cuts the line. The perpendicular to -- the line (tPerp) has the unit vector: -- -- tPerp = [-tSinAngle, tCosAngle] -- -- This unknown point on the line can be defined either as: -- a displacement from aPointOnLine to aPoint followed by a -- displacement along tPerp from aPoint towards the line -- or as -- a displacement along the tVector itself. -- The magnitude of the displacement along tVector and tPerp are -- both unknown. -- -- K * tVector = tDelta + tDistance * tPerp -- -- Taking the dot product of both sides by the perpendicular, we get -- -- 0 = tDelta.tPerp + tDistance * tPerp.tPerp -- -- So: -- -- tDistance = -tDelta.tPerp / (tPerp.tPerp) -- -- But tPerp is by definition a unit vector, so its dot product by -- itself = 1 -- -- tDistance = -tDelta.tPerp -- -- Expanding -- -- tDistance = -((-tSinAngle * tDeltaH) + (tCosAngle * tDeltaV)) -- -- Since we want to reflect aPoint in the line, we actually want to -- travel twice this distance, in the direction tPerp. tDistance = 2 * (tSinAngle * tDeltaH - tCosAngle * tDeltaV) tReflectVector = [-tSinAngle * tDistance, tCosAngle * tDistance] return aPoint + tReflectVector end ReflectPointInLine on GetPerpendicular(aPoint, aPointOnLine, anAngle) ------------------- -- INPUT: should be a point in 2D space -- should be a point in 2D space on the line -- should be the angle in radians that the line -- makes with the horizontal. -- OUTPUT: Returns a point which can be considered as the vector -- from aPoint to the given line. For details of the -- calculation, see the ReflectPointInLine() handler. -------------------------------------------------------------------- tDeltaH = aPoint.locH - aPointOnLine.locH tDeltaV = aPoint.locV - aPointOnLine.locV tCosAngle = cos(anAngle) tSinAngle = sin(anAngle) tDistance = tSinAngle * tDeltaH - tCosAngle * tDeltaV return point(-tSinAngle * tDistance, tCosAngle * tDistance) end GetPerpendicular on GetDistanceToLine(aPoint, aPointOnLine, anAngle) ------------------- -- INPUT: should be a point in 2D space -- should be a point in 2D space on the line -- should be the angle in radians that the line -- makes with the horizontal. -- OUTPUT: Returns the length of the perpendicular from aPoint to -- the given line. For details of the calculation, see the -- ReflectPointInLine() handler. -------------------------------------------------------------------- tDeltaH = aPoint.locH - aPointOnLine.locH tDeltaV = aPoint.locV - aPointOnLine.locV tCosAngle = cos(anAngle) tSinAngle = sin(anAngle) return tSinAngle * tDeltaH - tCosAngle * tDeltaV end GetDistanceToLine on GetDistanceFromLine(aPoint, aPointOnLine1, aPointOnLine2) --------- -- INPUT: should be a point in 2D space -- and should be distinct -- points on the line -- OUTPUT: Returns the length of the perpendicular from aPoint to -- the line passing through aPointOnLine1 and aPointOnLine2. -------------------------------------------------------------------- -- Determine the slope between the two points on the line tDelta = aPointOnLine1 - aPointOnLine2 tDeltaH = tDelta.locH tDeltaV = float(tDelta.locV) -- so that sqrt() below is a float -- Determine the length of the line tLength = sqrt(tDeltaH * tDeltaH + tDeltaV * tDeltaV) -- Create a unit vector perpendicular to the line. To do this, -- swap the x and y coordinates, and make one of them negative. -- Divide the result by the (float) length of the line, to give -- coordinates with a unit length (sine and cosine). tVectorH = tDeltaV / tLength tVectorV = -tDeltaH / tLength -- Recycle tDeltaH and tDeltaV to create a vector from one of the -- points on the line to the test point tDeltaH = aPoint.locH - aPointOnLine1.locH tDeltaV = aPoint.locV - aPointOnLine1.locV -- The distance from the line is the dot product of this vector and -- the perpendicular to the line. tDistance = tVectorH * tDeltaH + tVectorV * tDeltaV return abs(tDistance) -- convert negative to positive if necessary end GetDistanceFromLine on CircleCutsCircle(aCentre1, aRadius1, aCentre2, aRadius2) ------------ -- INPUT: and should be points -- and should be floats or integers -- may also be a property list with the format: -- [#centre1: , -- #centre2: , -- #radius1: , -- #radius2: ] -- If this is the case subsequent parameters will be ignored. -- ACTION: Calculates the intersection of two circles, centred on -- and and with radii of and -- -- OUTPUT: Returns a linear list of two points if the circles -- intersect, or a symbol. If the circles intersect at a -- single point, two points are still returned, but they will -- be identical. The points may contain #float values, to -- ensure accuracy. -- -- Symbols may be: -- #invalidData: if parameters cannot be converted to two -- points and two radii -- #noIntersection: if the circles do not touch -- #concentric: if the circles share the same centre and -- thus do not intersect (though they may -- touch everwhere) --------------------------------------------------------------------- if ilk(aCentre1, #propList) then -- Unpack the data in the proplist aRadius1 = aCentre1[#radius1] aCentre2 = aCentre1[#centre2] aRadius2 = aCentre1[#radius2] aCentre1 = aCentre1[#centre1] end if -- Ensure input data is valid if not ilk(aCentre1, #point) then return #invalidData else if not ilk(aCentre2, #point) then return #invalidData else if not ilk(aRadius1, #number) then return #invalidData else if not ilk(aRadius2, #number) then return #invalidData end if -- Find the square of the distance between centres... tVector = aCentre2 - aCentre1 tDelta2 = tVector.locH * tVector.locH + tVector.locV * tVector.locV if tDelta2 = 0 then -- The centres are identical: circles are concentric return #concentricCircles end if -- ... and the distance itself tDelta = sqrt(float(tDelta2)) if aRadius1 + aRadius2 < tDelta then -- The distance between the centers is greater than the sum of the -- two radii. The circles are too far apart to intersect. return #noIntersection else if min(aRadius1,aRadius2) + tDelta < max(aRadius1,aRadius2) then -- The smaller circle is completely inside the larger one. return #noIntersection end if -- Find where chord between intersection points crosses nte line -- between centres. We do this by solving simultaneous equations -- using Pythagoras' Theorem. We can create two right-angled -- triangles: one with angles at the center of circle 1, one of the -- intersections of the circles, and the point where the chord -- between the intersections crosses the line between the center. -- The angle at this last point is, by definition, a right angle. -- The length between the center and this point is unknown: we'll -- call it tOffset. The length of the second side is half of the -- length of the chord. This length is currently unknown. We'll -- call it tHalfChord. The other triangle has the same structure, -- except that its first angle is at the center of circle 2. We -- shall call the distance from aCenter2 to the chord "b". -- tDelta = tOffset + b. We first need to work out tOffset, and then -- tHalfChord -- -- aRadius1^2 = tHalfChord^2 + tOffset^2 -- aRadius2^2 = tHalfChord^2 + b^2 -- -- aRadius1^2 - aRadius2^2 = tOffset^2 - b^2 -- = tOffset^2 - (tDelta - tOffset)^2 -- = tOffset^2 - tDelta^2 + 2*tDelta*tOffset -- - tOffset^2 -- aRadius1^2 - aRadius2^2 = 2 * tDelta * tOffset - tDelta^2 -- -- tOffset = (aRadius1^2 - aRadius2^2 + tDelta^2) / 2 * tDelta tOffset = (aRadius1*aRadius1-aRadius2*aRadius2+tDelta2)/(2*tDelta) tChordCentre = aCentre1 + (tVector * tOffset) / tDelta -- Find half length of chord between intersection points. If the -- circles intersect at a single point, this will be 0. tHalfChord = sqrt(aRadius1*aRadius1 - tOffset*tOffset) -- Find a unit normal vector along the chord towards one of the -- intersection points... tNormal = point(tVector.locV, -tVector.locH) / tDelta -- ... and use this to find the intersection points tIntersection1 = tChordCentre + tHalfChord * tNormal tIntersection2 = tChordCentre - tHalfChord * tNormal -- -- Convert coordinates to integer values if appropriate -- integerValue = integer(tIntersection1.locH) -- if tIntersection1.locH = integerValue then -- tIntersection1.locH = integerValue -- end if -- integerValue = integer(tIntersection1.locV) -- if tIntersection1.locV = integerValue then -- tIntersection1.locV = integerValue -- end if -- integerValue = integer(tIntersection2.locH) -- if tIntersection2.locH = integerValue then -- tIntersection2.locH = integerValue -- end if -- integerValue = integer(tIntersection2.locV) -- if tIntersection2.locV = integerValue then -- tIntersection2.locV = integerValue -- end if return [tIntersection1, tIntersection2] end CircleCutsCircle on LineCutsCircle(aCenter, aRadius, aLine) --------------------------- -- ACTION: Calculates the intersection between and a circle, -- centered on and with radius -- -- PARAMETERS: -- should a point -- should be float or integer -- should be a property lists with one of the following -- formats: -- [#slope: , #zeroX: ] --> y = ax + b -- [#x: ] --> vertical line -- -- may also be a property list with the format: -- [#center: , #radius: , #line: ] -- If this is the case, subsequent parameters will be ignored. -- -- RETURNS: a linear list of two points if the line intersects the -- circle, or a symbol. If the line intersects the circle at a -- single point, two points are still returned, but they will be -- identical. The points may contain #float values, to ensure -- accuracy. -- -- Symbols may be: -- #invalidData: if parameters cannot be converted to line, point -- and radius -- #noIntersection: if the circle and line do not touch --------------------------------------------------------------------- -- Optional parameter verification case ilk(aCenter) of #propList: -- unpack the data in the proplist aRadius = aCenter[#radius] aLine = aCenter[#line] aCenter = aCenter[#center] #point: -- Other values should in subsequent parameters otherwise: return #invalidData end case if ilk(aCenter, #point) then centerH = aCenter.locH centerV = aCenter.locV else return #invalidData end if case ilk(aRadius) of #float, #integer: -- acceptable values radius2 = aRadius * aRadius otherwise: return #invalidData end case if ilk(aLine) = #propList then slope = aLine[#slope] case ilk(slope) of #float: -- Keep as it is #integer: slope = float(slope) -- for precise sqrt() results #void: -- aLine may represent a vertical line x = aLine[#x] if voidP(x) then return #invalidData else -- line may be vertical case ilk(x) of #float, #integer: -- acceptable values otherwise: return #invalidData end case end if otherwise: return #invalidData end case zeroX = aLine[#zeroX] case ilk(zeroX) of #float, #integer, #void: -- acceptable values otherwise: return #invalidData end case else -- aLine is not a propList return #invalidData end if -- End of optional parameter verification -- Find the point on nearest to the center of the circle. -- This will occur at the intersection between and a line -- perpendicular to the given one which passes through the center of -- the circle. if not voidP(x) then -- Line is vertical, perpendicular is horizontal: nearest point -- occurs at point(x, centerV) nearestX = x nearestY = centerV else if slope = 0 then -- Line is horizontal, perpendicular is vertical: nearest point -- occurs at point(centerH, zeroX) nearestX = centerH nearestY = zeroX else -- The perpendicular line has the slope -1/slope. Its equation -- is: -- y = -x/slope + b -- Solve this for center of circle which the line passes through -- => centerV = -centerH/slope + zeroXo -- => zeroXo = centerV + (centerH / slope) -- The intersection of the two lines occurs where -- y = slope * x + zeroX -- AND -- y = -x / slope + zeroXo -- => slope * x + zeroX = -x / slope + zeroXo -- => slope * x + (x / slope) = zeroXo - zeroX -- => nearestX = (zeroXo - zeroX) / (slope + 1/slope) nearestY = slope * nearestX + zeroX end if -- Calculate the square of distance between the intersection and the -- center of the circle, using Pythagoras' Theorem deltaH = centerH - nearestX deltaV = centerV - nearestY delta2 = float((deltaH * deltaH) + (deltaV * deltaV)) -- Special cases if delta2 > radius2 then -- The line doesn't intersect the circle return #noIntersection else if delta2 = radius2 then -- The line meets the circle at a tangent return [point(nearestX, nearestY), point(nearestX, nearestY)] end if -- General case: double intersection intersections = [] -- Calculate half the length of chord. This creates a right-angled -- triangle with aRadius as the hypotenuse and sqrt(delta2) as the -- third side halfChord = sqrt(radius2 - delta2) if voidP(slope) then -- Line is vertical: move halfChord up and down from nearestPoint intersectV = nearestY + halfChord intersections.append(point(x, intersectV)) intersectV = nearestY - halfChord intersections.append(point(x, intersectV)) else -- Determine a unit vector along the aLine slopeAdjust = sqrt((slope * slope) + 1) -- vector = point(slope / slopeAdjust, 1 / slopeAdjust) -- Move halfChord units up and down the line from nearestPoint intersectH = nearestX + halfChord / slopeAdjust intersectV = nearestY + halfChord * slope / slopeAdjust intersections.append(point(intersectH, intersectV)) intersectH = nearestX - halfChord / slopeAdjust intersectV = nearestY - halfChord * slope / slopeAdjust intersections.append(point(intersectH, intersectV)) end if return intersections end LineCutsCircle on LineCutsLine(aLine1, aLine2) ---------------------------------------- -- ACTION: Finds the intersection points for two infinite lines -- -- INPUT: -- and must be property lists with one of the -- following formats: -- [#slope: , #zeroX: ] --> y = ax + b -- [#x: ] --> vertical line -- See the lineEquation() handler for details. -- -- RETURNS: point(, ) if the -- lines intersect, or #parallel if they do not. -------------------------------------------------------------------- if voidP(aLine1[#slope]) then -- aLine1 is vertical if voidP(aLine2[#slope]) then -- aLine2 is also vertical return #parallel else -- Intersection with aLine2 will occur at aLine1.x x = aLine1.x y = aLine2.slope * x + aLine2.zeroX return point(x, y) end if else if voidP(aLine2[#slope]) then -- aLine2 is vertical: Swap aLine1 and aLine2 and try again return lineIntersection(aLine2, aLine1) else -- Both lines slope slopeDifference = aLine1.slope - aLine2.slope if slopeDifference = 0 then return #parallel end if x = (aLine2.zeroX - aLine1.zeroX) / slopeDifference y = aLine1.slope * x + aLine1.zeroX return point(x, y) end if end LineCutsLine on LineEquation(aPoint1, aPoint2) -------------------------------------- -- INPUT: and should be point objects. -- ACTION: Converts a 2D line defined by two points into a formula -- corresponding to: -- y = ax + b (or in Lingo : v = slope * h + zeroX). -- -- The two points used to define the line may be considered -- to be the end points of a segment, or one of them may be -- the end point of a ray. -- OUTPUT: Returns a list with one of the following formats: -- Sloping or horizontal line -- [#slope: , -- #zeroX: , -- #x1: , -- #x2: ] -- -- Vertical line -- [#x: , -- #y1: , -- #y2: ] -- -- In the first version, #slope corresponds to "a", #zeroX -- corresponds to "b" and #x1 and #x2 correspond to the -- values for x at the ends of the line segment. -- -- The second version is a special case for a vertical line. -- #x corresponds to the constant value of x for all values -- of y. #y1 and #y2 give the y values at the ends of the -- line segment. -------------------------------------------------------------------- -- Check parameters if ilk(aPoint1) <> #point then return #invalidPoint else if ilk(aPoint2) <> #point then return #invalidPoint else if aPoint1 = aPoint2 then return #identicalPoints end if -- End of checking h1 = aPoint1.locH v1 = aPoint1.locV h2 = aPoint2.locH v2 = aPoint2.locV tDeltaH = h1 - h2 if tDeltaH = 0 then -- The line is vertical tEquation = [#x: h1] tEquation[#y1] = v1 tEquation[#y2] = v2 else tDeltaH = float(tDeltaH) -- The line is horizontal or sloping. Solve y = ax + b for a, -- at (h1, v1) and (h2, v2). -- -- v1 = a * h1 + b -- v2 = a * h2 + b -- => b = v2 - a * h2 -- => v1 = a * h1 + v2 - a * h2 -- => a(h1 - h2) = v1 - v2 a = (v1 - v2) / tDeltaH -- When x = 0, y = b -- v1 = a * h1 + b -- v2 = a * h2 + b -- => a = (v2 - b) / h2 -- => v1 = (v2 - b) * h1 / h2 + b -- => v1 * h2 = v2 * h1 - b * h1 + b * h2 -- => b(h1 - h2) = v2 * h1 - v1 * h2 b = ((h1 * v2) - (h2 * v1)) / tDeltaH tEquation = [#slope: a, #zeroX: b] tEquation[#x1] = h1 tEquation[#x2] = h2 end if return tEquation end LineEquation on SegmentIntersection(aSegment1, aSegment2, isRecursive) ------------ -- ACTION: Finds the intersection points for two line segments -- INPUT: and should be property lists with -- one of the following formats: -- Sloping or horizontal line -- [#slope: , -- #zeroX: , -- #x1: , -- #x2: ] -- -- Vertical line -- [#x: , -- #y1: , -- #y2: ] -- -- should be left void in external calls -- -- OUTPUT: Returns a list with the following format: -- [#point: point(, ), -- #distance1: , -- #distance2: ] -- -- #point is the intersection point of the two lines. -- #distance1 is the relative distance from #x1 or #y1 to -- the intersection point along aSegment1. If it is within -- the range 0.0 to 1.0, the intersection of the lines -- occurs within the segment. 0.0 indicates intersection at -- the point #x1 or #y1; 1.0 indicates intersection at the -- point #x2 of #y2. Intermediate values indicate -- intersection at some intervening point. Values outside -- the range 0.0 - 1.0 indicate that intersection occurs -- outside the segment: Values less than 0 indicate -- intersection before #x1 or #y1; values greater than 1.0 -- indicate intersection beyond #x2 or #y2. -- #distance2 is a similar value for aSegment2. -- -- If the input parameters are not valid, then an -- #invalidLineEquation error symbol will be returned. -------------------------------------------------------------------- -- Check that parameters correspond to lines if isRecursive <> TRUE then if not isASegment(aSegment1) then return #invalidLineEquation else if not isASegment(aSegment2) then return #invalidLineEquation end if end if intersection = [:] if voidP(aSegment1[#slope]) then -- aSegment1 is vertical if voidP(aSegment2[#slope]) then -- aSegment2 is also vertical return #parallel else -- Intersection with aSegment2 will occur at x x = aSegment1.x y = aSegment2.slope * x + aSegment2.zeroX intersection[#point] = point(x, y) delta = (aSegment1.y1 - y) / (aSegment1.y1 - aSegment1.y2) if isRecursive then intersection[#distance2] = delta else intersection[#distance1] = delta end if deltaH = float(x - aSegment2.x1) deltaV = y - aSegment2.slope * x + aSegment2.zeroX delta = sqrt(deltaH * deltaH + deltaV * deltaV) if (deltaH > 0) <> (deltaV > 0) then delta = -delta end if if isRecursive then intersection[#distance1] = delta else intersection[#distance2] = delta end if end if else if voidP(aSegment2[#slope]) then -- aSegment2 is vertical: Swap aSegment1 and aSegment2 and try -- again return LineIntersection(aSegment2, aSegment1, TRUE) else -- Both lines slope x = (aSegment1.zeroX - aSegment2.zeroX) / \ (aSegment2.slope - aSegment1.slope) y = aSegment1.slope * x + aSegment1.zeroX intersection[#point] = point(x, y) x1 = float(aSegment1.x1) y1 = aSegment1.slope * x1 + aSegment1.zeroX deltaH = x - x1 deltaV = y - y1 delta = sqrt(deltaH * deltaH + deltaV * deltaV) x2 = aSegment1.x2 y2 = aSegment1.slope * x2 + aSegment1.zeroX deltaH = x1 - x2 deltaV = y1 - y2 delta = delta / sqrt(deltaH * deltaH + deltaV * deltaV) if (x - x2 > 0) = (x1 - x2 > 0) then delta = -delta end if intersection[#distance1] = delta x1 = float(aSegment2.x1) y1 = aSegment2.slope * x1 + aSegment2.zeroX deltaH = x - x1 deltaV = y - y1 delta = sqrt(deltaH * deltaH + deltaV * deltaV) x2 = aSegment2.x2 y2 = aSegment2.slope * x2 + aSegment2.zeroX deltaH = x1 - x2 deltaV = y1 - y2 delta = delta / sqrt(deltaH * deltaH + deltaV * deltaV) if (x - x2 > 0) = (x1 - x2 > 0) then delta = -delta end if intersection[#distance2] = delta end if return intersection end SegmentIntersection on IsASegment(aSegment) ---------------------------------------------- -- INPUT: should be a property lists with one of -- the following formats: -- Sloping or horizontal line -- [#slope: , -- #zeroX: , -- #x1: , -- #x2: ] -- -- Vertical line -- [#x: , -- #y1: , -- #y2: ] -- OUTPUT: TRUE or FALSE -------------------------------------------------------------------- if not ilk(aSegment, #propList) then return FALSE end if tSlope = aSegment[#slope] if ilk(tSlope, #number) then -- Line is oblique or horizontal if not ilk(aSegment[#zeroX], #number) then return FALSE else if not ilk(aSegment[#x1], #number) then return FALSE else if not ilk(aSegment[#x2], #number) then return FALSE end if -- Otherwise line is vertical else if not ilk(aSegment[#x], #number) then return FALSE else if not ilk(aSegment[#y1], #number) then return FALSE else if not ilk(aSegment[#y2], #number) then return FALSE end if return TRUE end IsASegment