A Rectangle2d
represents a rectangle in 2D space. This module contains
rectangle-related functionality such as:
Unlike bounding boxes, rectangles are not constrained to be axis-aligned - they can have arbitrary orientation and so can be rotated, mirrored etc.
Geometry.Types.Rectangle2d
from : Point2d -> Point2d -> Rectangle2d
Construct an axis-aligned rectangle stretching from one point to another. The order of the points does not matter, and they can represent either the lower left and upper right vertices or the upper left and lower right.
p1 =
Point2d.fromCoordinates ( 5, 2 )
p2 =
Point2d.fromCoordinates ( 1, 4 )
Rectangle2d.from p1 p2
--> Rectangle2d.fromExtrema
--> { minX = 1
--> , maxX = 5
--> , minY = 2
--> , maxY = 4
--> }
centeredOn : Frame2d -> ( Basics.Float, Basics.Float ) -> Rectangle2d
Construct a rectangle centered on the given axes (frame), with the given overall X/Y dimensions (width/height).
frame =
Frame2d.atCoordinates ( 3, 2 )
rectangle =
Rectangle2d.centeredOn frame ( 4, 3 )
Rectangle2d.vertices rectangle
--> { bottomLeft = Point2d.fromCoordinates ( 1, 0.5 )
--> , bottomRight = Point2d.fromCoordinates ( 5, 0.5 )
--> , topLeft = Point2d.fromCoordinates ( 1, 3.5 )
--> , topRight = Point2d.fromCoordinates ( 5, 3.5 )
--> }
fromExtrema : { minX : Basics.Float, maxX : Basics.Float, minY : Basics.Float, maxY : Basics.Float } -> Rectangle2d
Construct an axis-aligned rectangle by specifying its minimum and maximum X and Y coordinates. If the min and max are given in the wrong order, they will be swapped.
rectangle =
Rectangle2d.fromExtrema
{ minX = 2
, maxX = 5
, minY = 1
, maxY = 3
}
Rectangle2d.vertices rectangle
--> { bottomLeft = Point2d.fromCoordinates ( 2, 1 )
--> , bottomRight = Point2d.fromCoordinates ( 5, 1 )
--> , topLeft = Point2d.fromCoordinates ( 2, 3 )
--> , topRight = Point2d.fromCoordinates ( 5, 3 )
--> }
fromExtremaIn : Frame2d -> { minX : Basics.Float, maxX : Basics.Float, minY : Basics.Float, maxY : Basics.Float } -> Rectangle2d
Construct a rectangle by supplying its maximum and minimum X and Y values within a particular frame:
frame =
Frame2d.atCoordinates ( 5, 4 )
Rectangle2d.fromExtremaIn frame
{ minX = -1
, minY = -1
, maxX = 3
, maxY = 2
}
--> Rectangle2d.fromExtrema
--> { minX = 4
--> , minY = 3
--> , maxX = 8
--> , maxY = 6
--> }
Note that for simplicity we used a non-rotated frame in the above example - if
we had used a rotated frame, the result could not have been expressed using
Rectangle2d.fromExtrema
since it would no longer have been axis-aligned.
dimensions : Rectangle2d -> ( Basics.Float, Basics.Float )
Get the overall dimensions (width and height) of a rectangle:
rectangle =
Rectangle2d.fromExtrema
{ minX = 2
, maxX = 5
, minY = 1
, maxY = 3
}
Rectangle2d.dimensions rectangle
--> ( 3, 2 )
axes : Rectangle2d -> Frame2d
Get the central axes of a rectangle as a Frame2d
:
rectangle =
Rectangle2d.fromExtrema
{ minX = 2
, maxX = 5
, minY = 1
, maxY = 3
}
Rectangle2d.axes rectangle
--> Frame2d.atCoordinates ( 3.5, 2 )
The origin point of the frame will be the center point of the rectangle.
xAxis : Rectangle2d -> Axis2d
Get the X axis of a rectangle;
Rectangle2d.xAxis rectangle
is equivalent to
Frame2d.xAxis (Rectangle2d.axes rectangle)
yAxis : Rectangle2d -> Axis2d
Get the Y axis of a rectangle;
Rectangle2d.yAxis rectangle
is equivalent to
Frame2d.yAxis (Rectangle2d.axes rectangle)
centerPoint : Rectangle2d -> Point2d
Get the center point of a rectangle.
area : Rectangle2d -> Basics.Float
Get the area of a rectangle:
rectangle =
Rectangle2d.fromExtrema
{ minX = 2
, maxX = 5
, minY = 1
, maxY = 3
}
Rectangle2d.area rectangle
--> 6
vertices : Rectangle2d -> { bottomLeft : Point2d, bottomRight : Point2d, topRight : Point2d, topLeft : Point2d }
Get the vertices of a rectangle as a record. Note that 'bottom', 'top', 'left' and 'right' are with respect to the rectangle's axes, so the may not correspond to global up/down or left/right if the rectangle has been rotated or mirrored.
rectangle =
Rectangle2d.fromExtrema
{ minX = 2
, maxX = 5
, minY = 1
, maxY = 3
}
Rectangle2d.vertices rectangle
--> { bottomLeft = Point2d.fromCoordinates ( 2, 1 )
--> , bottomRight = Point2d.fromCoordinates ( 5, 1 )
--> , topLeft = Point2d.fromCoordinates ( 2, 3 )
--> , topRight = Point2d.fromCoordinates ( 5, 3 )
--> }
bottomLeftVertex : Rectangle2d -> Point2d
Get the bottom left vertex of a rectangle;
Rectangle2d.bottomLeftVertex rectangle
is equivalent to
(Rectangle2d.vertices rectangle).bottomLeft
but is more efficient.
bottomRightVertex : Rectangle2d -> Point2d
Get the bottom right vertex of a rectangle;
Rectangle2d.bottomRightVertex rectangle
is equivalent to
(Rectangle2d.vertices rectangle).bottomRight
but is more efficient.
topLeftVertex : Rectangle2d -> Point2d
Get the top left vertex of a rectangle;
Rectangle2d.topLeftVertex rectangle
is equivalent to
(Rectangle2d.vertices rectangle).topLeft
but is more efficient.
topRightVertex : Rectangle2d -> Point2d
Get the top right vertex of a rectangle;
Rectangle2d.topRightVertex rectangle
is equivalent to
(Rectangle2d.vertices rectangle).topRight
but is more efficient.
edges : Rectangle2d -> { bottom : LineSegment2d, right : LineSegment2d, top : LineSegment2d, left : LineSegment2d }
Get the edges of a rectangle as a record. Note that 'bottom', 'top', 'left' and 'right' are with respect to the rectangle's axes, so the may not correspond to global up/down or left/right if the rectangle has been rotated or mirrored. The orientation of each edge is chosen so that it will be in a counterclockwise direction (unless the rectangle has been mirrored):
bottom
edge is from the bottom left to bottom right vertexright
edge is from the bottom right to top right vertextop
edge is from the top right to top left vertexleft
edge is from the top left to bottom left vertex(Note that this ordering will lead to each edge being in a clockwise direction if the rectangle has been mirrored.)
rectangle =
Rectangle2d.fromExtrema
{ minX = 2
, maxX = 5
, minY = 1
, maxY = 3
}
Rectangle2d.edges rectangle
--> { bottom =
--> LineSegment2d.fromEndpoints
--> ( Point2d.fromCoordinates ( 2, 1 )
--> , Point2d.fromCoordinates ( 5, 1 )
--> )
--> , right =
--> LineSegment2d.fromEndpoints
--> ( Point2d.fromCoordinates ( 5, 1 )
--> , Point2d.fromCoordinates ( 5, 3 )
--> )
--> , top =
--> LineSegment2d.fromEndpoints
--> ( Point2d.fromCoordinates ( 5, 3 )
--> , Point2d.fromCoordinates ( 2, 3 )
--> )
--> , left =
--> LineSegment2d.fromEndpoints
--> ( Point2d.fromCoordinates ( 2, 3 )
--> , Point2d.fromCoordinates ( 2, 1 )
--> )
--> }
leftEdge : Rectangle2d -> LineSegment2d
Get the left edge of a rectangle;
Rectangle2d.leftEdge rectangle
is equivalent to
(Rectangle2d.edges rectangle).left
but is more efficient.
bottomEdge : Rectangle2d -> LineSegment2d
Get the bottom edge of a rectangle;
Rectangle2d.bottomEdge rectangle
is equivalent to
(Rectangle2d.edges rectangle).bottom
but is more efficient.
rightEdge : Rectangle2d -> LineSegment2d
Get the right edge of a rectangle;
Rectangle2d.rightEdge rectangle
is equivalent to
(Rectangle2d.edges rectangle).right
but is more efficient.
topEdge : Rectangle2d -> LineSegment2d
Get the top edge of a rectangle;
Rectangle2d.topEdge rectangle
is equivalent to
(Rectangle2d.edges rectangle).top
but is more efficient.
boundingBox : Rectangle2d -> BoundingBox2d
Get the minimal bounding box containing a given rectangle. This have exactly the same shape and size as the rectangle itself if the rectangle is axis-aligned, but will be larger than the rectangle if the rectangle is at an angle.
square =
Rectangle2d.fromExtrema
{ minX = 0
, maxX = 1
, minY = 0
, maxY = 1
}
diamond =
square
|> Rectangle2d.rotateAround Point2d.origin
(degrees 45)
Rectangle2d.boundingBox diamond
--> BoundingBox2d.fromExtrema
--> { minX = -0.7071
--> , maxX = 0.7071
--> , minY = 0
--> , maxY = 1.4142
--> }
contains : Point2d -> Rectangle2d -> Basics.Bool
Check if a rectangle contains a given point:
rectangle =
Rectangle2d.fromExtrema
{ minX = 2
, maxX = 5
, minY = 1
, maxY = 3
}
p1 =
Point2d.fromCoordinates ( 3, 2 )
p2 =
Point2d.fromCoordinates ( 3, 4 )
rectangle |> Rectangle2d.contains p1
--> True
rectangle |> Rectangle2d.contains p2
--> False
toPolygon : Rectangle2d -> Polygon2d
Convert a rectangle to a Polygon2d
.
scaleAbout : Point2d -> Basics.Float -> Rectangle2d -> Rectangle2d
Scale a rectangle about a given point by a given scale.
rectangle =
Rectangle2d.fromExtrema
{ minX = 2
, maxX = 5
, minY = 1
, maxY = 3
}
rectangle
|> Rectangle2d.scaleAbout Point2d.origin 2
--> Rectangle2d.fromExtrema
--> { minX = 4
--> , maxX = 10
--> , minY = 2
--> , maxY = 6
--> }
Note that scaling by a negative value will flip the handedness of the
rectangle's axes, and therefore the order/direction of results from
Rectangle2d.vertices
and Rectangle2d.edges
will change.
rotateAround : Point2d -> Basics.Float -> Rectangle2d -> Rectangle2d
Rotate a rectangle around a given point by a given angle (in radians).
rectangle =
Rectangle2d.fromExtrema
{ minX = 0
, maxX = 1
, minY = 0
, maxY = 1
}
rotated =
rectangle
|> Rectangle2d.rotateAround Point2d.origin
(degrees 45)
Rectangle2d.centerPoint rotated
--> Point2d.fromCoordinates ( 0, 0.7071 )
Rectangle2d.xDirection rotated
--> Direction2d.fromAngle (degrees 45)
Rectangle2d.vertices rotated
--> { bottomLeft =
--> Point2d.origin
--> , bottomRight =
--> Point2d.fromCoordinates ( 0.7071, 0.7071 )
--> , topRight =
--> Point2d.fromCoordinates ( 0, 1.4142 )
--> , topLeft =
--> Point2d.fromCoordinates ( -0.7071, 0.7071 )
--> }
translateBy : Vector2d -> Rectangle2d -> Rectangle2d
Translate a rectangle by a given displacement.
rectangle =
Rectangle2d.fromExtrema
{ minX = 2
, maxX = 5
, minY = 1
, maxY = 3
}
displacement =
Vector2d.fromComponents ( 2, -3 )
Rectangle2d.translateBy displacement rectangle
--> Rectangle2d.fromExtrema
--> { minX = 4
--> , maxX = 7
--> , minY = -2
--> , maxY = 0
--> }
translateIn : Direction2d -> Basics.Float -> Rectangle2d -> Rectangle2d
Translate a rectangle in a given direction by a given distance;
Rectangle2d.translateIn direction distance
is equivalent to
Rectangle2d.translateBy
(Vector2d.withLength distance direction)
mirrorAcross : Axis2d -> Rectangle2d -> Rectangle2d
Mirror a rectangle across a given axis.
rectangle =
Rectangle2d.fromExtrema
{ minX = 2
, maxX = 5
, minY = 1
, maxY = 3
}
Rectangle2d.mirrorAcross Axis2d.x rectangle
--> Rectangle2d.fromExtrema
--> { minX = 2
--> , maxX = 5
--> , minY = -3
--> , maxY = -1
--> }
Note that this will flip the handedness of the rectangle's axes, and therefore
the order/direction of results from Rectangle2d.vertices
and
Rectangle2d.edges
will change.
relativeTo : Frame2d -> Rectangle2d -> Rectangle2d
Take a rectangle defined in global coordinates, and return it expressed in local coordinates relative to a given reference frame.
rectangle =
Rectangle2d.fromExtrema
{ minX = 2
, maxX = 5
, minY = 1
, maxY = 3
}
localFrame =
Frame2d.atCoordinates ( 1, 2 )
Rectangle2d.relativeTo localFrame rectangle
--> Rectangle2d.fromExtrema
--> { minX = 1
--> , maxX = 4
--> , minY = -1
--> , maxY = 1
--> }
placeIn : Frame2d -> Rectangle2d -> Rectangle2d
Take a rectangle considered to be defined in local coordinates relative to a given reference frame, and return that rectangle expressed in global coordinates.
rectangle =
Rectangle2d.fromExtrema
{ minX = 2
, maxX = 5
, minY = 1
, maxY = 3
}
localFrame =
Frame2d.atCoordinates ( 1, 2 )
Rectangle2d.placeIn localFrame rectangle
--> Rectangle2d.fromExtrema
--> { minX = 3
--> , maxX = 6
--> , minY = 3
--> , maxY = 5
--> }