This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.

# Point2d A `Point2d` represents a position in 2D space and is defined by its X and Y coordinates. This module contains a variety of point-related functionality, such as

• Measuring distance between points
• Scaling, rotating, translating, mirroring and projecting points
• Converting points between different coordinate systems

Points are distinct from vectors but interact with them in well-defined ways; you can translate a point by a vector to result in a new point, or you can compute the vector from one point to another, but you cannot 'add' two points like you can add two vectors.

type alias Point2d = Types.Point2d

origin : Point2d

# Constructors

fromCoordinates : ( Float, Float ) -> Point2d
fromCoordinatesIn : Frame2d -> ( Float, Float ) -> Point2d
fromPolarCoordinates : ( Float, Float ) -> Point2d
fromPolarCoordinatesIn : Frame2d -> ( Float, Float ) -> Point2d
midpoint : Point2d -> Point2d -> Point2d
interpolateFrom : Point2d -> Point2d -> Float -> Point2d
along : Axis2d -> Float -> Point2d
circumcenter : Point2d -> Point2d -> Point2d -> Maybe Point2d

# Properties

coordinates : Point2d -> ( Float, Float )
xCoordinate : Point2d -> Float
yCoordinate : Point2d -> Float
polarCoordinates : Point2d -> ( Float, Float )

# Comparison

equalWithin : Float -> Point2d -> Point2d -> Bool

# Measurement

distanceFrom : Point2d -> Point2d -> Float
squaredDistanceFrom : Point2d -> Point2d -> Float
signedDistanceAlong : Axis2d -> Point2d -> Float
signedDistanceFrom : Axis2d -> Point2d -> Float

# Transformations

scaleAbout : Point2d -> Float -> Point2d -> Point2d
rotateAround : Point2d -> Float -> Point2d -> Point2d
translateBy : Vector2d -> Point2d -> Point2d
translateIn : Direction2d -> Float -> Point2d -> Point2d
mirrorAcross : Axis2d -> Point2d -> Point2d
projectOnto : Axis2d -> Point2d -> Point2d

# Coordinate conversions

relativeTo : Frame2d -> Point2d -> Point2d
placeIn : Frame2d -> Point2d -> Point2d
``````--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- This Source Code Form is subject to the terms of the Mozilla Public        --
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,  --
-- you can obtain one at http://mozilla.org/MPL/2.0/.                         --
--                                                                            --
-- Copyright 2016 by Ian Mackenzie                                            --
-- ian.e.mackenzie@gmail.com                                                  --
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

module Point2d
exposing
( Point2d
, along
, circumcenter
, coordinates
, distanceFrom
, equalWithin
, fromCoordinates
, fromCoordinatesIn
, fromPolarCoordinates
, fromPolarCoordinatesIn
, interpolateFrom
, midpoint
, mirrorAcross
, origin
, placeIn
, polarCoordinates
, projectOnto
, relativeTo
, rotateAround
, signedDistanceAlong
, signedDistanceFrom
, squaredDistanceFrom
, translateBy
, translateIn
, xCoordinate
, yCoordinate
)

{-| <img src="https://ianmackenzie.github.io/elm-geometry/1.0.0/Point2d/icon.svg" alt="Point2d" width="160">

A `Point2d` represents a position in 2D space and is defined by its X and Y
coordinates. This module contains a variety of point-related functionality, such
as

- Measuring distance between points
- Scaling, rotating, translating, mirroring and projecting points
- Converting points between different coordinate systems

Points are distinct from vectors but interact with them in well-defined ways;
you can translate a point by a vector to result in a new point, or you can
compute the vector from one point to another, but you cannot 'add' two points
like you can add two vectors.

@docs Point2d

# Constants

@docs origin

# Constructors

@docs fromCoordinates, fromCoordinatesIn, fromPolarCoordinates, fromPolarCoordinatesIn, midpoint, interpolateFrom, along, circumcenter

# Properties

@docs coordinates, xCoordinate, yCoordinate, polarCoordinates

# Comparison

@docs equalWithin

# Measurement

@docs distanceFrom, squaredDistanceFrom, signedDistanceAlong, signedDistanceFrom

# Transformations

@docs scaleAbout, rotateAround, translateBy, translateIn, mirrorAcross, projectOnto

# Coordinate conversions

@docs relativeTo, placeIn

-}

import Bootstrap.Axis2d as Axis2d
import Bootstrap.Frame2d as Frame2d
import Direction2d exposing (Direction2d)
import Float.Extra as Float
import Geometry.Types as Types exposing (Axis2d, Frame2d)
import Vector2d exposing (Vector2d)

addTo : Point2d -> Vector2d -> Point2d
translateBy vector point

{-| -}
type alias Point2d =
Types.Point2d

{-| -}
origin : Point2d
origin =
fromCoordinates ( 0, 0 )

{-| -}
fromCoordinates : ( Float, Float ) -> Point2d
fromCoordinates =
Types.Point2d

{-| -}
fromPolarCoordinates : ( Float, Float ) -> Point2d
fromPolarCoordinates polarCoordinates_ =
fromCoordinates (fromPolar polarCoordinates_)

{-| -}
midpoint : Point2d -> Point2d -> Point2d
midpoint firstPoint secondPoint =
interpolateFrom firstPoint secondPoint 0.5

{-| -}
interpolateFrom : Point2d -> Point2d -> Float -> Point2d
interpolateFrom p1 p2 t =
let
( x1, y1 ) =
coordinates p1

( x2, y2 ) =
coordinates p2
in
fromCoordinates
( Float.interpolateFrom x1 x2 t
, Float.interpolateFrom y1 y2 t
)

{-| -}
along : Axis2d -> Float -> Point2d
along axis distance =
Axis2d.originPoint axis
|> translateBy (Vector2d.withLength distance (Axis2d.direction axis))

{-| -}
fromCoordinatesIn : Frame2d -> ( Float, Float ) -> Point2d
fromCoordinatesIn frame localCoordinates =
placeIn frame (fromCoordinates localCoordinates)

{-| -}
fromPolarCoordinatesIn : Frame2d -> ( Float, Float ) -> Point2d
fromPolarCoordinatesIn frame polarCoordinates_ =
placeIn frame (fromPolarCoordinates polarCoordinates_)

{-| -}
circumcenter : Point2d -> Point2d -> Point2d -> Maybe Point2d
circumcenter p1 p2 p3 =
let
a2 =
squaredDistanceFrom p1 p2

b2 =
squaredDistanceFrom p2 p3

c2 =
squaredDistanceFrom p3 p1

t1 =
a2 * (b2 + c2 - a2)

t2 =
b2 * (c2 + a2 - b2)

t3 =
c2 * (a2 + b2 - c2)

sum =
t1 + t2 + t3
in
if sum == 0 then
Nothing
else
let
w1 =
t1 / sum

w2 =
t2 / sum

w3 =
t3 / sum

( x1, y1 ) =
coordinates p1

( x2, y2 ) =
coordinates p2

( x3, y3 ) =
coordinates p3
in
Just <|
fromCoordinates
( w1 * x3 + w2 * x1 + w3 * x2
, w1 * y3 + w2 * y1 + w3 * y2
)

{-| -}
coordinates : Point2d -> ( Float, Float )
coordinates (Types.Point2d coordinates_) =
coordinates_

{-| -}
xCoordinate : Point2d -> Float
xCoordinate (Types.Point2d ( x, _ )) =
x

{-| -}
yCoordinate : Point2d -> Float
yCoordinate (Types.Point2d ( _, y )) =
y

{-| -}
polarCoordinates : Point2d -> ( Float, Float )
polarCoordinates point =
toPolar (coordinates point)

{-| -}
equalWithin : Float -> Point2d -> Point2d -> Bool
equalWithin tolerance firstPoint secondPoint =
squaredDistanceFrom firstPoint secondPoint <= tolerance * tolerance

{-| -}
distanceFrom : Point2d -> Point2d -> Float
distanceFrom firstPoint secondPoint =
sqrt (squaredDistanceFrom firstPoint secondPoint)

{-| -}
squaredDistanceFrom : Point2d -> Point2d -> Float
squaredDistanceFrom firstPoint secondPoint =
Vector2d.squaredLength (Vector2d.from firstPoint secondPoint)

{-| -}
signedDistanceAlong : Axis2d -> Point2d -> Float
signedDistanceAlong axis point =
Vector2d.from (Axis2d.originPoint axis) point
|> Vector2d.componentIn (Axis2d.direction axis)

{-| -}
signedDistanceFrom : Axis2d -> Point2d -> Float
signedDistanceFrom axis point =
let
directionVector =
Direction2d.toVector (Axis2d.direction axis)

displacementVector =
Vector2d.from (Axis2d.originPoint axis) point
in
Vector2d.crossProduct directionVector displacementVector

{-| -}
scaleAbout : Point2d -> Float -> Point2d -> Point2d
Vector2d.from centerPoint point
|> Vector2d.scaleBy scale

{-| -}
rotateAround : Point2d -> Float -> Point2d -> Point2d
rotateAround centerPoint angle =
Vector2d.from centerPoint >> Vector2d.rotateBy angle >> addTo centerPoint

{-| -}
translateBy : Vector2d -> Point2d -> Point2d
translateBy vector point =
let
( vx, vy ) =
Vector2d.components vector

( px, py ) =
coordinates point
in
fromCoordinates ( px + vx, py + vy )

{-| -}
translateIn : Direction2d -> Float -> Point2d -> Point2d
translateIn direction distance point =
let
( dx, dy ) =
Direction2d.components direction

( px, py ) =
coordinates point
in
fromCoordinates ( px + distance * dx, py + distance * dy )

{-| -}
mirrorAcross : Axis2d -> Point2d -> Point2d
mirrorAcross axis =
Vector2d.from (Axis2d.originPoint axis)
>> Vector2d.mirrorAcross axis

{-| -}
projectOnto : Axis2d -> Point2d -> Point2d
projectOnto axis =
Vector2d.from (Axis2d.originPoint axis)
>> Vector2d.projectOnto axis

{-| -}
relativeTo : Frame2d -> Point2d -> Point2d
relativeTo frame point =
Vector2d.from (Frame2d.originPoint frame) point
|> Vector2d.relativeTo frame
|> Vector2d.components
|> fromCoordinates

{-| -}
placeIn : Frame2d -> Point2d -> Point2d
placeIn frame point =
Vector2d.fromComponents (coordinates point)
|> Vector2d.placeIn frame