A type synonym is a name for an existing type expression, introduced with
type, for example type Name = String. It improves documentation and makes type signatures easier to maintain. It creates no new distinct type: a synonym and its expansion remain interchangeable. An algebraic data type declared with data or newtype has a different role.UseA valid polygon is a finite list of at least three vertices in boundary order, with the final vertex connected back to the first. The first vertex is not repeated at the end. A simple polygon also has no intersecting nonadjacent edges. Numerical routines below use finite coordinates;
type Point = (Double,Double)
type Polygon = [Point]NaN and infinite coordinates are outside this representation's intended domain.The Euclidean distance isThus . The type synonym expands to pairs of floating-point coordinates.
distBetween :: Point -> Point -> Double
distBetween (x,y) (u,v) = sqrt ((x-u)^2 + (y-v)^2)First include the closing edge exactly once:The recursive version and right fold both sum the Euclidean distances between consecutive vertices, including the last-to-first pair. They take linear time. The empty-list convention gives zero, although an empty list is not a valid polygon.
edges :: Polygon -> [(Point,Point)]
edges [] = []
edges ps = zip ps (tail ps ++ [head ps])
perimeter :: Polygon -> Double
perimeter = total . edges
where total [] = 0
total ((p,q):es) = distBetween p q + total es
perimeterFold :: Polygon -> Double
perimeterFold = foldr (\(p,q) s -> distBetween p q + s) 0 . edgesEqual side lengths alone are insufficient: a nonsquare rhombus is not a regular polygon. Use the regular polygon edge rotation criterion: for , successive nonzero edge vectors must be related by the same rotation through either or .With exact real coordinates and exact equality in
regular :: Polygon -> Bool
regular ps
| length ps < 3 = False
| otherwise = norm2 (head es) > 0 && (fits 1 || fits (-1))
where
es = [ (u-x,v-y) | ((x,y),(u,v)) <- edges ps ]
angle = 2*pi / fromIntegral (length ps)
norm2 (x,y) = x*x+y*y
close x y = abs (x-y) <= 1e-10 * max 1 (max (abs x) (abs y))
same (x,y) (u,v) = close x u && close y v
turn s (x,y) = (cos angle*x - s*sin angle*y,
s*sin angle*x + cos angle*y)
fits s = and (zipWith (\a b -> same (turn s a) b)
es (tail es ++ [head es]))same, this is an if-and-only-if test for an ordinary convex regular polygon, in either boundary orientation. The displayed Double implementation tests that condition to the stated tolerance; it cannot promise exact geometric classification near the tolerance boundary. Both orientations are needed, and using the fundamental turn excludes regular star traversals. A repeated zero-length side fails the exact criterion.Here “centroid” means the vertex centroid, the arithmetic mean of the listed vertices, rather than the uniform-area centroid of the polygon's interior:The nonempty input restriction prevents division by zero; computing both sums and the length takes linear time.
centroid :: Polygon -> Point
centroid [] = error "centroid: empty vertex list"
centroid ps = (sx/n,sy/n)
where
(sx,sy) = foldr (\(x,y) (u,v) -> (x+u,y+v)) (0,0) ps
n = fromIntegral (length ps)Apply the same translation to every vertex:Every edge vector is unchanged because the added displacement cancels on subtraction. Hence lengths, angles, orientation and shape are preserved.
translate :: Point -> Polygon -> Polygon
translate (u,v) = map (\(x,y) -> (x+u,y+v))Translate the vertex centroid to the origin, rotate, and translate back:This follows the supplied rotation matrix, so positive rotates clockwise in the usual Cartesian axes. The opposite signs give the conventional counterclockwise matrix. Since the vertex centroid of the centered vertices is zero and a linear map commutes with their average, the final centroid remains
rotatePoly :: Polygon -> Double -> Polygon
rotatePoly ps theta =
(translate c . map turn . translate (-cx,-cy)) ps
where
c@(cx,cy) = centroid ps
turn (x,y) = (cos theta*x + sin theta*y,
-sin theta*x + cos theta*y)c. Articles by others on the same topic
There are currently no matching articles.