ianmackenzie / elm-geometry / SketchPlane3d

A SketchPlane3d represents a 2D planar coordinate system in 3D space, and is defined by its origin point and X and Y directions (which are always perpendicular to each other). Sketch planes are the primary tool for converting back and forth between 2D and 3D coordinates:

This allows you to create algorithms that project from 3D into 2D, perform some calculations in 2D, then convert the result back to 3D.

Many 3D data types have projectInto functions that return the corresponding 2D data type, and on functions for converting back to 3D. For example, Triangle3d.projectInto returns a Triangle2d and Triangle3d.on returns a Triangle3d. These pairs of functions are almost, but not quite, inverses of each other:

triangle2d
    |> Triangle3d.on sketchPlane
    |> Triangle3d.projectInto sketchPlane

will just return the original triangle2d value (within roundoff error), while

triangle3d
    |> Triangle3d.projectInto sketchPlane
    |> Triangle3d.on sketchPlane

is equivalent to

triangle3d
    |> Triangle3d.projectOnto
        (SketchPlane3d.toPlane sketchPlane)


type alias SketchPlane3d units coordinates defines =
Geometry.Types.SketchPlane3d units coordinates defines

The type parameters of a SketchPlane3d indicate what units and coordinate systems it's defined in, and what local 2D coordinate system (if any) it itself defines. A concrete SketchPlane3d type might look like

type alias SketchPlane =
    SketchPlane3d Meters World { defines : Sketch }

which can be read as "a SketchPlane3d defined in meters in world coordinates, which itself defines a local 2D sketch coordinate system". For sketch planes that don't define a local 2D coordinate system, you could use

type alias SketchPlane =
    SketchPlane3d Meters World {}

Many functions in this module don't care about the third type argument (whether it's a record with a defines field like in the first example, an empty record like in the second example, or even something else entirely) but functions like projectInto and on expect the { defines : localCoordinates } pattern.

Constants

These predefined sketch planes all have the global origin point as their origin point, and use the two indicated global axes as their X and Y axes. For example,

SketchPlane3d.originPoint SketchPlane3d.yz
--> Point3d.origin

SketchPlane3d.xDirection SketchPlane3d.yz
--> Direction3d.y

SketchPlane3d.yDirection SketchPlane3d.yz
--> Direction3d.z

xy : SketchPlane3d units coordinates defines

A sketch plane formed from the global X and Y axes.

yx : SketchPlane3d units coordinates defines

A sketch plane formed from the global Y and X axes.

yz : SketchPlane3d units coordinates defines

A sketch plane formed from the global Y and Z axes.

zy : SketchPlane3d units coordinates defines

A sketch plane formed from the global Z and Y axes.

zx : SketchPlane3d units coordinates defines

A sketch plane formed from the global Z and X axes.

xz : SketchPlane3d units coordinates defines

A sketch plane formed from the global X and Z axes.

Constructors

Sketch planes can also be constructed from Frame3d values using Frame3d.xySketchPlane etc.

through : Point3d units coordinates -> Direction3d coordinates -> SketchPlane3d units coordinates defines

Construct a sketch plane having the given origin point and normal direction. Perpendicular X and Y directions will be chosen arbitrarily; this is useful when constructing 'scratch' sketch planes where the specific X/Y directions are unimportant.

sketchPlane =
    SketchPlane3d.through Point3d.origin
        (Direction3d.xz (Angle.degrees 60))

SketchPlane3d.originPoint sketchPlane
--> Point3d.origin

SketchPlane3d.xDirection sketchPlane
--> Direction3d.xz (Angle.degrees -30)

SketchPlane3d.yDirection sketchPlane
--> Direction3d.y

withNormalDirection : Direction3d coordinates -> Point3d units coordinates -> SketchPlane3d units coordinates defines

Construct a sketch plane with the given normal direction, through the given point. Flipped version of through.

on : SketchPlane3d units coordinates3d { defines : coordinates2d } -> Frame2d units coordinates2d defines -> SketchPlane3d units coordinates3d defines

Construct one sketch plane lying on another sketch plane, but with a different origin point and X/Y directions. To do this, a Frame2d must be provided that specifies the origin point and X/Y directions of the new sketch plane, in 2D coordinates within the existing sketch plane. Whew!

frame2d =
    Frame2d.atPoint (Point2d.meters 2 3)
        |> Frame2d.rotateBy (Angle.degrees -30)

sketchPlane =
    SketchPlane3d.on SketchPlane3d.yz frame2d

SketchPlane3d.originPoint sketchPlane
--> Point3d.meters 0 2 3

SketchPlane3d.xDirection sketchPlane
--> Direction3d.yz (Angle.degrees -30)

SketchPlane3d.yDirection sketchPlane
--> Direction3d.yz (Angle.degrees 60)

throughPoints : Point3d units coordinates -> Point3d units coordinates -> Point3d units coordinates -> Maybe (SketchPlane3d units coordinates defines)

Attempt to construct a sketch plane that passes through the three given points. Returns a sketch plane where:

If the three given points are collinear, returns Nothing.

SketchPlane3d.throughPoints
    (Point3d.meters 2 0 0)
    (Point3d.meters 3 0 0)
    (Point3d.meters 4 1 1)
--> Just sketchPlane

SketchPlane3d.originPoint sketchPlane
--> Point3d.meters 2 0 0

SketchPlane3d.xDirection sketchPlane
--> Direction3d.x

SketchPlane3d.yDirection sketchPlane
--> Direction3d.yz (Angle.degrees 45)

SketchPlane3d.throughPoints
    (Point3d.meters 2 0 0)
    (Point3d.meters 3 0 0)
    (Point3d.meters 4 0 0)
--> Nothing

fromPlane : Plane3d units coordinates -> SketchPlane3d units coordinates defines

Construct a SketchPlane3d from the given plane;

SketchPlane3d.fromPlane plane

is equivalent to

SketchPlane3d.withNormalDirection
    (Plane3d.normalDirection plane)
    (Plane3d.originPoint plane)

Note that because the X and Y directions of the resulting sketch plane are chosen arbitrarily, conversions may not work exactly as you expect. For example, in the current implementation,

sketchPlane =
    SketchPlane3d.fromPlane Plane3d.xy

is not equal to SketchPlane3d.xy (although the two sketch planes have the same origin point and are coplanar):

SketchPlane3d.originPoint sketchPlane
--> Point3d.origin

SketchPlane3d.xDirection sketchPlane
--> Direction3d.negativeY

SketchPlane3d.yDirection sketchPlane
--> Direction3d.positiveX

copy : SketchPlane3d units coordinates defines1 -> SketchPlane3d units coordinates defines2

Create a 'fresh copy' of a sketch plane: one with the same origin point and X/Y directions, but that can be used to define a different local coordinate system. Sometimes useful in generic/library code. Despite the name, this is efficient: it really just returns the value you passed in, but with a different type.

unsafe : { originPoint : Point3d units coordinates, xDirection : Direction3d coordinates, yDirection : Direction3d coordinates } -> SketchPlane3d units coordinates defines

Construct a sketch plane directly from its origin point and X and Y directions:

sketchPlane =
    SketchPlane3d.unsafe
        { originPoint = Point3d.meters 2 1 3
        , xDirection = Direction3d.positiveY
        , yDirection = Direction3d.negativeZ
        }

If you construct a SketchPlane3d this way, you must ensure that the X and Y basis directions are perpendicular to each other.

Conversions

toPlane : SketchPlane3d units coordinates defines -> Plane3d units coordinates

Convert a SketchPlane3d to a Plane3d with the same origin point and normal direction.

SketchPlane3d.toPlane SketchPlane3d.xy
--> Plane3d.xy

SketchPlane3d.toPlane SketchPlane3d.yx
--> Plane3d.reverseNormal Plane3d.xy

toFrame : SketchPlane3d units coordinates defines2d -> Geometry.Types.Frame3d units coordinates defines3d

Convert a SketchPlane3d to a Frame3d with the same origin point and X and Y directions. The Z direction of the returned frame will be equal to the normal direction of the given sketch plane. This means that the given sketch plane will be the XY sketch plane of the returned frame.

Properties

originPoint : SketchPlane3d units coordinates defines -> Point3d units coordinates

Get the origin point of a sketch plane.

xDirection : SketchPlane3d units coordinates defines -> Direction3d coordinates

Get the X direction of a sketch plane (the direction of the sketch plane's X axis).

yDirection : SketchPlane3d units coordinates defines -> Direction3d coordinates

Get the Y direction of a sketch plane (the direction of the sketch plane's Y axis).

normalDirection : SketchPlane3d units coordinates defines -> Direction3d coordinates

Get the normal direction to a sketch plane. This is equal to the cross product of the sketch plane's X and Y directions.

SketchPlane3d.normalDirection SketchPlane3d.xy
--> Direction3d.z

SketchPlane3d.normalDirection SketchPlane3d.xz
--> Direction3d.negativeY

xAxis : SketchPlane3d units coordinates defines -> Axis3d units coordinates

Get the X axis of a sketch plane. A 2D X coordinate within the sketch plane corresponds to a distance along this axis in 3D.

SketchPlane3d.xAxis SketchPlane3d.zx
--> Axis3d.z

yAxis : SketchPlane3d units coordinates defines -> Axis3d units coordinates

Get the Y axis of a sketch plane. A 2D Y coordinate within the sketch plane corresponds to a distance along this axis in 3D.

SketchPlane3d.yAxis SketchPlane3d.zx
--> Axis3d.x

normalAxis : SketchPlane3d units coordinates defines -> Axis3d units coordinates

Get the normal axis to a sketch plane (the axis formed from the sketch plane's origin point and normal direction).

SketchPlane3d.normalAxis SketchPlane3d.xy
--> Axis3d.z

SketchPlane3d.normalAxis SketchPlane3d.xz
--> Axis3d.reverse Axis3d.y

Transformations

offsetBy : Quantity Basics.Float units -> SketchPlane3d units coordinates defines1 -> SketchPlane3d units coordinates defines2

Shift a sketch plane in its own normal direction by the given (signed) distance.

SketchPlane3d.xy
    |> SketchPlane3d.offsetBy (Length.meters -2.0)
    |> SketchPlane3d.originPoint
--> Point3d.meters 0 0 -2

SketchPlane3d.zx
    |> SketchPlane3d.offsetBy (Length.meters 1.0)
    |> SketchPlane3d.originPoint
--> Point3d.meters 0 1 0

reverseX : SketchPlane3d units coordinates defines1 -> SketchPlane3d units coordinates defines2

Reverse the X direction of a sketch plane, leaving its Y direction and origin point unchanged.

reverseY : SketchPlane3d units coordinates defines1 -> SketchPlane3d units coordinates defines2

Reverse the Y direction of a sketch plane, leaving its X direction and origin point unchanged.

moveTo : Point3d units coordinates -> SketchPlane3d units coordinates defines1 -> SketchPlane3d units coordinates defines2

Set the origin point of the given sketch plane to the given point, leaving its X and Y directions unchanged.

rotateAround : Axis3d units coordinates -> Angle -> SketchPlane3d units coordinates defines1 -> SketchPlane3d units coordinates defines2

Rotate a sketch plane around an axis by a given angle. The sketch plane's origin point and X and Y directions will all be rotated around the given axis.

SketchPlane3d.xy
    |> SketchPlane3d.rotateAround Axis3d.x
        (Angle.degrees 90)
--> SketchPlane3d.xz

rotateAroundOwn : (SketchPlane3d units coordinates defines1 -> Axis3d units coordinates) -> Angle -> SketchPlane3d units coordinates defines1 -> SketchPlane3d units coordinates defines2

Rotate a sketch plane around one of its own axes by a given angle.

The first argument is a function that returns the axis to rotate around, given the current sketch plane. The majority of the time this will be either SketchPlane3d.xAxis or SketchPlane3d.yAxis.

This function is convenient when constructing sketch planes via a series of transformations. For example,

sketchPlane =
    SketchPlane3d.xy
        |> SketchPlane3d.translateBy
            (Vector3d.meters 1 0 0)
        |> SketchPlane3d.rotateAroundOwn
            SketchPlane3d.yAxis
            (Angle.degrees -45)

SketchPlane3d.originPoint sketchPlane
--> Point3d.meters 1 0 0

SketchPlane3d.xDirection sketchPlane
--> Direction3d.xz (Angle.degrees 45)

SketchPlane3d.yDirection sketchPlane
--> Direction3d.y

Note that since the rotation was around the sketch plane's own Y axis (which passes through the sketch plane's origin point) instead of the global Y axis, the origin point itself was not affected by the rotation.

translateBy : Vector3d units coordinates -> SketchPlane3d units coordinates defines1 -> SketchPlane3d units coordinates defines2

Translate a sketch plane by a given displacement.

displacement =
    Vector3d.meters 2 1 3

sketchPlane =
    SketchPlane3d.xy
        |> SketchPlane3d.translateBy displacement

SketchPlane3d.originPoint sketchPlane
--> Point3d.meters 2 1 3

SketchPlane3d.xDirection sketchPlane
--> Direction3d.x

SketchPlane3d.yDirection sketchPlane
--> Direction3d.y

translateIn : Direction3d coordinates -> Quantity Basics.Float units -> SketchPlane3d units coordinates defines1 -> SketchPlane3d units coordinates defines2

Translate a sketch plane in a given direction by a given distance.

translateAlongOwn : (SketchPlane3d units coordinates defines1 -> Axis3d units coordinates) -> Quantity Basics.Float units -> SketchPlane3d units coordinates defines1 -> SketchPlane3d units coordinates defines2

Translate a sketch plane along one of its own axes by a given distance.

The first argument is a function that returns the axis to translate along, given the current sketch plane. The majority of the time this will be either SketchPlane3d.xAxis or SketchPlane3d.yAxis.

This function is convenient when constructing frames via a series of transformations. For example,

sketchPlane =
    SketchPlane3d.xy
        |> SketchPlane3d.rotateAround
            Axis3d.x
            (Angle.degrees 45)
        |> SketchPlane3d.translateAlongOwn
            SketchPlane3d.yAxis
            (Length.meters 2)

means 'take the global XY sketch plane, rotate it around the global X axis by 45 degrees, then translate the result 2 meters along its own (rotated) Y axis', resulting in

SketchPlane3d.originPoint sketchPlane
--> Point3d.meters 0 1.4142 1.4142

SketchPlane3d.xDirection sketchPlane
--> Direction3d.x

SketchPlane3d.yDirection sketchPlane
--> Direction3d.yz (Angle.degrees 45)

mirrorAcross : Plane3d units coordinates -> SketchPlane3d units coordinates defines1 -> SketchPlane3d units coordinates defines2

Mirror a sketch plane across a plane.

sketchPlane =
    SketchPlane3d.yz
        |> SketchPlane3d.moveTo (Point3d.meters 2 1 3)

mirroredSketchPlane =
    SketchPlane3d.mirrorAcross Plane3d.xy sketchPlane

SketchPlane3d.originPoint sketchPlane
--> Point3d.meters 2 1 -3

SketchPlane3d.xDirection sketchPlane
--> Direction3d.y

SketchPlane3d.yDirection sketchPlane
--> Direction3d.negativeZ

Unit conversions

at : Quantity Basics.Float (Quantity.Rate units2 units1) -> SketchPlane3d units1 coordinates defines -> SketchPlane3d units2 coordinates defines

Convert a sketch plane 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.

at_ : Quantity Basics.Float (Quantity.Rate units1 units2) -> SketchPlane3d units1 coordinates defines -> SketchPlane3d units2 coordinates defines

Convert a sketch plane from one units type to another, by providing an 'inverse' conversion factor given as a rate of change of source units with respect to destination units.

Coordinate conversions

relativeTo : Geometry.Types.Frame3d units globalCoordinates { defines : localCoordinates } -> SketchPlane3d units globalCoordinates defines -> SketchPlane3d units localCoordinates defines

Take a sketch plane defined in global coordinates, and return it expressed in local coordinates relative to a given reference frame.

placeIn : Geometry.Types.Frame3d units globalCoordinates { defines : localCoordinates } -> SketchPlane3d units localCoordinates defines -> SketchPlane3d units globalCoordinates defines

Take a sketch plane defined in local coordinates relative to a given reference frame, and return that sketch plane expressed in global coordinates.