<commit_before>{- 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 <NAME>
   <EMAIL>
-}


module OpenSolid.Core.Point2d
    exposing
        ( origin
        , polar
        , along
        , midpoint
        , interpolate
        , coordinates
        , fromCoordinates
        , polarCoordinates
        , fromPolarCoordinates
        , toRecord
        , fromRecord
        , xCoordinate
        , yCoordinate
        , vectorTo
        , vectorFrom
        , distanceFrom
        , squaredDistanceFrom
        , distanceAlong
        , distanceFromAxis
        , plus
        , minus
        , scaleAbout
        , rotateAround
        , translateAlong
        , mirrorAcross
        , projectOnto
        , toLocalIn
        , fromLocalIn
        )

{-| Various functions for constructing `Point2d` values and performing
operations on them. For the examples below, assume the following imports:

    import OpenSolid.Core.Types exposing (..)
    import OpenSolid.Core.Point2d as Point2d
    import OpenSolid.Core.Vector2d as Vector2d
    import OpenSolid.Core.Frame2d as Frame2d

Examples use `==` to indicate that two expressions are equivalent, even if (due
to numerical roundoff) they might not be exactly equal.

# Constants

@docs origin

# Constructors

Since `Point2d` is not an opaque type, the simplest way to construct one is
directly from its X and Y coordinates, for example `Point2d 2 3`. But that is
not the only way!

@docs polar, along, midpoint, interpolate

# Conversions

Various ways to convert to and from plain tuples and records. Primarily useful
for interoperability with other libraries. For example, you could define
conversion functions to and from `elm-linear-algebra`'s `Vec2` type with

    toVec2 : Point2d -> Math.Vector2.Vec2
    toVec2 =
        Point2d.coordinates >> Math.Vector2.fromTuple

    fromVec2 : Math.Vector2.Vec2 -> Point2d
    fromVec2 =
        Math.Vector2.toTuple >> Point2d.fromCoordinates

@docs coordinates, fromCoordinates, polarCoordinates, fromPolarCoordinates, toRecord, fromRecord

# Coordinates

@docs xCoordinate, yCoordinate

# Displacement and distance

@docs vectorTo, vectorFrom, distanceFrom, squaredDistanceFrom, distanceAlong, distanceFromAxis

# Arithmetic

@docs plus, minus

# Transformations

@docs scaleAbout, rotateAround, translateAlong, mirrorAcross, projectOnto

# Local coordinates

@docs toLocalIn, fromLocalIn
-}

import OpenSolid.Core.Types exposing (..)
import OpenSolid.Core.Vector2d as Vector2d
import OpenSolid.Core.Direction2d as Direction2d


{-| The point (0, 0).

    Point2d.origin == Point2d 0 0
-}
origin : Point2d
origin =
    Point2d 0 0


{-| Construct a point given its radius from the origin and its angle
counterclockwise from the positive X axis. Angles must be given in radians
(Elm's built-in `degrees` and `turns` functions may be useful).

    Point2d.polar 1 (degrees 45) == Point2d 0.7071 0.7071
-}
polar : Float -> Float -> Point2d
polar radius angle =
    fromPolarCoordinates ( radius, angle )


{-| Construct a point along an axis, at a particular distance from the axis'
origin point.

    axis =
        Axis2d (Point2d 1 1) Direction2d.x

    Point2d.along axis 3 == Point2d 4 1
    Point2d.along axis -3 == Point2d -2 1
-}
along : Axis2d -> Float -> Point2d
along axis distance =
    plus (Vector2d.along axis distance) axis.originPoint


{-| Construct a point halfway between two other points.

    Point2d.midpoint (Point2d 1 1) (Point2d 3 7) == Point2d 2 4
-}
midpoint : Point2d -> Point2d -> Point2d
midpoint firstPoint secondPoint =
    interpolate firstPoint secondPoint 0.5


{-| Construct a point by interpolating between two other points.

    Point2d.interpolate Point2d.origin (Point2d 8 8) 0 == Point2d 0 0
    Point2d.interpolate Point2d.origin (Point2d 8 8) 0.25 == Point2d 2 2
    Point2d.interpolate Point2d.origin (Point2d 8 8) 0.75 == Point2d 6 6
    Point2d.interpolate Point2d.origin (Point2d 8 8) 1 == Point2d 8 8

You can also pass values less than zero or larger than one to extrapolate:

    Point2d.interpolate Point2d.origin (Point2d 100 0) 1.1 == Point2d 110 0
-}
interpolate : Point2d -> Point2d -> Float -> Point2d
interpolate startPoint endPoint =
    let
        displacement =
            vectorFrom startPoint endPoint<commit_msg>Tweak Point2d documentation<commit_after>{- 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 <NAME>
   <EMAIL>
-}


module OpenSolid.Core.Point2d
    exposing
        ( origin
        , polar
        , along
        , midpoint
        , interpolate
        , coordinates
        , fromCoordinates
        , polarCoordinates
        , fromPolarCoordinates
        , toRecord
        , fromRecord
        , xCoordinate
        , yCoordinate
        , vectorTo
        , vectorFrom
        , distanceFrom
        , squaredDistanceFrom
        , distanceAlong
        , distanceFromAxis
        , plus
        , minus
        , scaleAbout
        , rotateAround
        , translateAlong
        , mirrorAcross
        , projectOnto
        , toLocalIn
        , fromLocalIn
        )

{-| Various functions for constructing `Point2d` values and performing
operations on them. For the examples below, assume the following imports:

    import OpenSolid.Core.Types exposing (..)
    import OpenSolid.Core.Point2d as Point2d
    import OpenSolid.Core.Vector2d as Vector2d
    import OpenSolid.Core.Frame2d as Frame2d

Examples use `==` to indicate that two expressions are equivalent, even if (due
to numerical roundoff) they might not be exactly equal.

# Constants

@docs origin

# Constructors

Since `Point2d` is not an opaque type, the simplest way to construct one is
directly from its X and Y coordinates, for example `Point2d 2 3`. But that is
not the only way!

@docs polar, along, midpoint, interpolate

# Conversions

Various ways to convert to and from plain tuples and records. Primarily useful
for interoperability with other libraries. For example, you could define
conversion functions to and from `elm-linear-algebra`'s `Vec2` type with

    toVec2 : Point2d -> Math.Vector2.Vec2
    toVec2 =
        Point2d.coordinates >> Math.Vector2.fromTuple

    fromVec2 : Math.Vector2.Vec2 -> Point2d
    fromVec2 =
        Math.Vector2.toTuple >> Point2d.fromCoordinates

@docs coordinates, fromCoordinates, polarCoordinates, fromPolarCoordinates, toRecord, fromRecord

# Coordinates

@docs xCoordinate, yCoordinate

# Displacement and distance

@docs vectorTo, vectorFrom, distanceFrom, squaredDistanceFrom, distanceAlong, distanceFromAxis

# Arithmetic

@docs plus, minus

# Transformations

@docs scaleAbout, rotateAround, translateAlong, mirrorAcross, projectOnto

# Local coordinates

@docs toLocalIn, fromLocalIn
-}

import OpenSolid.Core.Types exposing (..)
import OpenSolid.Core.Vector2d as Vector2d
import OpenSolid.Core.Direction2d as Direction2d


{-| The point (0, 0).

    Point2d.origin == Point2d 0 0
-}
origin : Point2d
origin =
    Point2d 0 0


{-| Construct a point given its radius from the origin and its angle
counterclockwise from the positive X axis. Angles must be given in radians
(Elm's built-in `degrees` and `turns` functions may be useful).

    Point2d.polar 1 (degrees 45) == Point2d 0.7071 0.7071
-}
polar : Float -> Float -> Point2d
polar radius angle =
    fromPolarCoordinates ( radius, angle )


{-| Construct a point along an axis, at a particular distance from the axis'
origin point.

    horizontalAxis =
        Axis2d (Point2d 1 1) Direction2d.x

    Point2d.along horizontalAxis 3 == Point2d 4 1
    Point2d.along horizontalAxis -3 == Point2d -2 1
-}
along : Axis2d -> Float -> Point2d
along axis distance =
    plus (Vector2d.along axis distance) axis.originPoint


{-| Construct a point halfway between two other points.

    Point2d.midpoint (Point2d 1 1) (Point2d 3 7) == Point2d 2 4
-}
midpoint : Point2d -> Point2d -> Point2d
midpoint firstPoint secondPoint =
    interpolate firstPoint secondPoint 0.5


{-| Construct a point by interpolating between two other points based on a
parameter that ranges from zero to one.

    interpolate : Float -> Point2d
    interpolate value =
        Point2d.interpolate Point2d.origin (Point2d 8 8) value

    interpolate 0 == Point2d 0 0
    interpolate 0.25 == Point2d 2 2
    interpolate 0.75 == Point2d 6 6
    interpolate 1 == Point2d 8 8

You can also pass values less than zero or larger than one to extrapolate:

    Point2d.interpolate Point2d.origin (Point2d 100 0) 1.1 == Point2d 110 0
-}
interpolate : Point2d -> Point2d -> Float -> Point2d
interpolate startPoint endPoint =
    let
        displacement =
            vectorFrom startPoint endPoint
{'fraction_non_alphanumeric': 0.06952646239554318, 'fraction_numerical': 0.03309192200557103, 'mean_word_length': 2.994659546061415, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2989363', 'n_tokens_mistral': 2905, 'n_tokens_neox': 2645, 'n_words': 966}