<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.Plane3d
    exposing
        ( xy
        , yz
        , zx
        , originPoint
        , normalDirection
        , sketchPlane
        , offsetBy
        , flip
        , normalAxis
        , rotateAround
        , translateBy
        , moveTo
        , mirrorAcross
        , relativeTo
        , placeIn
        )

{-| <img src="https://opensolid.github.io/images/geometry/icons/plane3d.svg" alt="Plane3d" width="160">

A `Plane3d` is an infinite flat plane in 3D. It is defined by an origin point
and normal direction and is useful for several operations including:

  - Mirroring across the plane
  - Projecting onto the plane
  - Measuring distance from the plane

Planes can by constructed by passing a record with `originPoint` and
`normalDirection` fields to the `Plane3d` constructor, for example:

    plane =
        Plane3d
            { originPoint = Point3d ( 2, 1, 3 )
            , normalDirection = Direction3d.y
            }

# Predefined planes

@docs xy, yz, zx

# Accessors

@docs originPoint, normalDirection

# Conversions

@docs normalAxis, sketchPlane

# Transformations

@docs offsetBy, flip, rotateAround, translateBy, moveTo, mirrorAcross

# Coordinate frames

@docs relativeTo, placeIn
-}

import OpenSolid.Geometry.Types exposing (..)
import OpenSolid.Point3d as Point3d
import OpenSolid.Direction3d as Direction3d


{-| The global XY plane, centered at the origin with a normal in the positive Z
direction.

    Plane3d.xy
    --> Plane3d
    -->     { originPoint = Point3d.origin
    -->     , normalDirection = Direction3d.z
    -->     }
-}
xy : Plane3d
xy =
    Plane3d
        { originPoint = Point3d.origin
        , normalDirection = Direction3d.z
        }


{-| The global YZ plane, centered at the origin with a normal in the positive X
direction.

    Plane3d.yz
    --> Plane3d
    -->     { originPoint = Point3d.origin
    -->     , normalDirection = Direction3d.x
    -->     }
-}
yz : Plane3d
yz =
    Plane3d
        { originPoint = Point3d.origin
        , normalDirection = Direction3d.x
        }


{-| The global ZX plane, centered at the origin with a normal in the positive Y
direction.

    Plane3d.zx
    --> Plane3d
    -->     { originPoint = Point3d.origin
    -->     , normalDirection = Direction3d.y
    -->     }
-}
zx : Plane3d
zx =
    Plane3d
        { originPoint = Point3d.origin
        , normalDirection = Direction3d.y
        }


{-| Get the origin point of a plane.

    Plane3d.originPoint Plane3d.xy
    --> Point3d.origin
-}
originPoint : Plane3d -> Point3d
originPoint (Plane3d properties) =
    properties.originPoint<commit_msg>Add Plane3d.throughPoints<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.Plane3d
    exposing
        ( xy
        , yz
        , zx
        , throughPoints
        , originPoint
        , normalDirection
        , sketchPlane
        , offsetBy
        , flip
        , normalAxis
        , rotateAround
        , translateBy
        , moveTo
        , mirrorAcross
        , relativeTo
        , placeIn
        )

{-| <img src="https://opensolid.github.io/images/geometry/icons/plane3d.svg" alt="Plane3d" width="160">

A `Plane3d` is an infinite flat plane in 3D. It is defined by an origin point
and normal direction and is useful for several operations including:

  - Mirroring across the plane
  - Projecting onto the plane
  - Measuring distance from the plane

Planes can by constructed by passing a record with `originPoint` and
`normalDirection` fields to the `Plane3d` constructor, for example:

    plane =
        Plane3d
            { originPoint = Point3d ( 2, 1, 3 )
            , normalDirection = Direction3d.y
            }

# Predefined planes

@docs xy, yz, zx

# Constructors

@docs throughPoints

# Accessors

@docs originPoint, normalDirection

# Conversions

@docs normalAxis, sketchPlane

# Transformations

@docs offsetBy, flip, rotateAround, translateBy, moveTo, mirrorAcross

# Coordinate frames

@docs relativeTo, placeIn
-}

import OpenSolid.Geometry.Types exposing (..)
import OpenSolid.Point3d as Point3d
import OpenSolid.Direction3d as Direction3d
import OpenSolid.Triangle3d as Triangle3d


{-| The global XY plane, centered at the origin with a normal in the positive Z
direction.

    Plane3d.xy
    --> Plane3d
    -->     { originPoint = Point3d.origin
    -->     , normalDirection = Direction3d.z
    -->     }
-}
xy : Plane3d
xy =
    Plane3d
        { originPoint = Point3d.origin
        , normalDirection = Direction3d.z
        }


{-| The global YZ plane, centered at the origin with a normal in the positive X
direction.

    Plane3d.yz
    --> Plane3d
    -->     { originPoint = Point3d.origin
    -->     , normalDirection = Direction3d.x
    -->     }
-}
yz : Plane3d
yz =
    Plane3d
        { originPoint = Point3d.origin
        , normalDirection = Direction3d.x
        }


{-| The global ZX plane, centered at the origin with a normal in the positive Y
direction.

    Plane3d.zx
    --> Plane3d
    -->     { originPoint = Point3d.origin
    -->     , normalDirection = Direction3d.y
    -->     }
-}
zx : Plane3d
zx =
    Plane3d
        { originPoint = Point3d.origin
        , normalDirection = Direction3d.y
        }


{-| Attempt to construct a plane passing through the three given points. The
origin point of the resulting plane will be equal to the first given point, and
the normal direction will be such that the three given points are in
counterclockwise order around it according to the right-hand rule. If the three
given points are collinear, returns `Nothing`.

    Plane3d.throughPoints
        (Point3d ( 2, 0, 0 ))
        (Point3d ( 3, 0, 0 ))
        (Point3d ( 4, 1, 1 ))
    --> Just
    -->     (Plane3d
    -->         { originPoint = Point3d ( 2, 0, 0 )
    -->         , normalDirection = Direction3d ( 0, -0.7071, 0.7071 )
    -->         }
    -->     )

    Plane3d.throughPoints
        (Point3d ( 2, 0, 0 ))
        (Point3d ( 3, 0, 0 ))
        (Point3d ( 4, 0, 0 ))
    --> Nothing
-}
throughPoints : Point3d -> Point3d -> Point3d -> Maybe Plane3d
throughPoints firstPoint secondPoint thirdPoint =
    let
        triangle =
            Triangle3d ( firstPoint, secondPoint, thirdPoint )

        a =
            Just
                (Plane3d
                    { originPoint = Point3d.origin
                    , normalDirection = Direction3d.z
                    }
                )
    in
        Triangle3d.normalDirection triangle
            |> Maybe.map
                (\normalDirection ->
                    Plane3d
                        { originPoint = firstPoint
                        , normalDirection = normalDirection
                        }
                )


{-| Get the origin point of a plane.

    Plane3d.originPoint Plane3d.xy
    --> Point3d.origin
-}
originPoint : Plane3d -> Point3d
originPoint (Plane3d properties) =
    properties.originPoint
{'fraction_non_alphanumeric': 0.15460875722884457, 'fraction_numerical': 0.020063731854124866, 'mean_word_length': 1.4218348099456988, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 49, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1847413', 'n_tokens_mistral': 2398, 'n_tokens_neox': 2268, 'n_words': 686}