Naming mess
Take the following overview of methods I came across while working on issue #99. Many names are used interchangeably for similar concepts.
Type
Class
Method
Remark
PolyLine2d
LocatedObject
.getGeometry()
Must remain line (not polygon) e.g. for traffic lights and detectors.
List<Point2d>
ConflictData
.getContour()
Polygon2d
SpatialObject
.getShape()
Polygon2d
DynamicSpatialObject
.getShape(Time)
PolyLine2d
TrafficLightDetectorData
.getGeometry()
Bounds2d
OtsLine2d
.getEnvelope()
Bounds
Locatable
.getBounds()
OtsBounds2d
OtsLocatable
.getBounds()
Polygon2d
Node
.getShape()
Never called.
What we need
We have several names for what seems to be the same: geometry, envelope, contour, shape and bounds.
There are good arguments to distinguish three functionally different definitions:
Geometry that defines where an object is in space, including its dimensionality (i.e. not just a point).
This can be used to check overlap between two non simple objects.
This is used to know where to animate objects.
Geometry that defines the shape of an object, regardless of its position.
For moving objects this is a necessity to determine 1.
This allows formulations that are quicker to compute.
For example, is a point within a rectangle? By transforming the point to the coordinate system of the shape, this becomes a very simple abs(x)<dx and abs(y)<dy check.
Note that this is much more efficient than transforming some geometry regarding a location (going from 2 to 1), and then checking whether the point is within this generalized geometry.
Similarly, signed distance functions (negative values inside the object) can be computed quickly. See here. These functions are required for spatial calculations for example regarding visibility.
Geometry that can be used quickly to filter many objects that are certainly not overlapping/not in need to animate/etc., wherever they may be.
What terms to use for which?Geometry: this is too broad of a term to specify what we mean.
Envelope: this is a very specific mathematical term regarding a family of curves. This is not what we mean.
Contour: this defines the edge of an object, and is a suitable term for function 1.
Shape: this seems a good fit for function 2, as the shape of an object does not change just because it moves.
Bounds: this seems a good fit for function 3, as bounds are generally perceived as min/max along a number of dimensions.
With locations given as OrientedPoint2d, this gives the following relationships:
Shape + Location = ContourBounds + Location = Bounds (possibly bigger due to ration)
What types are suitable?Contour
For the most general case, this is a PolyLine2d as some objects are lines without width. Note that point objects have no contour or shape, only a location (although possibly expanded to some shape for clickability). More specific classes can specify Polygon2d as output, which extends PolyLine2d.
Shape
Being defined relative to its origin, the contract with a shape is different from a contour. For example, in a contains(Point2d) method, the shape assumes the point to be translated to its own coordinate system. The origin does not need to be part of the shape (e.g. a donut). A shape can also be used for signed distance functions, which a PolyLine2d or Polygon2d do not have. Hence, a new class Shape is required, with two specific methods:
Polygon2d asPolygon()
double signedDistance(Point2d)
BoundsBounds2d from DJUTILS fits this function perfectly, and is used as such in DSOL.
What this gives
As the functions share much functionality, it is logical for them to have an inheritance relationship.
contains(Drawable), covers(Drawable), disjoint(Drawable): suggest removal, we cannot know whether the drawable is contained/covered, as it may be a line or a polygon. That is, the closing segment of a polygon may go outside bounds. E.g. the centerline of a U, is not contained in U if it defines a polygon. We can cover the cases for polyline and polygon as we know, but more sub-classes can be defined. The current implementation in e.g. Bounds2d just takes the Bounds2d of the input drawable, which tells you little on the actual shape.
intersects/intersection(Bounds): these methods only make sense for bounding boxes (as bounds are intended). However, to allow bounds to be extended by more complicated shapes that also serve as bounds (the first three bullets), they are suggested to be moved to BoxBounds.
intersects/intersection(Bounds): see last bullet at Bounds.
class org.djutils.draw.bounds.Bounds2 implements BoxBounds (DJUTILS)
interface Shape extends Bounds (OTS, currently called OtsBounds2d)
Polygon2d asPolygon()
double signedDistance(Point2d)
With implementations BoundingBox, BoundingBoxRounded, BoundingCircle, BoundingPolygon and BoundingRectangle. Possibly renamed to BoxShape etc.
Implementations have fast implementations of contains etc.
Note: BoxShape is a shape around the origin, BoxBounds are just min/max of wherever the object is.
Note: BoundingRectangle does not have the origin at its center (and is currently also used therefore as bounds at an actual location not containing the origin for compatibility in the current structure).
interface OtsLocatable extends Locatable (OTS)
Point2d getLocation(): specifies point type. Can be DirectedPoint2d for sub types.
OtsBounds2d getBounds(): suggested to be replaced by the following two.
default Bounds<?,?,?> getBounds() {return getShape();}: defined by Locatable as the bounds around the origin. Note that Shape extends Bounds.
Shape getShape()
Note: some sub types add a contour through various names. This may need to be harmonized by letting them implement/extend an interface that has PolyLine2d getContour(), possibly specified in implementations to Polygon2d getContour(). Perhaps LocatedObject is suitable for this.
Naming mess Take the following overview of methods I came across while working on issue #99. Many names are used interchangeably for similar concepts.
PolyLine2d
LocatedObject
.getGeometry()
List<Point2d>
ConflictData
.getContour()
Polygon2d
SpatialObject
.getShape()
Polygon2d
DynamicSpatialObject
.getShape(Time)
PolyLine2d
TrafficLightDetectorData
.getGeometry()
Bounds2d
OtsLine2d
.getEnvelope()
Bounds
Locatable
.getBounds()
OtsBounds2d
OtsLocatable
.getBounds()
Polygon2d
Node
.getShape()
What we need We have several names for what seems to be the same: geometry, envelope, contour, shape and bounds.
There are good arguments to distinguish three functionally different definitions:
What terms to use for which?
Geometry: this is too broad of a term to specify what we mean.Envelope: this is a very specific mathematical term regarding a family of curves. This is not what we mean. Contour: this defines the edge of an object, and is a suitable term for function 1. Shape: this seems a good fit for function 2, as the shape of an object does not change just because it moves. Bounds: this seems a good fit for function 3, as bounds are generally perceived as min/max along a number of dimensions.With locations given as
OrientedPoint2d
, this gives the following relationships: Shape + Location = Contour Bounds + Location = Bounds (possibly bigger due to ration)What types are suitable? Contour For the most general case, this is a
PolyLine2d
as some objects are lines without width. Note that point objects have no contour or shape, only a location (although possibly expanded to some shape for clickability). More specific classes can specifyPolygon2d
as output, which extendsPolyLine2d
.Shape Being defined relative to its origin, the contract with a shape is different from a contour. For example, in a
contains(Point2d)
method, the shape assumes the point to be translated to its own coordinate system. The origin does not need to be part of the shape (e.g. a donut). A shape can also be used for signed distance functions, which aPolyLine2d
orPolygon2d
do not have. Hence, a new classShape
is required, with two specific methods:Polygon2d asPolygon()
double signedDistance(Point2d)
Bounds
Bounds2d
from DJUTILS fits this function perfectly, and is used as such in DSOL.What this gives As the functions share much functionality, it is logical for them to have an inheritance relationship.
interface org.djutils.draw.bounds.Bounds<?, ?, ?>
(DJUTILS)contains(Point)
,covers(Point)
contains(Drawable)
,covers(Drawable)
,disjoint(Drawable)
: suggest removal, we cannot know whether the drawable is contained/covered, as it may be a line or a polygon. That is, the closing segment of a polygon may go outside bounds. E.g. the centerline of a U, is not contained in U if it defines a polygon. We can cover the cases for polyline and polygon as we know, but more sub-classes can be defined. The current implementation in e.g.Bounds2d
just takes theBounds2d
of the input drawable, which tells you little on the actual shape.intersects
/intersection(Bounds)
: these methods only make sense for bounding boxes (as bounds are intended). However, to allow bounds to be extended by more complicated shapes that also serve as bounds (the first three bullets), they are suggested to be moved toBoxBounds
.interface org.djutils.draw.bounds.BoxBounds<?, ?, ?> extends Bounds
(DJUTILS, new)intersects
/intersection(Bounds)
: see last bullet atBounds
.class org.djutils.draw.bounds.Bounds2 implements BoxBounds
(DJUTILS)interface Shape extends Bounds
(OTS, currently calledOtsBounds2d
)Polygon2d asPolygon()
double signedDistance(Point2d)
BoundingBox
,BoundingBoxRounded
,BoundingCircle
,BoundingPolygon
andBoundingRectangle
. Possibly renamed toBoxShape
etc.contains
etc.BoxShape
is a shape around the origin,BoxBounds
are just min/max of wherever the object is.BoundingRectangle
does not have the origin at its center (and is currently also used therefore as bounds at an actual location not containing the origin for compatibility in the current structure).interface OtsLocatable extends Locatable
(OTS)Point2d getLocation()
: specifies point type. Can beDirectedPoint2d
for sub types.OtsBounds2d getBounds()
: suggested to be replaced by the following two.default Bounds<?,?,?> getBounds() {return getShape();}
: defined byLocatable
as the bounds around the origin. Note thatShape
extendsBounds
.Shape getShape()
PolyLine2d getContour()
, possibly specified in implementations toPolygon2d getContour()
. PerhapsLocatedObject
is suitable for this.