From 904f7a99b97bbb869613a6717993108772f3a2fa Mon Sep 17 00:00:00 2001 From: Julia Longtin Date: Tue, 31 Mar 2026 21:44:06 +0000 Subject: [PATCH] forward port to newest ImplicitCAD. --- Graphics/Slicer/Formats/STL/Definitions.hs | 4 +- Graphics/Slicer/Formats/STL/Facets.hs | 10 +- Graphics/Slicer/Machine/GCode.hs | 22 +- Graphics/Slicer/Machine/Infill.hs | 18 +- Graphics/Slicer/Machine/Support.hs | 24 +- Graphics/Slicer/Math/Contour.hs | 22 +- Graphics/Slicer/Math/Definitions.hs | 40 +- Graphics/Slicer/Math/Ganja.hs | 4 +- Graphics/Slicer/Math/Line.hs | 8 +- Graphics/Slicer/Math/PGA.hs | 6 +- Graphics/Slicer/Math/PGAPrimitives.hs | 8 +- Graphics/Slicer/Math/Point.hs | 6 +- Graphics/Slicer/Math/RandomGeometry.hs | 26 +- hslice.cabal | 10 +- programs/extcuraengine.hs | 36 +- tests/GoldenSpec/Spec.hs | 26 +- tests/Math/Geometry/CommonTests.hs | 13 +- tests/Math/Geometry/Triangle.hs | 5 +- tests/Math/PGA.hs | 1094 ++++++++++---------- 19 files changed, 716 insertions(+), 666 deletions(-) diff --git a/Graphics/Slicer/Formats/STL/Definitions.hs b/Graphics/Slicer/Formats/STL/Definitions.hs index 5613239ac..6be495848 100644 --- a/Graphics/Slicer/Formats/STL/Definitions.hs +++ b/Graphics/Slicer/Formats/STL/Definitions.hs @@ -45,6 +45,8 @@ import Graphics.Slicer.Math.Tri (Tri(Tri)) import Graphics.Slicer.Definitions (Fastℕ, fromFastℕ) +import Linear (V3(V3)) + ---------------------------------------------------------------- ----------- Functions to deal with ASCII STL reading ----------- ---------------------------------------------------------------- @@ -82,7 +84,7 @@ readVertex s = readVertex' $ words s readVertex' :: [ByteString] -> Maybe Point3 readVertex' [vertex,xs,ys,zs] | vertex == "vertex" = case (readMaybe $ unpack xs, readMaybe $ unpack ys, readMaybe $ unpack zs) of - (Just x, Just y, Just z) -> Just $ Point3 (x,y,z) + (Just x, Just y, Just z) -> Just $ Point3 $ V3 x y z (_maybex,_maybey,_maybez) -> error "error reading." readVertex' _ = Nothing diff --git a/Graphics/Slicer/Formats/STL/Facets.hs b/Graphics/Slicer/Formats/STL/Facets.hs index 30e47ab32..8ff7728f3 100644 --- a/Graphics/Slicer/Formats/STL/Facets.hs +++ b/Graphics/Slicer/Formats/STL/Facets.hs @@ -50,6 +50,8 @@ import Text.Read (readMaybe) import GHC.Base (Int(I#), Char(C#), chr#, ord#, (+#)) +import Linear (V3(V3)) + import Graphics.Slicer.Math.Definitions (Point3(Point3)) import Graphics.Slicer.Math.Facet (Facet(Facet)) @@ -110,10 +112,10 @@ readVertexOrNormal s = readVertexOrNormal' $ words s ["endloop"] -> Nothing ["outer", "loop"] -> Nothing ["facet", "normal", xs, ys, zs] -> case (readMaybe $ unpack xs, readMaybe $ unpack ys, readMaybe $ unpack zs) of - (Just xv, Just yv, Just zv) -> Just $ Right $ Point3 (xv,yv,zv) + (Just xv, Just yv, Just zv) -> Just $ Right $ Point3 $ V3 xv yv zv (_maybex, _maybey, _maybez) -> error "could not read normal point." ["vertex" ,xs,ys,zs] -> case (readMaybe $ unpack xs,readMaybe $ unpack ys,readMaybe $ unpack zs) of - (Just xv, Just yv, Just zv) -> Just $ Left $ Point3 (xv,yv,zv) + (Just xv, Just yv, Just zv) -> Just $ Left $ Point3 $ V3 xv yv zv (_maybex, _maybey, _maybez) -> error "error reading vertex point." xs -> error $ "unexpected input in STL file: " <> concatMap show xs <> "\n" @@ -131,11 +133,11 @@ writeFacet (Facet ((p1,_),(p2,_),(p3,_)) n1) = stringUtf8 "facet " <> writeNorma -- | Generate the normal for a facet. Note that the caller is assumed to have already placed "facet " on the line of text being generated. writeNormal :: Point3 -> Builder -writeNormal (Point3 (x,y,z)) = "normal " <> formatFloat x <> " " <> formatFloat y <> " " <> formatFloat z <> "\n" +writeNormal (Point3 (V3 x y z)) = "normal " <> formatFloat x <> " " <> formatFloat y <> " " <> formatFloat z <> "\n" -- | Generate a vertex of a facet. writeVertex :: Point3 -> Builder -writeVertex (Point3 (x,y,z)) = "vertex " <> formatFloat x <> " " <> formatFloat y <> " " <> formatFloat z <> "\n" +writeVertex (Point3 (V3 x y z)) = "vertex " <> formatFloat x <> " " <> formatFloat y <> " " <> formatFloat z <> "\n" -- | Generate a formatted float for placement in an STL file. -- Inspired from code in cassava, and the scientific library. diff --git a/Graphics/Slicer/Machine/GCode.hs b/Graphics/Slicer/Machine/GCode.hs index 8bd6a0f55..a7657374f 100644 --- a/Graphics/Slicer/Machine/GCode.hs +++ b/Graphics/Slicer/Machine/GCode.hs @@ -48,6 +48,8 @@ import Data.Maybe ( Maybe(Just, Nothing), fromMaybe ) import Control.DeepSeq (NFData) +import Linear (V2(V2), V3(V3)) + import Graphics.Slicer.Definitions(ℝ, ℝ2, ℝ3, ℕ, Fastℕ, fromFastℕ) import Graphics.Slicer.Math.Contour (lastPointOfContour) @@ -138,7 +140,7 @@ cookGCode printer gcodes threads = do -- | Construct a GCode to travel to a point without extruding (2D) make2DTravelGCode :: Point2 -> Point2 -> GCode -make2DTravelGCode (Point2 (x1,y1)) (Point2 (x2,y2)) = GCMove2 (x1,y1) (x2,y2) +make2DTravelGCode (Point2 (V2 x1 y1)) (Point2 (V2 x2 y2)) = GCMove2 (V2 x1 y1) (V2 x2 y2) -- | Construct a GCode to travel to a point without extruding (3D) make3DTravelGCode :: Point3 -> Point3 -> GCode @@ -146,7 +148,7 @@ make3DTravelGCode (Point3 p1) (Point3 p2) = GCMove3 p1 p2 -- | Construct a GCode to travel to a point while extruding. make2DExtrudeGCode :: ℝ -> ℝ -> Point2 -> Point2 -> GCode -make2DExtrudeGCode pathThickness pathWidth p1@(Point2 (x1,y1)) p2@(Point2 (x2,y2)) = GCRawExtrude2 (x1, y1) (x2, y2) (RawExtrude pathLength pathWidth pathThickness) +make2DExtrudeGCode pathThickness pathWidth p1@(Point2 (V2 x1 y1)) p2@(Point2 (V2 x2 y2)) = GCRawExtrude2 (V2 x1 y1) (V2 x2 y2) (RawExtrude pathLength pathWidth pathThickness) where pathLength = distance p1 p2 @@ -167,16 +169,16 @@ infixl 9 ~== -- | Render a GCode into a piece of text, ready to print. Only handles 'cooked' gcode, that has had extrusion values calculated. gcodeToText :: GCode -> ByteString -gcodeToText (GCFeedRate f (GCMove2 (x1,y1) (x2,y2))) = "G0 F" <> posIze f <> " " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") +gcodeToText (GCFeedRate f (GCMove2 (V2 x1 y1) (V2 x2 y2))) = "G0 F" <> posIze f <> " " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") -gcodeToText (GCFeedRate f (GCMove3 (x1,y1,z1) (x2,y2,z2))) = "G0 F" <> posIze f <> " " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") <> (if z1 ~== z2 then "" else "Z" <> posIze z2) -gcodeToText (GCFeedRate f (GCExtrude2 (x1,y1) (x2,y2) e)) = "G1 F" <> posIze f <> " " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") <> "E" <> posIze e +gcodeToText (GCFeedRate f (GCMove3 (V3 x1 y1 z1) (V3 x2 y2 z2))) = "G0 F" <> posIze f <> " " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") <> (if z1 ~== z2 then "" else "Z" <> posIze z2) +gcodeToText (GCFeedRate f (GCExtrude2 (V2 x1 y1) (V2 x2 y2) e)) = "G1 F" <> posIze f <> " " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") <> "E" <> posIze e -gcodeToText (GCFeedRate f (GCExtrude3 (x1,y1,z1) (x2,y2,z2) e)) = "G1 F" <> posIze f <> " " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") <> (if z1 ~== z2 then "" else "Z" <> posIze z2) <> "E" <> posIze e -gcodeToText (GCMove2 (x1,y1) (x2,y2)) = "G0 " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") -gcodeToText (GCMove3 (x1,y1,z1) (x2,y2,z2)) = "G0 " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") <> (if z1 ~== z2 then "" else "Z" <> posIze z2) -gcodeToText (GCExtrude2 (x1,y1) (x2,y2) e) = "G1 " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") <> "E" <> posIze e -gcodeToText (GCExtrude3 (x1,y1,z1) (x2,y2,z2) e) = "G1 " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") <> (if z1 ~== z2 then "" else "Z" <> posIze z2 <> " ") <> "E" <> posIze e +gcodeToText (GCFeedRate f (GCExtrude3 (V3 x1 y1 z1) (V3 x2 y2 z2) e)) = "G1 F" <> posIze f <> " " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") <> (if z1 ~== z2 then "" else "Z" <> posIze z2) <> "E" <> posIze e +gcodeToText (GCMove2 (V2 x1 y1) (V2 x2 y2)) = "G0 " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") +gcodeToText (GCMove3 (V3 x1 y1 z1) (V3 x2 y2 z2)) = "G0 " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") <> (if z1 ~== z2 then "" else "Z" <> posIze z2) +gcodeToText (GCExtrude2 (V2 x1 y1) (V2 x2 y2) e) = "G1 " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") <> "E" <> posIze e +gcodeToText (GCExtrude3 (V3 x1 y1 z1) (V3 x2 y2 z2) e) = "G1 " <> (if x1 ~== x2 then "" else "X" <> posIze x2 <> " ") <> (if y1 ~== y2 then "" else "Y" <> posIze y2 <> " ") <> (if z1 ~== z2 then "" else "Z" <> posIze z2 <> " ") <> "E" <> posIze e gcodeToText (GCFeedRate f wtf) = error $ "applying feedrate " <> show (posIze f) <> " to something other than a GCmove(2,3) or a GCExtrude(2,3): " <> show wtf gcodeToText (GCRawFeedRate a b) = error $ "Attempting to generate gcode for a feedrate change command that has not yet been cooked:\nRate: " <> show a <> "\nGCode: " <> show b <> "\n" gcodeToText (GCRawExtrude2 a b c) = error $ "Attempting to generate gcode for a 2D extrude command that has not yet been cooked:\nStart: " <> show a <> "\nStop: " <> show b <> "\nExtrude: " <> show c <> "\n" diff --git a/Graphics/Slicer/Machine/Infill.hs b/Graphics/Slicer/Machine/Infill.hs index 1324fc763..5f4b7223b 100644 --- a/Graphics/Slicer/Machine/Infill.hs +++ b/Graphics/Slicer/Machine/Infill.hs @@ -37,6 +37,8 @@ import Data.List.Ordered (sort) import Data.Maybe (Maybe(Just, Nothing), mapMaybe, fromMaybe) +import Linear (V2(V2)) + import Graphics.Slicer.Definitions (ℝ) import Graphics.Slicer.Math.Definitions (Point2(Point2), Contour, LineSeg, addPoints, distance, lineSegsOfContour, minMaxPoints, xOf, yOf, roundToFifth) @@ -111,8 +113,8 @@ coveringPLinesPositive contour ls = makeLine <$> [0,lss..(xMax-xMinRaw)+(yMax-yM where makeLine a = join2EP (f a) $ addPoints (f a) slope (minPoint, maxPoint) = minMaxPoints contour - slope = Point2 (1,1) - f v = Point2 (v-xDiff,0) + slope = Point2 $ V2 1 1 + f v = Point2 $ V2 (v-xDiff) 0 xDiff = -(xMin - yMax) yMin = yOf minPoint yMax = yOf maxPoint @@ -131,8 +133,8 @@ coveringPLinesNegative contour ls = makeLine <$> [0,lss..(xMax-xMin)+(yMax-yMin) where makeLine a = join2EP (f a) $ addPoints (f a) slope (minPoint, maxPoint) = minMaxPoints contour - slope = Point2 (1,-1) - f v = Point2 (v+yDiff,0) + slope = Point2 $ V2 1 (-1) + f v = Point2 $ V2 (v+yDiff) 0 yDiff = xMin + yMin yMinRaw = yOf minPoint yMin = case yMinRaw `compare` 0 of @@ -151,8 +153,8 @@ coveringPLinesVertical contour ls = makeLine <$> [xMin,xMin+ls..xMax] where makeLine a = join2EP (f a) $ addPoints (f a) slope (minPoint, maxPoint) = minMaxPoints contour - slope = Point2 (0,1) - f v = Point2 (v,0) + slope = Point2 $ V2 0 1 + f v = Point2 $ V2 v 0 xMinRaw = xOf minPoint xMin = case xMinRaw `compare` 0 of GT -> ls * fromIntegral (ceiling (xMinRaw / ls) :: Integer) @@ -166,8 +168,8 @@ coveringPLinesHorizontal contour ls = makeLine <$> [yMin,yMin+ls..yMax] where makeLine a = join2EP (f a) $ addPoints (f a) slope (minPoint, maxPoint) = minMaxPoints contour - slope = Point2 (1,0) - f v = Point2 (0,v) + slope = Point2 $ V2 1 0 + f v = Point2 $ V2 0 v yMinRaw = yOf minPoint yMin = case yMinRaw `compare` 0 of GT -> ls * fromIntegral (ceiling (yMinRaw / ls) :: Integer) diff --git a/Graphics/Slicer/Machine/Support.hs b/Graphics/Slicer/Machine/Support.hs index 8f7e31289..b992ac252 100644 --- a/Graphics/Slicer/Machine/Support.hs +++ b/Graphics/Slicer/Machine/Support.hs @@ -31,6 +31,8 @@ import Data.List (concat) import Data.Maybe(mapMaybe) +import Linear (V2(V2)) + import Graphics.Slicer.Definitions (ℝ,ℝ2) import Graphics.Slicer.Math.Contour (makePointContour) @@ -45,7 +47,7 @@ shortenLineBy amt (LineSeg p m) = LineSeg newStart newSlope where pct = amt / magnitude m newStart = addPoints p $ scalePoint pct m newSlope = scalePoint (1 - 2 * pct) m - magnitude (Point2 (x1,y1)) = sqrt (x1 * x1 + y1 * y1) + magnitude (Point2 (V2 x1 y1)) = sqrt (x1 * x1 + y1 * y1) -- Generate support -- FIXME: hard coded infill amount. @@ -66,17 +68,17 @@ data BBox = BBox !ℝ2 !ℝ2 -- | Check if a bounding box is empty. isEmptyBBox :: BBox -> Bool -isEmptyBBox (BBox (x1,y1) (x2,y2)) = x1 == x2 || y1 == y2 +isEmptyBBox (BBox (V2 x1 y1) (V2 x2 y2)) = x1 == x2 || y1 == y2 -- Get a bounding box of all contours. boundingBoxAll :: [Contour] -> BBox boundingBoxAll contours = if isEmptyBBox box then error "empty box with a contour" else box where - box = BBox (minX, minY) (maxX, maxY) - minX = minimum $ (\(BBox (x1,_) _) -> x1) <$> bBoxes - minY = minimum $ (\(BBox (_,y1) _) -> y1) <$> bBoxes - maxX = maximum $ (\(BBox _ (x2,_)) -> x2) <$> bBoxes - maxY = maximum $ (\(BBox _ (_,y2)) -> y2) <$> bBoxes + box = BBox (V2 minX minY) (V2 maxX maxY) + minX = minimum $ (\(BBox (V2 x1 _) _) -> x1) <$> bBoxes + minY = minimum $ (\(BBox (V2 _ y1) _) -> y1) <$> bBoxes + maxX = maximum $ (\(BBox _ (V2 x2 _)) -> x2) <$> bBoxes + maxY = maximum $ (\(BBox _ (V2 _ y2)) -> y2) <$> bBoxes bBoxes = boundingBox <$> contours -- Get a bounding box of a contour. @@ -84,7 +86,7 @@ boundingBox :: Contour -> BBox boundingBox contour = if isEmptyBBox box then error "empty box with a contour" else box where (minPoint, maxPoint) = minMaxPoints contour - box = BBox (minX, minY) (maxX, maxY) + box = BBox (V2 minX minY) (V2 maxX maxY) minX = xOf minPoint minY = yOf minPoint maxX = xOf maxPoint @@ -93,9 +95,9 @@ boundingBox contour = if isEmptyBBox box then error "empty box with a contour" e -- add a bounding box to a list of contours, as the first contour in the list. -- FIXME: what is this for? addBBox :: [Contour] -> [Contour] -addBBox contours = makePointContour [Point2 (x1,y1),Point2 (x2,y1),Point2 (x2,y2),Point2 (x1,y2), Point2 (x1,y1)] : contours +addBBox contours = makePointContour [Point2 (V2 x1 y1),Point2 (V2 x2 y1),Point2 (V2 x2 y2),Point2 (V2 x1 y2), Point2 (V2 x1 y1)] : contours where bbox = boundingBoxAll contours - (BBox (x1, y1) (x2, y2)) = incBBox bbox 1 + (BBox (V2 x1 y1) (V2 x2 y2)) = incBBox bbox 1 -- Put a fixed amount around the 2d bounding box. - incBBox (BBox (nx1,ny1) (nx2,ny2)) amount = BBox (nx1+amount, ny1+amount) (nx2-amount, ny2-amount) + incBBox (BBox (V2 nx1 ny1) (V2 nx2 ny2)) amount = BBox (V2 (nx1+amount) (ny1+amount)) (V2 (nx2-amount) (ny2-amount)) diff --git a/Graphics/Slicer/Math/Contour.hs b/Graphics/Slicer/Math/Contour.hs index f0bee83a2..e514c0bde 100644 --- a/Graphics/Slicer/Math/Contour.hs +++ b/Graphics/Slicer/Math/Contour.hs @@ -53,6 +53,8 @@ import Data.Maybe (Maybe(Just,Nothing), catMaybes, fromJust, fromMaybe, isJust, import Data.MemoTrie (memo) +import Linear (V2(V2)) + import Slist (len, slist, safeLast, safeLast, safeHead) import Slist as SL (last) @@ -314,8 +316,8 @@ mostPerpPointAndLineSeg contour = (resPoint, resSeg) lineSegsAndAnglesNeg = [(lineSeg, outsideNegPoint, abs $ fst $ angleBetween2PL (fst $ join2EP outsideNegPoint $ midPoint lineSeg) (eToPLine2 lineSeg)) | lineSeg <- lineSegsOfContour myContour] midPoint lineSeg = pointBetweenPoints (startPoint lineSeg) (endPoint lineSeg) outsideMidPoint = pointBetweenPoints outsidePosPoint outsideNegPoint - outsidePosPoint = Point2 (xOf minPoint - 0.1 , yOf maxPoint + 0.1) - outsideNegPoint = Point2 (xOf minPoint - 0.1 , yOf minPoint - 0.1) + outsidePosPoint = Point2 $ V2 (xOf minPoint - 0.1) (yOf maxPoint + 0.1) + outsideNegPoint = Point2 $ V2 (xOf minPoint - 0.1) (yOf minPoint - 0.1) (minPoint, maxPoint) = minMaxPoints contour -- | Find a point that is guaranteed to be outside of the given contour, and is not on the same line as the first line segment of the contour. @@ -328,7 +330,7 @@ pointFarOutsideContours contour1 contour2 where (minPoint1, _)= minMaxPoints contour1 (minPoint2, _)= minMaxPoints contour2 - minPoint = Point2 (min (xOf minPoint1) (xOf minPoint2),min (yOf minPoint1) (yOf minPoint2)) + minPoint = Point2 $ V2 (min (xOf minPoint1) (xOf minPoint2)) (min (yOf minPoint1) (yOf minPoint2)) (p1, p2) = firstPointPairOfContour contour1 (p3, p4) = firstPointPairOfContour contour2 firstLine = join2EP p1 p2 @@ -336,9 +338,9 @@ pointFarOutsideContours contour1 contour2 line1 = join2EP p1 outsidePoint1 line2 = join2EP p1 outsidePoint2 line3 = join2EP p1 outsidePoint3 - outsidePoint1 = Point2 (xOf minPoint - 0.1 , yOf minPoint - 0.1) - outsidePoint2 = Point2 (xOf minPoint - 0.2 , yOf minPoint - 0.1) - outsidePoint3 = Point2 (xOf minPoint - 0.1 , yOf minPoint - 0.2) + outsidePoint1 = Point2 $ V2 (xOf minPoint - 0.1) (yOf minPoint - 0.1) + outsidePoint2 = Point2 $ V2 (xOf minPoint - 0.2) (yOf minPoint - 0.1) + outsidePoint3 = Point2 $ V2 (xOf minPoint - 0.1) (yOf minPoint - 0.2) -- | return the number of points in a contour. numPointsOfContour :: Contour -> Int @@ -383,8 +385,8 @@ makePointContour points = case points of [p1,p2] -> error $ "tried to create a contour with only two points:\n" <> show p1 <> "\n" <> show p2 <> "\n" (p1:p2:p3:pts) -> PointContour pL pH p1 p2 p3 (slist pts) where - pL = Point2 (minimum $ xOf <$> points, minimum $ yOf <$> points) - pH = Point2 (maximum $ xOf <$> points, maximum $ yOf <$> points) + pL = Point2 $ V2 (minimum $ xOf <$> points) (minimum $ yOf <$> points) + pH = Point2 $ V2 (maximum $ xOf <$> points) (maximum $ yOf <$> points) makeLineSegContour :: [LineSeg] -> Contour makeLineSegContour lineSegs = case lineSegs of @@ -395,8 +397,8 @@ makeLineSegContour lineSegs = case lineSegs of else LineSegContour pL pH l1 l2 (slist []) (l1:l2:lns) -> LineSegContour pL pH l1 l2 (slist lns) where - pL = Point2 (minimum $ xOf <$> allPoints, minimum $ yOf <$> allPoints) - pH = Point2 (maximum $ xOf <$> allPoints, maximum $ yOf <$> allPoints) + pL = Point2 $ V2 (minimum $ xOf <$> allPoints) (minimum $ yOf <$> allPoints) + pH = Point2 $ V2 (maximum $ xOf <$> allPoints) (maximum $ yOf <$> allPoints) allPoints = case lineSegs of [] -> error "tried to create an empty contour" (x:xs) -> startPoint x:endPoint x:(endPoint <$> xs) diff --git a/Graphics/Slicer/Math/Definitions.hs b/Graphics/Slicer/Math/Definitions.hs index 8436855e4..4e456dfa9 100644 --- a/Graphics/Slicer/Math/Definitions.hs +++ b/Graphics/Slicer/Math/Definitions.hs @@ -71,6 +71,8 @@ import Data.MemoTrie (HasTrie(enumerate, trie, untrie), Reg, (:->:), enumerateGe import GHC.Generics (Generic) +import Linear (V3(V3), V2(V2)) + import Slist.Type (Slist(Slist), size) import Slist.Size (Size(Infinity)) @@ -108,10 +110,10 @@ class LinAlg p where instance LinAlg Point3 where distance p1 p2 = magnitude $ addPoints p1 (negatePoint p2) where - magnitude (Point3 (x1,y1,z1)) = sqrt (x1 * x1 + y1 * y1 + z1 * z1) - addPoints (Point3 (x1,y1,z1)) (Point3 (x2,y2,z2)) = Point3 (x1+x2 ,y1+y2 ,z1+z2) - scalePoint val (Point3 (a,b,c)) = Point3 (val*a ,val*b ,val*c) - negatePoint (Point3 (a,b,c)) = Point3 (negate a, negate b, negate c) + magnitude (Point3 (V3 x1 y1 z1)) = sqrt (x1 * x1 + y1 * y1 + z1 * z1) + addPoints (Point3 (V3 x1 y1 z1)) (Point3 (V3 x2 y2 z2)) = Point3 $ V3 (x1+x2) (y1+y2) (z1+z2) + scalePoint val (Point3 (V3 a b c)) = Point3 $ V3 (val*a) (val*b) (val*c) + negatePoint (Point3 (V3 a b c)) = Point3 $ V3 (negate a) (negate b) (negate c) (~=) p1 p2 = roundPoint3 p1 == roundPoint3 p2 -- | perform linear algebra on 2D points. @@ -120,10 +122,10 @@ instance LinAlg Point2 where | p1 == p2 = 0 | otherwise = magnitude $ addPoints p1 (negatePoint p2) where - magnitude (Point2 (x1,y1)) = sqrt (x1 * x1 + y1 * y1) - addPoints (Point2 (x1,y1)) (Point2 (x2,y2)) = Point2 (x1+x2, y1+y2) - scalePoint val (Point2 (a,b)) = Point2 (val*a ,val*b) - negatePoint (Point2 (a,b)) = Point2 (negate a, negate b) + magnitude (Point2 (V2 x1 y1)) = sqrt (x1 * x1 + y1 * y1) + addPoints (Point2 (V2 x1 y1)) (Point2 (V2 x2 y2)) = Point2 $ V2 (x1+x2) (y1+y2) + scalePoint val (Point2 (V2 a b)) = Point2 $ V2 (val*a) (val*b) + negatePoint (Point2 (V2 a b)) = Point2 $ V2 (negate a) (negate b) (~=) p1 p2 = roundPoint2 p1 == roundPoint2 p2 -- | functions for working on points as if they are in a 2D plane. @@ -139,6 +141,12 @@ instance HasTrie Point2 where untrie = untrieGeneric unPoint2Trie enumerate = enumerateGeneric unPoint2Trie +instance HasTrie (V2 ℝ) where + newtype ((V2 ℝ):->: b) = V2Trie { unV2Trie :: Reg (V2 ℝ) :->: b } + trie = trieGeneric V2Trie + untrie = untrieGeneric unV2Trie + enumerate = enumerateGeneric unV2Trie + instance Ord Point2 where -- Orders points by x and y (x first, then sorted by y for the same x-values) compare p1 p2 @@ -150,13 +158,13 @@ instance Ord Point2 where -- | functions for getting a point's position on a 2D plane. If the point is 3d, assume the plane is aligned with the xy basis axes. instance PlanePoint Point3 where - xOf (Point3 (x,_,_)) = x - yOf (Point3 (_,y,_)) = y + xOf (Point3 (V3 x _ _)) = x + yOf (Point3 (V3 _ y _)) = y instance PlanePoint Point2 where - xOf (Point2 (x,_)) = x + xOf (Point2 (V2 x _)) = x {-# INLINABLE xOf #-} - yOf (Point2 (_,y)) = y + yOf (Point2 (V2 _ y)) = y {-# INLINABLE yOf #-} -- | functions for working on points in 3D space. @@ -167,8 +175,8 @@ class SpacePoint p where flatten :: p -> Point2 instance SpacePoint Point3 where - zOf (Point3 (_,_,z)) = z - flatten (Point3 (x,y,_)) = Point2 (x,y) + zOf (Point3 (V3 _ _ z)) = z + flatten (Point3 (V3 x y _)) = Point2 $ V2 x y -- | A euclidian line segment, starting at startPoint and stopping at endPoint. data LineSeg = LineSeg { startPoint :: !Point2, endPoint :: !Point2 } @@ -208,11 +216,11 @@ roundToFifth a = fromIntegral (round (100000 * a) :: Fastℕ) / 100000 -- | round a point (3d) roundPoint3 :: Point3 -> Point3 -roundPoint3 (Point3 (x1,y1,z1)) = Point3 (roundToFifth x1, roundToFifth y1, roundToFifth z1) +roundPoint3 (Point3 (V3 x1 y1 z1)) = Point3 $ V3 (roundToFifth x1) (roundToFifth y1) (roundToFifth z1) -- | round a point (2d) roundPoint2 :: Point2 -> Point2 -roundPoint2 (Point2 (x1,y1)) = Point2 (roundToFifth x1, roundToFifth y1) +roundPoint2 (Point2 (V2 x1 y1)) = Point2 $ V2 (roundToFifth x1) (roundToFifth y1) -- | like map, only with previous, current, and next item, and wrapping around so the first entry gets the last entry as previous, and vica versa. {-# INLINABLE mapWithNeighbors #-} diff --git a/Graphics/Slicer/Math/Ganja.hs b/Graphics/Slicer/Math/Ganja.hs index c6f711856..777e39054 100644 --- a/Graphics/Slicer/Math/Ganja.hs +++ b/Graphics/Slicer/Math/Ganja.hs @@ -90,6 +90,8 @@ import Data.List (concatMap) import Data.Maybe (Maybe(Nothing), catMaybes, fromJust, isJust) +import Linear (V2(V2)) + import Numeric (showFFloat) import Slist (isEmpty, last) @@ -114,7 +116,7 @@ instance GanjaAble String where toGanja string varname = (" // " <> varname <> " -- " <> string <> "\n","") instance GanjaAble Point2 where - toGanja (Point2 (x,y)) varname = ( + toGanja (Point2 (V2 x y)) varname = ( " var " <> varname <> " = point(" <> showFullPrecision x <> "," <> showFullPrecision y <> ");\n", " " <> varname <> ", " <> show varname <> ",\n") where diff --git a/Graphics/Slicer/Math/Line.hs b/Graphics/Slicer/Math/Line.hs index 22563b69f..59ccc4cf8 100644 --- a/Graphics/Slicer/Math/Line.hs +++ b/Graphics/Slicer/Math/Line.hs @@ -24,6 +24,8 @@ import Prelude ((/), (<), ($), (-), otherwise, (&&), (<=), (==), error, zipWith, import Data.Maybe (Maybe(Just, Nothing)) +import Linear (V3(V3)) + import Graphics.Slicer.Definitions (ℝ) import Graphics.Slicer.Math.Definitions (Point3(Point3), LineSeg(LineSeg), Point2, addPoints, scalePoint, zOf, flatten, makeLineSeg) @@ -56,7 +58,7 @@ pointAtZValue (startPoint,stopPoint) v | otherwise = Nothing where t = (v - zOf lineSegStart) / zOf lineEnd - lineEnd = (\ (Point3 (x1,y1,z1)) (Point3 (x2,y2,z2)) -> Point3 (x2-x1, y2-y1, z2-z1)) lineSegStart lineSegEnd + lineEnd = (\ (Point3 (V3 x1 y1 z1)) (Point3 (V3 x2 y2 z2)) -> Point3 (V3 (x2-x1) (y2-y1) (z2-z1))) lineSegStart lineSegEnd (lineSegStart,lineSegEnd) = if zOf startPoint < zOf stopPoint - then (startPoint,stopPoint) - else (stopPoint,startPoint) + then (startPoint, stopPoint) + else (stopPoint, startPoint) diff --git a/Graphics/Slicer/Math/PGA.hs b/Graphics/Slicer/Math/PGA.hs index 515e77226..53a65d91f 100644 --- a/Graphics/Slicer/Math/PGA.hs +++ b/Graphics/Slicer/Math/PGA.hs @@ -98,6 +98,8 @@ import Data.Maybe (Maybe(Just, Nothing), fromJust, fromMaybe, isJust, isNothing) import Data.Set (singleton, fromList) +import Linear (V2(V2)) + import Numeric.Rounded.Hardware (Rounded, RoundingMode(TowardInf, TowardNegInf)) import Graphics.Slicer.Definitions (ℝ) @@ -274,7 +276,7 @@ translateRotatePPoint2WithErr point d rotation = (res, resErr) -- A line along the X axis, crossing the provided point. (xLineThroughPPoint2, (nYLineErr, cPointErr, xLineErr)) = perpLineAt yLine point -- A line along the Y axis, crossing the origin. - (yLine, yLineErr) = eToPL $ makeLineSeg (Point2 (0,0)) (Point2 (0,1)) + (yLine, yLineErr) = eToPL $ makeLineSeg (Point2 (V2 0 0)) (Point2 (V2 0 1)) -- Our rotation motor, which rotates the provided angle around the provided point, in the clockwise direction. rotator = addVecPairWithoutErr scaledPVec (GVec [GVal (cos $ rotation/2) (singleton G0)]) (scaledPVec, scaledPVecErr) = mulScalarVecWithErr (sin $ rotation/2) pVec @@ -502,7 +504,7 @@ combineConsecutiveLineSegs lines = case lines of -- | Create a canonical euclidian projective point from the given euclidian point. euclidianToProjectivePoint2, eToPP :: Point2 -> ProjectivePoint -euclidianToProjectivePoint2 (Point2 (x,y)) = res +euclidianToProjectivePoint2 (Point2 (V2 x y)) = res where res = makeCPPoint2 x y eToPP = euclidianToProjectivePoint2 diff --git a/Graphics/Slicer/Math/PGAPrimitives.hs b/Graphics/Slicer/Math/PGAPrimitives.hs index fce503d49..30e0054d8 100644 --- a/Graphics/Slicer/Math/PGAPrimitives.hs +++ b/Graphics/Slicer/Math/PGAPrimitives.hs @@ -92,6 +92,8 @@ import Graphics.Slicer.Math.Definitions (Point2(Point2)) import Graphics.Slicer.Math.GeometricAlgebra (ErrVal(ErrVal), GNum(G0, GEPlus, GEZero), GVal(GVal), GVec(GVec), UlpSum(UlpSum), (⎣+), (⎤+), (∧+), (•), addErr, addValWithoutErr, addVecPairWithErr, addVecPairWithoutErr, divVecScalarWithErr, eValOf, getVal, mulScalarVecWithErr, scalarPart, sumErrVals, ulpRaw, valOf) +import Linear (V2(V2)) + -------------------------------- --- common support functions --- -------------------------------- @@ -485,7 +487,7 @@ pLineErrAtPPoint (line, lineErr) errPoint xInterceptDistance = fromRight 0 $ fst $ fromJust $ xIntercept (nPLine, nPLineErr) yInterceptDistance = fromRight 0 $ fst $ fromJust $ yIntercept (nPLine, nPLineErr) -- FIXME: collect this error, and take it into account. - (Point2 (xPos,yPos),_) = pToEP errPoint + (Point2 (V2 xPos yPos),_) = pToEP errPoint nPLineErr = nPLineErrRaw <> lineErr (nPLine, nPLineErrRaw) = normalizeL line @@ -787,7 +789,7 @@ idealNormOfProjectivePoint point (x,y) | e12Val == 0 = ( negate $ valOf 0 $ getVal [GEZero 1, GEPlus 2] rawVals , valOf 0 $ getVal [GEZero 1, GEPlus 1] rawVals) - | otherwise = (\(Point2 (x1,y1),_) -> (x1,y1)) $ pToEP point + | otherwise = (\(Point2 (V2 x1 y1),_) -> (x1,y1)) $ pToEP point e12Val = valOf 0 (getVal [GEPlus 1, GEPlus 2] rawVals) (GVec rawVals) = vecOfP point -- | Wrapper. @@ -856,7 +858,7 @@ projectivePointToEuclidianPoint point | projectivePointIsIdeal point = error "Attempted to create an infinite point when trying to convert from a Projective Point to a Euclidian Point." | otherwise = (res, resErr) where - res = Point2 (xVal, yVal) + res = Point2 $ V2 xVal yVal xVal = negate $ valOf 0 $ getVal [GEZero 1, GEPlus 2] vals yVal = valOf 0 $ getVal [GEZero 1, GEPlus 1] vals (GVec vals) = vecOfP pointRes diff --git a/Graphics/Slicer/Math/Point.hs b/Graphics/Slicer/Math/Point.hs index 84568987d..0d85b9c55 100644 --- a/Graphics/Slicer/Math/Point.hs +++ b/Graphics/Slicer/Math/Point.hs @@ -27,13 +27,15 @@ import Graphics.Slicer.Math.Definitions (Point3(Point3), Point2(Point2), zOf) import Graphics.Slicer.Definitions (ℝ) +import Linear(V3(V3), V2(V2)) + -- Basic Arithmatic crossProduct :: Point3 -> Point3 -> Point3 -crossProduct (Point3 (x1,y1,z1)) (Point3 (x2,y2,z2)) = Point3 (y1*z2 - z1*y2 , z1*x2 - x1*z2, x1*y2 - y1*x2) +crossProduct (Point3 (V3 x1 y1 z1)) (Point3 (V3 x2 y2 z2)) = Point3 $ V3 (y1*z2 - z1*y2) (z1*x2 - x1*z2) (x1*y2 - y1*x2) twoDCrossProduct :: Point2 -> Point2 -> ℝ twoDCrossProduct p1 p2 = zOf $ crossProduct (zeroPoint p1) (zeroPoint p2) where zeroPoint :: Point2 -> Point3 - zeroPoint (Point2 (x,y)) = Point3 (x,y,0) + zeroPoint (Point2 (V2 x y)) = Point3 $ V3 x y 0 diff --git a/Graphics/Slicer/Math/RandomGeometry.hs b/Graphics/Slicer/Math/RandomGeometry.hs index 9117dea76..0f6199d62 100644 --- a/Graphics/Slicer/Math/RandomGeometry.hs +++ b/Graphics/Slicer/Math/RandomGeometry.hs @@ -71,6 +71,8 @@ import Data.List.Unique (allUnique) import Data.Maybe (Maybe(Nothing, Just), fromJust, fromMaybe, isJust) +import Linear (V2(V2)) + import Math.Tau (tau) import Numeric (pi) @@ -193,7 +195,7 @@ randomTriangle centerX centerY rawRadians rawDists = randomStarPoly centerX cent a3 = (ad+0.2, if aa == 0 then 0.2 else aa/3) pointAroundCenter :: (Positive ℝ, Radian ℝ) -> ProjectivePoint pointAroundCenter (distanceFromPoint, angle) = translateRotatePPoint2 centerPPoint (coerce distanceFromPoint) (coerce angle) - centerPPoint = eToPP $ Point2 (centerX, centerY) + centerPPoint = eToPP $ Point2 $ V2 centerX centerY _ -> error "too many points." radians :: [Radian ℝ] radians = ensureUnique $ coerce rawRadians @@ -335,10 +337,10 @@ randomStarPoly centerX centerY radianDistPairs = fromMaybe dumpError $ maybeFlip contour = makePointContour points points = pToEPoint2 <$> pointsAroundCenter pointsAroundCenter = (\(distanceFromPoint, angle) -> translateRotatePPoint2 centerPPoint (coerce distanceFromPoint) (coerce angle)) <$> radianDistPairs - centerPPoint = eToPP $ Point2 (centerX, centerY) + centerPPoint = eToPP $ Point2 $ V2 centerX centerY dumpError = error $ "failed to flip a contour.\n" <> dumpGanjas ( [toGanja contour, - toGanja "Center point", toGanja (Point2 (centerX, centerY)), + toGanja "Center point", toGanja (Point2 $ V2 centerX centerY), toGanja "perp PLine", toGanja perpPl, toGanja "Other PLine", toGanja otherPl, toGanja "First MidPoint", toGanja midPoint, @@ -369,7 +371,7 @@ randomENode x y d1 rawR1 d2 rawR2 = makeENode p1 intersectionPoint p2 where r1 = rawR1 / 2 r2 = r1 + (rawR2 / 2) - intersectionPoint = Point2 (x,y) + intersectionPoint = Point2 $ V2 x y pp1 = translateRotatePPoint2 intersectionPPoint (coerce d1) (coerce r1) pp2 = translateRotatePPoint2 intersectionPPoint (coerce d2) (coerce r2) p1 = pToEPoint2 pp1 @@ -399,25 +401,25 @@ randomPLine x y dx dy = fst $ randomPLineWithErr x y dx dy -- | A helper function. constructs a random PLine. randomPLineWithErr :: ℝ -> ℝ -> NonZero ℝ -> NonZero ℝ -> (ProjectiveLine, PLine2Err) -randomPLineWithErr x y dx dy = eToPL $ makeLineSeg (Point2 (x, y)) (Point2 (x + coerce dx, y + coerce dy)) +randomPLineWithErr x y dx dy = eToPL $ makeLineSeg (Point2 (V2 x y)) (Point2 (V2 (x + coerce dx) (y + coerce dy))) -- | A helper function. constructs a random LineSeg. randomLineSeg :: ℝ -> ℝ -> ℝ -> ℝ -> LineSeg -randomLineSeg x y dx dy = makeLineSeg (Point2 (x,y)) (Point2 (dx, dy)) +randomLineSeg x y dx dy = makeLineSeg (Point2 (V2 x y)) (Point2 (V2 dx dy)) -- | A PLine that does not follow the X = Y line, and does not follow the other given line. randomPLineThroughOrigin :: ℝ -> ℝ -> (ProjectiveLine, PLine2Err) -randomPLineThroughOrigin x y = eToPL $ makeLineSeg (Point2 (x,y)) (Point2 (0,0)) +randomPLineThroughOrigin x y = eToPL $ makeLineSeg (Point2 (V2 x y)) (Point2 (V2 0 0)) -- | A PLine that does not follow the X = Y line, and does not follow the other given line. randomPLineThroughPoint :: ℝ -> ℝ -> ℝ -> (ProjectiveLine, PLine2Err) -randomPLineThroughPoint x y d = eToPL $ makeLineSeg (Point2 (x,y)) (Point2 (d,d)) +randomPLineThroughPoint x y d = eToPL $ makeLineSeg (Point2 (V2 x y)) (Point2 (V2 d d)) -- | A line segment ending at the origin. additionally, guaranteed not to be on the X = Y line. randomLineSegFromPointNotX1Y1 :: ℝ -> ℝ -> ℝ -> LineSeg randomLineSegFromPointNotX1Y1 rawX rawY d = res where - res = makeLineSeg (Point2 (d, d)) (Point2 (x, y)) + res = makeLineSeg (Point2 (V2 d d)) (Point2 (V2 x y)) (x, y) | rawX == 0 && rawY == 0 = (0,0.1) | rawX == rawY = (rawX,0.1) @@ -427,7 +429,7 @@ randomLineSegFromPointNotX1Y1 rawX rawY d = res randomLineSegFromOriginNotX1Y1 :: ℝ -> ℝ -> LineSeg randomLineSegFromOriginNotX1Y1 rawX rawY = res where - res = makeLineSeg (Point2 (0, 0)) (Point2 (x, y)) + res = makeLineSeg (Point2 (V2 0 0)) (Point2 (V2 x y)) (x, y) | rawX == 0 && rawY == 0 = (0,0.1) | rawX == rawY = (rawX,0.1) @@ -436,14 +438,14 @@ randomLineSegFromOriginNotX1Y1 rawX rawY = res randomX1Y1LineSegToOrigin :: NonZero ℝ -> LineSeg randomX1Y1LineSegToOrigin rawD = res where - res = makeLineSeg (Point2 (d,d)) (Point2 (0,0)) + res = makeLineSeg (Point2 (V2 d d)) (Point2 (V2 0 0)) d :: ℝ d = coerce rawD randomX1Y1LineSegToPoint :: NonZero ℝ -> ℝ -> LineSeg randomX1Y1LineSegToPoint rawD1 d2 = res where - res = makeLineSeg (Point2 (d1,d1)) (Point2 (d2,d2)) + res = makeLineSeg (Point2 (V2 d1 d1)) (Point2 (V2 d2 d2)) d1 :: ℝ d1 = coerce rawD1 diff --git a/hslice.cabal b/hslice.cabal index 284580bfb..6dea8ab41 100644 --- a/hslice.cabal +++ b/hslice.cabal @@ -5,7 +5,7 @@ license: AGPL-3.0-or-later license-file: LICENSE maintainer: Julia Longtin author: Julia Longtin -tested-with: GHC == 8.8.4, GHC == 8.10.4, GHC == 9.4.6 +tested-with: GHC == 9.6.6, GHC == 9.10.1 homepage: https://implicitcad.org/ synopsis: A GCode generator, that accepts STL files. description: A slicer in Haskell. Use it to slice 3D prints. @@ -80,7 +80,8 @@ library double-conversion -any, extra -any, floating-bits >0.3.0.0, - implicit >0.2.0.0 && <0.4.0.0, + implicit >0.4.0.0, + linear -any, MemoTrie -any, mtl -any, numbers -any, @@ -111,7 +112,9 @@ executable extcuraengine extra -any, hslice -any, implicit -any, + linear -any, mtl -any, + text -any, optparse-applicative -any, parallel -any, slist >=0.2.0.0, @@ -175,6 +178,7 @@ test-suite test-hslice directory -any, hspec -any, hslice -any, + linear -any, QuickCheck -any, quickcheck-io -any, rounded-hw -any, @@ -215,6 +219,7 @@ test-suite test-broken directory -any, hspec -any, hslice -any, + linear -any, QuickCheck -any, quickcheck-io -any, rounded-hw -any, @@ -254,6 +259,7 @@ test-suite test-stat directory -any, hspec -any, hslice -any, + linear -any, QuickCheck -any, quickcheck-io -any, rounded-hw -any, diff --git a/programs/extcuraengine.hs b/programs/extcuraengine.hs index 158b2ebf6..4ce1ccea0 100644 --- a/programs/extcuraengine.hs +++ b/programs/extcuraengine.hs @@ -39,7 +39,7 @@ import Control.Monad ((>>=)) import Data.Bool(Bool(True, False), otherwise) -import Data.ByteString.UTF8 (fromString) +import Data.Text.Lazy.Encoding (encodeUtf8) import Data.Eq ((==), (/=)) @@ -51,7 +51,9 @@ import Data.List.Extra (unsnoc) import Data.Maybe (Maybe(Just, Nothing), catMaybes, fromMaybe, mapMaybe) -import Data.String (String) +import Data.String (String, fromString) + +import Linear (V2(V2), V3(V3)) import Slist.Type (Slist(Slist)) @@ -59,7 +61,7 @@ import System.IO (IO) import Text.Show(show) -import Data.ByteString (readFile, writeFile, ByteString) +import Data.ByteString (readFile, writeFile, toStrict, ByteString) import Data.ByteString.Char8 (unlines) @@ -125,7 +127,7 @@ https://cadquery.readthedocs.io/en/latest/apireference.html#selectors --------------------------------------------------------------------------- centeredTrisFromSTLNonTotal :: BuildArea -> ByteString -> [Tri] -centeredTrisFromSTLNonTotal (RectArea (bedX,bedY,_)) stl = centeredTrisFromSTL bedX bedY stl +centeredTrisFromSTLNonTotal (RectArea (V3 bedX bedY _)) stl = centeredTrisFromSTL bedX bedY stl centeredTrisFromSTLNonTotal _ _ = error "centeredTrisFromSTLNonTotal: bad arguments." -- Center triangles relative to the center of the build area. @@ -133,7 +135,7 @@ centeredTrisFromSTLNonTotal _ _ = error "centeredTrisFromSTLNonTotal: bad argume centeredTrisFromSTL :: ℝ -> ℝ -> ByteString -> [Tri] centeredTrisFromSTL bedX bedY stl = shiftedTris where - centerPoint = Point3 (dx,dy,dz) + centerPoint = Point3 $ V3 dx dy dz shiftedTris = [shiftTri centerPoint tri | tri <- tris] `using` parListChunk (div (length tris) (fromFastℕ threads)) rseq tris = trianglesFromSTL threads stl (dx,dy,dz) = (bedX/2-x0, bedY/2-y0, -zMin) @@ -310,12 +312,12 @@ sliceLayer printer print@(Print _ infillRatio _ _ _ _ _ _ ls outerWallBeforeInne let -- FIXME: make travel gcode from the previous contour's last position? travelToContour :: Contour -> [GCode] - travelToContour contour = [addFeedRate travelFeedRate $ make3DTravelGCode (Point3 (0,0,0)) (raise $ firstPointOfContour contour)] + travelToContour contour = [addFeedRate travelFeedRate $ make3DTravelGCode (Point3 (V3 0 0 0)) (raise $ firstPointOfContour contour)] travelBetweenContours :: Contour -> Contour -> [GCode] travelBetweenContours source dest = [addFeedRate travelFeedRate $ make2DTravelGCode (firstPointOfContour source) $ firstPointOfContour dest] travelFromContourToInfill :: Contour -> [[LineSeg]] -> [GCode] travelFromContourToInfill source lines - | firstPointOfInfill lines /= Nothing = [addFeedRate travelFeedRate $ make2DTravelGCode (lastPointOfContour source) $ fromMaybe (Point2 (0,0)) $ firstPointOfInfill lines] + | firstPointOfInfill lines /= Nothing = [addFeedRate travelFeedRate $ make2DTravelGCode (lastPointOfContour source) $ fromMaybe (Point2 (V2 0 0)) $ firstPointOfInfill lines] | otherwise = [] renderContourTreeSet :: ContourTreeSet -> [GCode] renderContourTreeSet (ContourTreeSet firstContourTree moreContourTrees) = renderContourTree firstContourTree <> concatMap renderContourTree moreContourTrees @@ -421,7 +423,7 @@ sliceLayer printer print@(Print _ infillRatio _ _ _ _ _ _ ls outerWallBeforeInne layerStart = [GCMarkLayerStart layerNumber] -- FIXME: make travel gcode from the previous contour's last position? travelToLayerChange :: [GCode] - travelToLayerChange = [addFeedRate travelFeedRate $ make2DTravelGCode (Point2 (0,0)) $ firstPointOfContour $ firstContourOfContourTreeSet allContours] + travelToLayerChange = [addFeedRate travelFeedRate $ make2DTravelGCode (Point2 (V2 0 0)) $ firstPointOfContour $ firstContourOfContourTreeSet allContours] -- FIXME: not all support is support. what about supportInterface? support :: [GCode] support = [] -- if null supportGCode then [] else GCMarkSupportStart : supportGCode @@ -452,7 +454,7 @@ sliceLayer printer print@(Print _ infillRatio _ _ _ _ _ _ ls outerWallBeforeInne | layerNumber == 0 = layer0Speed print | otherwise = travelSpeed print -- convert a 2D point to a 3D location. - raise (Point2 (x,y)) = Point3 (x, y, zHeightOfLayer print layerNumber) + raise (Point2 (V2 x y)) = Point3 $ V3 x y (zHeightOfLayer print layerNumber) extruder = getExtruder printer ---------------------------------------------------------- @@ -618,7 +620,7 @@ run rawArgs = do inFile = fromMaybe "in.stl" $ inputFileOpt args stl <- readFile inFile -- FIXME: do something with messages. - (settings, _messages) <- addConstants $ settingOpts args + (settings, _messages) <- addConstants (settingOpts args) False let printer = printerFromSettings settings buildarea = getBuildArea printer @@ -656,12 +658,12 @@ run rawArgs = do -- FIXME: interpret 'machine_shape', and implement eliptic beds. -- The bed of the printer. assumed to be some form of rectangle, with the build area coresponding to all of the space above it. - getPrintBed var = RectBed ( fromMaybe 100 $ maybeX var - , fromMaybe 100 $ maybeY var ) + getPrintBed var = RectBed $ V2 (fromMaybe 100 $ maybeX var) + (fromMaybe 100 $ maybeY var) -- The area we can print inside of. - defaultBuildArea var = RectArea ( fromMaybe 100 $ maybeX var - , fromMaybe 100 $ maybeY var - , fromMaybe 100 $ maybeZ var ) + defaultBuildArea var = RectArea $ V3 (fromMaybe 100 $ maybeX var) + (fromMaybe 100 $ maybeY var) + (fromMaybe 100 $ maybeZ var) -- The Extruder. note that this includes the diameter of the feed filament. defaultExtruder :: VarLookup -> Extruder defaultExtruder var = Extruder (fromMaybe 2.85 $ maybeFilamentDiameter var) @@ -739,7 +741,7 @@ run rawArgs = do -- maybeTopBottomSpeed (lookupVarIn "speed_topbottom" -> Just (ONum speed)) = Just speed -- maybeTopBottomSpeed _ = Nothing startingGCode, endingGCode :: VarLookup -> ByteString - startingGCode (lookupVarIn "machine_start_gcode" -> Just (OString startGCode)) = fromString startGCode + startingGCode (lookupVarIn "machine_start_gcode" -> Just (OString startGCode)) = toStrict $ encodeUtf8 startGCode startingGCode _ = ";FLAVOR:Marlin\n" <> "G21 ;metric values\n" <> "G90 ;absolute positioning\n" @@ -755,7 +757,7 @@ run rawArgs = do <> "G1 F4200 ;default speed\n" <> ";Put printing message on LCD screen\n" <> "M117\n" - endingGCode (lookupVarIn "machine_end_gcode" -> Just (OString endGCode)) = fromString endGCode + endingGCode (lookupVarIn "machine_end_gcode" -> Just (OString endGCode)) = toStrict $ encodeUtf8 endGCode endingGCode _ = ";End GCode\n" <> "M104 S0 ;extruder heater off\n" <> "M140 S0 ;heated bed heater off (if you have it)\n" diff --git a/tests/GoldenSpec/Spec.hs b/tests/GoldenSpec/Spec.hs index 2333c76b4..5c60c94b1 100644 --- a/tests/GoldenSpec/Spec.hs +++ b/tests/GoldenSpec/Spec.hs @@ -26,6 +26,8 @@ import Data.Maybe (fromMaybe, fromJust) import GoldenSpec.Util (golden, goldens) +import Linear (V2(V2)) + import Test.Hspec (describe, Spec) import Graphics.Slicer.Math.Skeleton.Skeleton (findStraightSkeleton) @@ -144,18 +146,18 @@ goldenSpec = describe "golden tests" $ do (toGanja <$> (infiniteInset 0.1 $ facesOf $ fromMaybe (error "got Nothing") $ findStraightSkeleton rectangle []))) golden "rectangle-Faces-Default" $ facesOf $ fromMaybe (error "no skeleton?") $ findStraightSkeleton rectangle [] where - c0 = makePointContour [Point2 (0,0), Point2 (-1,-1), Point2 (1,-1), Point2 (1,1), Point2 (-1,1)] - c0l0 = LineSeg (Point2 (0,0)) (Point2 (-1,-1)) - c1 = makePointContour [Point2 (-1,-1), Point2 (0,0), Point2 (1,-1), Point2 (1,1), Point2 (-1,1)] - c2 = makePointContour [Point2 (-1,-1), Point2 (1,-1), Point2 (0,0), Point2 (1,1), Point2 (-1,1)] - c3 = makePointContour [Point2 (-1,-1), Point2 (1,-1), Point2 (1,1), Point2 (0,0), Point2 (-1,1)] - c4 = makePointContour [Point2 (-1,-1), Point2 (1,-1), Point2 (1,1), Point2 (-1,1), Point2 (0,0)] - c5 = makePointContour [Point2 (-1,-1), Point2 (1,-1), Point2 (2,0), Point2 (1,1), Point2 (-1,1), Point2 (0,0)] - c6 = makePointContour [Point2 (-1,-1), Point2 (-0.5,-1), Point2 (0,0), Point2 (0.5,-1), Point2 (1,-1), Point2 (1,1), Point2 (-1,1)] - c7 = makePointContour [Point2 (0,-1), Point2 (1,-1), Point2 (1,1), Point2 (0.5,1), Point2 (0.5,0), Point2 (0,1), Point2 (-1,1), Point2 (-1,0), Point2 (0,0)] + c0 = makePointContour [Point2 (V2 0 0), Point2 (V2 (-1) (-1)), Point2 (V2 1 (-1)), Point2 (V2 1 1), Point2 (V2 (-1) 1)] + c0l0 = LineSeg (Point2 (V2 0 0)) (Point2 (V2 (-1) (-1))) + c1 = makePointContour [Point2 (V2 (-1) (-1)), Point2 (V2 0 0), Point2 (V2 1 (-1)), Point2 (V2 1 1), Point2 (V2 (-1) 1)] + c2 = makePointContour [Point2 (V2 (-1) (-1)), Point2 (V2 1 (-1)), Point2 (V2 0 0), Point2 (V2 1 1), Point2 (V2 (-1) 1)] + c3 = makePointContour [Point2 (V2 (-1) (-1)), Point2 (V2 1 (-1)), Point2 (V2 1 1), Point2 (V2 0 0), Point2 (V2 (-1) 1)] + c4 = makePointContour [Point2 (V2 (-1) (-1)), Point2 (V2 1 (-1)), Point2 (V2 1 1), Point2 (V2 (-1) 1), Point2 (V2 0 0)] + c5 = makePointContour [Point2 (V2 (-1) (-1)), Point2 (V2 1 (-1)), Point2 (V2 2 0), Point2 (V2 1 1), Point2 (V2 (-1) 1), Point2 (V2 0 0)] + c6 = makePointContour [Point2 (V2 (-1) (-1)), Point2 (V2 (-0.5) (-1)), Point2 (V2 0 0), Point2 (V2 0.5 (-1)), Point2 (V2 1 (-1)), Point2 (V2 1 1), Point2 (V2 (-1) 1)] + c7 = makePointContour [Point2 (V2 0 (-1)), Point2 (V2 1 (-1)), Point2 (V2 1 1), Point2 (V2 0.5 1), Point2 (V2 0.5 0), Point2 (V2 0 1), Point2 (V2 (-1) 1), Point2 (V2 (-1) 0), Point2 (V2 0 0)] -- A simple triangle. - triangle = makePointContour [Point2 (2,0), Point2 (1.0,sqrt 3), Point2 (0,0)] + triangle = makePointContour [Point2 (V2 2 0), Point2 (V2 1.0 (sqrt 3)), Point2 (V2 0 0)] -- A simple square. - square = makePointContour [Point2 (-1,1), Point2 (-1,-1), Point2 (1,-1), Point2 (1,1)] + square = makePointContour [Point2 (V2 (-1) 1), Point2 (V2 (-1) (-1)), Point2 (V2 1 (-1)), Point2 (V2 1 1)] -- A simple rectangle. - rectangle = makePointContour [Point2 (-1.5,1), Point2 (-1.5,-1), Point2 (1.5,-1), Point2 (1.5,1)] + rectangle = makePointContour [Point2 (V2 (-1.5) 1), Point2 (V2 (-1.5) (-1)), Point2 (V2 1.5 (-1)), Point2 (V2 1.5 1)] diff --git a/tests/Math/Geometry/CommonTests.hs b/tests/Math/Geometry/CommonTests.hs index 395649573..9eac7705b 100644 --- a/tests/Math/Geometry/CommonTests.hs +++ b/tests/Math/Geometry/CommonTests.hs @@ -1,6 +1,6 @@ {- ORMOLU_DISABLE -} {- HSlice. - - Copyright 2020-2022 Julia Longtin + - Copyright 2020-2026 Julia Longtin - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by @@ -44,6 +44,9 @@ import Data.List (concatMap) -- The Maybe library. import Data.Maybe (Maybe(Just, Nothing), fromMaybe) +-- Import the types used to store Point(2|3)s. +import Linear (V2(V2), V3(V3)) + -- Slists, a form of list with a stated size in the structure. import Slist (len, slist) import Slist.Type(Slist(Slist)) @@ -166,8 +169,8 @@ prop_InsetIsSmaller distance contour where insetIsSmaller = minIX > minRX && minIY > minRY && maxRX > maxIX && maxRY > maxIY where - (Point2 (minRX, minRY), Point2 (maxRX, maxRY)) = minMaxPoints contour - (Point2 (minIX, minIY), Point2 (maxIX, maxIY)) = minMaxPoints insetContour + (Point2 (V2 minRX minRY), Point2 (V2 maxRX maxRY)) = minMaxPoints contour + (Point2 (V2 minIX minIY), Point2 (V2 maxIX maxIY)) = minMaxPoints insetContour insetContour = head foundContours (foundContours, _) = insetBy distance faces faces = facesOf $ fromMaybe (error $ "could not get a straight skeleton for: " <> show contour) $ findStraightSkeleton contour [] @@ -189,8 +192,8 @@ prop_InsetOfInsetIsSmaller distance1 distance2 contour <> dumpGanjas ([toGanja contour] <> if not (null insetContours) then [toGanja insetContour] else []) insetIsSmaller = minIX > minRX && minIY > minRY && maxRX > maxIX && maxRY > maxIY where - (Point2 (minRX, minRY), Point2 (maxRX, maxRY)) = minMaxPoints contour - (Point2 (minIX, minIY), Point2 (maxIX, maxIY)) = minMaxPoints foundContour + (Point2 (V2 minRX minRY), Point2 (V2 maxRX maxRY)) = minMaxPoints contour + (Point2 (V2 minIX minIY), Point2 (V2 maxIX maxIY)) = minMaxPoints foundContour foundContour = head foundContours (foundContours, foundFaces) = insetBy distance2 (slist insetFaces) insetContour = head insetContours diff --git a/tests/Math/Geometry/Triangle.hs b/tests/Math/Geometry/Triangle.hs index ec83d38a0..1bcf23cd8 100644 --- a/tests/Math/Geometry/Triangle.hs +++ b/tests/Math/Geometry/Triangle.hs @@ -35,6 +35,9 @@ import Data.List (concat, concatMap, transpose) -- The Maybe library. import Data.Maybe (fromMaybe, fromJust) +-- The type used for 2D points. +import Linear (V2(V2)) + -- Slists, a form of list with a stated size in the structure. import Slist (len) @@ -202,4 +205,4 @@ triangleSpec = do expectationFromTriangle f x y rawRadians rawDists = f triangle where triangle = randomTriangle x y rawRadians rawDists - unitTriangle = makePointContour [Point2 (2,0), Point2 (1.0,sqrt 3), Point2 (0,0)] + unitTriangle = makePointContour [Point2 (V2 2 0), Point2 (V2 1.0 (sqrt 3)), Point2 (V2 0 0)] diff --git a/tests/Math/PGA.hs b/tests/Math/PGA.hs index 98e3737b1..9c687c0e8 100644 --- a/tests/Math/PGA.hs +++ b/tests/Math/PGA.hs @@ -43,6 +43,8 @@ import Data.Maybe (fromMaybe, fromJust, isJust, isNothing, Maybe(Just)) import Data.Set (singleton, fromList) +import Linear (V2(V2)) + import Numeric.Rounded.Hardware (Rounded, RoundingMode(TowardInf)) -- Slists, a form of list with a stated size in the structure. @@ -109,12 +111,12 @@ contourSpec = do it "retains order in a contour passed through combineConsecutiveLineSegs" $ makeLineSegContour (combineConsecutiveLineSegs $ lineSegsOfContour c1) --> makeLineSegContour (lineSegsOfContour c1) where - cp1 = [Point2 (1,0), Point2 (1,1), Point2 (0,1), Point2 (0,0)] - cl1 = [(Point2 (0,0), Point2 (0,1)), (Point2 (0,1), Point2 (1,1)), (Point2 (1,1), Point2 (1,0)), (Point2 (1,0), Point2 (0,0))] - oocl1 = [(Point2 (1,0), Point2 (0,0)), (Point2 (0,1), Point2 (1,1)), (Point2 (0,0), Point2 (0,1)), (Point2 (1,1), Point2 (1,0))] + cp1 = [Point2 (V2 1 0), Point2 (V2 1 1), Point2 (V2 0 1), Point2 (V2 0 0)] + cl1 = [(Point2 (V2 0 0), Point2 (V2 0 1)), (Point2 (V2 0 1), Point2 (V2 1 1)), (Point2 (V2 1 1), Point2 (V2 1 0)), (Point2 (V2 1 0), Point2 (V2 0 0))] + oocl1 = [(Point2 (V2 1 0), Point2 (V2 0 0)), (Point2 (V2 0 1), Point2 (V2 1 1)), (Point2 (V2 0 0), Point2 (V2 0 1)), (Point2 (V2 1 1), Point2 (V2 1 0))] c1 = makePointContour cp1 - c2 = makePointContour [Point2 (0.75,0.25), Point2 (0.75,0.75), Point2 (0.25,0.75), Point2 (0.25,0.25)] - c3 = makePointContour [Point2 (3,0), Point2 (3,1), Point2 (2,1), Point2 (2,0)] + c2 = makePointContour [Point2 (V2 0.75 0.25), Point2 (V2 0.75 0.75), Point2 (V2 0.25 0.75), Point2 (V2 0.25 0.25)] + c3 = makePointContour [Point2 (V2 3 0), Point2 (V2 3 1), Point2 (V2 2 1), Point2 (V2 2 0)] lineSpec :: Spec lineSpec = do @@ -122,7 +124,7 @@ lineSpec = do it "contours converted from points to lines then back to points give the input list" $ pointsOfContour (makePointContour cp1) --> cp1 where - cp1 = [Point2 (1,0), Point2 (1,1), Point2 (0,1), Point2 (0,0)] + cp1 = [Point2 (V2 1 0), Point2 (V2 1 1), Point2 (V2 0 1), Point2 (V2 0 0)] linearAlgSpec :: Spec linearAlgSpec = do @@ -137,19 +139,19 @@ linearAlgSpec = do (roundPoint2 <$> pointsOfContour (fromMaybe (error "got Nothing") $ expandContour 0.1 [] $ fromMaybe (error "got Nothing") $ shrinkContour 0.1 [] c2)) --> roundPoint2 <$> pointsOfContour c2 describe "Infill (machine/infill)" $ do it "infills exactly one line inside of a box big enough for only one line (Horizontal)" $ do - makeInfill c1 [] 0.5 Horiz --> [[LineSeg (Point2 (0.0,0.5)) (Point2 (1.0,0.5))]] + makeInfill c1 [] 0.5 Horiz --> [[LineSeg (Point2 (V2 0.0 0.5)) (Point2 (V2 1.0 0.5))]] it "infills exactly one line inside of a box big enough for only one line (Vertical)" $ do - makeInfill c1 [] 0.5 Vert --> [[LineSeg (Point2 (0.5,0.0)) (Point2 (0.5,1.0))]] + makeInfill c1 [] 0.5 Vert --> [[LineSeg (Point2 (V2 0.5 0.0)) (Point2 (V2 0.5 1.0))]] -- describe "Contours (Skeleton/line)" $ do -- it "a contour algorithmically shrunk has the same amount of points as the input contour" $ -- numPointsOfContour (justOneContourFrom $ addInset 1 0.1 $ facesOf $ fromMaybe (error "got Nothing") $ findStraightSkeleton c1 []) --> numPointsOfContour c1 -- it "a contour algorithmically shrunk and mechanically expanded is about equal to where it started" $ -- roundPoint2 <$> pointsOfContour (fromMaybe (error "got Nothing") $ expandContour 0.1 [] $ justOneContourFrom $ addInset 1 0.1 $ orderedFacesOf c2l1 $ fromMaybe (error "got Nothing") $ findStraightSkeleton c2 []) --> roundPoint2 <$> pointsOfContour c2 where - cp1 = [Point2 (1,0), Point2 (1,1), Point2 (0,1), Point2 (0,0)] + cp1 = [Point2 (V2 1 0), Point2 (V2 1 1), Point2 (V2 0 1), Point2 (V2 0 0)] c1 = makePointContour cp1 cl1 = makeLineSegContour (lineSegsOfContour c1) - c2 = makePointContour [Point2 (0.75,0.25), Point2 (0.75,0.75), Point2 (0.25,0.75), Point2 (0.25,0.25)] + c2 = makePointContour [Point2 (V2 0.75 0.25), Point2 (V2 0.75 0.75), Point2 (V2 0.25 0.75), Point2 (V2 0.25 0.25)] geomAlgSpec :: Spec geomAlgSpec = do @@ -334,11 +336,11 @@ geomAlgSpec = do prop_ScalarDotScalar :: ℝ -> ℝ -> ℝ -> ℝ -> Bool prop_ScalarDotScalar v1 v2 v3 v4 = scalarPart (rawPPoint2 (v1,v2) ⋅ rawPPoint2 (v3,v4)) == (-1) where - rawPPoint2 (x,y) = vecOfP $ eToPP (Point2 (x,y)) + rawPPoint2 (x,y) = vecOfP $ eToPP (Point2 (V2 x y)) -- | A test making sure that the wedge product of two PLines along two different axises is always in e1e2. prop_TwoAxisAlignedLines :: NonZero ℝ -> NonZero ℝ -> NonZero ℝ -> NonZero ℝ -> Expectation -prop_TwoAxisAlignedLines d1 d2 r1 r2 = (\(GVec gVals) -> bases gVals) (vecOfL (eToPLine2 (makeLineSeg (Point2 (coerce d1,0)) (Point2 (coerce d1 - coerce r1,0)))) ∧ vecOfL (eToPLine2 (makeLineSeg (Point2 (0,coerce d2)) (Point2 (0,coerce d2 - coerce r2))))) --> [fromList [GEPlus 1, GEPlus 2]] +prop_TwoAxisAlignedLines d1 d2 r1 r2 = (\(GVec gVals) -> bases gVals) (vecOfL (eToPLine2 (makeLineSeg (Point2 (V2 (coerce d1) 0)) (Point2 (V2 (coerce d1 - coerce r1) 0)))) ∧ vecOfL (eToPLine2 (makeLineSeg (Point2 (V2 0 (coerce d2))) (Point2 (V2 0 (coerce d2 - coerce r2)))))) --> [fromList [GEPlus 1, GEPlus 2]] where bases gvals = (\(GVal _ base) -> base) <$> gvals @@ -365,21 +367,21 @@ proj2DGeomAlgSpec = do describe "Lines (Math/PGA)" $ do -- (-2e2)*2e1 = 4e12 it "the intersection of a line along the X axis and a line along the Y axis is the origin point" $ - vecOfL (eToPLine2 (LineSeg (Point2 (-1,0)) (Point2 (1,0)))) ∧ vecOfL (eToPLine2 (LineSeg (Point2 (0,-1)) (Point2 (0,1)))) --> GVec [GVal 4 (fromList [GEPlus 1, GEPlus 2])] + vecOfL (eToPLine2 (LineSeg (Point2 (V2 (-1) 0)) (Point2 (V2 1 0)))) ∧ vecOfL (eToPLine2 (LineSeg (Point2 (V2 0 (-1))) (Point2 (V2 0 1)))) --> GVec [GVal 4 (fromList [GEPlus 1, GEPlus 2])] it "the intersection of two axis aligned lines is a multiple of e1e2" $ property prop_TwoAxisAlignedLines -- (-2e0+1e1)^(2e0-1e2) = -1e01+2e02-e12 it "the intersection of a line two points above the X axis, and a line two points to the right of the Y axis is at (2,2) in the upper right quadrant" $ - vectorPart (vecOfL (eToPLine2 (LineSeg (Point2 (2,0)) (Point2 (2,1)))) ∧ vecOfL (eToPLine2 (LineSeg (Point2 (0,2)) (Point2 (1,2))))) --> + vectorPart (vecOfL (eToPLine2 (LineSeg (Point2 (V2 2 0)) (Point2 (V2 2 1)))) ∧ vecOfL (eToPLine2 (LineSeg (Point2 (V2 0 2)) (Point2 (V2 1 2))))) --> GVec [GVal (-2) (fromList [GEZero 1, GEPlus 1]), GVal 2 (fromList [GEZero 1, GEPlus 2]), GVal (-1) (fromList [GEPlus 1, GEPlus 2])] it "the geometric product of any two overlapping lines is only a Scalar" $ property prop_TwoOverlappingLinesScalar it "the geometric product of any two overlapping lines does not produce a vector component" $ property prop_TwoOverlappingLinesVector it "A line constructed from a line segment is correct" $ - eToPLine2 (LineSeg (Point2 (0,0)) (Point2 (1,1))) --> pl1 + eToPLine2 (LineSeg (Point2 (V2 0 0)) (Point2 (V2 1 1))) --> pl1 it "A line constructed from by joining two points is correct" $ - fst (join2PP (eToPP (Point2 (0,0))) (eToPP (Point2 (1,1)))) --> pl1 + fst (join2PP (eToPP (Point2 (V2 0 0))) (eToPP (Point2 (V2 1 1)))) --> pl1 where pl1 = PLine2 $ GVec [GVal 1 (singleton (GEPlus 1)), GVal (-1) (singleton (GEPlus 2))] @@ -429,11 +431,11 @@ prop_perpAt90Degrees x y rawX2 y2 rawD prop_SameSideOfAxis :: NonZero ℝ -> NonZero ℝ -> Positive ℝ -> Positive ℝ -> Positive ℝ -> Bool -> Bool -> Expectation prop_SameSideOfAxis rawV1 rawV2 rawP1 rawP2 rawMagnitude xAxis positiveSide | xAxis = if positiveSide - then pPointsOnSameSideOfPLine (eToPP $ Point2 (v1,p1)) (eToPP $ Point2 (v2,p2)) (eToPLine2 $ LineSeg (Point2 (0,0)) (Point2 (mag,0))) --> Just True - else pPointsOnSameSideOfPLine (eToPP $ Point2 (v1,-p1)) (eToPP $ Point2 (v2,-p2)) (eToPLine2 $ LineSeg (Point2 (0,0)) (Point2 (mag,0))) --> Just True + then pPointsOnSameSideOfPLine (eToPP $ Point2 (V2 v1 p1)) (eToPP $ Point2 (V2 v2 p2)) (eToPLine2 $ LineSeg (Point2 (V2 0 0)) (Point2 (V2 mag 0))) --> Just True + else pPointsOnSameSideOfPLine (eToPP $ Point2 (V2 v1 (-p1))) (eToPP $ Point2 (V2 v2 (-p2))) (eToPLine2 $ LineSeg (Point2 (V2 0 0)) (Point2 (V2 mag 0))) --> Just True | otherwise = if positiveSide - then pPointsOnSameSideOfPLine (eToPP $ Point2 (p1,v1)) (eToPP $ Point2 (p2,v2)) (eToPLine2 $ LineSeg (Point2 (0,0)) (Point2 (0,1))) --> Just True - else pPointsOnSameSideOfPLine (eToPP $ Point2 (-p1,v1)) (eToPP $ Point2 (-p1,v2)) (eToPLine2 $ LineSeg (Point2 (0,0)) (Point2 (0,1))) --> Just True + then pPointsOnSameSideOfPLine (eToPP $ Point2 (V2 p1 v1)) (eToPP $ Point2 (V2 p2 v2)) (eToPLine2 $ LineSeg (Point2 (V2 0 0)) (Point2 (V2 0 1))) --> Just True + else pPointsOnSameSideOfPLine (eToPP $ Point2 (V2 (-p1) v1)) (eToPP $ Point2 (V2 (-p1) v2)) (eToPLine2 $ LineSeg (Point2 (V2 0 0)) (Point2 (V2 0 1))) --> Just True where p1 = coerce rawP1 p2 = coerce rawP2 @@ -446,11 +448,11 @@ prop_SameSideOfAxis rawV1 rawV2 rawP1 rawP2 rawMagnitude xAxis positiveSide prop_OtherSideOfAxis :: NonZero ℝ -> NonZero ℝ -> Positive ℝ -> Positive ℝ -> Bool -> Bool -> Expectation prop_OtherSideOfAxis v1 v2 p1 p2 xAxis positive | xAxis = if positive - then pPointsOnSameSideOfPLine (eToPP (Point2 (coerce v1,coerce p1))) (eToPP (Point2 (coerce v2,-(coerce p2)))) (eToPLine2 (LineSeg (Point2 (0,0)) (Point2 (1,0)))) --> Just False - else pPointsOnSameSideOfPLine (eToPP (Point2 (coerce v1,-(coerce p1)))) (eToPP (Point2 (coerce v2,coerce p2))) (eToPLine2 (LineSeg (Point2 (0,0)) (Point2 (1,0)))) --> Just False + then pPointsOnSameSideOfPLine (eToPP (Point2 (V2 (coerce v1) (coerce p1)))) (eToPP (Point2 (V2 (coerce v2) (-coerce p2)))) (eToPLine2 (LineSeg (Point2 (V2 0 0)) (Point2 (V2 1 0)))) --> Just False + else pPointsOnSameSideOfPLine (eToPP (Point2 (V2 (coerce v1)(-coerce p1)))) (eToPP (Point2 (V2 (coerce v2) (coerce p2)))) (eToPLine2 (LineSeg (Point2 (V2 0 0)) (Point2 (V2 1 0)))) --> Just False | otherwise = if positive - then pPointsOnSameSideOfPLine (eToPP (Point2 (coerce p1,coerce v1))) (eToPP (Point2 (-(coerce p2),coerce v2))) (eToPLine2 (LineSeg (Point2 (0,0)) (Point2 (0,1)))) --> Just False - else pPointsOnSameSideOfPLine (eToPP (Point2 (-(coerce p1),coerce v1))) (eToPP (Point2 (coerce p1,coerce v2))) (eToPLine2 (LineSeg (Point2 (0,0)) (Point2 (0,1)))) --> Just False + then pPointsOnSameSideOfPLine (eToPP (Point2 (V2 (coerce p1) (coerce v1)))) (eToPP (Point2 (V2 (-coerce p2) (coerce v2)))) (eToPLine2 (LineSeg (Point2 (V2 0 0)) (Point2 (V2 0 1)))) --> Just False + else pPointsOnSameSideOfPLine (eToPP (Point2 (V2 (-coerce p1) (coerce v1)))) (eToPP (Point2 (V2 (coerce p1) (coerce v2)))) (eToPLine2 (LineSeg (Point2 (V2 0 0)) (Point2 (V2 0 1)))) --> Just False -- | Ensure that a PLine translated, then translated back is approximately the same PLine. prop_PerpTranslateID :: ℝ -> ℝ -> NonZero ℝ -> NonZero ℝ -> NonZero ℝ -> Bool @@ -509,8 +511,8 @@ prop_QuadBisectorCrosses rawX1 rawY1 rawX2 rawY2 intersect4 = outputIntersectsLineSeg eNode lineSeg2 -- note that our bisector always intersects the origin. (bisector1, bisector1Err) = normalizeL bisector - (bisector, _) = eToPL $ makeLineSeg (Point2 (0,0)) (Point2 (x3,y3)) - eNode = makeENode (Point2 (x1,y1)) (Point2 (0,0)) (Point2 (x2,y2)) + (bisector, _) = eToPL $ makeLineSeg (Point2 (V2 0 0)) (Point2 (V2 x3 y3)) + eNode = makeENode (Point2 (V2 x1 y1)) (Point2 (V2 0 0)) (Point2 (V2 x2 y2)) -- X1, Y1 and X2 forced uniqueness. additionally, forced "not 180 degree opposition). x1,y1,x2,y2 :: ℝ x1 @@ -561,8 +563,8 @@ prop_QuadBisectorCrossesMultiple rawX1 rawY1 rawX2 rawY2 rawTimes intersect4 = outputIntersectsLineSeg eNode lineSeg2 -- note that our bisector always intersects the origin. (bisector1, bisector1Err) = normalizeL bisector - (bisector, _) = eToPL $ makeLineSeg (Point2 (0,0)) (Point2 (x3,y3)) - eNode = makeENode (Point2 (x1,y1)) (Point2 (0,0)) (Point2 (x2,y2)) + (bisector, _) = eToPL $ makeLineSeg (Point2 (V2 0 0)) (Point2 (V2 x3 y3)) + eNode = makeENode (Point2 (V2 x1 y1)) (Point2 (V2 0 0)) (Point2 (V2 x2 y2)) -- X1, Y1 and X2 forced uniqueness. additionally, forced "not 180 degree opposition). x1,y1,x2,y2,times :: ℝ x1 @@ -603,7 +605,7 @@ prop_LineSegIntersectionStableAtOrigin d1 x1 y1 rawX2 rawY2 <> "lineSegTo: " <> show x1y1LineSegToOrigin <> "\n" <> "lineSegFrom: " <> show lineSegFromOrigin <> "\n" <> "pline through origin: " <> show pLineThroughOriginNotX1Y1NotOther <> "\n" - <> "equivalent LineSeg: " <> show (makeLineSeg (Point2 (x2,y2)) (Point2 (0,0))) <> "\n" + <> "equivalent LineSeg: " <> show (makeLineSeg (Point2 (V2 x2 y2)) (Point2 (V2 0 0))) <> "\n" <> (if isStartPoint res2 then "Hit start." else "Missed start.\n" @@ -619,8 +621,8 @@ prop_LineSegIntersectionStableAtOrigin d1 x1 y1 rawX2 rawY2 res1 = intersectsWithErr (Right pLineThroughOriginNotX1Y1NotOther) (Left x1y1LineSegToOrigin :: Either LineSeg (ProjectiveLine, PLine2Err)) res2 = intersectsWithErr (Right pLineThroughOriginNotX1Y1NotOther) (Left lineSegFromOrigin :: Either LineSeg (ProjectiveLine, PLine2Err)) distanceStart = case res2 of - (Left (NoIntersection iPoint ulpSum)) -> show iPoint <> "\nDistance: " <> show (distance2PP (iPoint,mempty) (eToPP $ Point2 (0,0), mempty)) <> "\nUlpSum:" <> show ulpSum <> "\n" - (Right (IntersectsIn iPoint ulpSum)) -> show iPoint <> "\nDistance: " <> show (distance2PP (iPoint,mempty) (eToPP $ Point2 (0,0), mempty)) <> "\nUlpSum:" <> show ulpSum <> "\n" + (Left (NoIntersection iPoint ulpSum)) -> show iPoint <> "\nDistance: " <> show (distance2PP (iPoint,mempty) (eToPP $ Point2 (V2 0 0), mempty)) <> "\nUlpSum:" <> show ulpSum <> "\n" + (Right (IntersectsIn iPoint ulpSum)) -> show iPoint <> "\nDistance: " <> show (distance2PP (iPoint,mempty) (eToPP $ Point2 (V2 0 0), mempty)) <> "\nUlpSum:" <> show ulpSum <> "\n" _ -> "" pLineThroughOriginNotX1Y1NotOther = randomPLineThroughOrigin x2 y2 x1y1LineSegToOrigin = randomX1Y1LineSegToOrigin d1 @@ -646,11 +648,11 @@ prop_LineSegIntersectionStableAtX1Y1Point pointD rawD1 x1 y1 rawX2 rawY2 | isEndPoint res1 && isStartPoint res2 = True | otherwise = error $ "missed!\n" - <> "x1y1 Point:" <> show (Point2 (d2,d2)) <> "\n" + <> "x1y1 Point:" <> show (Point2 (V2 d2 d2)) <> "\n" <> "x1y1SegTo: " <> show x1y1LineSegToPoint <> "\n" <> "lineSegFrom: " <> show lineSegFromPointNotX1Y1 <> "\n" <> "pline through x1y1: " <> show pLineThroughPointNotX1Y1NotOther <> "\n" - <> "equivalent LineSeg: " <> show (makeLineSeg (Point2 (x2,y2)) (Point2 (d2,d2))) <> "\n" + <> "equivalent LineSeg: " <> show (makeLineSeg (Point2 (V2 x2 y2)) (Point2 (V2 d2 d2))) <> "\n" <> (if isStartPoint res2 then "Hit start." else "Missed start: " <> show res2 <> "\n" @@ -665,12 +667,12 @@ prop_LineSegIntersectionStableAtX1Y1Point pointD rawD1 x1 y1 rawX2 rawY2 res1 = intersectsWithErr (Right pLineThroughPointNotX1Y1NotOther) (Left x1y1LineSegToPoint :: Either LineSeg (ProjectiveLine, PLine2Err)) res2 = intersectsWithErr (Right pLineThroughPointNotX1Y1NotOther) (Left lineSegFromPointNotX1Y1 :: Either LineSeg (ProjectiveLine, PLine2Err)) distanceStart = case res2 of - (Left (NoIntersection iPoint ulpSum)) -> show iPoint <> "\nDistance: " <> show (distance2PP (iPoint,mempty) (eToPP $ Point2 (d2,d2),mempty)) <> "\nUlpSum:" <> show ulpSum <> "\n" - (Right (IntersectsIn iPoint ulpSum)) -> show iPoint <> "\nDistance: " <> show (distance2PP (iPoint,mempty) (eToPP $ Point2 (d2,d2),mempty)) <> "\nUlpSum:" <> show ulpSum <> "\n" + (Left (NoIntersection iPoint ulpSum)) -> show iPoint <> "\nDistance: " <> show (distance2PP (iPoint,mempty) (eToPP $ Point2 (V2 d2 d2),mempty)) <> "\nUlpSum:" <> show ulpSum <> "\n" + (Right (IntersectsIn iPoint ulpSum)) -> show iPoint <> "\nDistance: " <> show (distance2PP (iPoint,mempty) (eToPP $ Point2 (V2 d2 d2),mempty)) <> "\nUlpSum:" <> show ulpSum <> "\n" _ -> "" distanceEnd = case res1 of - (Left (NoIntersection iPoint ulpSum)) -> show iPoint <> "\nDistance: " <> show (distance2PP (iPoint,mempty) (eToPP $ Point2 (d2,d2),mempty)) <> "\nUlpSum:" <> show ulpSum <> "\n" - (Right (IntersectsIn iPoint ulpSum)) -> show iPoint <> "\nDistance: " <> show (distance2PP (iPoint,mempty) (eToPP $ Point2 (d2,d2),mempty)) <> "\nUlpSum:" <> show ulpSum <> "\n" + (Left (NoIntersection iPoint ulpSum)) -> show iPoint <> "\nDistance: " <> show (distance2PP (iPoint,mempty) (eToPP $ Point2 (V2 d2 d2),mempty)) <> "\nUlpSum:" <> show ulpSum <> "\n" + (Right (IntersectsIn iPoint ulpSum)) -> show iPoint <> "\nDistance: " <> show (distance2PP (iPoint,mempty) (eToPP $ Point2 (V2 d2 d2),mempty)) <> "\nUlpSum:" <> show ulpSum <> "\n" _ -> "" pLineThroughPointNotX1Y1NotOther = randomPLineThroughPoint x2 y2 d2 x1y1LineSegToPoint = randomX1Y1LineSegToPoint d1 d2 @@ -703,16 +705,16 @@ prop_LineSegIntersectionStableAtX1Y1Point pointD rawD1 x1 y1 rawX2 rawY2 -- NOTE: hack, using angleBetween2PL to filter out minor numerical imprecision. prop_AxisAlignedRightAngles :: Bool -> Bool -> ℝ -> Positive ℝ -> Positive ℝ -> Bool prop_AxisAlignedRightAngles xPos yPos offset rawMagnitude1 rawMagnitude2 - | xPos && yPos = getFirstArc (Point2 (offset,offset+mag1)) (Point2 (offset,offset)) (Point2 (offset+mag2,offset)) + | xPos && yPos = getFirstArc (Point2 (V2 offset (offset+mag1))) (Point2 (V2 offset offset)) (Point2 (V2 (offset+mag2) offset)) `sameDirection` NPLine2 (GVec [GVal 0.7071067811865475 (singleton (GEPlus 1)), GVal (-0.7071067811865475) (singleton (GEPlus 2))]) - | xPos = getFirstArc (Point2 (offset,-offset-mag1)) (Point2 (offset,-offset)) (Point2 (offset+mag2,-offset)) + | xPos = getFirstArc (Point2 (V2 offset (-offset-mag1))) (Point2 (V2 offset (-offset))) (Point2 (V2 (offset+mag2) (-offset))) `sameDirection` NPLine2 (GVec [GVal (-0.7071067811865475) (singleton (GEPlus 1)), GVal (-0.7071067811865475) (singleton (GEPlus 2))]) - | not xPos && yPos = getFirstArc (Point2 (-offset,offset+mag1)) (Point2 (-offset,offset)) (Point2 (-offset-mag2,offset)) + | not xPos && yPos = getFirstArc (Point2 (V2 (-offset) (offset+mag1))) (Point2 (V2 (-offset) offset)) (Point2 (V2 (-offset-mag2) offset)) `sameDirection` NPLine2 (GVec [GVal 0.7071067811865475 (singleton (GEPlus 1)), GVal 0.7071067811865475 (singleton (GEPlus 2))]) - | otherwise = getFirstArc (Point2 (-offset,-offset-mag1)) (Point2 (-offset,-offset)) (Point2 (-offset-mag2,-offset)) + | otherwise = getFirstArc (Point2 (V2 (-offset) (-offset-mag1))) (Point2 (V2 (-offset) (-offset))) (Point2 (V2 (-offset-mag2) (-offset))) `sameDirection` NPLine2 (GVec [GVal (-0.7071067811865475) (singleton (GEPlus 1)), GVal 0.7071067811865475 (singleton (GEPlus 2))]) where @@ -724,16 +726,16 @@ prop_AxisAlignedRightAngles xPos yPos offset rawMagnitude1 rawMagnitude2 -- NOTE: hack, using angleBetween2PL and >= to filter out minor numerical imprecision. prop_AxisAligned135DegreeAngles :: Bool -> Bool -> ℝ -> Positive ℝ -> Positive ℝ -> Bool prop_AxisAligned135DegreeAngles xPos yPos offset rawMagnitude1 rawMagnitude2 - | xPos && yPos = getFirstArc (Point2 (offset,offset+mag1)) (Point2 (offset,offset)) (Point2 (offset+mag2,offset-mag2)) + | xPos && yPos = getFirstArc (Point2 (V2 offset (offset+mag1))) (Point2 (V2 offset offset)) (Point2 (V2 (offset+mag2) (offset-mag2))) `sameDirection` NPLine2 (GVec [GVal 0.3826834323650899 (singleton (GEPlus 1)), GVal (-0.9238795325112867) (singleton (GEPlus 2))]) - | xPos = getFirstArc (Point2 (offset,-offset-mag1)) (Point2 (offset,-offset)) (Point2 (offset+mag2,mag2-offset)) + | xPos = getFirstArc (Point2 (V2 offset (-offset-mag1))) (Point2 (V2 offset (-offset))) (Point2 (V2 (offset+mag2) (mag2-offset))) `sameDirection` NPLine2 (GVec [GVal (-0.3826834323650899) (singleton (GEPlus 1)), GVal (-0.9238795325112867) (singleton (GEPlus 2))]) - | not xPos && yPos = getFirstArc (Point2 (-offset,offset+mag1)) (Point2 (-offset,offset)) (Point2 (-offset-mag2,offset-mag2)) + | not xPos && yPos = getFirstArc (Point2 (V2 (-offset) (offset+mag1))) (Point2 (V2 (-offset) offset)) (Point2 (V2 (-offset-mag2) (offset-mag2))) `sameDirection` NPLine2 (GVec [GVal 0.3826834323650899 (singleton (GEPlus 1)), GVal 0.9238795325112867 (singleton (GEPlus 2))]) - | otherwise = getFirstArc (Point2 (-offset,-offset-mag1)) (Point2 (-offset,-offset)) (Point2 (-offset-mag2,mag2-offset)) + | otherwise = getFirstArc (Point2 (V2 (-offset) (-offset-mag1))) (Point2 (V2 (-offset) (-offset))) (Point2 (V2 (-offset-mag2) (mag2-offset))) `sameDirection` NPLine2 (GVec [GVal (-0.3826834323650899) (singleton (GEPlus 1)), GVal 0.9238795325112867 (singleton (GEPlus 2))]) where @@ -745,16 +747,16 @@ prop_AxisAligned135DegreeAngles xPos yPos offset rawMagnitude1 rawMagnitude2 -- NOTE: hack, using angleBetween2PL to filter out minor numerical imprecision. prop_AxisAligned45DegreeAngles :: Bool -> Bool -> ℝ -> Positive ℝ -> Positive ℝ -> Bool prop_AxisAligned45DegreeAngles xPos yPos offset rawMagnitude1 rawMagnitude2 - | xPos && yPos = getFirstArc (Point2 (offset+mag1,offset+mag1)) (Point2 (offset,offset)) (Point2 (offset+mag2,offset)) + | xPos && yPos = getFirstArc (Point2 (V2 (offset+mag1) (offset+mag1))) (Point2 (V2 offset offset)) (Point2 (V2 (offset+mag2) offset)) `sameDirection` NPLine2 (GVec [GVal 0.3826834323650899 (singleton (GEPlus 1)), GVal (-0.9238795325112867) (singleton (GEPlus 2))]) - | xPos = getFirstArc (Point2 (offset+mag1,-offset-mag1)) (Point2 (offset,-offset)) (Point2 (offset+mag2,-offset)) + | xPos = getFirstArc (Point2 (V2 (offset+mag1) (-offset-mag1))) (Point2 (V2 offset (-offset))) (Point2 (V2 (offset+mag2) (-offset))) `sameDirection` NPLine2 (GVec [GVal (-0.3826834323650899) (singleton (GEPlus 1)), GVal (-0.9238795325112867) (singleton (GEPlus 2))]) - | not xPos && yPos = getFirstArc (Point2 (-offset-mag1,offset+mag1)) (Point2 (-offset,offset)) (Point2 (-offset-mag2,offset)) + | not xPos && yPos = getFirstArc (Point2 (V2 (-offset-mag1) (offset+mag1))) (Point2 (V2 (-offset) offset)) (Point2 (V2 (-offset-mag2) offset)) `sameDirection` NPLine2 (GVec [GVal 0.3826834323650899 (singleton (GEPlus 1)), GVal 0.9238795325112867 (singleton (GEPlus 2))]) - | otherwise = getFirstArc (Point2 (-offset-mag1,-offset-mag1)) (Point2 (-offset,-offset)) (Point2 (-offset-mag2,-offset)) + | otherwise = getFirstArc (Point2 (V2 (-offset-mag1) (-offset-mag1))) (Point2 (V2 (-offset) (-offset))) (Point2 (V2 (-offset-mag2) (-offset))) `sameDirection` NPLine2 (GVec [GVal (-0.3826834323650899) (singleton (GEPlus 1)), GVal 0.9238795325112867 (singleton (GEPlus 2))]) where @@ -768,23 +770,23 @@ prop_AxisAligned45DegreeAngles xPos yPos offset rawMagnitude1 rawMagnitude2 prop_AxisAlignedRightAnglesOutside :: Bool -> Bool -> ℝ -> Positive ℝ -> Bool prop_AxisAlignedRightAnglesOutside xPos yPos offset rawMagnitude | xPos && yPos = - getOutsideArc (eToPP $ Point2 (offset,offset+mag), mempty) (eToPL $ LineSeg (Point2 (offset,offset+mag)) (Point2 (offset,offset))) - (eToPP $ Point2 (offset+mag,offset), mempty) (eToPL $ LineSeg (Point2 (offset+mag,offset)) (Point2 (offset,offset))) + getOutsideArc (eToPP $ Point2 (V2 offset (offset+mag)), mempty) (eToPL $ LineSeg (Point2 (V2 offset (offset+mag))) (Point2 (V2 offset offset))) + (eToPP $ Point2 (V2 (offset+mag) offset), mempty) (eToPL $ LineSeg (Point2 (V2 (offset+mag) offset)) (Point2 (V2 offset offset))) `sameDirection` NPLine2 (GVec [GVal (-0.7071067811865475) (singleton (GEPlus 1)), GVal 0.7071067811865475 (singleton (GEPlus 2))]) | xPos = - getOutsideArc (eToPP $ Point2 (offset,-(offset+mag)), mempty) (eToPL $ LineSeg (Point2 (offset,-(offset+mag))) (Point2 (offset,-offset))) - (eToPP $ Point2 (offset+mag,-offset), mempty) (eToPL $ LineSeg (Point2 (offset+mag,-offset)) (Point2 (offset,-offset))) + getOutsideArc (eToPP $ Point2 (V2 offset (-(offset+mag))), mempty) (eToPL $ LineSeg (Point2 (V2 offset (-(offset+mag)))) (Point2 (V2 offset (-offset)))) + (eToPP $ Point2 (V2 (offset+mag) (-offset)), mempty) (eToPL $ LineSeg (Point2 (V2 (offset+mag) (-offset))) (Point2 (V2 offset (-offset)))) `sameDirection` NPLine2 (GVec [GVal 0.7071067811865475 (singleton (GEPlus 1)), GVal 0.7071067811865475 (singleton (GEPlus 2))]) | not xPos && yPos = - getOutsideArc (eToPP $ Point2 (-offset,offset+mag), mempty) (eToPL $ LineSeg (Point2 (-offset,offset+mag)) (Point2 (-offset,offset))) - (eToPP $ Point2 (-(offset+mag),offset), mempty) (eToPL $ LineSeg (Point2 (-(offset+mag),offset)) (Point2 (-offset,offset))) + getOutsideArc (eToPP $ Point2 (V2 (-offset) (offset+mag)), mempty) (eToPL $ LineSeg (Point2 (V2 (-offset) (offset+mag))) (Point2 (V2 (-offset) offset))) + (eToPP $ Point2 (V2 (-(offset+mag)) offset), mempty) (eToPL $ LineSeg (Point2 (V2 (-(offset+mag)) offset)) (Point2 (V2 (-offset) (offset)))) `sameDirection` NPLine2 (GVec [GVal (-0.7071067811865475) (singleton (GEPlus 1)), GVal (-0.7071067811865475) (singleton (GEPlus 2))]) | otherwise = - getOutsideArc (eToPP $ Point2 (-offset,-(offset+mag)), mempty) (eToPL $ LineSeg (Point2 (-offset,-(offset+mag))) (Point2 (-offset,-offset))) - (eToPP $ Point2 (-(offset+mag),-offset), mempty) (eToPL $ LineSeg (Point2 (-(offset+mag),-offset)) (Point2 (-offset,-offset))) + getOutsideArc (eToPP $ Point2 (V2 (-offset) (-(offset+mag))), mempty) (eToPL $ LineSeg (Point2 (V2 (-offset) (-(offset+mag)))) (Point2 (V2 (-offset) (-offset)))) + (eToPP $ Point2 (V2 (-(offset+mag)) (-offset)), mempty) (eToPL $ LineSeg (Point2 (V2 (-(offset+mag)) (-offset))) (Point2 (V2 (-offset) (-offset)))) `sameDirection` NPLine2 (GVec [GVal 0.7071067811865475 (singleton (GEPlus 1)), GVal (-0.7071067811865475) (singleton (GEPlus 2))]) where @@ -799,23 +801,23 @@ prop_AxisAlignedRightAnglesOutside xPos yPos offset rawMagnitude prop_AxisAligned135DegreeAnglesOutside :: Bool -> Bool -> Positive ℝ -> Positive ℝ -> Bool prop_AxisAligned135DegreeAnglesOutside xPos yPos rawOffset rawMagnitude | xPos && yPos = - getOutsideArc (eToPP $ Point2 (offset+mag,offset), mempty) (eToPL $ LineSeg (Point2 (offset+mag,offset)) (Point2 (offset,offset))) - (eToPP $ Point2 (offset+mag,offset+mag), mempty) (eToPL $ LineSeg (Point2 (offset+mag,offset+mag)) (Point2 (offset,offset))) + getOutsideArc (eToPP $ Point2 (V2 (offset+mag) offset), mempty) (eToPL $ LineSeg (Point2 (V2 (offset+mag) offset)) (Point2 (V2 offset offset))) + (eToPP $ Point2 (V2 (offset+mag) (offset+mag)), mempty) (eToPL $ LineSeg (Point2 (V2 (offset+mag) (offset+mag))) (Point2 (V2 offset offset))) `sameDirection` NPLine2 (GVec [GVal (-0.3826834323650899) (singleton (GEPlus 1)), GVal 0.9238795325112867 (singleton (GEPlus 2))]) | xPos = - getOutsideArc (eToPP $ Point2 (offset+mag,-offset), mempty) (eToPL $ LineSeg (Point2 (offset+mag,-offset)) (Point2 (offset,-offset))) - (eToPP $ Point2 (offset+mag,-(offset+mag)), mempty) (eToPL $ LineSeg (Point2 (offset+mag,-(offset+mag))) (Point2 (offset,-offset))) + getOutsideArc (eToPP $ Point2 (V2 (offset+mag) (-offset)), mempty) (eToPL $ LineSeg (Point2 (V2 (offset+mag) (-offset))) (Point2 (V2 offset (-offset)))) + (eToPP $ Point2 (V2 (offset+mag) (-(offset+mag))), mempty) (eToPL $ LineSeg (Point2 (V2 (offset+mag) (-(offset+mag)))) (Point2 (V2 offset (-offset)))) `sameDirection` NPLine2 (GVec [GVal 0.3826834323650899 (singleton (GEPlus 1)), GVal 0.9238795325112867 (singleton (GEPlus 2))]) | not xPos && yPos = - getOutsideArc (eToPP $ Point2 (-(offset+mag),offset), mempty) (eToPL $ LineSeg (Point2 (-(offset+mag),offset)) (Point2 (-offset,offset))) - (eToPP $ Point2 (-(offset+mag),offset+mag), mempty) (eToPL $ LineSeg (Point2 (-(offset+mag),offset+mag)) (Point2 (-offset,offset))) + getOutsideArc (eToPP $ Point2 (V2 (-(offset+mag)) offset), mempty) (eToPL $ LineSeg (Point2 (V2 (-(offset+mag)) offset)) (Point2 (V2 (-offset) offset))) + (eToPP $ Point2 (V2 (-(offset+mag)) (offset+mag)), mempty) (eToPL $ LineSeg (Point2 (V2 (-(offset+mag)) (offset+mag))) (Point2 (V2 (-offset) offset))) `sameDirection` NPLine2 (GVec [GVal (-0.3826834323650899) (singleton (GEPlus 1)), GVal (-0.9238795325112867) (singleton (GEPlus 2))]) | otherwise = - getOutsideArc (eToPP $ Point2 (-(offset+mag),-offset), mempty) (eToPL $ LineSeg (Point2 (-(offset+mag),-offset)) (Point2 (-offset,-offset))) - (eToPP $ Point2 (-(offset+mag),-(offset+mag)), mempty) (eToPL $ LineSeg (Point2 (-(offset+mag),-(offset+mag))) (Point2 (-offset,-offset))) + getOutsideArc (eToPP $ Point2 (V2 (-(offset+mag)) (-offset)), mempty) (eToPL $ LineSeg (Point2 (V2 (-(offset+mag)) (-offset))) (Point2 (V2 (-offset) (-offset)))) + (eToPP $ Point2 (V2 (-(offset+mag)) (-(offset+mag))), mempty) (eToPL $ LineSeg (Point2 (V2 (-(offset+mag)) (-(offset+mag)))) (Point2 (V2 (-offset) (-offset)))) `sameDirection` NPLine2 (GVec [GVal 0.3826834323650899 (singleton (GEPlus 1)), GVal (-0.9238795325112867) (singleton (GEPlus 2))]) where @@ -827,16 +829,16 @@ prop_AxisAligned135DegreeAnglesOutside xPos yPos rawOffset rawMagnitude -- NOTE: hack, using angleBetween2PL to filter out minor numerical imprecision. prop_AxisAlignedRightAnglesInENode :: Bool -> Bool -> ℝ -> Positive ℝ -> Positive ℝ -> Bool prop_AxisAlignedRightAnglesInENode xPos yPos offset rawMagnitude1 rawMagnitude2 - | xPos && yPos = outOf (onlyOne $ makeENodes [LineSeg (Point2 (offset,offset+mag1)) (Point2 (offset,offset)),LineSeg (Point2 (offset,offset)) (Point2 (offset+mag2,offset))]) + | xPos && yPos = outOf (onlyOne $ makeENodes [LineSeg (Point2 (V2 offset (offset+mag1))) (Point2 (V2 offset offset)),LineSeg (Point2 (V2 offset offset)) (Point2 (V2 (offset+mag2) offset))]) `sameDirection` NPLine2 (GVec [GVal 0.7071067811865475 (singleton (GEPlus 1)), GVal (-0.7071067811865475) (singleton (GEPlus 2))]) - | xPos = outOf (onlyOne $ makeENodes [LineSeg (Point2 (offset,-(offset+mag1))) (Point2 (offset,-offset)),LineSeg (Point2 (offset,-offset)) (Point2 (offset+mag2,-offset))]) + | xPos = outOf (onlyOne $ makeENodes [LineSeg (Point2 (V2 offset (-(offset+mag1)))) (Point2 (V2 offset (-offset))),LineSeg (Point2 (V2 offset (-offset))) (Point2 (V2 (offset+mag2) (-offset)))]) `sameDirection` NPLine2 (GVec [GVal (-0.7071067811865475) (singleton (GEPlus 1)), GVal (-0.7071067811865475) (singleton (GEPlus 2))]) - | not xPos && yPos = outOf (onlyOne $ makeENodes [LineSeg (Point2 (-offset,offset+mag1)) (Point2 (-offset,offset)),LineSeg (Point2 (-offset,offset)) (Point2 (-(offset+mag2),offset))]) + | not xPos && yPos = outOf (onlyOne $ makeENodes [LineSeg (Point2 (V2 (-offset) (offset+mag1))) (Point2 (V2 (-offset) offset)),LineSeg (Point2 (V2 (-offset) offset)) (Point2 (V2 (-(offset+mag2)) offset))]) `sameDirection` NPLine2 (GVec [GVal 0.7071067811865475 (singleton (GEPlus 1)), GVal 0.7071067811865475 (singleton (GEPlus 2))]) - | otherwise = outOf (onlyOne $ makeENodes [LineSeg (Point2 (-offset,-(offset+mag1))) (Point2 (-offset,-offset)),LineSeg (Point2 (-offset,-offset)) (Point2 (-(offset+mag2),-offset))]) + | otherwise = outOf (onlyOne $ makeENodes [LineSeg (Point2 (V2 (-offset) (-(offset+mag1)))) (Point2 (V2 (-offset) (-offset))),LineSeg (Point2 (V2 (-offset) (-offset))) (Point2 (V2 (-(offset+mag2)) (-offset)))]) `sameDirection` NPLine2 (GVec [GVal (-0.7071067811865475) (singleton (GEPlus 1)), GVal 0.7071067811865475 (singleton (GEPlus 2))]) where @@ -848,16 +850,16 @@ prop_AxisAlignedRightAnglesInENode xPos yPos offset rawMagnitude1 rawMagnitude2 -- NOTE: hack, using angleBetween2PL and >= to filter out minor numerical imprecision. prop_AxisAligned135DegreeAnglesInENode :: Bool -> Bool -> ℝ -> Positive ℝ -> Positive ℝ -> Bool prop_AxisAligned135DegreeAnglesInENode xPos yPos offset rawMagnitude1 rawMagnitude2 - | xPos && yPos = outOf (onlyOne $ makeENodes [LineSeg (Point2 (offset,offset+mag1)) (Point2 (offset,offset)),LineSeg (Point2 (offset,offset)) (Point2 (offset+mag2,offset-mag2))]) + | xPos && yPos = outOf (onlyOne $ makeENodes [LineSeg (Point2 (V2 offset (offset+mag1))) (Point2 (V2 offset offset)),LineSeg (Point2 (V2 offset offset)) (Point2 (V2 (offset+mag2) (offset-mag2)))]) `sameDirection` NPLine2 (GVec [GVal 0.3826834323650899 (singleton (GEPlus 1)), GVal (-0.9238795325112867) (singleton (GEPlus 2))]) - | xPos = outOf (onlyOne $ makeENodes [LineSeg (Point2 (offset,-(offset+mag1))) (Point2 (offset,-offset)),LineSeg (Point2 (offset,-offset)) (Point2 (offset+mag2,-(offset-mag2)))]) + | xPos = outOf (onlyOne $ makeENodes [LineSeg (Point2 (V2 offset (-(offset+mag1)))) (Point2 (V2 offset (-offset))),LineSeg (Point2 (V2 offset (-offset))) (Point2 (V2 (offset+mag2) (-(offset-mag2))))]) `sameDirection` NPLine2 (GVec [GVal (-0.3826834323650899) (singleton (GEPlus 1)), GVal (-0.9238795325112867) (singleton (GEPlus 2))]) - | not xPos && yPos = outOf (onlyOne $ makeENodes [LineSeg (Point2 (-offset,offset+mag1)) (Point2 (-offset,offset)),LineSeg (Point2 (-offset,offset)) (Point2 (-(offset+mag2),offset-mag2))]) + | not xPos && yPos = outOf (onlyOne $ makeENodes [LineSeg (Point2 (V2 (-offset) (offset+mag1))) (Point2 (V2 (-offset) offset)),LineSeg (Point2 (V2 (-offset) offset)) (Point2 (V2 (-(offset+mag2)) (offset-mag2)))]) `sameDirection` NPLine2 (GVec [GVal 0.3826834323650899 (singleton (GEPlus 1)), GVal 0.9238795325112867 (singleton (GEPlus 2))]) - | otherwise = outOf (onlyOne $ makeENodes [LineSeg (Point2 (-offset,-(offset+mag1))) (Point2 (-offset,-offset)),LineSeg (Point2 (-offset,-offset)) (Point2 (-(offset+mag2),-(offset-mag2)))]) + | otherwise = outOf (onlyOne $ makeENodes [LineSeg (Point2 (V2 (-offset) (-(offset+mag1)))) (Point2 (V2 (-offset) (-offset))),LineSeg (Point2 (V2 (-offset) (-offset))) (Point2 (V2 (-(offset+mag2)) (-(offset-mag2))))]) `sameDirection` NPLine2 (GVec [GVal (-0.3826834323650899) (singleton (GEPlus 1)), GVal 0.9238795325112867 (singleton (GEPlus 2))]) where @@ -869,16 +871,16 @@ prop_AxisAligned135DegreeAnglesInENode xPos yPos offset rawMagnitude1 rawMagnitu -- NOTE: hack, using angleBetween2PL to filter out minor numerical imprecision. prop_AxisAligned45DegreeAnglesInENode :: Bool -> Bool -> ℝ -> Positive ℝ -> Positive ℝ -> Bool prop_AxisAligned45DegreeAnglesInENode xPos yPos offset rawMagnitude1 rawMagnitude2 - | xPos && yPos = outOf (makeENode (Point2 (offset+mag1,offset+mag1)) (Point2 (offset,offset)) (Point2 (offset+mag2,offset))) + | xPos && yPos = outOf (makeENode (Point2 (V2 (offset+mag1) (offset+mag1))) (Point2 (V2 offset offset)) (Point2 (V2 (offset+mag2) offset))) `sameDirection` NPLine2 (GVec [GVal 0.3826834323650899 (singleton (GEPlus 1)), GVal (-0.9238795325112867) (singleton (GEPlus 2))]) - | xPos = outOf (makeENode (Point2 (offset+mag1,-offset-mag1)) (Point2 (offset,-offset)) (Point2 (offset+mag2,-offset))) + | xPos = outOf (makeENode (Point2 (V2 (offset+mag1) (-offset-mag1))) (Point2 (V2 offset (-offset))) (Point2 (V2 (offset+mag2) (-offset)))) `sameDirection` NPLine2 (GVec [GVal (-0.3826834323650899) (singleton (GEPlus 1)), GVal (-0.9238795325112867) (singleton (GEPlus 2))]) - | not xPos && yPos = outOf (makeENode (Point2 (-offset-mag1,offset+mag1)) (Point2 (-offset,offset)) (Point2 (-offset-mag2,offset))) + | not xPos && yPos = outOf (makeENode (Point2 (V2 (-offset-mag1) (offset+mag1))) (Point2 (V2 (-offset) offset)) (Point2 (V2 (-offset-mag2) offset))) `sameDirection` NPLine2 (GVec [GVal 0.3826834323650899 (singleton (GEPlus 1)), GVal 0.9238795325112867 (singleton (GEPlus 2))]) - | otherwise = outOf (makeENode (Point2 (-offset-mag1,-offset-mag1)) (Point2 (-offset,-offset)) (Point2 (-offset-mag2,-offset))) + | otherwise = outOf (makeENode (Point2 (V2 (-offset-mag1) (-offset-mag1))) (Point2 (V2 (-offset) (-offset))) (Point2 (V2 (-offset-mag2) (-offset)))) `sameDirection` NPLine2 (GVec [GVal (-0.3826834323650899) (singleton (GEPlus 1)), GVal 0.9238795325112867 (singleton (GEPlus 2))]) where @@ -910,8 +912,8 @@ prop_LineSegWithinErrRange x1 y1 rawX2 rawY2 | res2 > 0 = error "too big endPoint" | otherwise = True where - res1 = distance (startPoint lineSeg) (Point2 (x1,y1)) - res2 = distance (endPoint lineSeg) (Point2 (x2,y2)) + res1 = distance (startPoint lineSeg) (Point2 (V2 x1 y1)) + res2 = distance (endPoint lineSeg) (Point2 (V2 x2 y2)) lineSeg = randomLineSeg x1 y1 x2 y2 (x2,y2) | x1 == rawX2 && y1 == rawY2 = if x1 == 0 && y1 == 0 @@ -1120,11 +1122,11 @@ prop_PLineIntersectsAtXAxis x y dx dy m errSum = ulpVal $ axisIntersectionErr <> distanceErr (foundDistance, (_,_, distanceErr)) = distance2PP (axisIntersectionPoint,mempty) (intersectionPPoint2, intersectionErr) axisIntersectionErr = pLineErrAtPPoint (randomPLine1, pline1Err) axisIntersectionPoint - axisIntersectionPoint = eToPP $ Point2 (fromRight (error "not right?") $ fst $ fromJust axisIntersection, 0) + axisIntersectionPoint = eToPP $ Point2 (V2 (fromRight (error "not right?") $ fst $ fromJust axisIntersection) 0) axisIntersection = xIntercept (randomPLine1, pline1Err) (intersectionPPoint2, (_,_,intersectionErr)) = intersect2PL randomPLine1 axisPLine (randomPLine1, pline1Err) = randomPLineWithErr x y dx dy - (axisPLine, _) = eToPL $ makeLineSeg (Point2 (0,0)) (Point2 (coerce m,0)) + (axisPLine, _) = eToPL $ makeLineSeg (Point2 (V2 0 0)) (Point2 (V2 (coerce m) 0)) prop_PLineIntersectsAtYAxis :: NonZero ℝ -> ℝ -> ℝ -> NonZero ℝ -> NonZero ℝ -> Bool prop_PLineIntersectsAtYAxis x y x2 rawY2 m @@ -1148,11 +1150,11 @@ prop_PLineIntersectsAtYAxis x y x2 rawY2 m errSum = ulpVal $ axisIntersectionErr <> distanceErr (foundDistance, (_,_, distanceErr)) = distance2PP (axisIntersectionPoint, mempty) (intersectionPPoint2, intersectionErr) axisIntersectionErr = snd $ fromJust axisIntersection - axisIntersectionPoint = eToPP $ Point2 (0, fromRight (error "not right?") $ fst $ fromJust axisIntersection) + axisIntersectionPoint = eToPP $ Point2 (V2 0(fromRight (error "not right?") $ fst $ fromJust axisIntersection)) axisIntersection = yIntercept (randomPLine1, pline1Err) (intersectionPPoint2, (_,_,intersectionErr)) = intersect2PL randomPLine1 axisPLine (randomPLine1, pline1Err) = randomPLineWithErr (coerce x) y (coerce x2) (coerce y2) - (axisPLine, _) = eToPL $ makeLineSeg (Point2 (0,0)) (Point2 (0,coerce m)) + (axisPLine, _) = eToPL $ makeLineSeg (Point2 (V2 0 0)) (Point2 (V2 0 (coerce m))) y2 :: ℝ y2 = coerce rawY2 @@ -1163,7 +1165,7 @@ unit_LineContourIntersection1 = isJust res line = (PLine2 (GVec [GVal 1.9109380841879906 (fromList [GEZero 1]),GVal 1.0 (fromList [GEPlus 1]),GVal (-1.0) (fromList [GEPlus 2])]), PLine2Err [] [] (UlpSum 0.0) (UlpSum 0.0) (UlpSum 0.0) ([ErrVal (UlpSum 3.3306690738754696e-16) (fromList [GEPlus 2]),ErrVal (UlpSum 2.220446049250313e-16) (fromList [GEPlus 1]),ErrVal (UlpSum 2.220446049250313e-16) (fromList [GEZero 1])],[ErrVal (UlpSum 2.220446049250313e-16) (fromList [GEPlus 2])]) ) - contour = LineSegContour (Point2 (95.69999999999982,95.69999999999982)) (Point2 (104.3000000000001,104.3000000000001)) (LineSeg (Point2 (95.69999999999982,95.69999999999982)) (Point2 (104.3000000000001,95.69999999999993))) (LineSeg (Point2 (104.3000000000001,95.69999999999993)) (Point2 (104.3,104.3))) (slist [LineSeg (Point2 (104.3,104.3)) (Point2 (95.69999999999993,104.3000000000001)), LineSeg (Point2 (95.69999999999993,104.3000000000001)) (Point2 (95.69999999999982,95.69999999999982))]) + contour = LineSegContour (Point2 (V2 95.69999999999982 95.69999999999982)) (Point2 (V2 104.3000000000001 104.3000000000001)) (LineSeg (Point2 (V2 95.69999999999982 95.69999999999982)) (Point2 (V2 104.3000000000001 95.69999999999993))) (LineSeg (Point2 (V2 104.3000000000001 95.69999999999993)) (Point2 (V2 104.3 104.3))) (slist [LineSeg (Point2 (V2 104.3 104.3)) (Point2 (V2 95.69999999999993 104.3000000000001)), LineSeg (Point2 (V2 95.69999999999993 104.3000000000001)) (Point2 (V2 95.69999999999982 95.69999999999982))]) -- | a contour that failed. unit_ContourFlip1 :: Bool @@ -1175,150 +1177,150 @@ unit_ContourFlip1 res = maybeFlipContour contour contour = makeLineSegContour [ - LineSeg (Point2 (93.5,94.90828649116408)) (Point2 (93.50076817859392,94.96819764062953)) - , LineSeg (Point2 (93.50076817859392,94.96819764062953)) (Point2 (93.5,95.0)) - , LineSeg (Point2 (93.5,95.0)) (Point2 (93.50076817859392,95.03180235937047)) - , LineSeg (Point2 (93.50076817859392,95.03180235937047)) (Point2 (93.5,95.09171350883592)) - , LineSeg (Point2 (93.5,95.09171350883592)) (Point2 (93.50802402291995,95.12805658872026)) - , LineSeg (Point2 (93.50802402291995,95.12805658872026)) (Point2 (93.51042508054853,95.17571341324486)) - , LineSeg (Point2 (93.51042508054853,95.17571341324486)) (Point2 (93.51650085187936,95.20928521609989)) - , LineSeg (Point2 (93.51650085187936,95.20928521609989)) (Point2 (93.53030551178848,95.3)) - , LineSeg (Point2 (93.53030551178848,95.3)) (Point2 (93.5303052036906,95.3)) - , LineSeg (Point2 (93.5303052036906,95.3)) (Point2 (93.54623152772308,95.36137354922205)) - , LineSeg (Point2 (93.54623152772308,95.36137354922205)) (Point2 (93.5543599506901,95.3926959847688)) - , LineSeg (Point2 (93.5543599506901,95.3926959847688)) (Point2 (93.56928030410899,95.45059503353703)) - , LineSeg (Point2 (93.56928030410899,95.45059503353703)) (Point2 (93.59377323794409,95.51632485154659)) - , LineSeg (Point2 (93.59377323794409,95.51632485154659)) (Point2 (93.62517113206894,95.6)) - , LineSeg (Point2 (93.62517113206894,95.6)) (Point2 (93.66980260367518,95.68796916309205)) - , LineSeg (Point2 (93.66980260367518,95.68796916309205)) (Point2 (93.70107642110081,95.75017147975183)) - , LineSeg (Point2 (93.70107642110081,95.75017147975183)) (Point2 (93.75361660957962,95.83016909486017)) - , LineSeg (Point2 (93.75361660957962,95.83016909486017)) (Point2 (93.79991901117867,95.9)) - , LineSeg (Point2 (93.79991901117867,95.9)) (Point2 (93.8,95.90018235516857)) - , LineSeg (Point2 (93.8,95.90018235516857)) (Point2 (93.86807142062428,95.97866928708568)) - , LineSeg (Point2 (93.86807142062428,95.97866928708568)) (Point2 (93.9393399,96.0606601)) - , LineSeg (Point2 (93.9393399,96.0606601)) (Point2 (94.02133071291432,96.13192857937572)) - , LineSeg (Point2 (94.02133071291432,96.13192857937572)) (Point2 (94.09981764483143,96.2)) - , LineSeg (Point2 (94.09981764483143,96.2)) (Point2 (94.1,96.20008098882133)) - , LineSeg (Point2 (94.1,96.20008098882133)) (Point2 (94.16983090513983,96.24638339042038)) - , LineSeg (Point2 (94.16983090513983,96.24638339042038)) (Point2 (94.24982852024817,96.29892357889919)) - , LineSeg (Point2 (94.24982852024817,96.29892357889919)) (Point2 (94.31203083690795,96.33019739632482)) - , LineSeg (Point2 (94.31203083690795,96.33019739632482)) (Point2 (94.4,96.37482886793106)) - , LineSeg (Point2 (94.4,96.37482886793106)) (Point2 (94.48367514845341,96.40622676205591)) - , LineSeg (Point2 (94.48367514845341,96.40622676205591)) (Point2 (94.54940496646297,96.43071969589101)) - , LineSeg (Point2 (94.54940496646297,96.43071969589101)) (Point2 (94.6073040152312,96.4456400493099)) - , LineSeg (Point2 (94.6073040152312,96.4456400493099)) (Point2 (94.7,96.46969448821152)) - , LineSeg (Point2 (94.7,96.46969448821152)) (Point2 (94.79071478390011,96.48349914812064)) - , LineSeg (Point2 (94.79071478390011,96.48349914812064)) (Point2 (94.82428658675514,96.48957491945147)) - , LineSeg (Point2 (94.82428658675514,96.48957491945147)) (Point2 (94.87194341127974,96.49197597708005)) - , LineSeg (Point2 (94.87194341127974,96.49197597708005)) (Point2 (94.90828649116408,96.5)) - , LineSeg (Point2 (94.90828649116408,96.5)) (Point2 (94.96819764062953,96.49923182140608)) - , LineSeg (Point2 (94.96819764062953,96.49923182140608)) (Point2 (95.0,96.5)) - , LineSeg (Point2 (95.0,96.5)) (Point2 (95.03180235937047,96.49923182140608)) - , LineSeg (Point2 (95.03180235937047,96.49923182140608)) (Point2 (95.09171350883592,96.5)) - , LineSeg (Point2 (95.09171350883592,96.5)) (Point2 (95.12805658872026,96.49197597708005)) - , LineSeg (Point2 (95.12805658872026,96.49197597708005)) (Point2 (95.17571341324486,96.48957491945147)) - , LineSeg (Point2 (95.17571341324486,96.48957491945147)) (Point2 (95.20928521609989,96.48349914812064)) - , LineSeg (Point2 (95.20928521609989,96.48349914812064)) (Point2 (95.3,96.46969448821152)) - , LineSeg (Point2 (95.3,96.46969448821152)) (Point2 (95.3926959847688,96.4456400493099)) - , LineSeg (Point2 (95.3926959847688,96.4456400493099)) (Point2 (95.45059503353703,96.43071969589101)) - , LineSeg (Point2 (95.45059503353703,96.43071969589101)) (Point2 (95.51632485154659,96.40622676205591)) - , LineSeg (Point2 (95.51632485154659,96.40622676205591)) (Point2 (95.6,96.37482886793106)) - , LineSeg (Point2 (95.6,96.37482886793106)) (Point2 (95.68796916309205,96.33019739632482)) - , LineSeg (Point2 (95.68796916309205,96.33019739632482)) (Point2 (95.75017147975183,96.29892357889919)) - , LineSeg (Point2 (95.75017147975183,96.29892357889919)) (Point2 (95.83016909486017,96.24638339042038)) - , LineSeg (Point2 (95.83016909486017,96.24638339042038)) (Point2 (95.9,96.20008098882133)) - , LineSeg (Point2 (95.9,96.20008098882133)) (Point2 (95.90018235516857,96.2)) - , LineSeg (Point2 (95.90018235516857,96.2)) (Point2 (95.97866928708568,96.13192857937572)) - , LineSeg (Point2 (95.97866928708568,96.13192857937572)) (Point2 (96.0606601,96.0606601)) - , LineSeg (Point2 (96.0606601,96.0606601)) (Point2 (96.13192857937572,95.97866928708568)) - , LineSeg (Point2 (96.13192857937572,95.97866928708568)) (Point2 (96.2,95.90018235516857)) - , LineSeg (Point2 (96.2,95.90018235516857)) (Point2 (96.20008098882133,95.9)) - , LineSeg (Point2 (96.20008098882133,95.9)) (Point2 (96.24638339042038,95.83016909486017)) - , LineSeg (Point2 (96.24638339042038,95.83016909486017)) (Point2 (96.29892357889919,95.75017147975183)) - , LineSeg (Point2 (96.29892357889919,95.75017147975183)) (Point2 (96.33019739632482,95.68796916309205)) - , LineSeg (Point2 (96.33019739632482,95.68796916309205)) (Point2 (96.37482886793106,95.6)) - , LineSeg (Point2 (96.37482886793106,95.6)) (Point2 (96.40622676205591,95.51632485154659)) - , LineSeg (Point2 (96.40622676205591,95.51632485154659)) (Point2 (96.43071969589101,95.45059503353703)) - , LineSeg (Point2 (96.43071969589101,95.45059503353703)) (Point2 (96.4456400493099,95.3926959847688)) - , LineSeg (Point2 (96.4456400493099,95.3926959847688)) (Point2 (96.46969448821152,95.3)) - , LineSeg (Point2 (96.46969448821152,95.3)) (Point2 (96.4696947963094,95.3)) - , LineSeg (Point2 (96.4696947963094,95.3)) (Point2 (96.47883479278863,95.23993819399247)) - , LineSeg (Point2 (96.47883479278863,95.23993819399247)) (Point2 (96.48349914812064,95.20928521609989)) - , LineSeg (Point2 (96.48349914812064,95.20928521609989)) (Point2 (96.48957491945147,95.17571341324486)) - , LineSeg (Point2 (96.48957491945147,95.17571341324486)) (Point2 (96.49197597708005,95.12805658872026)) - , LineSeg (Point2 (96.49197597708005,95.12805658872026)) (Point2 (96.5,95.09171350883592)) - , LineSeg (Point2 (96.5,95.09171350883592)) (Point2 (96.49923182140608,95.03180235937047)) - , LineSeg (Point2 (96.49923182140608,95.03180235937047)) (Point2 (96.5,95.0)) - , LineSeg (Point2 (96.5,95.0)) (Point2 (96.49923182140608,94.96819764062953)) - , LineSeg (Point2 (96.49923182140608,94.96819764062953)) (Point2 (96.5,94.90828649116408)) - , LineSeg (Point2 (96.5,94.90828649116408)) (Point2 (96.49197597708005,94.87194341127974)) - , LineSeg (Point2 (96.49197597708005,94.87194341127974)) (Point2 (96.48957491945147,94.82428658675514)) - , LineSeg (Point2 (96.48957491945147,94.82428658675514)) (Point2 (96.48349914812064,94.79071478390011)) - , LineSeg (Point2 (96.48349914812064,94.79071478390011)) (Point2 (96.46969448821152,94.7)) - , LineSeg (Point2 (96.46969448821152,94.7)) (Point2 (96.4696947963094,94.7)) - , LineSeg (Point2 (96.4696947963094,94.7)) (Point2 (96.45376847227692,94.63862645077795)) - , LineSeg (Point2 (96.45376847227692,94.63862645077795)) (Point2 (96.4456400493099,94.6073040152312)) - , LineSeg (Point2 (96.4456400493099,94.6073040152312)) (Point2 (96.43071969589101,94.54940496646297)) - , LineSeg (Point2 (96.43071969589101,94.54940496646297)) (Point2 (96.40622676205591,94.48367514845341)) - , LineSeg (Point2 (96.40622676205591,94.48367514845341)) (Point2 (96.37482886793106,94.4)) - , LineSeg (Point2 (96.37482886793106,94.4)) (Point2 (96.33019739632482,94.31203083690795)) - , LineSeg (Point2 (96.33019739632482,94.31203083690795)) (Point2 (96.29892357889919,94.24982852024817)) - , LineSeg (Point2 (96.29892357889919,94.24982852024817)) (Point2 (96.24638339042038,94.16983090513983)) - , LineSeg (Point2 (96.24638339042038,94.16983090513983)) (Point2 (96.20008098882133,94.1)) - , LineSeg (Point2 (96.20008098882133,94.1)) (Point2 (96.2,94.09981764483143)) - , LineSeg (Point2 (96.2,94.09981764483143)) (Point2 (96.13192857937572,94.02133071291432)) - , LineSeg (Point2 (96.13192857937572,94.02133071291432)) (Point2 (96.0606601,93.9393399)) - , LineSeg (Point2 (96.0606601,93.9393399)) (Point2 (95.97866928708568,93.86807142062428)) - , LineSeg (Point2 (95.97866928708568,93.86807142062428)) (Point2 (95.90018235516857,93.8)) - , LineSeg (Point2 (95.90018235516857,93.8)) (Point2 (95.9,93.79991901117867)) - , LineSeg (Point2 (95.9,93.79991901117867)) (Point2 (95.83016909486017,93.75361660957962)) - , LineSeg (Point2 (95.83016909486017,93.75361660957962)) (Point2 (95.75017147975183,93.70107642110081)) - , LineSeg (Point2 (95.75017147975183,93.70107642110081)) (Point2 (95.68796916309205,93.66980260367518)) - , LineSeg (Point2 (95.68796916309205,93.66980260367518)) (Point2 (95.6,93.62517113206894)) - , LineSeg (Point2 (95.6,93.62517113206894)) (Point2 (95.51632485154659,93.59377323794409)) - , LineSeg (Point2 (95.51632485154659,93.59377323794409)) (Point2 (95.45059503353703,93.56928030410899)) - , LineSeg (Point2 (95.45059503353703,93.56928030410899)) (Point2 (95.3926959847688,93.5543599506901)) - , LineSeg (Point2 (95.3926959847688,93.5543599506901)) (Point2 (95.3,93.53030551178848)) - , LineSeg (Point2 (95.3,93.53030551178848)) (Point2 (95.20928521609989,93.51650085187936)) - , LineSeg (Point2 (95.20928521609989,93.51650085187936)) (Point2 (95.17571341324486,93.51042508054853)) - , LineSeg (Point2 (95.17571341324486,93.51042508054853)) (Point2 (95.12805658872026,93.50802402291995)) - , LineSeg (Point2 (95.12805658872026,93.50802402291995)) (Point2 (95.09171350883592,93.5)) - , LineSeg (Point2 (95.09171350883592,93.5)) (Point2 (95.03180235937047,93.50076817859392)) - , LineSeg (Point2 (95.03180235937047,93.50076817859392)) (Point2 (95.0,93.5)) - , LineSeg (Point2 (95.0,93.5)) (Point2 (94.96819764062953,93.50076817859392)) - , LineSeg (Point2 (94.96819764062953,93.50076817859392)) (Point2 (94.90828649116408,93.5)) - , LineSeg (Point2 (94.90828649116408,93.5)) (Point2 (94.87194341127974,93.50802402291995)) - , LineSeg (Point2 (94.87194341127974,93.50802402291995)) (Point2 (94.82428658675514,93.51042508054853)) - , LineSeg (Point2 (94.82428658675514,93.51042508054853)) (Point2 (94.79071478390011,93.51650085187936)) - , LineSeg (Point2 (94.79071478390011,93.51650085187936)) (Point2 (94.7,93.53030551178848)) - , LineSeg (Point2 (94.7,93.53030551178848)) (Point2 (94.7,93.5303052036906)) - , LineSeg (Point2 (94.7,93.5303052036906)) (Point2 (94.63862645077795,93.54623152772308)) - , LineSeg (Point2 (94.63862645077795,93.54623152772308)) (Point2 (94.6073040152312,93.5543599506901)) - , LineSeg (Point2 (94.6073040152312,93.5543599506901)) (Point2 (94.54940496646297,93.56928030410899)) - , LineSeg (Point2 (94.54940496646297,93.56928030410899)) (Point2 (94.48367514845341,93.59377323794409)) - , LineSeg (Point2 (94.48367514845341,93.59377323794409)) (Point2 (94.4,93.62517113206894)) - , LineSeg (Point2 (94.4,93.62517113206894)) (Point2 (94.31203083690795,93.66980260367518)) - , LineSeg (Point2 (94.31203083690795,93.66980260367518)) (Point2 (94.25353875995638,93.69901822960128)) - , LineSeg (Point2 (94.25353875995638,93.69901822960128)) (Point2 (94.19794823502583,93.73505399213997)) - , LineSeg (Point2 (94.19794823502583,93.73505399213997)) (Point2 (94.1,93.8)) - , LineSeg (Point2 (94.1,93.8)) (Point2 (93.99141809848126,93.89417267448127)) - , LineSeg (Point2 (93.99141809848126,93.89417267448127)) (Point2 (93.9393399,93.9393399)) - , LineSeg (Point2 (93.9393399,93.9393399)) (Point2 (93.89417267448127,93.99141809848126)) - , LineSeg (Point2 (93.89417267448127,93.99141809848126)) (Point2 (93.8,94.1)) - , LineSeg (Point2 (93.8,94.1)) (Point2 (93.73505399213997,94.19794823502583)) - , LineSeg (Point2 (93.73505399213997,94.19794823502583)) (Point2 (93.69901822960128,94.25353875995638)) - , LineSeg (Point2 (93.69901822960128,94.25353875995638)) (Point2 (93.66980260367518,94.31203083690795)) - , LineSeg (Point2 (93.66980260367518,94.31203083690795)) (Point2 (93.62517113206894,94.4)) - , LineSeg (Point2 (93.62517113206894,94.4)) (Point2 (93.59377323794409,94.48367514845341)) - , LineSeg (Point2 (93.59377323794409,94.48367514845341)) (Point2 (93.56928030410899,94.54940496646297)) - , LineSeg (Point2 (93.56928030410899,94.54940496646297)) (Point2 (93.5543599506901,94.6073040152312)) - , LineSeg (Point2 (93.5543599506901,94.6073040152312)) (Point2 (93.53030551178848,94.7)) - , LineSeg (Point2 (93.53030551178848,94.7)) (Point2 (93.5303052036906,94.7)) - , LineSeg (Point2 (93.5303052036906,94.7)) (Point2 (93.52116520721137,94.76006180600753)) - , LineSeg (Point2 (93.52116520721137,94.76006180600753)) (Point2 (93.51650085187936,94.79071478390011)) - , LineSeg (Point2 (93.51650085187936,94.79071478390011)) (Point2 (93.51042508054853,94.82428658675514)) - , LineSeg (Point2 (93.51042508054853,94.82428658675514)) (Point2 (93.50802402291995,94.87194341127974)) - , LineSeg (Point2 (93.50802402291995,94.87194341127974)) (Point2 (93.5,94.90828649116408)) + LineSeg (Point2 (V2 93.5 94.90828649116408)) (Point2 (V2 93.50076817859392 94.96819764062953)) + , LineSeg (Point2 (V2 93.50076817859392 94.96819764062953)) (Point2 (V2 93.5 95.0)) + , LineSeg (Point2 (V2 93.5 95.0)) (Point2 (V2 93.50076817859392 95.03180235937047)) + , LineSeg (Point2 (V2 93.50076817859392 95.03180235937047)) (Point2 (V2 93.5 95.09171350883592)) + , LineSeg (Point2 (V2 93.5 95.09171350883592)) (Point2 (V2 93.50802402291995 95.12805658872026)) + , LineSeg (Point2 (V2 93.50802402291995 95.12805658872026)) (Point2 (V2 93.51042508054853 95.17571341324486)) + , LineSeg (Point2 (V2 93.51042508054853 95.17571341324486)) (Point2 (V2 93.51650085187936 95.20928521609989)) + , LineSeg (Point2 (V2 93.51650085187936 95.20928521609989)) (Point2 (V2 93.53030551178848 95.3)) + , LineSeg (Point2 (V2 93.53030551178848 95.3)) (Point2 (V2 93.5303052036906 95.3)) + , LineSeg (Point2 (V2 93.5303052036906 95.3)) (Point2 (V2 93.54623152772308 95.36137354922205)) + , LineSeg (Point2 (V2 93.54623152772308 95.36137354922205)) (Point2 (V2 93.5543599506901 95.3926959847688)) + , LineSeg (Point2 (V2 93.5543599506901 95.3926959847688)) (Point2 (V2 93.56928030410899 95.45059503353703)) + , LineSeg (Point2 (V2 93.56928030410899 95.45059503353703)) (Point2 (V2 93.59377323794409 95.51632485154659)) + , LineSeg (Point2 (V2 93.59377323794409 95.51632485154659)) (Point2 (V2 93.62517113206894 95.6)) + , LineSeg (Point2 (V2 93.62517113206894 95.6)) (Point2 (V2 93.66980260367518 95.68796916309205)) + , LineSeg (Point2 (V2 93.66980260367518 95.68796916309205)) (Point2 (V2 93.70107642110081 95.75017147975183)) + , LineSeg (Point2 (V2 93.70107642110081 95.75017147975183)) (Point2 (V2 93.75361660957962 95.83016909486017)) + , LineSeg (Point2 (V2 93.75361660957962 95.83016909486017)) (Point2 (V2 93.79991901117867 95.9)) + , LineSeg (Point2 (V2 93.79991901117867 95.9)) (Point2 (V2 93.8 95.90018235516857)) + , LineSeg (Point2 (V2 93.8 95.90018235516857)) (Point2 (V2 93.86807142062428 95.97866928708568)) + , LineSeg (Point2 (V2 93.86807142062428 95.97866928708568)) (Point2 (V2 93.9393399 96.0606601)) + , LineSeg (Point2 (V2 93.9393399 96.0606601)) (Point2 (V2 94.02133071291432 96.13192857937572)) + , LineSeg (Point2 (V2 94.02133071291432 96.13192857937572)) (Point2 (V2 94.09981764483143 96.2)) + , LineSeg (Point2 (V2 94.09981764483143 96.2)) (Point2 (V2 94.1 96.20008098882133)) + , LineSeg (Point2 (V2 94.1 96.20008098882133)) (Point2 (V2 94.16983090513983 96.24638339042038)) + , LineSeg (Point2 (V2 94.16983090513983 96.24638339042038)) (Point2 (V2 94.24982852024817 96.29892357889919)) + , LineSeg (Point2 (V2 94.24982852024817 96.29892357889919)) (Point2 (V2 94.31203083690795 96.33019739632482)) + , LineSeg (Point2 (V2 94.31203083690795 96.33019739632482)) (Point2 (V2 94.4 96.37482886793106)) + , LineSeg (Point2 (V2 94.4 96.37482886793106)) (Point2 (V2 94.48367514845341 96.40622676205591)) + , LineSeg (Point2 (V2 94.48367514845341 96.40622676205591)) (Point2 (V2 94.54940496646297 96.43071969589101)) + , LineSeg (Point2 (V2 94.54940496646297 96.43071969589101)) (Point2 (V2 94.6073040152312 96.4456400493099)) + , LineSeg (Point2 (V2 94.6073040152312 96.4456400493099)) (Point2 (V2 94.7 96.46969448821152)) + , LineSeg (Point2 (V2 94.7 96.46969448821152)) (Point2 (V2 94.79071478390011 96.48349914812064)) + , LineSeg (Point2 (V2 94.79071478390011 96.48349914812064)) (Point2 (V2 94.82428658675514 96.48957491945147)) + , LineSeg (Point2 (V2 94.82428658675514 96.48957491945147)) (Point2 (V2 94.87194341127974 96.49197597708005)) + , LineSeg (Point2 (V2 94.87194341127974 96.49197597708005)) (Point2 (V2 94.90828649116408 96.5)) + , LineSeg (Point2 (V2 94.90828649116408 96.5)) (Point2 (V2 94.96819764062953 96.49923182140608)) + , LineSeg (Point2 (V2 94.96819764062953 96.49923182140608)) (Point2 (V2 95.0 96.5)) + , LineSeg (Point2 (V2 95.0 96.5)) (Point2 (V2 95.03180235937047 96.49923182140608)) + , LineSeg (Point2 (V2 95.03180235937047 96.49923182140608)) (Point2 (V2 95.09171350883592 96.5)) + , LineSeg (Point2 (V2 95.09171350883592 96.5)) (Point2 (V2 95.12805658872026 96.49197597708005)) + , LineSeg (Point2 (V2 95.12805658872026 96.49197597708005)) (Point2 (V2 95.17571341324486 96.48957491945147)) + , LineSeg (Point2 (V2 95.17571341324486 96.48957491945147)) (Point2 (V2 95.20928521609989 96.48349914812064)) + , LineSeg (Point2 (V2 95.20928521609989 96.48349914812064)) (Point2 (V2 95.3 96.46969448821152)) + , LineSeg (Point2 (V2 95.3 96.46969448821152)) (Point2 (V2 95.3926959847688 96.4456400493099)) + , LineSeg (Point2 (V2 95.3926959847688 96.4456400493099)) (Point2 (V2 95.45059503353703 96.43071969589101)) + , LineSeg (Point2 (V2 95.45059503353703 96.43071969589101)) (Point2 (V2 95.51632485154659 96.40622676205591)) + , LineSeg (Point2 (V2 95.51632485154659 96.40622676205591)) (Point2 (V2 95.6 96.37482886793106)) + , LineSeg (Point2 (V2 95.6 96.37482886793106)) (Point2 (V2 95.68796916309205 96.33019739632482)) + , LineSeg (Point2 (V2 95.68796916309205 96.33019739632482)) (Point2 (V2 95.75017147975183 96.29892357889919)) + , LineSeg (Point2 (V2 95.75017147975183 96.29892357889919)) (Point2 (V2 95.83016909486017 96.24638339042038)) + , LineSeg (Point2 (V2 95.83016909486017 96.24638339042038)) (Point2 (V2 95.9 96.20008098882133)) + , LineSeg (Point2 (V2 95.9 96.20008098882133)) (Point2 (V2 95.90018235516857 96.2)) + , LineSeg (Point2 (V2 95.90018235516857 96.2)) (Point2 (V2 95.97866928708568 96.13192857937572)) + , LineSeg (Point2 (V2 95.97866928708568 96.13192857937572)) (Point2 (V2 96.0606601 96.0606601)) + , LineSeg (Point2 (V2 96.0606601 96.0606601)) (Point2 (V2 96.13192857937572 95.97866928708568)) + , LineSeg (Point2 (V2 96.13192857937572 95.97866928708568)) (Point2 (V2 96.2 95.90018235516857)) + , LineSeg (Point2 (V2 96.2 95.90018235516857)) (Point2 (V2 96.20008098882133 95.9)) + , LineSeg (Point2 (V2 96.20008098882133 95.9)) (Point2 (V2 96.24638339042038 95.83016909486017)) + , LineSeg (Point2 (V2 96.24638339042038 95.83016909486017)) (Point2 (V2 96.29892357889919 95.75017147975183)) + , LineSeg (Point2 (V2 96.29892357889919 95.75017147975183)) (Point2 (V2 96.33019739632482 95.68796916309205)) + , LineSeg (Point2 (V2 96.33019739632482 95.68796916309205)) (Point2 (V2 96.37482886793106 95.6)) + , LineSeg (Point2 (V2 96.37482886793106 95.6)) (Point2 (V2 96.40622676205591 95.51632485154659)) + , LineSeg (Point2 (V2 96.40622676205591 95.51632485154659)) (Point2 (V2 96.43071969589101 95.45059503353703)) + , LineSeg (Point2 (V2 96.43071969589101 95.45059503353703)) (Point2 (V2 96.4456400493099 95.3926959847688)) + , LineSeg (Point2 (V2 96.4456400493099 95.3926959847688)) (Point2 (V2 96.46969448821152 95.3)) + , LineSeg (Point2 (V2 96.46969448821152 95.3)) (Point2 (V2 96.4696947963094 95.3)) + , LineSeg (Point2 (V2 96.4696947963094 95.3)) (Point2 (V2 96.47883479278863 95.23993819399247)) + , LineSeg (Point2 (V2 96.47883479278863 95.23993819399247)) (Point2 (V2 96.48349914812064 95.20928521609989)) + , LineSeg (Point2 (V2 96.48349914812064 95.20928521609989)) (Point2 (V2 96.48957491945147 95.17571341324486)) + , LineSeg (Point2 (V2 96.48957491945147 95.17571341324486)) (Point2 (V2 96.49197597708005 95.12805658872026)) + , LineSeg (Point2 (V2 96.49197597708005 95.12805658872026)) (Point2 (V2 96.5 95.09171350883592)) + , LineSeg (Point2 (V2 96.5 95.09171350883592)) (Point2 (V2 96.49923182140608 95.03180235937047)) + , LineSeg (Point2 (V2 96.49923182140608 95.03180235937047)) (Point2 (V2 96.5 95.0)) + , LineSeg (Point2 (V2 96.5 95.0)) (Point2 (V2 96.49923182140608 94.96819764062953)) + , LineSeg (Point2 (V2 96.49923182140608 94.96819764062953)) (Point2 (V2 96.5 94.90828649116408)) + , LineSeg (Point2 (V2 96.5 94.90828649116408)) (Point2 (V2 96.49197597708005 94.87194341127974)) + , LineSeg (Point2 (V2 96.49197597708005 94.87194341127974)) (Point2 (V2 96.48957491945147 94.82428658675514)) + , LineSeg (Point2 (V2 96.48957491945147 94.82428658675514)) (Point2 (V2 96.48349914812064 94.79071478390011)) + , LineSeg (Point2 (V2 96.48349914812064 94.79071478390011)) (Point2 (V2 96.46969448821152 94.7)) + , LineSeg (Point2 (V2 96.46969448821152 94.7)) (Point2 (V2 96.4696947963094 94.7)) + , LineSeg (Point2 (V2 96.4696947963094 94.7)) (Point2 (V2 96.45376847227692 94.63862645077795)) + , LineSeg (Point2 (V2 96.45376847227692 94.63862645077795)) (Point2 (V2 96.4456400493099 94.6073040152312)) + , LineSeg (Point2 (V2 96.4456400493099 94.6073040152312)) (Point2 (V2 96.43071969589101 94.54940496646297)) + , LineSeg (Point2 (V2 96.43071969589101 94.54940496646297)) (Point2 (V2 96.40622676205591 94.48367514845341)) + , LineSeg (Point2 (V2 96.40622676205591 94.48367514845341)) (Point2 (V2 96.37482886793106 94.4)) + , LineSeg (Point2 (V2 96.37482886793106 94.4)) (Point2 (V2 96.33019739632482 94.31203083690795)) + , LineSeg (Point2 (V2 96.33019739632482 94.31203083690795)) (Point2 (V2 96.29892357889919 94.24982852024817)) + , LineSeg (Point2 (V2 96.29892357889919 94.24982852024817)) (Point2 (V2 96.24638339042038 94.16983090513983)) + , LineSeg (Point2 (V2 96.24638339042038 94.16983090513983)) (Point2 (V2 96.20008098882133 94.1)) + , LineSeg (Point2 (V2 96.20008098882133 94.1)) (Point2 (V2 96.2 94.09981764483143)) + , LineSeg (Point2 (V2 96.2 94.09981764483143)) (Point2 (V2 96.13192857937572 94.02133071291432)) + , LineSeg (Point2 (V2 96.13192857937572 94.02133071291432)) (Point2 (V2 96.0606601 93.9393399)) + , LineSeg (Point2 (V2 96.0606601 93.9393399)) (Point2 (V2 95.97866928708568 93.86807142062428)) + , LineSeg (Point2 (V2 95.97866928708568 93.86807142062428)) (Point2 (V2 95.90018235516857 93.8)) + , LineSeg (Point2 (V2 95.90018235516857 93.8)) (Point2 (V2 95.9 93.79991901117867)) + , LineSeg (Point2 (V2 95.9 93.79991901117867)) (Point2 (V2 95.83016909486017 93.75361660957962)) + , LineSeg (Point2 (V2 95.83016909486017 93.75361660957962)) (Point2 (V2 95.75017147975183 93.70107642110081)) + , LineSeg (Point2 (V2 95.75017147975183 93.70107642110081)) (Point2 (V2 95.68796916309205 93.66980260367518)) + , LineSeg (Point2 (V2 95.68796916309205 93.66980260367518)) (Point2 (V2 95.6 93.62517113206894)) + , LineSeg (Point2 (V2 95.6 93.62517113206894)) (Point2 (V2 95.51632485154659 93.59377323794409)) + , LineSeg (Point2 (V2 95.51632485154659 93.59377323794409)) (Point2 (V2 95.45059503353703 93.56928030410899)) + , LineSeg (Point2 (V2 95.45059503353703 93.56928030410899)) (Point2 (V2 95.3926959847688 93.5543599506901)) + , LineSeg (Point2 (V2 95.3926959847688 93.5543599506901)) (Point2 (V2 95.3 93.53030551178848)) + , LineSeg (Point2 (V2 95.3 93.53030551178848)) (Point2 (V2 95.20928521609989 93.51650085187936)) + , LineSeg (Point2 (V2 95.20928521609989 93.51650085187936)) (Point2 (V2 95.17571341324486 93.51042508054853)) + , LineSeg (Point2 (V2 95.17571341324486 93.51042508054853)) (Point2 (V2 95.12805658872026 93.50802402291995)) + , LineSeg (Point2 (V2 95.12805658872026 93.50802402291995)) (Point2 (V2 95.09171350883592 93.5)) + , LineSeg (Point2 (V2 95.09171350883592 93.5)) (Point2 (V2 95.03180235937047 93.50076817859392)) + , LineSeg (Point2 (V2 95.03180235937047 93.50076817859392)) (Point2 (V2 95.0 93.5)) + , LineSeg (Point2 (V2 95.0 93.5)) (Point2 (V2 94.96819764062953 93.50076817859392)) + , LineSeg (Point2 (V2 94.96819764062953 93.50076817859392)) (Point2 (V2 94.90828649116408 93.5)) + , LineSeg (Point2 (V2 94.90828649116408 93.5)) (Point2 (V2 94.87194341127974 93.50802402291995)) + , LineSeg (Point2 (V2 94.87194341127974 93.50802402291995)) (Point2 (V2 94.82428658675514 93.51042508054853)) + , LineSeg (Point2 (V2 94.82428658675514 93.51042508054853)) (Point2 (V2 94.79071478390011 93.51650085187936)) + , LineSeg (Point2 (V2 94.79071478390011 93.51650085187936)) (Point2 (V2 94.7 93.53030551178848)) + , LineSeg (Point2 (V2 94.7 93.53030551178848)) (Point2 (V2 94.7 93.5303052036906)) + , LineSeg (Point2 (V2 94.7 93.5303052036906)) (Point2 (V2 94.63862645077795 93.54623152772308)) + , LineSeg (Point2 (V2 94.63862645077795 93.54623152772308)) (Point2 (V2 94.6073040152312 93.5543599506901)) + , LineSeg (Point2 (V2 94.6073040152312 93.5543599506901)) (Point2 (V2 94.54940496646297 93.56928030410899)) + , LineSeg (Point2 (V2 94.54940496646297 93.56928030410899)) (Point2 (V2 94.48367514845341 93.59377323794409)) + , LineSeg (Point2 (V2 94.48367514845341 93.59377323794409)) (Point2 (V2 94.4 93.62517113206894)) + , LineSeg (Point2 (V2 94.4 93.62517113206894)) (Point2 (V2 94.31203083690795 93.66980260367518)) + , LineSeg (Point2 (V2 94.31203083690795 93.66980260367518)) (Point2 (V2 94.25353875995638 93.69901822960128)) + , LineSeg (Point2 (V2 94.25353875995638 93.69901822960128)) (Point2 (V2 94.19794823502583 93.73505399213997)) + , LineSeg (Point2 (V2 94.19794823502583 93.73505399213997)) (Point2 (V2 94.1 93.8)) + , LineSeg (Point2 (V2 94.1 93.8)) (Point2 (V2 93.99141809848126 93.89417267448127)) + , LineSeg (Point2 (V2 93.99141809848126 93.89417267448127)) (Point2 (V2 93.9393399 93.9393399)) + , LineSeg (Point2 (V2 93.9393399 93.9393399)) (Point2 (V2 93.89417267448127 93.99141809848126)) + , LineSeg (Point2 (V2 93.89417267448127 93.99141809848126)) (Point2 (V2 93.8 94.1)) + , LineSeg (Point2 (V2 93.8 94.1)) (Point2 (V2 93.73505399213997 94.19794823502583)) + , LineSeg (Point2 (V2 93.73505399213997 94.19794823502583)) (Point2 (V2 93.69901822960128 94.25353875995638)) + , LineSeg (Point2 (V2 93.69901822960128 94.25353875995638)) (Point2 (V2 93.66980260367518 94.31203083690795)) + , LineSeg (Point2 (V2 93.66980260367518 94.31203083690795)) (Point2 (V2 93.62517113206894 94.4)) + , LineSeg (Point2 (V2 93.62517113206894 94.4)) (Point2 (V2 93.59377323794409 94.48367514845341)) + , LineSeg (Point2 (V2 93.59377323794409 94.48367514845341)) (Point2 (V2 93.56928030410899 94.54940496646297)) + , LineSeg (Point2 (V2 93.56928030410899 94.54940496646297)) (Point2 (V2 93.5543599506901 94.6073040152312)) + , LineSeg (Point2 (V2 93.5543599506901 94.6073040152312)) (Point2 (V2 93.53030551178848 94.7)) + , LineSeg (Point2 (V2 93.53030551178848 94.7)) (Point2 (V2 93.5303052036906 94.7)) + , LineSeg (Point2 (V2 93.5303052036906 94.7)) (Point2 (V2 93.52116520721137 94.76006180600753)) + , LineSeg (Point2 (V2 93.52116520721137 94.76006180600753)) (Point2 (V2 93.51650085187936 94.79071478390011)) + , LineSeg (Point2 (V2 93.51650085187936 94.79071478390011)) (Point2 (V2 93.51042508054853 94.82428658675514)) + , LineSeg (Point2 (V2 93.51042508054853 94.82428658675514)) (Point2 (V2 93.50802402291995 94.87194341127974)) + , LineSeg (Point2 (V2 93.50802402291995 94.87194341127974)) (Point2 (V2 93.5 94.90828649116408)) ] unit_ContourStraightSkeleton :: Bool @@ -1336,310 +1338,310 @@ unit_ContourStraightSkeleton foundCrashTree = crashMotorcycles contour [] contour = makePointContour [ - Point2 (90.52523656434744,95.00000174891758) - , Point2 (90.53142329122582,94.79396066779452) - , Point2 (90.53329723636156,94.73153680661488) - , Point2 (90.54033450891663,94.65368440793033) - , Point2 (90.55756606924172,94.46308666918914) - , Point2 (90.58651545318247,94.27236502645694) - , Point2 (90.59831416553266,94.19463047494156) - , Point2 (90.63427942825298,94.02726792711351) - , Point2 (90.6565799102664,93.92350075036973) - , Point2 (90.68091987240932,93.83312630349931) - , Point2 (90.69161721584192,93.7934078846186) - , Point2 (90.45798854627252,94.72464821764876) - , Point2 (90.70851141288935,95.0035666558769) - , Point2 (90.72470857221676,93.6787962257674) - , Point2 (90.71686751134479,93.70462952271815) - , Point2 (90.72952213831952,93.66287058994163) - , Point2 (90.78070835247406,93.51653297708901) - , Point2 (90.82520802497912,93.3892688534728) - , Point2 (90.90624931444934,93.19804504021239) - , Point2 (90.94150257884705,93.11489841608606) - , Point2 (90.95572991964394,93.08485212346775) - , Point2 (90.96313171312099,93.06922211966878) - , Point2 (90.72652681410516,93.57890934126299) - , Point2 (90.84262888113695,93.64614576163498) - , Point2 (91.00457140327511,92.9877165187992) - , Point2 (90.99729940346542,93.00153612830023) - , Point2 (91.07310800340393,92.85443085993114) - , Point2 (91.19549665585357,92.64817812784116) - , Point2 (91.21433185597525,92.61531992422698) - , Point2 (91.23159288196383,92.59000000562422) - , Point2 (91.24249360257754,92.57306689824158) - , Point2 (91.27416224820777,92.52306138001785) - , Point2 (91.31292335349919,92.46920879270783) - , Point2 (91.42314316680815,92.3110058858731) - , Point2 (91.45203881053632,92.2737028943519) - , Point2 (91.50856391778473,92.20084333118147) - , Point2 (91.54860908146797,92.15316473577967) - , Point2 (91.63803055044139,92.0466706450613) - , Point2 (91.67743528902548,92.00382438277838) - , Point2 (91.77893367224766,91.89353345085307) - , Point2 (91.89347699284706,91.77899013025392) - , Point2 (91.94074811840437,91.73551406197616) - , Point2 (92.04675728664768,91.63795609422435) - , Point2 (92.10101271492351,91.59238851031962) - , Point2 (92.20068613513772,91.50869425480059) - , Point2 (92.24723328986644,91.47263118569387) - , Point2 (92.31116595249517,91.42303164854623) - , Point2 (92.46920879270783,91.31292335349919) - , Point2 (92.52306138001785,91.27416224820777) - , Point2 (92.57306689824158,91.24249360257754) - , Point2 (92.59000000562422,91.23159288196383) - , Point2 (92.61531992422698,91.21433185597525) - , Point2 (92.64817812784116,91.19549665585357) - , Point2 (92.85443085993114,91.07310800340393) - , Point2 (93.00153612830023,90.99729940346542) - , Point2 (92.9877165187992,91.00457140327511) - , Point2 (93.64614576163498,90.84262888113695) - , Point2 (93.57890934126299,90.72652681410516) - , Point2 (93.06921257352505,90.96313614459115) - , Point2 (93.42500016128389,90.79466573133263) - , Point2 (93.42500016128389,90.81008228377397) - , Point2 (93.2553067080979,90.88199893489247) - , Point2 (93.3893185640321,90.82518875825394) - , Point2 (93.58014939008443,90.75843963386609) - , Point2 (93.66283004683464,90.72953442450273) - , Point2 (93.70462952271815,90.71686751134479) - , Point2 (93.6787962257674,90.72470857221676) - , Point2 (95.0035666558769,90.70851141288935) - , Point2 (94.72464821764876,90.45798854627252) - , Point2 (93.79340645273629,90.69161757507065) - , Point2 (94.32499905369538,90.54844719520653) - , Point2 (94.32499905369538,90.57030039121904) - , Point2 (94.06540699489828,90.62608525342779) - , Point2 (94.19463503093796,90.59831336971094) - , Point2 (94.36182397553434,90.57293598272166) - , Point2 (94.46308075203177,90.55756688471223) - , Point2 (94.52907271560787,90.55160185380022) - , Point2 (94.73154266868215,90.53329695028441) - , Point2 (94.93394738885749,90.52721941116873) - , Point2 (94.99999825080576,90.52523656434427) - , Point2 (95.20603864909656,90.53142327070195) - , Point2 (95.26845915434926,90.53329711511131) - , Point2 (95.47092597864834,90.55160173577174) - , Point2 (95.5369179009237,90.55756676293966) - , Point2 (95.72763456627625,90.5865153913174) - , Point2 (95.80536952523627,90.59831416556366) - , Point2 (95.97273091437924,90.63427917952613) - , Point2 (95.67500241241035,90.57029469842847) - , Point2 (95.67500241241035,90.54844759006447) - , Point2 (95.99233448829969,90.63391257540528) - , Point2 (96.04267935701206,90.72130322420693) - , Point2 (96.32120377431346,90.72470857222879) - , Point2 (96.2953704828859,90.71686751302332) - , Point2 (96.3371294100193,90.7295221382979) - , Point2 (96.48346706519771,90.78070836720458) - , Point2 (96.61073114647759,90.82520802495871) - , Point2 (96.80195481893021,90.90624925476074) - , Point2 (96.57500197520388,90.81002371716855) - , Point2 (96.57500197520388,90.79466674295354) - , Point2 (96.7505871557286,90.87780878877794) - , Point2 (96.7808911720591,90.9476598147312) - , Point2 (97.01228348120087,91.00457140326334) - , Point2 (96.99846387205933,90.99729940364361) - , Point2 (97.14556914002745,91.07310800337467) - , Point2 (97.35182187137244,91.19549665538213) - , Point2 (97.38468007534733,91.2143318557108) - , Point2 (97.40999999109025,91.23159287974991) - , Point2 (97.42693310995041,91.24249360775116) - , Point2 (97.47693861989968,91.27416224814222) - , Point2 (97.53079120744584,91.31292335360351) - , Point2 (97.68899411397008,91.42314316669616) - , Point2 (97.7262971254248,91.45203882586043) - , Point2 (97.79915666886333,91.5085639178057) - , Point2 (97.84683531111433,91.54860912088927) - , Point2 (97.95332935540218,91.63803055082391) - , Point2 (97.99617555962381,91.67743523601872) - , Point2 (98.10646654911997,91.77893367221348) - , Point2 (98.22100986988748,91.893476992981) - , Point2 (98.26448598740386,91.94074817209514) - , Point2 (98.36204390620595,92.04675728712832) - , Point2 (98.40761130286943,92.10101249256334) - , Point2 (98.49130574500188,92.20068613491986) - , Point2 (98.52736879008327,92.2472332586774) - , Point2 (98.5769683514337,92.31116595246483) - , Point2 (98.68707664525635,92.46920879092053) - , Point2 (98.72583775174817,92.52306137989812) - , Point2 (98.75750639174875,92.57306688923168) - , Point2 (98.76840712043132,92.5900000091495) - , Point2 (98.7856681440925,92.61531992433784) - , Point2 (98.80450334418863,92.64817812790682) - , Point2 (98.92689199658932,92.8544308599146) - , Point2 (99.00270059440984,93.0015361241765) - , Point2 (98.99542859666329,92.9877165185938) - , Point2 (99.05234018524767,93.21910882794803) - , Point2 (99.12220223165113,93.24941762536655) - , Point2 (99.04427031185622,93.08485261291638) - , Point2 (99.0584797213727,93.11486103656337) - , Point2 (99.11800101000759,93.25530657805943) - , Point2 (99.17481124170774,93.3893185639057) - , Point2 (99.24156033966989,93.58014931441157) - , Point2 (99.27046557560026,93.66283004715103) - , Point2 (99.28313248099097,93.70462949739651) - , Point2 (99.27529142774954,93.67879622559256) - , Point2 (99.27869677577166,93.9573206429153) - , Point2 (99.36608892343524,94.00766637510688) - , Point2 (99.31908204351448,93.833133417053) - , Point2 (99.34341914371794,93.92349723780309) - , Point2 (99.37391472738378,94.06540690717972) - , Point2 (99.4016866303127,94.19463503106583) - , Point2 (99.42706361269667,94.36182130792311) - , Point2 (99.44243311530897,94.46308075223536) - , Point2 (99.44839819551188,94.52907326162845) - , Point2 (99.46670304970871,94.73154266868238) - , Point2 (99.47278063225963,94.93394883753771) - , Point2 (99.47476343565559,94.99999825070864) - , Point2 (99.46857670970934,95.20603930178119) - , Point2 (99.46670276362087,95.26846319370384) - , Point2 (99.45966555325245,95.34631490361156) - , Point2 (99.44243393075298,95.53691333087573) - , Point2 (99.41348459608173,95.72763464802651) - , Point2 (99.40168583447436,95.8053695250555) - , Point2 (99.36572072216647,95.97273137104125) - , Point2 (99.34342008973506,96.07649924960621) - , Point2 (99.31908080382114,96.16687118413628) - , Point2 (99.30838278414635,96.2065921153522) - , Point2 (99.54201145370311,95.27535178237046) - , Point2 (99.29148858710127,94.99643334415902) - , Point2 (99.27529142777428,96.3212037742354) - , Point2 (99.2831325042824,96.29537042580031) - , Point2 (99.27047786178193,96.33712940977867) - , Point2 (99.21929163217742,96.48346706695861) - , Point2 (99.17479197502927,96.61073114649997) - , Point2 (99.09375071189352,96.80195489765781) - , Point2 (99.05849742129114,96.88510158355312) - , Point2 (99.04426994211163,96.91514816784013) - , Point2 (99.03686829621603,96.93077786057788) - , Point2 (99.27347318599062,96.42109065888862) - , Point2 (99.23145620824842,96.39675800702065) - , Point2 (98.9887378945167,97.0255582518726) - , Point2 (98.92689199658712,97.14556914008277) - , Point2 (98.80450334376476,97.35182187280202) - , Point2 (98.78566814411468,97.38468007559177) - , Point2 (98.76840712264506,97.40999998756496) - , Point2 (98.75750638475104,97.42693312179145) - , Point2 (98.72583775177804,97.47693862002909) - , Point2 (98.68707664602151,97.53079120798513) - , Point2 (98.57685683330901,97.68899411396428) - , Point2 (98.5479611708476,97.72629712964388) - , Point2 (98.4914360824291,97.79915666856763) - , Point2 (98.45139095863219,97.84683521640524) - , Point2 (98.36196944949798,97.95332935502714) - , Point2 (98.32256476526807,97.99617555817369) - , Point2 (98.22106632740235,98.1064665495116) - , Point2 (98.10652300728816,98.22100986962587) - , Point2 (98.05925189022336,98.264485930152) - , Point2 (97.95324271337233,98.36204390576556) - , Point2 (97.89898734388426,98.40761144019713) - , Point2 (97.7993138653753,98.49130574476509) - , Point2 (97.75276674051467,98.52736879068212) - , Point2 (97.68883404738446,98.57696835154178) - , Point2 (97.53079120798513,98.68707664602151) - , Point2 (97.47693862002909,98.72583775177804) - , Point2 (97.42693312179145,98.75750638475104) - , Point2 (97.40999998756496,98.76840712264506) - , Point2 (97.38468007559177,98.78566814411468) - , Point2 (97.35182187280202,98.80450334376476) - , Point2 (97.14556914008277,98.92689199658712) - , Point2 (97.0255582518726,98.9887378945167) - , Point2 (96.39675800702065,99.23145620824842) - , Point2 (96.42109065888862,99.27347318599062) - , Point2 (96.93078740986465,99.03686386328597) - , Point2 (96.5749992941212,99.20533452655235) - , Point2 (96.57499929412121,99.18991794702926) - , Point2 (96.74469323969993,99.11800108723378) - , Point2 (96.61068143584744,99.174811241793) - , Point2 (96.41985067443075,99.2415603436121) - , Point2 (96.3371699526587,99.27046557566783) - , Point2 (96.29537042580031,99.2831325042824) - , Point2 (96.3212037742354,99.27529142777428) - , Point2 (94.99643334415902,99.29148858710127) - , Point2 (95.27535178237046,99.54201145370311) - , Point2 (96.20659354843383,99.30838242461583) - , Point2 (95.67499388234063,99.45155470728702) - , Point2 (95.67499388234063,99.429701126789) - , Point2 (95.9345930669576,99.37391473310454) - , Point2 (95.80536496906157,99.40168663029196) - , Point2 (95.63818083325516,99.42706328822015) - , Point2 (95.53691924734949,99.44243311535939) - , Point2 (95.47092637362476,99.44839822852755) - , Point2 (95.26845733130304,99.46670304971644) - , Point2 (95.06605397617153,99.47278054771773) - , Point2 (95.00000174901494,99.4747634356524) - , Point2 (94.79396001510987,99.46857668918547) - , Point2 (94.73153680663427,99.46670276363139) - , Point2 (94.65368398104647,99.45966545242192) - , Point2 (94.4630866691153,99.4424339307494) - , Point2 (94.27236628806229,99.41348473831613) - , Point2 (94.19463047496532,99.40168583448144) - , Point2 (94.02726922936988,99.36572085121198) - , Point2 (94.32499905369538,99.42970561665034) - , Point2 (94.32499905369538,99.45155280479676) - , Point2 (94.00766551163201,99.36608742458083) - , Point2 (93.9573206429153,99.27869677577166) - , Point2 (93.67879622559256,99.27529142774954) - , Point2 (93.70462949739651,99.28313248099097) - , Point2 (93.6628705901826,99.27047786176048) - , Point2 (93.5165329755313,99.21929164704339) - , Point2 (93.3892688534513,99.17479197500914) - , Point2 (93.19804506646996,99.0937506966894) - , Point2 (93.4249974802012,99.18997605194838) - , Point2 (93.4249974802012,99.20533299911274) - , Point2 (93.24941284425896,99.12219121115578) - , Point2 (93.23517951491657,99.0893832609998) - , Point2 (92.97444174818017,98.98873789454744) - , Point2 (92.8544308599146,98.92689199658932) - , Point2 (92.64817812790682,98.80450334418863) - , Point2 (92.61531992433784,98.7856681440925) - , Point2 (92.5900000091495,98.76840712043132) - , Point2 (92.57306688923168,98.75750639174875) - , Point2 (92.52306137989812,98.72583775174817) - , Point2 (92.46920879092053,98.68707664525635) - , Point2 (92.3110058858783,98.57685683319652) - , Point2 (92.2737028901376,98.5479611862004) - , Point2 (92.20084333147669,98.49143608244958) - , Point2 (92.15316483055265,98.45139099806059) - , Point2 (92.04667064499658,98.36196944951091) - , Point2 (92.00382439167613,98.32256471915899) - , Point2 (91.89353345084716,98.22106632775365) - , Point2 (91.77899013010654,98.10652300701301) - , Point2 (91.73551401344223,98.05925182882105) - , Point2 (91.63795609367615,97.95324271274465) - , Point2 (91.59238870718953,97.89898751943518) - , Point2 (91.50869425483597,97.79931386489767) - , Point2 (91.47263118510182,97.75276670932834) - , Point2 (91.42303164843861,97.68883404735429) - , Point2 (91.31292335360351,97.53079120744584) - , Point2 (91.27416224814222,97.47693861989968) - , Point2 (91.24249360775116,97.42693310995041) - , Point2 (91.23159287974991,97.40999999109025) - , Point2 (91.2143318557108,97.38468007534733) - , Point2 (91.19549665538213,97.35182187137244) - , Point2 (91.07310800337467,97.14556914002745) - , Point2 (91.01126210549467,97.02555825191367) - , Point2 (90.91061673901486,96.7648204851061) - , Point2 (90.87779776835599,96.75058237465284) - , Point2 (90.95572946023208,96.9151469057644) - , Point2 (90.94152027883361,96.88513896392662) - , Point2 (90.88199894680963,96.74469332004125) - , Point2 (90.8251887582333,96.6106814359307) - , Point2 (90.75843964697009,96.4198506474299) - , Point2 (90.72953442443512,96.33716995297458) - , Point2 (90.71686751302332,96.2953704828859) - , Point2 (90.72470857222879,96.32120377431346) - , Point2 (90.72130322420693,96.04267935701206) - , Point2 (90.63391107647031,95.99233362477842) - , Point2 (90.68092111210268,96.1668783002161) - , Point2 (90.65658085625388,96.07650276206564) - , Point2 (90.62608523245162,95.93459290804716) - , Point2 (90.59831336970156,95.80536496899053) - , Point2 (90.57293630616262,95.63817815459794) - , Point2 (90.55756688466185,95.5369192475533) - , Point2 (90.55160173577174,95.47092597864834) - , Point2 (90.53329695028086,95.26845733116474) - , Point2 (90.52721945817349,95.0660541767252) + Point2 (V2 90.52523656434744 95.00000174891758) + , Point2 (V2 90.53142329122582 94.79396066779452) + , Point2 (V2 90.53329723636156 94.73153680661488) + , Point2 (V2 90.54033450891663 94.65368440793033) + , Point2 (V2 90.55756606924172 94.46308666918914) + , Point2 (V2 90.58651545318247 94.27236502645694) + , Point2 (V2 90.59831416553266 94.19463047494156) + , Point2 (V2 90.63427942825298 94.02726792711351) + , Point2 (V2 90.6565799102664 93.92350075036973) + , Point2 (V2 90.68091987240932 93.83312630349931) + , Point2 (V2 90.69161721584192 93.7934078846186) + , Point2 (V2 90.45798854627252 94.72464821764876) + , Point2 (V2 90.70851141288935 95.0035666558769) + , Point2 (V2 90.72470857221676 93.6787962257674) + , Point2 (V2 90.71686751134479 93.70462952271815) + , Point2 (V2 90.72952213831952 93.66287058994163) + , Point2 (V2 90.78070835247406 93.51653297708901) + , Point2 (V2 90.82520802497912 93.3892688534728) + , Point2 (V2 90.90624931444934 93.19804504021239) + , Point2 (V2 90.94150257884705 93.11489841608606) + , Point2 (V2 90.95572991964394 93.08485212346775) + , Point2 (V2 90.96313171312099 93.06922211966878) + , Point2 (V2 90.72652681410516 93.57890934126299) + , Point2 (V2 90.84262888113695 93.64614576163498) + , Point2 (V2 91.00457140327511 92.9877165187992) + , Point2 (V2 90.99729940346542 93.00153612830023) + , Point2 (V2 91.07310800340393 92.85443085993114) + , Point2 (V2 91.19549665585357 92.64817812784116) + , Point2 (V2 91.21433185597525 92.61531992422698) + , Point2 (V2 91.23159288196383 92.59000000562422) + , Point2 (V2 91.24249360257754 92.57306689824158) + , Point2 (V2 91.27416224820777 92.52306138001785) + , Point2 (V2 91.31292335349919 92.46920879270783) + , Point2 (V2 91.42314316680815 92.3110058858731) + , Point2 (V2 91.45203881053632 92.2737028943519) + , Point2 (V2 91.50856391778473 92.20084333118147) + , Point2 (V2 91.54860908146797 92.15316473577967) + , Point2 (V2 91.63803055044139 92.0466706450613) + , Point2 (V2 91.67743528902548 92.00382438277838) + , Point2 (V2 91.77893367224766 91.89353345085307) + , Point2 (V2 91.89347699284706 91.77899013025392) + , Point2 (V2 91.94074811840437 91.73551406197616) + , Point2 (V2 92.04675728664768 91.63795609422435) + , Point2 (V2 92.10101271492351 91.59238851031962) + , Point2 (V2 92.20068613513772 91.50869425480059) + , Point2 (V2 92.24723328986644 91.47263118569387) + , Point2 (V2 92.31116595249517 91.42303164854623) + , Point2 (V2 92.46920879270783 91.31292335349919) + , Point2 (V2 92.52306138001785 91.27416224820777) + , Point2 (V2 92.57306689824158 91.24249360257754) + , Point2 (V2 92.59000000562422 91.23159288196383) + , Point2 (V2 92.61531992422698 91.21433185597525) + , Point2 (V2 92.64817812784116 91.19549665585357) + , Point2 (V2 92.85443085993114 91.07310800340393) + , Point2 (V2 93.00153612830023 90.99729940346542) + , Point2 (V2 92.9877165187992 91.00457140327511) + , Point2 (V2 93.64614576163498 90.84262888113695) + , Point2 (V2 93.57890934126299 90.72652681410516) + , Point2 (V2 93.06921257352505 90.96313614459115) + , Point2 (V2 93.42500016128389 90.79466573133263) + , Point2 (V2 93.42500016128389 90.81008228377397) + , Point2 (V2 93.2553067080979 90.88199893489247) + , Point2 (V2 93.3893185640321 90.82518875825394) + , Point2 (V2 93.58014939008443 90.75843963386609) + , Point2 (V2 93.66283004683464 90.72953442450273) + , Point2 (V2 93.70462952271815 90.71686751134479) + , Point2 (V2 93.6787962257674 90.72470857221676) + , Point2 (V2 95.0035666558769 90.70851141288935) + , Point2 (V2 94.72464821764876 90.45798854627252) + , Point2 (V2 93.79340645273629 90.69161757507065) + , Point2 (V2 94.32499905369538 90.54844719520653) + , Point2 (V2 94.32499905369538 90.57030039121904) + , Point2 (V2 94.06540699489828 90.62608525342779) + , Point2 (V2 94.19463503093796 90.59831336971094) + , Point2 (V2 94.36182397553434 90.57293598272166) + , Point2 (V2 94.46308075203177 90.55756688471223) + , Point2 (V2 94.52907271560787 90.55160185380022) + , Point2 (V2 94.73154266868215 90.53329695028441) + , Point2 (V2 94.93394738885749 90.52721941116873) + , Point2 (V2 94.99999825080576 90.52523656434427) + , Point2 (V2 95.20603864909656 90.53142327070195) + , Point2 (V2 95.26845915434926 90.53329711511131) + , Point2 (V2 95.47092597864834 90.55160173577174) + , Point2 (V2 95.5369179009237 90.55756676293966) + , Point2 (V2 95.72763456627625 90.5865153913174) + , Point2 (V2 95.80536952523627 90.59831416556366) + , Point2 (V2 95.97273091437924 90.63427917952613) + , Point2 (V2 95.67500241241035 90.57029469842847) + , Point2 (V2 95.67500241241035 90.54844759006447) + , Point2 (V2 95.99233448829969 90.63391257540528) + , Point2 (V2 96.04267935701206 90.72130322420693) + , Point2 (V2 96.32120377431346 90.72470857222879) + , Point2 (V2 96.2953704828859 90.71686751302332) + , Point2 (V2 96.3371294100193 90.7295221382979) + , Point2 (V2 96.48346706519771 90.78070836720458) + , Point2 (V2 96.61073114647759 90.82520802495871) + , Point2 (V2 96.80195481893021 90.90624925476074) + , Point2 (V2 96.57500197520388 90.81002371716855) + , Point2 (V2 96.57500197520388 90.79466674295354) + , Point2 (V2 96.7505871557286 90.87780878877794) + , Point2 (V2 96.7808911720591 90.9476598147312) + , Point2 (V2 97.01228348120087 91.00457140326334) + , Point2 (V2 96.99846387205933 90.99729940364361) + , Point2 (V2 97.14556914002745 91.07310800337467) + , Point2 (V2 97.35182187137244 91.19549665538213) + , Point2 (V2 97.38468007534733 91.2143318557108) + , Point2 (V2 97.40999999109025 91.23159287974991) + , Point2 (V2 97.42693310995041 91.24249360775116) + , Point2 (V2 97.47693861989968 91.27416224814222) + , Point2 (V2 97.53079120744584 91.31292335360351) + , Point2 (V2 97.68899411397008 91.42314316669616) + , Point2 (V2 97.7262971254248 91.45203882586043) + , Point2 (V2 97.79915666886333 91.5085639178057) + , Point2 (V2 97.84683531111433 91.54860912088927) + , Point2 (V2 97.95332935540218 91.63803055082391) + , Point2 (V2 97.99617555962381 91.67743523601872) + , Point2 (V2 98.10646654911997 91.77893367221348) + , Point2 (V2 98.22100986988748 91.893476992981) + , Point2 (V2 98.26448598740386 91.94074817209514) + , Point2 (V2 98.36204390620595 92.04675728712832) + , Point2 (V2 98.40761130286943 92.10101249256334) + , Point2 (V2 98.49130574500188 92.20068613491986) + , Point2 (V2 98.52736879008327 92.2472332586774) + , Point2 (V2 98.5769683514337 92.31116595246483) + , Point2 (V2 98.68707664525635 92.46920879092053) + , Point2 (V2 98.72583775174817 92.52306137989812) + , Point2 (V2 98.75750639174875 92.57306688923168) + , Point2 (V2 98.76840712043132 92.5900000091495) + , Point2 (V2 98.7856681440925 92.61531992433784) + , Point2 (V2 98.80450334418863 92.64817812790682) + , Point2 (V2 98.92689199658932 92.8544308599146) + , Point2 (V2 99.00270059440984 93.0015361241765) + , Point2 (V2 98.99542859666329 92.9877165185938) + , Point2 (V2 99.05234018524767 93.21910882794803) + , Point2 (V2 99.12220223165113 93.24941762536655) + , Point2 (V2 99.04427031185622 93.08485261291638) + , Point2 (V2 99.0584797213727 93.11486103656337) + , Point2 (V2 99.11800101000759 93.25530657805943) + , Point2 (V2 99.17481124170774 93.3893185639057) + , Point2 (V2 99.24156033966989 93.58014931441157) + , Point2 (V2 99.27046557560026 93.66283004715103) + , Point2 (V2 99.28313248099097 93.70462949739651) + , Point2 (V2 99.27529142774954 93.67879622559256) + , Point2 (V2 99.27869677577166 93.9573206429153) + , Point2 (V2 99.36608892343524 94.00766637510688) + , Point2 (V2 99.31908204351448 93.833133417053) + , Point2 (V2 99.34341914371794 93.92349723780309) + , Point2 (V2 99.37391472738378 94.06540690717972) + , Point2 (V2 99.4016866303127 94.19463503106583) + , Point2 (V2 99.42706361269667 94.36182130792311) + , Point2 (V2 99.44243311530897 94.46308075223536) + , Point2 (V2 99.44839819551188 94.52907326162845) + , Point2 (V2 99.46670304970871 94.73154266868238) + , Point2 (V2 99.47278063225963 94.93394883753771) + , Point2 (V2 99.47476343565559 94.99999825070864) + , Point2 (V2 99.46857670970934 95.20603930178119) + , Point2 (V2 99.46670276362087 95.26846319370384) + , Point2 (V2 99.45966555325245 95.34631490361156) + , Point2 (V2 99.44243393075298 95.53691333087573) + , Point2 (V2 99.41348459608173 95.72763464802651) + , Point2 (V2 99.40168583447436 95.8053695250555) + , Point2 (V2 99.36572072216647 95.97273137104125) + , Point2 (V2 99.34342008973506 96.07649924960621) + , Point2 (V2 99.31908080382114 96.16687118413628) + , Point2 (V2 99.30838278414635 96.2065921153522) + , Point2 (V2 99.54201145370311 95.27535178237046) + , Point2 (V2 99.29148858710127 94.99643334415902) + , Point2 (V2 99.27529142777428 96.3212037742354) + , Point2 (V2 99.2831325042824 96.29537042580031) + , Point2 (V2 99.27047786178193 96.33712940977867) + , Point2 (V2 99.21929163217742 96.48346706695861) + , Point2 (V2 99.17479197502927 96.61073114649997) + , Point2 (V2 99.09375071189352 96.80195489765781) + , Point2 (V2 99.05849742129114 96.88510158355312) + , Point2 (V2 99.04426994211163 96.91514816784013) + , Point2 (V2 99.03686829621603 96.93077786057788) + , Point2 (V2 99.27347318599062 96.42109065888862) + , Point2 (V2 99.23145620824842 96.39675800702065) + , Point2 (V2 98.9887378945167 97.0255582518726) + , Point2 (V2 98.92689199658712 97.14556914008277) + , Point2 (V2 98.80450334376476 97.35182187280202) + , Point2 (V2 98.78566814411468 97.38468007559177) + , Point2 (V2 98.76840712264506 97.40999998756496) + , Point2 (V2 98.75750638475104 97.42693312179145) + , Point2 (V2 98.72583775177804 97.47693862002909) + , Point2 (V2 98.68707664602151 97.53079120798513) + , Point2 (V2 98.57685683330901 97.68899411396428) + , Point2 (V2 98.5479611708476 97.72629712964388) + , Point2 (V2 98.4914360824291 97.79915666856763) + , Point2 (V2 98.45139095863219 97.84683521640524) + , Point2 (V2 98.36196944949798 97.95332935502714) + , Point2 (V2 98.32256476526807 97.99617555817369) + , Point2 (V2 98.22106632740235 98.1064665495116) + , Point2 (V2 98.10652300728816 98.22100986962587) + , Point2 (V2 98.05925189022336 98.264485930152) + , Point2 (V2 97.95324271337233 98.36204390576556) + , Point2 (V2 97.89898734388426 98.40761144019713) + , Point2 (V2 97.7993138653753 98.49130574476509) + , Point2 (V2 97.75276674051467 98.52736879068212) + , Point2 (V2 97.68883404738446 98.57696835154178) + , Point2 (V2 97.53079120798513 98.68707664602151) + , Point2 (V2 97.47693862002909 98.72583775177804) + , Point2 (V2 97.42693312179145 98.75750638475104) + , Point2 (V2 97.40999998756496 98.76840712264506) + , Point2 (V2 97.38468007559177 98.78566814411468) + , Point2 (V2 97.35182187280202 98.80450334376476) + , Point2 (V2 97.14556914008277 98.92689199658712) + , Point2 (V2 97.0255582518726 98.9887378945167) + , Point2 (V2 96.39675800702065 99.23145620824842) + , Point2 (V2 96.42109065888862 99.27347318599062) + , Point2 (V2 96.93078740986465 99.03686386328597) + , Point2 (V2 96.5749992941212 99.20533452655235) + , Point2 (V2 96.57499929412121 99.18991794702926) + , Point2 (V2 96.74469323969993 99.11800108723378) + , Point2 (V2 96.61068143584744 99.174811241793) + , Point2 (V2 96.41985067443075 99.2415603436121) + , Point2 (V2 96.3371699526587 99.27046557566783) + , Point2 (V2 96.29537042580031 99.2831325042824) + , Point2 (V2 96.3212037742354 99.27529142777428) + , Point2 (V2 94.99643334415902 99.29148858710127) + , Point2 (V2 95.27535178237046 99.54201145370311) + , Point2 (V2 96.20659354843383 99.30838242461583) + , Point2 (V2 95.67499388234063 99.45155470728702) + , Point2 (V2 95.67499388234063 99.429701126789) + , Point2 (V2 95.9345930669576 99.37391473310454) + , Point2 (V2 95.80536496906157 99.40168663029196) + , Point2 (V2 95.63818083325516 99.42706328822015) + , Point2 (V2 95.53691924734949 99.44243311535939) + , Point2 (V2 95.47092637362476 99.44839822852755) + , Point2 (V2 95.26845733130304 99.46670304971644) + , Point2 (V2 95.06605397617153 99.47278054771773) + , Point2 (V2 95.00000174901494 99.4747634356524) + , Point2 (V2 94.79396001510987 99.46857668918547) + , Point2 (V2 94.73153680663427 99.46670276363139) + , Point2 (V2 94.65368398104647 99.45966545242192) + , Point2 (V2 94.4630866691153 99.4424339307494) + , Point2 (V2 94.27236628806229 99.41348473831613) + , Point2 (V2 94.19463047496532 99.40168583448144) + , Point2 (V2 94.02726922936988 99.36572085121198) + , Point2 (V2 94.32499905369538 99.42970561665034) + , Point2 (V2 94.32499905369538 99.45155280479676) + , Point2 (V2 94.00766551163201 99.36608742458083) + , Point2 (V2 93.9573206429153 99.27869677577166) + , Point2 (V2 93.67879622559256 99.27529142774954) + , Point2 (V2 93.70462949739651 99.28313248099097) + , Point2 (V2 93.6628705901826 99.27047786176048) + , Point2 (V2 93.5165329755313 99.21929164704339) + , Point2 (V2 93.3892688534513 99.17479197500914) + , Point2 (V2 93.19804506646996 99.0937506966894) + , Point2 (V2 93.4249974802012 99.18997605194838) + , Point2 (V2 93.4249974802012 99.20533299911274) + , Point2 (V2 93.24941284425896 99.12219121115578) + , Point2 (V2 93.23517951491657 99.0893832609998) + , Point2 (V2 92.97444174818017 98.98873789454744) + , Point2 (V2 92.8544308599146 98.92689199658932) + , Point2 (V2 92.64817812790682 98.80450334418863) + , Point2 (V2 92.61531992433784 98.7856681440925) + , Point2 (V2 92.5900000091495 98.76840712043132) + , Point2 (V2 92.57306688923168 98.75750639174875) + , Point2 (V2 92.52306137989812 98.72583775174817) + , Point2 (V2 92.46920879092053 98.68707664525635) + , Point2 (V2 92.3110058858783 98.57685683319652) + , Point2 (V2 92.2737028901376 98.5479611862004) + , Point2 (V2 92.20084333147669 98.49143608244958) + , Point2 (V2 92.15316483055265 98.45139099806059) + , Point2 (V2 92.04667064499658 98.36196944951091) + , Point2 (V2 92.00382439167613 98.32256471915899) + , Point2 (V2 91.89353345084716 98.22106632775365) + , Point2 (V2 91.77899013010654 98.10652300701301) + , Point2 (V2 91.73551401344223 98.05925182882105) + , Point2 (V2 91.63795609367615 97.95324271274465) + , Point2 (V2 91.59238870718953 97.89898751943518) + , Point2 (V2 91.50869425483597 97.79931386489767) + , Point2 (V2 91.47263118510182 97.75276670932834) + , Point2 (V2 91.42303164843861 97.68883404735429) + , Point2 (V2 91.31292335360351 97.53079120744584) + , Point2 (V2 91.27416224814222 97.47693861989968) + , Point2 (V2 91.24249360775116 97.42693310995041) + , Point2 (V2 91.23159287974991 97.40999999109025) + , Point2 (V2 91.2143318557108 97.38468007534733) + , Point2 (V2 91.19549665538213 97.35182187137244) + , Point2 (V2 91.07310800337467 97.14556914002745) + , Point2 (V2 91.01126210549467 97.02555825191367) + , Point2 (V2 90.91061673901486 96.7648204851061) + , Point2 (V2 90.87779776835599 96.75058237465284) + , Point2 (V2 90.95572946023208 96.9151469057644) + , Point2 (V2 90.94152027883361 96.88513896392662) + , Point2 (V2 90.88199894680963 96.74469332004125) + , Point2 (V2 90.8251887582333 96.6106814359307) + , Point2 (V2 90.75843964697009 96.4198506474299) + , Point2 (V2 90.72953442443512 96.33716995297458) + , Point2 (V2 90.71686751302332 96.2953704828859) + , Point2 (V2 90.72470857222879 96.32120377431346) + , Point2 (V2 90.72130322420693 96.04267935701206) + , Point2 (V2 90.63391107647031 95.99233362477842) + , Point2 (V2 90.68092111210268 96.1668783002161) + , Point2 (V2 90.65658085625388 96.07650276206564) + , Point2 (V2 90.62608523245162 95.93459290804716) + , Point2 (V2 90.59831336970156 95.80536496899053) + , Point2 (V2 90.57293630616262 95.63817815459794) + , Point2 (V2 90.55756688466185 95.5369192475533) + , Point2 (V2 90.55160173577174 95.47092597864834) + , Point2 (V2 90.53329695028086 95.26845733116474) + , Point2 (V2 90.52721945817349 95.0660541767252) ] facetBrokenSpec :: Spec @@ -1758,7 +1760,7 @@ facetSpec = do (Just (PLine2 (GVec [GVal 1.0606601717798212 (singleton (GEZero 1)), GVal (-1.414213562373095) (singleton (GEPlus 1))]),PLine2Err [ErrVal (UlpSum 2.220446049250313e-16) (singleton (GEPlus 1))] [] mempty mempty mempty mempty)) describe "Motorcycles (Skeleton/Motorcycles)" $ do it "finds the motorcycle in our second simple shape" $ - convexMotorcycles c1 --> [Motorcycle (LineSeg (Point2 (-1.0,-1.0)) (Point2 (0.0,0.0)), LineSeg (Point2 (0.0,0.0)) (Point2 (1.0,-1.0))) (PLine2 (GVec [GVal 1.414213562373095 (singleton (GEPlus 1))])) (PLine2Err [ErrVal (UlpSum 2.220446049250313e-16) (singleton (GEPlus 1))] [] mempty mempty mempty mempty)] + convexMotorcycles c1 --> [Motorcycle (LineSeg (Point2 (V2 (-1.0) (-1.0))) (Point2 (V2 0.0 0.0)), LineSeg (Point2 (V2 0.0 0.0)) (Point2 (V2 1.0 (-1.0)))) (PLine2 (GVec [GVal 1.414213562373095 (singleton (GEPlus 1))])) (PLine2Err [ErrVal (UlpSum 2.220446049250313e-16) (singleton (GEPlus 1))] [] mempty mempty mempty mempty)] describe "Cells (Skeleton/Cells)" $ do it "finds an infill line (unit)" unit_LineContourIntersection1 @@ -1846,7 +1848,7 @@ facetSpec = do it "sorts PLines (rectangle 1)" $ sortPLinesByReference pl7 [pl6, pl5] --> [pl5, pl6] where - c1 = makePointContour [Point2 (-1,-1), Point2 (0,0), Point2 (1,-1), Point2 (1,1), Point2 (-1,1)] + c1 = makePointContour [Point2 (V2 (-1) (-1)), Point2 (V2 0 0), Point2 (V2 1 (-1)), Point2 (V2 1 1), Point2 (V2 (-1) 1)] -- The next corners are part of a 2x2 square around the origin with a piece missing: (c2 from above) -- __ <-- corner 1 -- | / @@ -1854,11 +1856,11 @@ facetSpec = do -- ~~~ <-- corner 3 -- ^-- corner 4 -- the top and the left side. - c2c2E1 = makeENode (Point2 (1.0,1.0)) (Point2 (-1.0,1.0)) (Point2 (-1.0,-1.0)) + c2c2E1 = makeENode (Point2 (V2 1.0 1.0)) (Point2 (V2 (-1.0) 1.0)) (Point2 (V2 (-1.0) (-1.0))) -- the left and the bottom side. - c2c3E1 = makeENode (Point2 (-1.0,1.0)) (Point2 (-1.0,-1.0)) (Point2 (1.0,-1.0)) + c2c3E1 = makeENode (Point2 (V2 (-1.0) 1.0)) (Point2 (V2 (-1.0) (-1.0))) (Point2 (V2 1.0 (-1.0))) -- the bottom and the entrance to the convex angle. - c2c4E1 = makeENode (Point2 (-1.0,-1.0)) (Point2 (1.0,-1.0)) (Point2 (0.0,0.0)) + c2c4E1 = makeENode (Point2 (V2 (-1.0) (-1.0))) (Point2 (V2 1.0 (-1.0))) (Point2 (V2 0.0 0.0)) -- The next corners are part of a 2x2 square around the origin with a slice and a corner missing: (c7 from above) -- v----- corner 2 -- ┌───┐ ┌─┐<-- corner 1 @@ -1866,16 +1868,16 @@ facetSpec = do -- └───┐ │ -- │ │ -- └───┘ - c7c1E1 = makeENode (Point2 (1.0,-1.0)) (Point2 (1.0,1.0)) (Point2 (0.5,1.0)) - c7c2E1 = makeENode (Point2 (1.0,1.0)) (Point2 (0.5,1.0)) (Point2 (0.5,0.0)) + c7c1E1 = makeENode (Point2 (V2 1.0 (-1.0))) (Point2 (V2 1.0 1.0)) (Point2 (V2 0.5 1.0)) + c7c2E1 = makeENode (Point2 (V2 1.0 1.0)) (Point2 (V2 0.5 1.0)) (Point2 (V2 0.5 0.0)) -- a line to the origin, from the positive Y direction - pl1 = eToPL $ makeLineSeg (Point2 (0,1)) (Point2 (0,0)) + pl1 = eToPL $ makeLineSeg (Point2 (V2 0 1)) (Point2 (V2 0 0)) -- a line to the origin, from the positive X direction - pl2 = eToPL $ makeLineSeg (Point2 (2,0)) (Point2 (0,0)) + pl2 = eToPL $ makeLineSeg (Point2 (V2 2 0)) (Point2 (V2 0 0)) -- a line to the origin, from the -x-y direction. - pl3 = eToPL $ makeLineSeg (Point2 (-3,-3)) (Point2 (0,0)) + pl3 = eToPL $ makeLineSeg (Point2 (V2 (-3) (-3))) (Point2 (V2 0 0)) -- a line to the origin, from the negative Y direction - pl4 = eToPL $ makeLineSeg (Point2 (0,-4)) (Point2 (0,0)) - pl5 = eToPL $ makeLineSeg (Point2 (1,0.5)) (Point2 (0.5,0)) - pl6 = eToPL $ makeLineSeg (Point2 (1,-0.5)) (Point2 (0.5,0)) - pl7 = eToPL $ makeLineSeg (Point2 (0.5,0)) (Point2 (-0.5,0)) + pl4 = eToPL $ makeLineSeg (Point2 (V2 0 (-4))) (Point2 (V2 0 0)) + pl5 = eToPL $ makeLineSeg (Point2 (V2 1 0.5)) (Point2 (V2 0.5 0)) + pl6 = eToPL $ makeLineSeg (Point2 (V2 1 (-0.5))) (Point2 (V2 0.5 0)) + pl7 = eToPL $ makeLineSeg (Point2 (V2 0.5 0)) (Point2 (V2 (-0.5) 0))