From 12a60d9408bc13396948b6d874c96d38068101ee Mon Sep 17 00:00:00 2001 From: Jakub Hampl Date: Thu, 18 Mar 2021 10:53:39 +0000 Subject: [PATCH 1/4] Adds a constructor for regular polygons --- src/Polygon2d.elm | 26 ++++++++++++++++++++-- tests/Tests/Polygon2d.elm | 45 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/Polygon2d.elm b/src/Polygon2d.elm index 13ca1de1..b4c1a535 100644 --- a/src/Polygon2d.elm +++ b/src/Polygon2d.elm @@ -9,7 +9,7 @@ module Polygon2d exposing ( Polygon2d - , singleLoop, withHoles, convexHull + , singleLoop, withHoles, convexHull, regular , outerLoop, innerLoops, vertices, edges, perimeter, area, centroid, boundingBox , contains , scaleAbout, rotateAround, translateBy, translateIn, mirrorAcross @@ -32,7 +32,7 @@ holes. This module contains a variety of polygon-related functionality, such as # Constructors -@docs singleLoop, withHoles, convexHull +@docs singleLoop, withHoles, convexHull, regular # Properties @@ -261,6 +261,28 @@ convexHull points = singleLoop (lower ++ upper) +{-| Constructs a regular convex polygon with the specified center point, circumradius and number of sides. +-} +regular : Point2d units coordinates -> Quantity Float units -> Int -> Polygon2d units coordinates +regular center radius sides = + let + n = + toFloat sides + + angle = + Angle.turns 1 |> Quantity.divideBy n + + startAngle = + Angle.degrees 90 |> Quantity.minus (Angle.degrees 180 |> Quantity.divideBy n) + + point index = + Point2d.translateBy (Vector2d.rTheta radius (Quantity.plus startAngle (Quantity.multiplyBy index angle))) center + in + List.range 0 (sides - 1) + |> List.map (toFloat >> point) + |> singleLoop + + {-| Convert a polygon from one units type to another, by providing a conversion factor given as a rate of change of destination units with respect to source units. diff --git a/tests/Tests/Polygon2d.elm b/tests/Tests/Polygon2d.elm index d8ec8962..415c5edb 100644 --- a/tests/Tests/Polygon2d.elm +++ b/tests/Tests/Polygon2d.elm @@ -3,13 +3,14 @@ module Tests.Polygon2d exposing , convexHullContainsAllPoints , convexHullIsConvex , rectangleCentroidIsInTheCenter + , regularTest , rotatingAroundCentroidKeepsCentroid , triangulationHasCorrectArea , triangulationHasCorrectNumberOfTriangles , triangulationHasCorrectWeightedCentroid ) -import Area +import Angle import Expect import Fuzz import Geometry.Expect as Expect @@ -26,6 +27,48 @@ import TriangularMesh import Vector2d +{-| Implements the formula for area of a regular polygon. +-} +areaOfRegularNGon : Quantity.Quantity Float units -> Float -> Quantity.Quantity Float (Quantity.Squared units) +areaOfRegularNGon radius sides = + Quantity.squared radius |> Quantity.multiplyBy sides |> Quantity.multiplyBy (Angle.sin (Angle.turns (1 / sides))) |> Quantity.divideBy 2 + + +regularTest : Test +regularTest = + Test.describe "regular" + [ Test.fuzz3 Fuzz.point2d + Fuzz.length + (Fuzz.intRange 3 300) + "A centroid of a regular polygon is in the center" + <| + \center radius sides -> + Polygon2d.regular center radius sides + |> Polygon2d.centroid + |> Expect.just (Expect.point2d center) + , Test.fuzz3 Fuzz.point2d + Fuzz.length + (Fuzz.intRange 3 300) + "The area matches what we would expect from a regular polygon" + <| + \center radius sides -> + Polygon2d.regular center radius sides + |> Polygon2d.area + |> Expect.quantity (areaOfRegularNGon radius (toFloat sides)) + , Test.test "sanity check" <| + \() -> + Polygon2d.regular (Point2d.meters 0.5 0.5) (meters (sqrt 2 / 2)) 4 + |> Expect.polygon2d + (Polygon2d.singleLoop + [ Point2d.meters 1 0 + , Point2d.meters 0 0 + , Point2d.meters 0 1 + , Point2d.meters 1 1 + ] + ) + ] + + convexHullIsConvex : Test convexHullIsConvex = Test.fuzz (Fuzz.list Fuzz.point2d) From b92374816de4343611970dbf0b41254c71f441ce Mon Sep 17 00:00:00 2001 From: Ian Mackenzie Date: Sat, 27 Mar 2021 20:06:02 -0400 Subject: [PATCH 2/4] Tweak regular polygon construction logic Have start point be right end of bottom edge and end point be left end of bottom edge (assuming Y-up) --- src/Polygon2d.elm | 2 +- tests/Tests/Polygon2d.elm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Polygon2d.elm b/src/Polygon2d.elm index b4c1a535..e1f4f507 100644 --- a/src/Polygon2d.elm +++ b/src/Polygon2d.elm @@ -273,7 +273,7 @@ regular center radius sides = Angle.turns 1 |> Quantity.divideBy n startAngle = - Angle.degrees 90 |> Quantity.minus (Angle.degrees 180 |> Quantity.divideBy n) + Angle.degrees -90 |> Quantity.plus (Angle.degrees 180 |> Quantity.divideBy n) point index = Point2d.translateBy (Vector2d.rTheta radius (Quantity.plus startAngle (Quantity.multiplyBy index angle))) center diff --git a/tests/Tests/Polygon2d.elm b/tests/Tests/Polygon2d.elm index 415c5edb..ed933129 100644 --- a/tests/Tests/Polygon2d.elm +++ b/tests/Tests/Polygon2d.elm @@ -61,9 +61,9 @@ regularTest = |> Expect.polygon2d (Polygon2d.singleLoop [ Point2d.meters 1 0 - , Point2d.meters 0 0 - , Point2d.meters 0 1 , Point2d.meters 1 1 + , Point2d.meters 0 1 + , Point2d.meters 0 0 ] ) ] From 962f5ad32a8c842efc6f2629bebaa8981bfa9954 Mon Sep 17 00:00:00 2001 From: Ian Mackenzie Date: Sat, 27 Mar 2021 20:08:38 -0400 Subject: [PATCH 3/4] Expand on Polygon2d.regular docs a bit --- src/Polygon2d.elm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Polygon2d.elm b/src/Polygon2d.elm index e1f4f507..e1b33861 100644 --- a/src/Polygon2d.elm +++ b/src/Polygon2d.elm @@ -261,7 +261,10 @@ convexHull points = singleLoop (lower ++ upper) -{-| Constructs a regular convex polygon with the specified center point, circumradius and number of sides. +{-| Constructs a regular convex polygon with the specified center point, +circumradius and number of sides. The polygon will be oriented so that the +bottom edge is horizontal (assuming a Y-up coordinate system; note that SVG +uses Y-down instead!). -} regular : Point2d units coordinates -> Quantity Float units -> Int -> Polygon2d units coordinates regular center radius sides = From ba88276a39bda14d9bd1a36fe12390fc26db4b1f Mon Sep 17 00:00:00 2001 From: Jakub Hampl Date: Thu, 8 Apr 2021 15:19:04 +0100 Subject: [PATCH 4/4] Changes regular to get record arguments --- src/Polygon2d.elm | 10 +++++----- tests/Tests/Polygon2d.elm | 11 +++++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Polygon2d.elm b/src/Polygon2d.elm index b4c1a535..0eba20aa 100644 --- a/src/Polygon2d.elm +++ b/src/Polygon2d.elm @@ -263,11 +263,11 @@ convexHull points = {-| Constructs a regular convex polygon with the specified center point, circumradius and number of sides. -} -regular : Point2d units coordinates -> Quantity Float units -> Int -> Polygon2d units coordinates -regular center radius sides = +regular : { centerPoint : Point2d units coordinates, circumradius : Quantity Float units, numSides : Int } -> Polygon2d units coordinates +regular { centerPoint, circumradius, numSides } = let n = - toFloat sides + toFloat numSides angle = Angle.turns 1 |> Quantity.divideBy n @@ -276,9 +276,9 @@ regular center radius sides = Angle.degrees 90 |> Quantity.minus (Angle.degrees 180 |> Quantity.divideBy n) point index = - Point2d.translateBy (Vector2d.rTheta radius (Quantity.plus startAngle (Quantity.multiplyBy index angle))) center + Point2d.translateBy (Vector2d.rTheta circumradius (Quantity.plus startAngle (Quantity.multiplyBy index angle))) centerPoint in - List.range 0 (sides - 1) + List.range 0 (numSides - 1) |> List.map (toFloat >> point) |> singleLoop diff --git a/tests/Tests/Polygon2d.elm b/tests/Tests/Polygon2d.elm index 415c5edb..c304b8ad 100644 --- a/tests/Tests/Polygon2d.elm +++ b/tests/Tests/Polygon2d.elm @@ -31,7 +31,10 @@ import Vector2d -} areaOfRegularNGon : Quantity.Quantity Float units -> Float -> Quantity.Quantity Float (Quantity.Squared units) areaOfRegularNGon radius sides = - Quantity.squared radius |> Quantity.multiplyBy sides |> Quantity.multiplyBy (Angle.sin (Angle.turns (1 / sides))) |> Quantity.divideBy 2 + Quantity.squared radius + |> Quantity.multiplyBy sides + |> Quantity.multiplyBy (Angle.sin (Angle.turns (1 / sides))) + |> Quantity.divideBy 2 regularTest : Test @@ -43,7 +46,7 @@ regularTest = "A centroid of a regular polygon is in the center" <| \center radius sides -> - Polygon2d.regular center radius sides + Polygon2d.regular { centerPoint = center, circumradius = radius, numSides = sides } |> Polygon2d.centroid |> Expect.just (Expect.point2d center) , Test.fuzz3 Fuzz.point2d @@ -52,12 +55,12 @@ regularTest = "The area matches what we would expect from a regular polygon" <| \center radius sides -> - Polygon2d.regular center radius sides + Polygon2d.regular { centerPoint = center, circumradius = radius, numSides = sides } |> Polygon2d.area |> Expect.quantity (areaOfRegularNGon radius (toFloat sides)) , Test.test "sanity check" <| \() -> - Polygon2d.regular (Point2d.meters 0.5 0.5) (meters (sqrt 2 / 2)) 4 + Polygon2d.regular { centerPoint = Point2d.meters 0.5 0.5, circumradius = meters (sqrt 2 / 2), numSides = 4 } |> Expect.polygon2d (Polygon2d.singleLoop [ Point2d.meters 1 0