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

Circle3d

Circle3d

A Circle3d is defined by its center point, axial direction and radius. The axial direction is the direction of the axis through the center of the circle that all points on the circle are equidistant from, or equivalently the normal direction of the plane defined by the circle. This module contains functionality for:

  • Constructing circles around axes, on planes, or through points
  • Scaling, rotating and translating circles
  • Extracting circle properties like center point and area
type alias Circle3d = Types.Circle3d

Constructors

withRadius : Float -> Direction3d -> Point3d -> Circle3d
sweptAround : Axis3d -> Point3d -> Circle3d
on : SketchPlane3d -> Circle2d -> Circle3d
throughPoints : Point3d -> Point3d -> Point3d -> Maybe Circle3d

Properties

centerPoint : Circle3d -> Point3d
axialDirection : Circle3d -> Direction3d
radius : Circle3d -> Float
diameter : Circle3d -> Float
axis : Circle3d -> Axis3d
plane : Circle3d -> Plane3d
area : Circle3d -> Float
circumference : Circle3d -> Float
boundingBox : Circle3d -> BoundingBox3d

Transformations

scaleAbout : Point3d -> Float -> Circle3d -> Circle3d
rotateAround : Axis3d -> Float -> Circle3d -> Circle3d
translateBy : Vector3d -> Circle3d -> Circle3d
translateIn : Direction3d -> Float -> Circle3d -> Circle3d
mirrorAcross : Plane3d -> Circle3d -> Circle3d
projectInto : SketchPlane3d -> Circle3d -> Types.Ellipse2d

Coordinate conversions

relativeTo : Frame3d -> Circle3d -> Circle3d
placeIn : Frame3d -> Circle3d -> Circle3d
module Circle3d
    exposing
        ( Circle3d
        , area
        , axialDirection
        , axis
        , boundingBox
        , centerPoint
        , circumference
        , diameter
        , mirrorAcross
        , on
        , placeIn
        , plane
        , projectInto
        , radius
        , relativeTo
        , rotateAround
        , scaleAbout
        , sweptAround
        , throughPoints
        , translateBy
        , translateIn
        , withRadius
        )

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

A `Circle3d` is defined by its center point, axial direction and radius. The
axial direction is the direction of the axis through the center of the circle
that all points on the circle are equidistant from, or equivalently the normal
direction of the plane defined by the circle. This module contains functionality
for:

  - Constructing circles around axes, on planes, or through points
  - Scaling, rotating and translating circles
  - Extracting circle properties like center point and area

@docs Circle3d


# Constructors

@docs withRadius, sweptAround, on, throughPoints


# Properties

@docs centerPoint, axialDirection, radius, diameter, axis, plane, area, circumference, boundingBox


# Transformations

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


# Coordinate conversions

@docs relativeTo, placeIn

-}

import Axis3d exposing (Axis3d)
import BoundingBox3d exposing (BoundingBox3d)
import Circle2d exposing (Circle2d)
import Direction3d exposing (Direction3d)
import Frame2d exposing (Frame2d)
import Frame3d exposing (Frame3d)
import Geometry.Types as Types
import Plane3d exposing (Plane3d)
import Point3d exposing (Point3d)
import SketchPlane3d exposing (SketchPlane3d)
import Vector2d exposing (Vector2d)
import Vector3d exposing (Vector3d)


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


{-| -}
withRadius : Float -> Direction3d -> Point3d -> Circle3d
withRadius radius_ axialDirection_ centerPoint_ =
    Types.Circle3d
        { centerPoint = centerPoint_
        , axialDirection = axialDirection_
        , radius = abs radius_
        }


{-| -}
sweptAround : Axis3d -> Point3d -> Circle3d
sweptAround axis_ point =
    let
        centerPoint_ =
            Point3d.projectOntoAxis axis_ point
    in
    withRadius (Point3d.distanceFrom centerPoint_ point)
        (Axis3d.direction axis_)
        centerPoint_


{-| -}
on : SketchPlane3d -> Circle2d -> Circle3d
on sketchPlane circle =
    withRadius (Circle2d.radius circle)
        (SketchPlane3d.normalDirection sketchPlane)
        (Point3d.on sketchPlane (Circle2d.centerPoint circle))


{-| -}
throughPoints : Point3d -> Point3d -> Point3d -> Maybe Circle3d
throughPoints p1 p2 p3 =
    Maybe.map2
        (\centerPoint_ plane_ ->
            let
                r1 =
                    Point3d.distanceFrom centerPoint_ p1

                r2 =
                    Point3d.distanceFrom centerPoint_ p2

                r3 =
                    Point3d.distanceFrom centerPoint_ p3

                r =
                    (r1 + r2 + r3) / 3
            in
            withRadius r (Plane3d.normalDirection plane_) centerPoint_
        )
        (Point3d.circumcenter p1 p2 p3)
        (Plane3d.throughPoints p1 p2 p3)


{-| -}
centerPoint : Circle3d -> Point3d
centerPoint (Types.Circle3d circle) =
    circle.centerPoint


{-| -}
axialDirection : Circle3d -> Direction3d
axialDirection (Types.Circle3d circle) =
    circle.axialDirection


{-| -}
axis : Circle3d -> Axis3d
axis (Types.Circle3d circle) =
    Axis3d.through circle.centerPoint circle.axialDirection


{-| -}
plane : Circle3d -> Plane3d
plane circle =
    Plane3d.through (centerPoint circle) (axialDirection circle)


{-| -}
radius : Circle3d -> Float
radius (Types.Circle3d properties) =
    properties.radius


{-| -}
diameter : Circle3d -> Float
diameter circle =
    2 * radius circle


{-| -}
area : Circle3d -> Float
area circle =
    let
        r =
            radius circle
    in
    pi * r * r


{-| -}
circumference : Circle3d -> Float
circumference circle =
    2 * pi * radius circle


{-| -}
scaleAbout : Point3d -> Float -> Circle3d -> Circle3d
scaleAbout point scale circle =
    withRadius (abs scale * radius circle)
        (if scale >= 0 then
            axialDirection circle
         else
            Direction3d.reverse (axialDirection circle)
        )
        (Point3d.scaleAbout point scale (centerPoint circle))


{-| -}
rotateAround : Axis3d -> Float -> Circle3d -> Circle3d
rotateAround axis_ angle =
    let
        rotatePoint =
            Point3d.rotateAround axis_ angle

        rotateDirection =
            Direction3d.rotateAround axis_ angle
    in
    \circle ->
        withRadius (radius circle)
            (rotateDirection (axialDirection circle))
            (rotatePoint (centerPoint circle))


{-| -}
translateBy : Vector3d -> Circle3d -> Circle3d
translateBy displacement circle =
    withRadius (radius circle)
        (axialDirection circle)
        (Point3d.translateBy displacement (centerPoint circle))


{-| -}
translateIn : Direction3d -> Float -> Circle3d -> Circle3d
translateIn direction distance circle =
    translateBy (Vector3d.withLength distance direction) circle


{-| -}
mirrorAcross : Plane3d -> Circle3d -> Circle3d
mirrorAcross plane_ circle =
    withRadius (radius circle)
        (Direction3d.mirrorAcross plane_ (axialDirection circle))
        (Point3d.mirrorAcross plane_ (centerPoint circle))


{-| -}
projectInto : SketchPlane3d -> Circle3d -> Types.Ellipse2d
projectInto sketchPlane circle =
    let
        projectedAxialDirection =
            axialDirection circle
                |> Direction3d.toVector
                |> Vector3d.projectInto sketchPlane

        projectedCenter =
            centerPoint circle |> Point3d.projectInto sketchPlane

        xRadius =
            radius circle
    in
    case Vector2d.direction projectedAxialDirection of
        Just yDirection ->
            let
                normalDirection =
                    SketchPlane3d.normalDirection sketchPlane

                yRatio =
                    axialDirection circle
                        |> Direction3d.componentIn normalDirection
                        |> abs

                yRadius =
                    yRatio * xRadius

                axes =
                    Frame2d.withYDirection yDirection projectedCenter
            in
            Types.Ellipse2d
                { axes = axes
                , xRadius = xRadius
                , yRadius = yRadius
                }

        Nothing ->
            Types.Ellipse2d
                { axes = Frame2d.atPoint projectedCenter
                , xRadius = xRadius
                , yRadius = xRadius
                }


{-| -}
relativeTo : Frame3d -> Circle3d -> Circle3d
relativeTo frame circle =
    withRadius (radius circle)
        (Direction3d.relativeTo frame (axialDirection circle))
        (Point3d.relativeTo frame (centerPoint circle))


{-| -}
placeIn : Frame3d -> Circle3d -> Circle3d
placeIn frame circle =
    withRadius (radius circle)
        (Direction3d.placeIn frame (axialDirection circle))
        (Point3d.placeIn frame (centerPoint circle))


{-| -}
boundingBox : Circle3d -> BoundingBox3d
boundingBox circle =
    let
        ( nx, ny, nz ) =
            Direction3d.components (axialDirection circle)

        nx2 =
            nx * nx

        ny2 =
            ny * ny

        nz2 =
            nz * nz

        r =
            radius circle

        dx =
            r * sqrt (ny2 + nz2)

        dy =
            r * sqrt (nx2 + nz2)

        dz =
            r * sqrt (nx2 + ny2)

        ( cx, cy, cz ) =
            Point3d.coordinates (centerPoint circle)
    in
    BoundingBox3d.fromExtrema
        { minX = cx - dx
        , maxX = cx + dx
        , minY = cy - dy
        , maxY = cy + dy
        , minZ = cz - dz
        , maxZ = cz + dz
        }