Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "GEF/GEF4/Geometry"

< GEF‎ | GEF4
m
(Geometry.Convert.FX)
(144 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
''Note to non-wiki readers: This documentation is generated from the Eclipse wiki - if you have corrections or additions it would be awesome if you added them in [http://wiki.eclipse.org/GEF/GEF4/Geometry the original wiki page]''.
 
''Note to non-wiki readers: This documentation is generated from the Eclipse wiki - if you have corrections or additions it would be awesome if you added them in [http://wiki.eclipse.org/GEF/GEF4/Geometry the original wiki page]''.
  
__TOC__
+
__NOTOC__
  
 
== Introduction ==
 
== Introduction ==
  
This is the reference documentation of the GEF 4 Geometry API. You can use this component independent of the other GEF 4 components. The Geometry API provides classes to store geometric objects and to do geometric computations on those objects. It is developed to be intuitively usable. Nonetheless, it is of no harm to know the underlying design decisions which are explained in the following chapters.
+
The [[GEF/GEF4/Geometry|<span style="color:#268558">GEF4 Geometry</span>]] component provides classes to store geometric objects and to perform geometric computations based on those objects. It is internally structured into three modules, namely '''[[#Geometry|Geometry]]''', '''[[#Geometry.Convert.FX|Geometry.Convert.FX]]''', and '''[[#Geometry.Convert.SWT|Geometry.Convert.SWT]]'''.
  
== Planar Geometry ==
+
[[Image:GEF4-Components-Geometry.png|600px]]
 +
 
 +
----
 +
 
 +
== Geometry ==
 +
 
 +
*'''feature: org.eclipse.gef4.geometry'''
 +
*'''bundle: org.eclipse.gef4.geometry'''
 +
 
 +
Different kinds of abstractions are provided to support different kinds of geometric calculations, within 2-dimensional Euclidean vector space or its related projective space, or based on 2-dimensional planar objects. Furthermore, conversions are supported to import/export from/to related SWT and AWT representations.
 +
 
 +
The API is universally based on double precision calculations. Result values are computed as precise as possible, most of the time. In situations where result values are approximated, the approximation is as precise as required for the related test methods to agree on the values. An imprecision is used in the comparisons of double precision values throughout the implementation. These imprecise comparisons shall ensure consistency with regard to floating point and approximation errors.
 +
 
 +
{|border="0" style="border:1px black solid;border-collapse:collapse" cellpadding="5" cellspacing="0" size="10"
 +
!colspan="4" style="border:1px black solid"|[[Image:GEF4Geometry-jdt-icons-package_obj.gif]][[#Planar|Planar]]
 +
!bgcolor="#fffdc8" style="border:1px black solid"|[[Image:GEF4Geometry-jdt-icons-package_obj.gif]][[#Euclidean|Euclidean]]
 +
!style="border:1px black solid"|[[Image:GEF4Geometry-jdt-icons-package_obj.gif]][[#Projective|Projective]]
 +
!bgcolor="#fffdc8" style="border:1px black solid"|[[Image:GEF4Geometry-jdt-icons-package_obj.gif]][[#Convert.AWT|Convert.AWT]]
 +
|-
 +
!style="border-right:1px grey solid; border-bottom:1px grey solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-int_obj.gif]]ICurve
 +
!style="border-right:1px grey solid; border-bottom:1px grey solid"|[[Image:GEF4Geometry-jdt-icons-int_obj.gif]]IShape
 +
!style="border-right:1px grey solid; border-bottom:1px grey solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-int_obj.gif]]IMultiShape
 +
|style="border-right:1px black solid"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Path|Path]]
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Angle|Angle]]
 +
|style="border-right:1px black solid"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Straight3D|Straight3D]]
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Geometry2AWT|Geometry2AWT]]
 +
|-
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Arc|Arc]]
 +
|style="border-right:1px grey solid"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Ellipse|Ellipse]]
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Region|Region]]
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Straight|Straight]]
 +
|style="border-right:1px black solid"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Vector3D|Vector3D]]
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#AWT2Geometry|AWT2Geometry]]
 +
|-
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#BezierCurve|BezierCurve]]
 +
|style="border-right:1px grey solid"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Pie|Pie]]
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Ring|Ring]]
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Vector|Vector]]
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|&nbsp;
 +
|-
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#CubicCurve|CubicCurve]]
 +
|style="border-right:1px grey solid"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Polygon|Polygon]]
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|&nbsp;
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|&nbsp;
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|&nbsp;
 +
|-
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Line|Line]]
 +
|style="border-right:1px grey solid"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Rectangle|Rectangle]]
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|&nbsp;
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|&nbsp;
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|&nbsp;
 +
|-
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#QuadraticCurve|QuadraticCurve]]
 +
|style="border-right:1px grey solid"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#RoundedRectangle|RoundedRectangle]]
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|&nbsp;
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|&nbsp;
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|&nbsp;
 +
|-
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#PolyBezier|PolyBezier]]
 +
|style="border-right:1px grey solid"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#CurvedPolygon|CurvedPolygon]]
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|&nbsp;
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|&nbsp;
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|&nbsp;
 +
|-
 +
|style="border-right:1px grey solid" bgcolor="#fffdc8"|[[Image:GEF4Geometry-jdt-icons-class_obj.gif]][[#Polyline|Polyline]]
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|&nbsp;
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|&nbsp;
 +
|style="border-right:1px black solid"|&nbsp;
 +
|style="border-right:1px black solid" bgcolor="#fffdc8"|&nbsp;
 +
|}
 +
 
 +
<small>To ease navigation, the following sections are organized around the source code packages (org.eclipse.gef4.geomtry.*) of the API, as they were designed to represent the different domains of abstractions.</small>
 +
 
 +
----
 +
 
 +
=== Planar ===
  
 
*'''package: org.eclipse.gef4.geometry.planar'''
 
*'''package: org.eclipse.gef4.geometry.planar'''
  
[[Image:GEF4Geometry-planar-overview.png|Interface hierarchy]]
+
The planar package provides basic abstractions for computations based on 2-dimensional geometric objects.  
  
This diagram depicts the interface hierarchy which underlies the individual geometry classes. It classifies the geometry classes mainly into either being ICurves or IShapes. An ICurve is a one dimensional geometry, i.e. the result that you get by drawing a continuous line with a pencil. It has a start and an end point and you can approximate it by a series of Bézier curves. On the other hand, an IShape is a two dimensional geometry, i.e. it continuously encloses a region on the drawing area, without holes. You can retrieve the outline of an IShape, which is an IPolyCurve, a special case of an ICurve. It defines a curve that is composed of multiple connected ICurves and its purpose is to be able to operate on them as a whole. Similarly and especially important for clipping is another set of planar geometries, the IPolyShapes. Other than the relationship between ICurve and IPolyCurve, an IPolyShape is not an IShape. An IPolyShape is a (possibly) non-continuous set of IShapes. An example for an IPolyShape is the [[GEF/GEF4/Geometry#Region|Region]]. A [[GEF/GEF4/Geometry#Region|Region]] is the area that results from composing multiple [[GEF/GEF4/Geometry#Rectangle|Rectangle]]s. It corresponds to the SWT [http://help.eclipse.org/indigo/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/Region.html Region].
+
[[Image:GEF4Geometry-planar-overview.png|1104px|Interface hierarchy]]
  
This interface hierarchy structures the geometry API. It describes how the individual classes are related to each other and how to transfer objects of one type to a number of objects of other types, which is the most important part of the geometry API.
+
As outlined above, with the exception of the [[#Path|Path]] abstraction, all objects are classified into either being curves, shapes, or multi shapes by means of respective interfaces. An ICurve is a one dimensional geometry, i.e. the result that you get by drawing a continuous line with a pencil. It has a start and an end point and you can approximate it by a series of [[#BezierCurve|BezierCurve]]s. An IShape is a two dimensional geometry, i.e. it continuously encloses a region on the drawing area, without holes. An IMultiShape is a (possibly) non-continuous set of IShapes. An example for an IMultiShape is the [[#Region|Region]]. A [[#Region|Region]] represents the area that results from composing multiple [[#Rectangle|Rectangle]]s. Accordingly, a [[#Ring|Ring]] represents the area that results from composing multiple [[#Polygon|Polygon]]s. It corresponds to the SWT [http://help.eclipse.org/indigo/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/Region.html Region].
  
The most general type in the hierarchy is the [[GEF/GEF4/Geometry#Path|Path]], because every geometric object can be transformed into it. Unfortunately, the [[GEF/GEF4/Geometry#Path|Path]] is incompatible to the rest of the API in that it does not implement the different interfaces, it does not ensure a certain precision for the results of its test and manipulation methods, and it cannot be transferred back into compatible objects.
+
The most general type in the hierarchy is the [[#Path|Path]], because every geometric object can be transfered into it. Unfortunately, the [[#Path|Path]] is incompatible to the rest of the API in that it does not implement the different interfaces, it does not ensure a certain precision for the results of its test and manipulation methods, and it cannot be transferred back into compatible objects.
  
[[Image:GEF4Geometry-planar-abstractions-hierarchy.png|Important functionality]]
+
[[Image:GEF4Geometry-planar-abstractions-hierarchy.png|930px|Important functionality]]
  
As you can see in this diagram, an ICurve can be approximated by a number of [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]]s using the toBezier() method. The outline of an IShape can be retrieved using its getOutline() method. Additionally, you can split an IShape into a number of ICurves -- which form the outline -- using the getOutlineSegments() method. IPolyShape provides a getShapes() method to get the individual IShapes that are combined by the IPolyShape. It does provide a getOutlineSegments() method, too, which is used to split the IPolyShape into several ICurves. These transfer methods allow the decomposition of any geometric object into a bunch of [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]]s:
+
As you can see in this diagram, an ICurve can be approximated by a number of [[#BezierCurve|BezierCurve]]s using the toBezier() method. The outline of an IShape can be retrieved using its getOutline() method. Additionally, you can split an IShape into a number of ICurves -- which form the outline -- using the getOutlineSegments() method. IMultiShape provides a getShapes() method to get the individual IShapes that are combined by the IMultiShape. It does provide a getOutlineSegments() method, too, which is used to split the IMultiShape into several ICurves. These transfer methods allow the decomposition of any geometric object into a bunch of [[#BezierCurve|BezierCurve]]s:
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">
 
<source lang="java">
BezierCurves[] fromCurve = curve.toBezier();
+
BezierCurve[] fromCurve = curve.toBezier();
BezierCurves[] fromShape = shape.getOutline().toBezier();
+
BezierCurve[] fromShape = shape.getOutline().toBezier();
ICurve[] fromPolyShape = polyShape.getOutlineSegments();
+
  
// okay, need to transfer the ICurves
+
ICurve[] fromPolyShape = polyShape.getOutlineSegments();
 
List<BezierCurve> beziers = new ArrayList<BezierCurve>();
 
List<BezierCurve> beziers = new ArrayList<BezierCurve>();
 
for (ICurve c : fromPolyShape)
 
for (ICurve c : fromPolyShape)
 
     beziers.addAll(Arrays.asList(c.toBezier()));
 
     beziers.addAll(Arrays.asList(c.toBezier()));
 
</source>
 
</source>
 +
</div>
  
An important part of a geometry API in general, is the possibility to test the relationship of two geometric objects. The GEF 4 Geometry API provides four methods that perform relation tests. Universally usable is the touches() method for planar objects. It tests if two objects have at least one point in common. Additionally, ICurves can be tested for points of intersection using the intersects() method and for an overlap using the overlaps() method, among each other. An IShape provides a contains() method to test if it fully contains a given planar object. Moreover, the point test is available for every geometric object. It tests if a given [[GEF/GEF4/Geometry#Point|Point]] is incidental to the particular object. Supplementary to the intersects() test, a getIntersections() method is offered among ICurves. [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]]s do also facilitate the extraction of overlapping segments via the getOverlap() method.
+
An important part of a geometry API in general, is the possibility to test the relationship of two geometric objects. The GEF 4 Geometry API provides four methods that perform relation tests. Universally usable is the touches() method for planar objects. It tests if two objects have at least one point in common. Additionally, ICurves can be tested for points of intersection using the intersects() method and for an overlap using the overlaps() method, among each other. An IShape provides a contains() method to test if it fully contains a given planar object. Moreover, the point test is available for every geometric object. It tests if a given [[#Point|Point]] is incidental to the particular object. Supplementary to the intersects() test, a getIntersections() method is offered among ICurves. [[#BezierCurve|BezierCurve]]s do also facilitate the extraction of overlapping segments via the getOverlap() method.
  
 
So, let us consider a few examples:
 
So, let us consider a few examples:
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">
 
<source lang="java">
 
boolean contained = arc.contains(point);
 
boolean contained = arc.contains(point);
Line 48: Line 138:
 
boolean contained = region.contains(polygon);
 
boolean contained = region.contains(polygon);
 
</source>
 
</source>
 +
</div>
  
 
Noticeably, the use of interfaces unifies similar operations on different types. Therefore, the fundamental interfaces (ICurve, IShape, etc.) are complemented by three transformation interfaces.
 
Noticeably, the use of interfaces unifies similar operations on different types. Therefore, the fundamental interfaces (ICurve, IShape, etc.) are complemented by three transformation interfaces.
  
[[Image:GEF4Geometry-planar-transformations-overview.png|Transformation interfaces]]
+
[[Image:GEF4Geometry-planar-transformations-overview.png|785px|Transformation interfaces]]
  
 
You can either transform your geometric objects via instances of the AffineTransform class, or by using the short-cut methods provided by the ITranslatable, IScalable, and IRotatable interfaces. Transformations can either be directly applied to an object, modifying the object in-place, or to a copy of the original object. This distinction is represented by the names of the short-cut methods. All names starting with 'get' are applied to a copy of the original object. The other methods modify the object in-place.
 
You can either transform your geometric objects via instances of the AffineTransform class, or by using the short-cut methods provided by the ITranslatable, IScalable, and IRotatable interfaces. Transformations can either be directly applied to an object, modifying the object in-place, or to a copy of the original object. This distinction is represented by the names of the short-cut methods. All names starting with 'get' are applied to a copy of the original object. The other methods modify the object in-place.
  
Translating an object means moving the object. You can move an object in x- and y-direction. Scaling an object means resizing the object. You can individually scale the object in x- and y-direction. Additionally, scaling requires a relative [[GEF/GEF4/Geometry#Point|Point]] to scale to/away from. If you omit this [[GEF/GEF4/Geometry#Point|Point]], the scaling method will appropriately choose the relative [[GEF/GEF4/Geometry#Point|Point]]. Normally, this will be the center [[GEF/GEF4/Geometry#Point|Point]] of the geometric object that you want to scale. Rotation is special in that not all geometric objects can be rotated in-place. [[GEF/GEF4/Geometry#Rectangle|Rectangle]]s, for example, are always parallel to the x- and y-axes. That's why the IRotatable interface does only include the getRotated*() short-cut methods which are not directly applied. However, some geometric objects do provide in-place rotation methods. As with scaling, rotation is performed around a relative [[GEF/GEF4/Geometry#Point|Point]]. If you omit this [[GEF/GEF4/Geometry#Point|Point]], the rotation method will appropriately choose it. Normally, this will be the center [[GEF/GEF4/Geometry#Point|Point]] of the geometric object that you want to rotate.
+
Translating an object means moving the object. You can move an object in x- and y-direction. Scaling an object means resizing the object. You can individually scale the object in x- and y-direction. Additionally, scaling requires a relative [[#Point|Point]] to scale to/away from. If you omit this [[#Point|Point]], the scaling method will appropriately choose the relative [[#Point|Point]]. Normally, this will be the center [[#Point|Point]] of the geometric object that you want to scale. Rotation is special in that not all geometric objects can be rotated in-place. [[#Rectangle|Rectangle]]s, for example, are always parallel to the x- and y-axes. That's why the IRotatable interface does only include the getRotated*() short-cut methods which are not directly applied. However, some geometric objects do provide in-place rotation methods. As with scaling, rotation is performed around a relative [[#Point|Point]]. If you omit this [[#Point|Point]], the rotation method will appropriately choose it. Normally, this will be the center [[#Point|Point]] of the geometric object that you want to rotate.
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">
 
<source lang="java">
 
Polygon rhomb = new Rectangle(10, 10, 10, 10).getRotatedCCW(Angle.fromDeg(45));
 
Polygon rhomb = new Rectangle(10, 10, 10, 10).getRotatedCCW(Angle.fromDeg(45));
Line 62: Line 154:
 
Ring rotatedClippingArea = region.getRotatedCCW(Angle.fromDeg(300));
 
Ring rotatedClippingArea = region.getRotatedCCW(Angle.fromDeg(300));
 
</source>
 
</source>
 +
</div>
  
Augmenting the interface hierarchy, all concrete classes are based on abstract geometry classes, depending on the type of geometry used for constructing the objects (i.e. [[GEF/GEF4/Geometry#Ellipse|Ellipse]] is an AbstractRectangleBasedGeometry, because it is constructed by means of a [[GEF/GEF4/Geometry#Rectangle|Rectangle]]).
+
Augmenting the interface hierarchy, all concrete classes are based on abstract geometry classes, depending on the type of geometry used for constructing the objects (i.e. [[#Ellipse|Ellipse]] is an AbstractRectangleBasedGeometry, because it is constructed by means of a [[#Rectangle|Rectangle]]).
  
[[Image:GEF4Geometry-planar-inheritance-hierarchy.png|Inheritance hierarchy]]
+
[[Image:GEF4Geometry-planar-inheritance-hierarchy.png|1109px|Inheritance hierarchy]]
  
 
This classification by the construction type of the individual geometry objects allows the generalization of many operations in a few abstract classes. Those abstract classes implement methods that should return an object of the same type as the inheriting class. Thus, type parameters are used to specify such return types.
 
This classification by the construction type of the individual geometry objects allows the generalization of many operations in a few abstract classes. Those abstract classes implement methods that should return an object of the same type as the inheriting class. Thus, type parameters are used to specify such return types.
  
=== Point ===
+
==== Point ====
  
[[GEF/GEF4/Geometry#Point|Point]] objects represent a point in two dimensional space. For the purpose of imagination, you can assume the coordinate system to be originated in the top left corner of your drawing area, expanding to the right and to the bottom. From a list of [[GEF/GEF4/Geometry#Point|Point]] objects, you can build up most of the planar geometric objects:
+
<code>Point</code> objects represent a point in 2-dimensional space. For the purpose of imagination, you can assume the coordinate system to be originated in the top left corner of your drawing area, expanding to the right and to the bottom. From a list of <code>Point</code> objects, you can build up most of the planar geometric objects:
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">
 
<source lang="java">
 
Point p0 = new Point(); // defaults: x=0, y=0
 
Point p0 = new Point(); // defaults: x=0, y=0
Line 79: Line 173:
 
Polygon triangle = new Polygon(p0, p1, p2);
 
Polygon triangle = new Polygon(p0, p1, p2);
 
</source>
 
</source>
 +
</div>
  
Additionally, the [[GEF/GEF4/Geometry#Point|Point]] class provides static utility methods to operate on a list of [[GEF/GEF4/Geometry#Point|Point]]s: getBounds([[GEF/GEF4/Geometry#Point|Point]]...), getCentroid([[GEF/GEF4/Geometry#Point|Point]]...), and getConvexHull([[GEF/GEF4/Geometry#Point|Point]]...). They construct a bounding box, the centroid, and a convex hull of the given [[GEF/GEF4/Geometry#Point|Point]] list, respectively.
+
Additionally, the <code>Point</code> class provides static utility methods to operate on a list of <code>Point</code>s: getBounds(Point...), getCentroid(Point...), and getConvexHull(Point...). They construct a bounding box, the centroid, and a convex hull of the given <code>Point</code> list, respectively.
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">
 
<source lang="java">
 
Polygon convexHull = Point.getConvexHull(points);
 
Polygon convexHull = Point.getConvexHull(points);
 
</source>
 
</source>
 +
</div>
  
=== Dimension ===
+
==== Dimension ====
  
The [[GEF/GEF4/Geometry#Dimension|Dimension]] class is the pendant of the org.eclipse.draw2d.geometry.Dimension class. It decouples the location and the width and height of a rectangular object.
+
The [[#Dimension|Dimension]] class is the pendant of the org.eclipse.draw2d.geometry.Dimension class. It decouples the location and the width and height of a rectangular object.
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">
 
<source lang="java">
 
Rectangle bounds = new Rectangle(
 
Rectangle bounds = new Rectangle(
Line 96: Line 194:
 
);
 
);
 
</source>
 
</source>
 
+
</div>
=== Line ===
+
==== Line ====
  
 
[[Image:GEF4Geometry-planar-line-example.png|Line example]]
 
[[Image:GEF4Geometry-planar-line-example.png|Line example]]
  
*'''extends:''' [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]]
+
*'''extends:''' [[#BezierCurve|BezierCurve]]
 
*'''implements:''' ICurve, ITranslatable, IScalable, IRotatable
 
*'''implements:''' ICurve, ITranslatable, IScalable, IRotatable
  
A [[GEF/GEF4/Geometry#Line|Line]] is the straight connection of two [[GEF/GEF4/Geometry#Point|Point]]s:
+
A <code>Line</code> is the straight connection of two [[#Point|Point]]s:
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">Line line = new Line(p0, p1);</source>
 
<source lang="java">Line line = new Line(p0, p1);</source>
 +
</div>
  
As it inherits from the [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]] class, all the operations for [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]]s are available for [[GEF/GEF4/Geometry#Line|Line]] objects, too. Because of its frequent use, [[GEF/GEF4/Geometry#Line|Line]] overrides many of those operations to provide faster implementations for the [[GEF/GEF4/Geometry#Line|Line]]/[[GEF/GEF4/Geometry#Line|Line]] and [[GEF/GEF4/Geometry#Line|Line]]/[[GEF/GEF4/Geometry#Point|Point]] cases (equals(), touches(), contains(), intersects(), overlaps(), getIntersections(), and many more). If you want to display a [[GEF/GEF4/Geometry#Line|Line]] using SWT, you can use its toSWTPointArray() method as follows:
+
As it inherits from the [[#BezierCurve|BezierCurve]] class, all the operations for [[#BezierCurve|BezierCurve]]s are available for <code>Line</code> objects, too. Because of its frequent use, <code>Line</code> overrides many of those operations to provide faster implementations for the <code>Line</code>/<code>Line</code> and <code>Line</code>/[[#Point|Point]] cases (equals(), touches(), contains(), intersects(), overlaps(), getIntersections(), and many more). If you want to display a <code>Line</code> using SWT, you can use the Geometry2SWT.toSWTPointArray() method as follows:
  
<source lang="java">gc.drawPolyline(line.toSWTPointArray());</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">gc.drawPolyline(Geometry2SWT.toSWTPointArray(line));</source>
 +
</div>
  
=== Rectangle ===
+
==== Rectangle ====
  
 
[[Image:GEF4Geometry-planar-rectangle-example.png|Rectangle example]]
 
[[Image:GEF4Geometry-planar-rectangle-example.png|Rectangle example]]
Line 119: Line 221:
 
*'''implements:''' IShape, ITranslatable, IScalable, IRotatable
 
*'''implements:''' IShape, ITranslatable, IScalable, IRotatable
  
A [[GEF/GEF4/Geometry#Rectangle|Rectangle]] is the axes-parallel rectangle defined by a location (x- and y-coordinates) and a [[GEF/GEF4/Geometry#Dimension|Dimension]] (width and height):
+
A <code>Rectangle</code> is the axes-parallel rectangle defined by a location (x- and y-coordinates) and a [[#Dimension|Dimension]] (width and height):
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">Rectangle rect = new Rectangle(x, y, w, h);</source>
 
<source lang="java">Rectangle rect = new Rectangle(x, y, w, h);</source>
 +
</div>
  
Rotating a [[GEF/GEF4/Geometry#Rectangle|Rectangle]] results in a [[GEF/GEF4/Geometry#Polygon|Polygon]]:
+
Rotating a <code>Rectangle</code> results in a [[#Polygon|Polygon]]:
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">Polygon slanted = rect.getRotatedCCW(Angle.fromDeg(30));</source>
 
<source lang="java">Polygon slanted = rect.getRotatedCCW(Angle.fromDeg(30));</source>
 +
</div>
  
[[GEF/GEF4/Geometry#Rectangle|Rectangle]] objects are frequently used, that's why some operations are overridden to provide faster implementations for designated parameter types (equals(), contains(), touches()). If you want to display a [[GEF/GEF4/Geometry#Rectangle|Rectangle]] using SWT, you can use its toSWTRectangle() method as follows:
+
<code>Rectangle</code> objects are frequently used, that's why some operations are overridden to provide faster implementations for designated parameter types (equals(), contains(), touches()). If you want to display a <code>Rectangle</code> using SWT, you can use the Geometry2SWT.toSWTRectangle() method as follows:
  
<source lang="java">gc.drawRectangle(rect.toSWTRectangle());</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
gc.drawRectangle(Geometry2SWT.toSWTRectangle(rect));
 +
</source>
 +
</div>
  
=== Polyline ===
+
==== Polyline ====
  
 
[[Image:GEF4Geometry-planar-polyline-example.png|PolyLine example]]
 
[[Image:GEF4Geometry-planar-polyline-example.png|PolyLine example]]
  
 
*'''extends:''' AbstractPointListBasedGeometry
 
*'''extends:''' AbstractPointListBasedGeometry
*'''implements:''' IPolyCurve, ITranslatable, IScalable, IRotatable
+
*'''implements:''' ICurve, ITranslatable, IScalable, IRotatable
  
A [[GEF/GEF4/Geometry#Polyline|Polyline]] combines multiple [[GEF/GEF4/Geometry#Line|Line]] segments to address them as a whole. Consecutive [[GEF/GEF4/Geometry#Line|Line]] segments of a [[GEF/GEF4/Geometry#Polyline|Polyline]] share at least one end [[GEF/GEF4/Geometry#Point|Point]]. The outline of some of the IShape implementations can be represented by a [[GEF/GEF4/Geometry#Polyline|Polyline]] ([[GEF/GEF4/Geometry#Rectangle|Rectangle]] and [[GEF/GEF4/Geometry#Polygon|Polygon]]):
+
A <code>Polyline</code> combines multiple [[#Line|Line]] segments to address them as a whole. Consecutive [[#Line|Line]] segments of a <code>Polyline</code> share at least one end [[#Point|Point]]. The outline of some of the IShape implementations can be represented by a <code>Polyline</code> ([[#Rectangle|Rectangle]] and [[#Polygon|Polygon]]):
  
<source lang="java">Polyline polyLine = new Polyline(new Line(p0, p1), new Line(p1, p2));
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
Polyline outline = Polygon.getOutline();</source>
+
<source lang="java">
 +
Polyline polyLine = new Polyline(new Line(p0, p1), new Line(p1, p2));
 +
Polyline outline = Polygon.getOutline();
 +
</source>
 +
</div>
  
To render a [[GEF/GEF4/Geometry#Polyline|Polyline]] with SWT, you can its toSWTPointArray() method as follows:
+
To render a <code>Polyline</code> with SWT, you can use the Geometry2SWT.toSWTPointArray() method as follows:
  
<source lang="java">gc.drawPolyline(polyline.toSWTPointArray());</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
gc.drawPolyline(Geometry2SWT.toSWTPointArray(polyline));
 +
</source>
 +
</div>
  
=== Polygon ===
+
==== Polygon ====
  
 
[[Image:GEF4Geometry-planar-polygon-example.png|Polygon example]]
 
[[Image:GEF4Geometry-planar-polygon-example.png|Polygon example]]
Line 154: Line 272:
 
*'''implements:''' IShape, ITranslatable, IScalable, IRotatable
 
*'''implements:''' IShape, ITranslatable, IScalable, IRotatable
  
A [[GEF/GEF4/Geometry#Polygon|Polygon]] represents a simple polygon, i.e one that does not have intersecting sides:
+
A <code>Polygon</code> represents a simple polygon, i.e one that does not have intersecting sides:
  
<source lang="java">Polygon rhomb = new Polygon(0, 0, 1, -1, 2, 0, 1, 1);</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
Polygon rhomb = new Polygon(0, 0, 1, -1, 2, 0, 1, 1);
 +
</source>
 +
</div>
  
If you need to process self-intersecting polygons, you can use the [[GEF/GEF4/Geometry#Ring|Ring]] instead.
+
If you need to process self-intersecting polygons, you can use the [[#Ring|Ring]] instead.
  
A [[GEF/GEF4/Geometry#Polygon|Polygon]] can be rendered with SWT using its toSWTPointArray() method as follows:
+
A <code>Polygon</code> can be rendered with SWT using the Geometry2SWT.toSWTPointArray() method as follows:
  
<source lang="java">gc.drawPolyline(polygon.toSWTPointArray());</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
gc.drawPolyline(Geometry2SWT.toSWTPointArray(polygon));
 +
</source>
 +
</div>
  
=== Ellipse ===
+
==== Ellipse ====
  
 
[[Image:GEF4Geometry-planar-ellipse-example.png|Ellipse example]]
 
[[Image:GEF4Geometry-planar-ellipse-example.png|Ellipse example]]
Line 171: Line 297:
 
*'''implements:''' IShape, ITranslatable, IScalable, IRotatable
 
*'''implements:''' IShape, ITranslatable, IScalable, IRotatable
  
An [[GEF/GEF4/Geometry#Ellipse|Ellipse]] is the axes-symmetric oval that can be put into an axes-parallel rectangle:
+
An <code>Ellipse</code> is the axes-symmetric oval that can be put into an axes-parallel [[#Rectangle|Rectangle]]:
  
<source lang="java">Ellipse ellipse = new Ellipse(rect);</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
Ellipse ellipse = new Ellipse(rect);
 +
</source>
 +
</div>
  
Therefore, rotating an [[GEF/GEF4/Geometry#Ellipse|Ellipse]] does not result in another [[GEF/GEF4/Geometry#Ellipse|Ellipse]], but in a [[GEF/GEF4/Geometry#PolyBezier|PolyBezier]] which approximates the rotated [[GEF/GEF4/Geometry#Ellipse|Ellipse]]:
+
Therefore, rotating an <code>Ellipse</code> does not result in another <code>Ellipse</code>, but in a [[#PolyBezier|PolyBezier]] which approximates the rotated <code>Ellipse</code>:
  
<source lang="java">PolyBezier rotatedEllipse = ellipse.getRotatedCCW(Angle.fromDeg(45));</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
PolyBezier rotatedEllipse = ellipse.getRotatedCCW(Angle.fromDeg(45));
 +
</source>
 +
</div>
  
You can always transfrom a [[GEF/GEF4/Geometry#PolyBezier|PolyBezier]] into an [[GEF/GEF4/Geometry#Ellipse|Ellipse]] by using the [[GEF/GEF4/Geometry#PolyBezier|PolyBezier]]'s bounds as the [[GEF/GEF4/Geometry#Ellipse|Ellipse]]'s bounds:
+
You can always transfrom a [[#PolyBezier|PolyBezier]] into an <code>Ellipse</code> by using the [[#PolyBezier|PolyBezier]]'s bounds as the <code>Ellipse</code>'s bounds:
  
<source lang="java">Ellipse rotated = new Ellipse(rotatedEllipse.getBounds());</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
Ellipse rotated = new Ellipse(rotatedEllipse.getBounds());
 +
</source>
 +
</div>
  
If you want to draw an [[GEF/GEF4/Geometry#Ellipse|Ellipse]] using SWT, you can directly use the GC's drawOval() method as follows:
+
If you want to draw an <code>Ellipse</code> using SWT, you can directly use the GC's drawOval() method as follows:
  
<source lang="java">gc.drawOval((int) ellipse.getX(), (int) ellipse.getY(), (int) ellipse.getWidth(), (int) ellipse.getHeight());</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
gc.drawOval((int) ellipse.getX(), (int) ellipse.getY(), (int) ellipse.getWidth(), (int) ellipse.getHeight());
 +
</source>
 +
</div>
  
=== Arc ===
+
==== Arc ====
  
 
[[Image:GEF4Geometry-planar-arc-example.png|Arc example]]
 
[[Image:GEF4Geometry-planar-arc-example.png|Arc example]]
Line 194: Line 336:
 
*'''implements:''' ICurve, ITranslatable, IScalable, IRotatable
 
*'''implements:''' ICurve, ITranslatable, IScalable, IRotatable
  
An [[GEF/GEF4/Geometry#Arc|Arc]] is an open segment of an [[GEF/GEF4/Geometry#Ellipse|Ellipse]]:
+
An <code>Arc</code> is an open segment of an [[#Ellipse|Ellipse]]:
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">Arc arc = new Arc(ellipse, Angle.fromDeg(45), Angle.fromDeg(90));</source>
 
<source lang="java">Arc arc = new Arc(ellipse, Angle.fromDeg(45), Angle.fromDeg(90));</source>
 +
</div>
  
Rotating an [[GEF/GEF4/Geometry#Arc|Arc]] does not necessarily result in another [[GEF/GEF4/Geometry#Arc|Arc]], that's why the rotation methods return [[GEF/GEF4/Geometry#PolyBezier|PolyBezier]]s instead:
+
Rotating an <code>Arc</code> does not necessarily result in another <code>Arc</code>, that's why the rotation methods return [[#PolyBezier|PolyBezier]]s instead:
  
<source lang="java">PolyBezier polyBezier = arc.getRotatedCCW(Angle.fromDeg(15), new Point());</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
PolyBezier polyBezier = arc.getRotatedCCW(Angle.fromDeg(15), new Point());
 +
</source>
 +
</div>
  
Unfortunately, it is impossible to transfrom a [[GEF/GEF4/Geometry#PolyBezier|PolyBezier]] into an [[GEF/GEF4/Geometry#Arc|Arc]].
+
Unfortunately, it is impossible to transfrom a [[#PolyBezier|PolyBezier]] into an <code>Arc</code>.
  
=== Pie ===
+
==== Pie ====
  
 
[[Image:GEF4Geometry-planar-pie-example.png|Pie example]]
 
[[Image:GEF4Geometry-planar-pie-example.png|Pie example]]
Line 211: Line 359:
 
*'''implements:''' IShape, ITranslatable, IScalable, IRotatable
 
*'''implements:''' IShape, ITranslatable, IScalable, IRotatable
  
A [[GEF/GEF4/Geometry#Pie|Pie]] is a closed [[GEF/GEF4/Geometry#Arc|Arc]]. Closing the [[GEF/GEF4/Geometry#Arc|Arc]] is done by creating two segments: one from the mid [[GEF/GEF4/Geometry#Point|Point]] of the related [[GEF/GEF4/Geometry#Ellipse|Ellipse]] to the start [[GEF/GEF4/Geometry#Point|Point]] of the related [[GEF/GEF4/Geometry#Arc|Arc]], the other from the mid [[GEF/GEF4/Geometry#Point|Point]] of the [[GEF/GEF4/Geometry#Ellipse|Ellipse]] to the end [[GEF/GEF4/Geometry#Point|Point]] of the [[GEF/GEF4/Geometry#Arc|Arc]].
+
A <code>Pie</code> is a closed [[#Arc|Arc]]. Closing the [[#Arc|Arc]] is done by creating two segments: one from the mid [[#Point|Point]] of the related [[#Ellipse|Ellipse]] to the start [[#Point|Point]] of the related [[#Arc|Arc]], the other from the mid [[#Point|Point]] of the [[#Ellipse|Ellipse]] to the end [[#Point|Point]] of the [[#Arc|Arc]].
  
<source lang="java">Pie pie = new Pie(arc);</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
Pie pie = new Pie(arc);
 +
</source>
 +
</div>
  
Rotating a [[GEF/GEF4/Geometry#Pie|Pie]] results in a [[GEF/GEF4/Geometry#Path|Path]], which, unfortunately, cannot be transformed back into a [[GEF/GEF4/Geometry#Pie|Pie]]:
+
Rotating a <code>Pie</code> results in a [[#Path|Path]], which, unfortunately, cannot be transformed back into a <code>Pie</code>:
  
<source lang="java">Path rotatedPie = pie.getRotatedCCW(Angle.fromDeg(15), new Point());</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
Path rotatedPie = pie.getRotatedCCW(Angle.fromDeg(15), new Point());#
 +
</source>
 +
</div>
  
=== RoundedRectangle ===
+
==== RoundedRectangle ====
  
 
[[Image:GEF4Geometry-planar-roundedrectangle-example.png|RoundedRectangle example]]
 
[[Image:GEF4Geometry-planar-roundedrectangle-example.png|RoundedRectangle example]]
Line 226: Line 382:
 
*'''implements:''' IShape, ITranslatable, IScalable, IRotatable
 
*'''implements:''' IShape, ITranslatable, IScalable, IRotatable
  
A [[GEF/GEF4/Geometry#RoundedRectangle|RoundedRectangle]] is a rectangle with round corners. The corners are 90 degrees [[GEF/GEF4/Geometry#Arc|Arc]] objects:
+
A <code>RoundedRectangle</code> is a rectangle with round corners. The corners are 90 degrees [[#Arc|Arc]] objects:
  
<source lang="java">RoundedRectangle rr = new RoundedRectangle(bounds, arcWidth, arcHeight);</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
RoundedRectangle rr = new RoundedRectangle(bounds, arcWidth, arcHeight);
 +
</source>
 +
</div>
  
Rotating a [[GEF/GEF4/Geometry#RoundedRectangle|RoundedRectangle]] does not result in another [[GEF/GEF4/Geometry#RoundedRectangle|RoundedRectangle]], but rather in a [[GEF/GEF4/Geometry#PolyBezier|PolyBezier]] describing the rotated outline:
+
Rotating a <code>RoundedRectangle</code> does not result in another <code>RoundedRectangle</code>, but rather in a [[#PolyBezier|PolyBezier]] describing the rotated outline:
  
<source lang="java">PolyBezier rotated = rr.getRotatedCCW();</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
PolyBezier rotated = rr.getRotatedCCW();
 +
</source>
 +
</div>
  
Unfortunately, it is impossible to transform a [[GEF/GEF4/Geometry#PolyBezier|PolyBezier]] into a [[GEF/GEF4/Geometry#RoundedRectangle|RoundedRectangle]].
+
Unfortunately, it is impossible to transform a [[#PolyBezier|PolyBezier]] into a <code>RoundedRectangle</code>.
  
=== BezierCurve ===
+
==== BezierCurve ====
  
 
[[Image:GEF4Geometry-planar-beziercurve-example.png|BezierCurve example]]
 
[[Image:GEF4Geometry-planar-beziercurve-example.png|BezierCurve example]]
Line 243: Line 407:
 
*'''implements:''' ICurve, ITranslatable, IScalable, IRotatable
 
*'''implements:''' ICurve, ITranslatable, IScalable, IRotatable
  
A [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]] is constructed by a number of control [[GEF/GEF4/Geometry#Point|Point]]s: the start [[GEF/GEF4/Geometry#Point|Point]], an arbitrary number of handle [[GEF/GEF4/Geometry#Point|Point]]s, and the end [[GEF/GEF4/Geometry#Point|Point]]. The curve approaches the handle [[GEF/GEF4/Geometry#Point|Point]]s. Therefore, the handle [[GEF/GEF4/Geometry#Point|Point]]s describe the flow of the curve. The more handle [[GEF/GEF4/Geometry#Point|Point]]s used, the more converges the [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]] to the [[GEF/GEF4/Geometry#Polyline|Polyline]] through the control [[GEF/GEF4/Geometry#Point|Point]]s:
+
A <code>BezierCurve</code> is constructed by a number of control [[#Point|Point]]s: the start [[#Point|Point]], an arbitrary number of handle [[#Point|Point]]s, and the end [[#Point|Point]]. The curve approaches the handle [[#Point|Point]]s. Therefore, the handle [[#Point|Point]]s describe the flow of the curve. The more handle [[#Point|Point]]s used, the more converges the <code>BezierCurve</code> to the [[#Polyline|Polyline]] through the control [[#Point|Point]]s:
  
<source lang="java">BezierCurve curve = new BezierCurve(pStart, pHandle0, pHandle1, pHandle2, ..., pEnd);</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
BezierCurve curve = new BezierCurve(pStart, pHandle0, pHandle1, pHandle2, ..., pEnd);
 +
</source>
 +
</div>
  
=== QuadraticCurve ===
+
==== QuadraticCurve ====
  
 
[[Image:GEF4Geometry-planar-quadraticcurve-example.png|QuadraticCurve example]]
 
[[Image:GEF4Geometry-planar-quadraticcurve-example.png|QuadraticCurve example]]
  
*'''extends:''' [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]]
+
*'''extends:''' [[#BezierCurve|BezierCurve]]
 
*'''implements:''' ICurve, ITranslatable, IScalable, IRotatable
 
*'''implements:''' ICurve, ITranslatable, IScalable, IRotatable
  
A [[GEF/GEF4/Geometry#QuadraticCurve|QuadraticCurve]] is a [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]] with three control [[GEF/GEF4/Geometry#Point|Point]]s: the start [[GEF/GEF4/Geometry#Point|Point]], one handle [[GEF/GEF4/Geometry#Point|Point]], and the end [[GEF/GEF4/Geometry#Point|Point]].
+
A <code>QuadraticCurve</code> is a [[#BezierCurve|BezierCurve]] with three control [[#Point|Point]]s: the start [[#Point|Point]], one handle [[#Point|Point]], and the end [[#Point|Point]].
  
=== CubicCurve ===
+
==== CubicCurve ====
  
 
[[Image:GEF4Geometry-planar-cubiccurve-example.png|CubicCurve example]]
 
[[Image:GEF4Geometry-planar-cubiccurve-example.png|CubicCurve example]]
  
*'''extends:''' [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]]
+
*'''extends:''' [[#BezierCurve|BezierCurve]]
 
*'''implements:''' ICurve, ITranslatable, IScalable, IRotatable
 
*'''implements:''' ICurve, ITranslatable, IScalable, IRotatable
  
A [[GEF/GEF4/Geometry#CubicCurve|CubicCurve]] is a [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]] with four control [[GEF/GEF4/Geometry#Point|Point]]s: the start [[GEF/GEF4/Geometry#Point|Point]], two handle [[GEF/GEF4/Geometry#Point|Point]]s, and the end [[GEF/GEF4/Geometry#Point|Point]]. Many geometry objects approximate their round outline segments using a number of [[GEF/GEF4/Geometry#CubicCurve|CubicCurve]]s ([[GEF/GEF4/Geometry#Ellipse|Ellipse]], [[GEF/GEF4/Geometry#Arc|Arc]], [[GEF/GEF4/Geometry#Pie|Pie]], and [[GEF/GEF4/Geometry#RoundedRectangle|RoundedRectangle]]).
+
A <code>CubicCurve</code> is a [[#BezierCurve|BezierCurve]] with four control [[#Point|Point]]s: the start [[#Point|Point]], two handle [[#Point|Point]]s, and the end [[#Point|Point]]. Many geometry objects approximate their round outline segments using a number of <code>CubicCurve</code>s ([[#Ellipse|Ellipse]], [[#Arc|Arc]], [[#Pie|Pie]], and [[#RoundedRectangle|RoundedRectangle]]).
  
=== PolyBezier ===
+
==== PolyBezier ====
  
 
[[Image:GEF4Geometry-planar-polybezier-example.png|PolyBezier example]]
 
[[Image:GEF4Geometry-planar-polybezier-example.png|PolyBezier example]]
  
 
*'''extends:''' AbstractGeometry
 
*'''extends:''' AbstractGeometry
*'''implements:''' IPolyCurve, ITranslatable, IScalable, IRotatable
+
*'''implements:''' ICurve, ITranslatable, IScalable, IRotatable
  
A [[GEF/GEF4/Geometry#PolyBezier|PolyBezier]] combines multiple [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]] segments to address them as a whole:
+
A <code>PolyBezier</code> combines multiple [[#BezierCurve|BezierCurve]] segments to address them as a whole:
  
<source lang="java">PolyBezier polyBezier = new PolyBezier(line, quadCurve, cubicCurve, arbitraryBezierCurve);</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
PolyBezier polyBezier = new PolyBezier(line, quadCurve, cubicCurve, arbitraryBezierCurve);
 +
</source>
 +
</div>
  
Consecutive [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]]s are connected with each other, i.e. the end [[GEF/GEF4/Geometry#Point|Point]] of one [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]] is the start [[GEF/GEF4/Geometry#Point|Point]] of the subsequent [[GEF/GEF4/Geometry#BezierCurve|BezierCurve]]. The outline of several IShape implementations can be represented by a [[GEF/GEF4/Geometry#PolyBezier|PolyBezier]] ([[GEF/GEF4/Geometry#Ellipse|Ellipse]], [[GEF/GEF4/Geometry#Pie|Pie]], and [[GEF/GEF4/Geometry#RoundedRectangle|RoundedRectangle]]):
+
Consecutive [[#BezierCurve|BezierCurve]]s are connected with each other, i.e. the end [[#Point|Point]] of one [[#BezierCurve|BezierCurve]] is the start [[#Point|Point]] of the subsequent [[#BezierCurve|BezierCurve]]. The outline of several IShape implementations can be represented by a <code>PolyBezier</code> ([[#Ellipse|Ellipse]], [[#Pie|Pie]], and [[#RoundedRectangle|RoundedRectangle]]):
  
<source lang="java">PolyBezier outline = pie.getOutline();</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
PolyBezier outline = pie.getOutline();
 +
</source>
 +
</div>
  
Besides, the [[GEF/GEF4/Geometry#PolyBezier|PolyBezier]] class provides a method to interpolate a number of [[GEF/GEF4/Geometry#CubicCurve|CubicCurve]]s through a set of [[GEF/GEF4/Geometry#Point|Point]]s:
+
Besides, the <code>PolyBezier</code> class provides a method to interpolate a number of [[#CubicCurve|CubicCurve]]s through a set of [[#Point|Point]]s:
  
<source lang="java">PolyBezier interpolation = PolyBezier.interpolateCubic(p0, p1, p2, p3, ...);</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
PolyBezier interpolation = PolyBezier.interpolateCubic(p0, p1, p2, p3, ...);
 +
</source>
 +
</div>
 +
 
 +
==== CurvedPolygon ====
 +
 
 +
[[Image:GEF4Geometry-planar-CurvedPolygon-example.png|CurvedPolygon example]]
 +
 
 +
*'''extends:''' AbstractGeometry
 +
*'''implements:''' IShape, ITranslatable, IScalable, IRotatable
 +
 
 +
A CurvedPolygon is composed by a number of BezierCurves where two subsequent BezierCurves have to share one end Point. Moreover, a CurvedPolygon is always closed, so the end Point of the last BezierCurve has to be equal to the start Point of the first BezierCurve.
  
=== Region ===
+
==== Region ====
  
 
[[Image:GEF4Geometry-planar-Region-example.png|Region example]]
 
[[Image:GEF4Geometry-planar-Region-example.png|Region example]]
  
 
*'''extends:''' AbstractPolyShape
 
*'''extends:''' AbstractPolyShape
*'''implements:''' IPolyShape, ITranslatable, IScalable, IRotatable
+
*'''implements:''' IMultiShape, ITranslatable, IScalable, IRotatable
  
A [[GEF/GEF4/Geometry#Region|Region]] is build up of multiple [[GEF/GEF4/Geometry#Rectangle|Rectangle]]s to address their enclosing area as a unit. The [[GEF/GEF4/Geometry#Rectangle|Rectangle]]s that build up the [[GEF/GEF4/Geometry#Region|Region]] do not have to touch each other. If they intersect, the [[GEF/GEF4/Geometry#Rectangle|Rectangle]]s are divided into a number of internal [[GEF/GEF4/Geometry#Rectangle|Rectangle]]s that do not intersect:
+
A <code>Region</code> is build up of multiple [[#Rectangle|Rectangle]]s to address their enclosing area as a unit. The [[#Rectangle|Rectangle]]s that build up the <code>Region</code> do not have to touch each other. If they intersect, the [[#Rectangle|Rectangle]]s are divided into a number of internal [[#Rectangle|Rectangle]]s that do not intersect:
  
<source lang="java">Region region = new Region(rect0, rect1, rect2);</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
Region region = new Region(rect0, rect1, rect2);
 +
</source>
 +
</div>
  
You can use a [[GEF/GEF4/Geometry#Region|Region]] as a clipping area as in the example image above. For this purpose, it can be transfered into a SWT [[GEF/GEF4/Geometry#Region|Region]] using its toSWTRegion() method as follows:
+
You can use a <code>Region</code> as a clipping area as in the example image above. For this purpose, it can be transfered into a SWT [http://help.eclipse.org/indigo/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/Region.html org.eclipse.swt.graphics.Region] using the Geometry2SWT.toSWTRegion() method as follows:
  
<source lang="java">gc.setClipping(region.toSWTRegion());</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
gc.setClipping(Geometry2SWT.toSWTRegion(region));
 +
</source>
 +
</div>
  
Rotating a [[GEF/GEF4/Geometry#Region|Region]] results in a [[GEF/GEF4/Geometry#Ring|Ring]]:
+
Rotating a <code>Region</code> results in a [[#Ring|Ring]]:
  
<source lang="java">Ring rotatedRegion = region.getRotatedCCW(Angle.fromDeg(45));</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
Ring rotatedRegion = region.getRotatedCCW(Angle.fromDeg(45));
 +
</source>
 +
</div>
  
=== Ring ===
+
==== Ring ====
  
 
[[Image:GEF4Geometry-planar-ring-example.png|Ring example]]
 
[[Image:GEF4Geometry-planar-ring-example.png|Ring example]]
  
 
*'''extends:''' AbstractPolyShape
 
*'''extends:''' AbstractPolyShape
*'''implements:''' IPolyShape, ITranslatable, IScalable, IRotatable
+
*'''implements:''' IMultiShape, ITranslatable, IScalable, IRotatable
  
A [[GEF/GEF4/Geometry#Ring|Ring]] is build up of multiple [[GEF/GEF4/Geometry#Polygon|Polygon]]s to address their enclosing area as a unit. The [[GEF/GEF4/Geometry#Polygon|Polygon]]s that build up the [[GEF/GEF4/Geometry#Ring|Ring]] do not have to touch each other. They are transfered into an internal number of triangles that do not intersect:
+
A <code>Ring</code> is build up of multiple [[#Polygon|Polygon]]s to address their enclosing area as a unit. The [[#Polygon|Polygon]]s that build up the <code>Ring</code> do not have to touch each other. They are transfered into an internal number of triangles that do not intersect:
  
<source lang="java">Ring ring = new Ring(poly0, poly1, poly2);</source>
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
Ring ring = new Ring(poly0, poly1, poly2);
 +
</source>
 +
</div>
  
=== Path ===
+
==== Path ====
  
 
[[Image:GEF4Geometry-planar-path-example.png|Path example]]
 
[[Image:GEF4Geometry-planar-path-example.png|Path example]]
Line 320: Line 525:
 
*'''extends:''' AbstractGeometry
 
*'''extends:''' AbstractGeometry
  
Using a [[GEF/GEF4/Geometry#Path|Path]] is like drawing the joker. You can transfer every other geometric object into a [[GEF/GEF4/Geometry#Path|Path]] using the toPath() method. But the [[GEF/GEF4/Geometry#Path|Path]] does not implement the GEF 4 Geometry interfaces. It simply delegates to the java.awt.geom.Path2D. That's why you should try to avoid using the [[GEF/GEF4/Geometry#Path|Path]] if you want to perform further computations. On the other hand, a [[GEF/GEF4/Geometry#Path|Path]] is easy to render via SWT:
+
Using a <code>Path</code> is like drawing the joker. You can transfer every other geometric object into a <code>Path</code> using the toPath() method. But the <code>Path</code> does not implement the [[GEF/GEF4/Geometry|GEF4 Geometry]] interfaces. It simply delegates to the java.awt.geom.Path2D. That's why you should try to avoid using the <code>Path</code> if you want to perform further computations. On the other hand, a <code>Path</code> is easy to render via SWT:
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">
 
<source lang="java">
gc.drawPath(new org.eclipse.swt.graphics.Path(Display.getCurrent(), gef4Path.toSWTPathData());
+
gc.drawPath(new org.eclipse.swt.graphics.Path(Display.getCurrent(), Geometry2SWT.toSWTPathData(gef4Path));
gc.fillPath(new org.eclipse.swt.graphics.Path(Display.getCurrent(), gef4Path.toSWTPathData());
+
gc.fillPath(new org.eclipse.swt.graphics.Path(Display.getCurrent(), Geometry2SWT.toSWTPathData(gef4Path));
 
</source>
 
</source>
 +
</div>
  
== Euclidean Geometry ==
+
----
 +
 
 +
=== Euclidean ===
  
 
*'''package: org.eclipse.gef4.geometry.euclidean'''
 
*'''package: org.eclipse.gef4.geometry.euclidean'''
  
[[Image:GEF4Geometry-euclidean-overview.png|Angle, Vector, and Straight]]
+
The euclidean package provides core abstractions ([[#Vector|Vector]], [[#Straight|Straight]], and [[#Angle|Angle]]) to support calculations within 2-dimensional Euclidean space.
  
The euclidean package contains classes that describe basic euclidean elements such as straight lines and angles. Additionally, a [[GEF/GEF4/Geometry#Vector|Vector]] class is present.
+
[[Image:GEF4Geometry-euclidean-overview.png|907px|Angle, Vector, and Straight]]
  
=== Angle ===
+
==== Angle ====
  
Considering rotation and the angular relationship of two straight lines, [[GEF/GEF4/Geometry#Angle|Angle]] objects come into play. They abstract over the two commonly used angle units, degrees and radians. The user has to specify the unit of the value an [[GEF/GEF4/Geometry#Angle|Angle]] object is constructed from. Moreover, the user can read the value of an [[GEF/GEF4/Geometry#Angle|Angle]] object in either degrees or radians. Therefore, the use of [[GEF/GEF4/Geometry#Angle|Angle]] objects assures that correct values are used in calculations. This indirection is done due to an inconsistency of several APIs, for example, org.eclipse.swt.graphics.Transform vs. org.eclipse.draw2d.geometry.Transform.
+
Considering rotation and the angular relationship of two straight lines, <code>Angle</code> objects come into play. They abstract over the two commonly used angle units, degrees and radians. The user has to specify the unit of the value an <code>Angle</code> object is constructed from. Moreover, the user can read the value of an <code>Angle</code> object in either degrees or radians. Therefore, the use of <code>Angle</code> objects assures that correct values are used in calculations. This indirection is done due to an inconsistency of several APIs, for example, org.eclipse.swt.graphics.Transform vs. org.eclipse.draw2d.geometry.Transform.
 +
 
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">
 
<source lang="java">
 
// creates a 75% pie chart
 
// creates a 75% pie chart
 
Pie chart = new Pie(0, 0, 100, 100, Angle.fromDeg(15), Angle.fromDeg(270));
 
Pie chart = new Pie(0, 0, 100, 100, Angle.fromDeg(15), Angle.fromDeg(270));
 
</source>
 
</source>
 +
</div>
  
=== Vector ===
+
==== Vector ====
  
A [[GEF/GEF4/Geometry#Vector|Vector]] has two components x and y. It can be interpreted as a planar [[GEF/GEF4/Geometry#Point|Point]] (toPoint()). The [[GEF/GEF4/Geometry#Vector|Vector]] class implements the common arithmetic operations for vectors: addition, multiplication with a scalar, dot product, cross product, and [[GEF/GEF4/Geometry#Angle|Angle]] calculation between two [[GEF/GEF4/Geometry#Vector|Vector]]s:
+
A <code>Vector</code> has two components x and y. It can be interpreted as a planar [[#Point|Point]] (toPoint()). The <code>Vector</code> class implements the common arithmetic operations for vectors: addition, multiplication with a scalar, dot product, cross product, and [[#Angle|Angle]] calculation between two <code>Vector</code>s:
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">Vector u = new Vector(1, 0);
 
<source lang="java">Vector u = new Vector(1, 0);
 
Vector v = new Vector(0, 1);
 
Vector v = new Vector(0, 1);
double zero = u.getDotProduct(v);</source>
+
double zero = u.getDotProduct(v);
 +
</source>
 +
</div>
  
=== Straight ===
+
==== Straight ====
  
A [[GEF/GEF4/Geometry#Straight|Straight]] is an infinite planar line. You can build it up from either two [[GEF/GEF4/Geometry#Point|Point]]s which the [[GEF/GEF4/Geometry#Straight|Straight]] passes through, or by specifying a position and a direction [[GEF/GEF4/Geometry#Vector|Vector]]:
+
A <code>Straight</code> is an infinite planar line. You can build it up from either two [[#Point|Point]]s which the <code>Straight</code> passes through, or by specifying a position and a direction [[#Vector|Vector]]:
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">
 
<source lang="java">
 
Straight diagonal = new Straight(new Point(1, 1), new Point(2, 2));
 
Straight diagonal = new Straight(new Point(1, 1), new Point(2, 2));
 
Straight diagonal = new Straight(new Vector(1, 1), new Vector(1, 1)); // exactly the same Straight
 
Straight diagonal = new Straight(new Vector(1, 1), new Vector(1, 1)); // exactly the same Straight
 
</source>
 
</source>
 +
</div>
  
== Projective Geometry ==
+
----
 +
 
 +
=== Projective ===
  
 
*'''package: org.eclipse.gef4.geometry.projective'''
 
*'''package: org.eclipse.gef4.geometry.projective'''
  
[[Image:GEF4Geometry-projective-overview.png|Vector3D and Straight3D]]
+
The projective package provides classes ([[#Vector3D|Vector3D]], [[#Straight3D|Straight3D]]) to represent euclidean elements in the projective plane.
  
Projective geometry is an interesting perspective to (planar) geometry. A point and a line can both be represented by a (x, y, z) triple. And, in fact, people speak of the duality between points and lines, because for any relation between points and lines, the inverse relation holds if you substitute point by line and vice versa. To retain the semantic distinction of points and lines, both concepts are separated in the Vector3D and Straight3D classes. You may wonder why two dimensional objects are specified by three components. This is the case, because a planar projective point is really a three dimensional euclidean line, that passes through the origin of the three dimensional coordinate system. The x, y, and z values are the components of the direction vector of that line. Similarly, a planar projective line is really a three dimensional euclidean plane, that contains the origin of the three dimensional coordinate system. The x, y, and z components specify that plane's normal vector. Notice that the z = 1 plane is considered to be the two dimensional plane. Therefore, a Vector3D with the components (x, y, z) represents a [[GEF/GEF4/Geometry#Point|Point]] with components (x/z, y/z).
+
[[Image:GEF4Geometry-projective-overview.png|479px|Vector3D and Straight3D]]
  
This approach leads to elegant mathematical solutions to some of the basic planar geometric operations. You want to know if a point lies on a line? Simply substitute its coordinate values into the Straight3D's formula. You want to know the distance of a point to a line? If the Straight3D's vector is normalized (a^2 + b^2 = 1), the formula evaluates to the signed distance of the point to the line, i.e. on one side of the line it is positive and on the other side it is negative. You want to know where two lines are intersecting? Simply compute the cross product of two (x, y, z) triples. These operations are packed in appropriately named methods.
+
Projective geometry is an interesting perspective to (planar) geometry. A point and a line can both be represented by a (x, y, z) triple. And, in fact, people speak of the duality between points and lines, because for any relation between points and lines, the inverse relation holds if you substitute point by line and vice versa. To retain the semantic distinction of points and lines, both concepts are separated in the [[#Vector3D|Vector3D]] and [[#Straight3D|Straight3D]] classes. You may wonder why 2-dimensional objects are specified by three components. This is the case, because a planar projective point is really a three dimensional euclidean line, that passes through the origin of the three dimensional coordinate system. The x, y, and z values are the components of the direction vector of that line. Similarly, a planar projective line is really a three dimensional euclidean plane, that contains the origin of the three dimensional coordinate system. The x, y, and z components specify that plane's normal vector. Notice that the z = 1 plane is considered to be the 2-dimensional plane. Therefore, a [[#Vector3D|Vector3D]] with the components (x, y, z) represents a [[#Point|Point]] with components (x/z, y/z).
  
<source lang="java">Straight3D s = Straight3D.through(new Vector3D(s0), new Vector3D(s1)); // s0, s1 are Points
+
This approach leads to elegant mathematical solutions to some of the basic planar geometric operations. You want to know if a point lies on a line? Simply substitute its coordinate values into the [[#Straight3D|Straight3D]]'s formula. You want to know the distance of a point to a line? If the [[#Straight3D|Straight3D]]'s vector is normalized (a^2 + b^2 = 1), the formula evaluates to the signed distance of the point to the line, i.e. on one side of the line it is positive and on the other side it is negative. You want to know where two lines are intersecting? Simply compute the cross product of two (x, y, z) triples. These operations are packed in appropriately named methods.
 +
 
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
Straight3D s = Straight3D.through(new Vector3D(s0), new Vector3D(s1)); // s0, s1 are Points
 
double signedDistance = s.getSignedDistanceCW(p); // Math.abs() => absolute distance
 
double signedDistance = s.getSignedDistanceCW(p); // Math.abs() => absolute distance
 
Straight3D r = Straight3D.through(new Vector3D(r0), new Vector3D(r1)); // r0, r1 are Points
 
Straight3D r = Straight3D.through(new Vector3D(r0), new Vector3D(r1)); // r0, r1 are Points
 
Vector3D intersection = s.getIntersection(r);
 
Vector3D intersection = s.getIntersection(r);
Point poi = intersection.toPoint();</source>
+
Point poi = intersection.toPoint();
 
+
</source>
=== Vector3D ===
+
</div>
  
A Vector3D consists of three components (x, y, z). It represents the Point (x/z, y/z) in two dimensional space. You can use the common arithmetic operations for vectors on a Vector3D object:
+
==== Vector3D ====
 +
A <code>Vector3D</code> consists of three components (x, y, z). It represents the [[#Point|Point]] (x/z, y/z) in 2-dimensional space. You can use the common arithmetic operations for vectors on a <code>Vector3D</code> object:
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">
 
<source lang="java">
 
Vector3D v = new Vector3D(1, 2, 3);
 
Vector3D v = new Vector3D(1, 2, 3);
Line 385: Line 610:
 
double zero = v.getDotProduct(u);
 
double zero = v.getDotProduct(u);
 
</source>
 
</source>
 +
</div>
  
=== Straight3D ===
+
==== Straight3D ====
 
+
A <code>Straight3D</code> consists of three components (x, y, z). It represents the line ax + by + z = 0 in 2-dimensional space, where (a, b) is a planar [[#Point|Point]]. You can use a <code>Straight3D</code> to calculate the distance of a [[#Vector3D|Vector3D]] to the <code>Straight3D</code>. Moreover, you can compute the point of intersection of two <code>Straight3D</code>s:
A Straight3D consists of three components (x, y, z). It represents the line ax + by + z = 0 in two dimensional space, where (a, b) is a planar Point. You can use a Straight3D to calculate the distance of a Vector3D to the Straight3D. Moreover, you can compute the point of intersection of two Straight3Ds:
+
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">
 
<source lang="java">
 
Straight3D s = Straight3D.through(new Vector3D(1, 1, 1), new Vector3D(2, 1, 1));
 
Straight3D s = Straight3D.through(new Vector3D(1, 1, 1), new Vector3D(2, 1, 1));
 
double one = s.getSignedDistanceCW(new Vector3D(1.5, 2, 1));
 
double one = s.getSignedDistanceCW(new Vector3D(1.5, 2, 1));
 
</source>
 
</source>
 +
</div>
  
== Affine transformations ==
+
----
  
*'''package: org.eclipse.gef4.geometry.transform'''
+
=== Convert.AWT ===
  
Delegates to the java.awt.geom.AffineTransform implementation. It should be way more efficient. At least if you combine several transformations into one AffineTransform object, because the AffineTransform manages one matrix that handles rotation, scaling, shearing, and translation.
+
*'''package: org.eclipse.gef4.geometry.convert.awt'''
  
== Conversions ==
+
The Convert.AWT package contains helper classes to transfer data from AWT/Geometry to one another.
  
*'''package: org.eclipse.gef4.geometry.convert'''
+
[[Image:GEF4Geometry-conversions-AWT.png|766px|AWT/Geometry conversions]]
  
[[Image:GEF4Geometry-conversions-overview.png|Conversions]]
+
==== Geometry2AWT ====
  
=== From Geometry to SWT ===
+
[[#Point|Point]], [[#Line|Line]], [[#Rectangle|Rectangle]], [[#RoundedRectangle|RoundedRectangle]], and AffineTransform objects can be transfered into their AWT pendants using the toAWT*() methods of the [[#Geometry2AWT |Geometry2AWT]] class:
  
Many geometric objects provide a toSWT*() method that transfers the individual object into an SWT alternative. Besides, the transformation into a [[GEF/GEF4/Geometry#Path|Path]] using the toPath() method enables you to construct an SWT [[GEF/GEF4/Geometry#Path|Path]] using the [[GEF/GEF4/Geometry#Path|Path]].toSWTPathData() method:
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
RoundRectangle2D rr2d = Geometry2AWT.toAWTRoundedRectangle(rr);
 +
</source>
 +
</div>
 +
==== AWT2Geomety ====
 +
 
 +
Correspondingly, the [[#AWT2Geometry |AWT2Geometry]] class provides methods to transfer AWT objects into GEF 4 Geometry objects:
  
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<source lang="java">
 
<source lang="java">
org.eclipse.swt.graphics.Path pathSWT = new org.eclipse.swt.graphics.Path(Display.getCurrent(), anyGeometricObject.toPath().toSWTPathData());
+
RoundedRectangle rr = AWT2Geometry.toRoundedRectangle(rr2d);
 
</source>
 
</source>
 +
</div>
  
This is useful to render the geometric objects:
+
----
  
<source lang="java">gc.drawPath(pathSWT);</source>
+
== Geometry.Convert.FX ==
  
=== From Geometry to AWT ===
+
*'''feature: org.eclipse.gef4.geometry.convert.fx'''
 +
*'''bundle: org.eclipse.gef4.geometry.convert.fx'''
  
[[GEF/GEF4/Geometry#Point|Point]], [[GEF/GEF4/Geometry#Line|Line]], [[GEF/GEF4/Geometry#Rectangle|Rectangle]], [[GEF/GEF4/Geometry#RoundedRectangle|RoundedRectangle]], and AffineTransform objects can be transfered into their AWT pendants using the toAWT*() methods of the Geometry2AWT class:
+
The Geometry.Convert.FX bundle contains helper classes for the conversion of JavaFX/Geometry objects to one another.
  
<source lang="java">RoundRectangle2D rr2d = Geometry2AWT.toAWTRoundedRectangle(rr);</source>
+
----
  
=== From AWT to Geometry ===
+
=== Convert.FX ===
  
Correspondingly, the AWT2Geometry class provides methods to transfer AWT objects into GEF 4 Geometry objects:
+
*'''package: org.eclipse.gef4.geometry.convert.fx'''
  
<source lang="java">RoundedRectangle rr = AWT2Geometry.toRoundedRectangle(rr2d);</source>
+
The Convert.FX package contains helper classes to transfer data from JavaFX/Geometry to one another.
  
=== From AWT to SWT ===
+
[[Image:GEF4Geometry-conversions-FX.png|517px|JavaFX/Geometry conversions]]
  
The AWT2SWT class contains a toSWTPathData() method which transfers an AWT PathIterator into an SWT PathData. Consider that the winding rule of the AWT PathIterator is not kept in the SWT PathData, because the latter does not store this information. Instead, it is provided by an SWT [[GEF/GEF4/Geometry#Path|Path]] or by the SWT GC that is used to draw the SWT PathData object:
+
==== Geometry2JavaFX ====
  
<source lang="java">PathData pathData = AWT2SWT.toSWTPathData(pathIterator);</source>
+
AffineTransform, Path, Point, and Rectangle objects can be transfered into their JavaFX pendants using the toFX*() methods provided by the <code>Geometry2JavaFX</code> class:
  
=== From SWT to AWT ===
+
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
Rectangle rect = new Rectangle(10, 10, 100, 50);
 +
javafx.geometry.Bounds rectFx = Geometry2JavaFX.toFXBounds(rect);
 +
</source>
 +
</div>
  
The SWT2AWT class contains a toPathIterator() method which transfers an SWT PathData into an AWT PathIterator.
+
Additionally, the #toPathElements(Path) method allows the conversion of a Path object into JavaFX PathElements.
  
<source lang="java">PathIterator pathIterator = SWT2AWT.toPathIterator(pathData, windingRule);</source>
+
==== JavaFX2Geometry ====
 +
 
 +
JavaFX Bounds, Transform, Path, and Point2D can be transfered into their Geometry pendants using the to*() methods provided by the <code>JavaFX2Geometry</code> class.
 +
 
 +
----
 +
 
 +
== Geometry.Convert.SWT ==
 +
 
 +
*'''feature: org.eclipse.gef4.geometry.convert.swt'''
 +
*'''bundle: org.eclipse.gef4.geometry.convert.swt'''
 +
 
 +
The Geometry.Convert.SWT bundle contains helper classes for the conversion of SWT/Geometry objects to one another and SWT/AWT objects to one another.
 +
 
 +
----
 +
 
 +
=== Convert.SWT ===
 +
 
 +
*'''package: org.eclipse.gef4.geometry.convert.swt'''
 +
 
 +
The Convert.SWT package contains helper classes to transfer data from SWT/Geometry to one another and from SWT/AWT to one another.
 +
 
 +
[[Image:GEF4Geometry-conversions-SWT.png|608px|SWT/Geometry conversions]]
 +
 
 +
==== Geometry2SWT ====
 +
 
 +
[[#Path|Path]], [[#Point|Point]], [[#Line|Line]], [[#Polygon|Polygon]], [[#Polyline|Polyline]], [[#Rectangle|Rectangle]], [[#Region|Region]], and [[#Ring|Ring]] objects can be transfered into their SWT pendants using the toSWT*() methods provided by the <code>Geometry2SWT</code> class:
 +
 
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
Rectangle rect = new Rectangle(10, 10, 100, 50);
 +
org.eclipse.swt.graphics.Rectangle rectSWT = Geometry2SWT.toSWTRectangle(rect);
 +
</source>
 +
</div>
 +
 
 +
Using the IGeometry#toPath() method, you can easily convert any [[GEF/GEF4/Geometry|GEF4 Geometry]] object into an SWT PathData representation:
 +
 
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
CubicCurve curve = new CubicCurve(0, 0, 50, 0, 0, 50, 50, 50);
 +
PathData pd = Geometry2SWT.toSWTPathData(curve.toPath());
 +
</source>
 +
</div>
 +
 
 +
==== SWT2Geometry ====
 +
 
 +
The <code>SWT2Geometry</code> class contains methods to transfer SWT objects into [[GEF/GEF4/Geometry|GEF4 Geometry]] representations.
 +
 
 +
==== SWT2AWT ====
 +
 
 +
The <code>SWT2AWT</code> class contains a toPathIterator() method which transfers an SWT PathData into an [http://docs.oracle.com/javase/7/docs/api/index.html?java/awt/geom/PathIterator.html java.awt.geom.PathIterator].
 +
 
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
PathIterator pathIterator = SWT2AWT.toPathIterator(pathData, windingRule);
 +
</source>
 +
</div>
 +
 
 +
==== AWT2SWT ====
 +
 
 +
The <code>AWT2SWT</code> class contains a toSWTPathData() method which transfers an [http://docs.oracle.com/javase/7/docs/api/index.html?java/awt/geom/PathIterator.html java.awt.geom.PathIterator] into an org.eclipse.swt.graphics.PathData. Consider that the winding rule of the AWT PathIterator is not kept in the SWT PathData, because the latter does not store this information. Instead, it is provided by an SWT Path or by the SWT GC that is used to draw the SWT PathData object:
 +
 
 +
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 +
<source lang="java">
 +
PathData pathData = AWT2SWT.toSWTPathData(pathIterator);
 +
</source>
 +
</div>
 +
[[Category:GEF]]

Revision as of 04:45, 25 May 2015

Note to non-wiki readers: This documentation is generated from the Eclipse wiki - if you have corrections or additions it would be awesome if you added them in the original wiki page.


Introduction

The GEF4 Geometry component provides classes to store geometric objects and to perform geometric computations based on those objects. It is internally structured into three modules, namely Geometry, Geometry.Convert.FX, and Geometry.Convert.SWT.

GEF4-Components-Geometry.png


Geometry

  • feature: org.eclipse.gef4.geometry
  • bundle: org.eclipse.gef4.geometry

Different kinds of abstractions are provided to support different kinds of geometric calculations, within 2-dimensional Euclidean vector space or its related projective space, or based on 2-dimensional planar objects. Furthermore, conversions are supported to import/export from/to related SWT and AWT representations.

The API is universally based on double precision calculations. Result values are computed as precise as possible, most of the time. In situations where result values are approximated, the approximation is as precise as required for the related test methods to agree on the values. An imprecision is used in the comparisons of double precision values throughout the implementation. These imprecise comparisons shall ensure consistency with regard to floating point and approximation errors.

GEF4Geometry-jdt-icons-package obj.gifPlanar GEF4Geometry-jdt-icons-package obj.gifEuclidean GEF4Geometry-jdt-icons-package obj.gifProjective GEF4Geometry-jdt-icons-package obj.gifConvert.AWT
GEF4Geometry-jdt-icons-int obj.gifICurve GEF4Geometry-jdt-icons-int obj.gifIShape GEF4Geometry-jdt-icons-int obj.gifIMultiShape GEF4Geometry-jdt-icons-class obj.gifPath GEF4Geometry-jdt-icons-class obj.gifAngle GEF4Geometry-jdt-icons-class obj.gifStraight3D GEF4Geometry-jdt-icons-class obj.gifGeometry2AWT
GEF4Geometry-jdt-icons-class obj.gifArc GEF4Geometry-jdt-icons-class obj.gifEllipse GEF4Geometry-jdt-icons-class obj.gifRegion   GEF4Geometry-jdt-icons-class obj.gifStraight GEF4Geometry-jdt-icons-class obj.gifVector3D GEF4Geometry-jdt-icons-class obj.gifAWT2Geometry
GEF4Geometry-jdt-icons-class obj.gifBezierCurve GEF4Geometry-jdt-icons-class obj.gifPie GEF4Geometry-jdt-icons-class obj.gifRing   GEF4Geometry-jdt-icons-class obj.gifVector    
GEF4Geometry-jdt-icons-class obj.gifCubicCurve GEF4Geometry-jdt-icons-class obj.gifPolygon          
GEF4Geometry-jdt-icons-class obj.gifLine GEF4Geometry-jdt-icons-class obj.gifRectangle          
GEF4Geometry-jdt-icons-class obj.gifQuadraticCurve GEF4Geometry-jdt-icons-class obj.gifRoundedRectangle          
GEF4Geometry-jdt-icons-class obj.gifPolyBezier GEF4Geometry-jdt-icons-class obj.gifCurvedPolygon          
GEF4Geometry-jdt-icons-class obj.gifPolyline            

To ease navigation, the following sections are organized around the source code packages (org.eclipse.gef4.geomtry.*) of the API, as they were designed to represent the different domains of abstractions.


Planar

  • package: org.eclipse.gef4.geometry.planar

The planar package provides basic abstractions for computations based on 2-dimensional geometric objects.

Interface hierarchy

As outlined above, with the exception of the Path abstraction, all objects are classified into either being curves, shapes, or multi shapes by means of respective interfaces. An ICurve is a one dimensional geometry, i.e. the result that you get by drawing a continuous line with a pencil. It has a start and an end point and you can approximate it by a series of BezierCurves. An IShape is a two dimensional geometry, i.e. it continuously encloses a region on the drawing area, without holes. An IMultiShape is a (possibly) non-continuous set of IShapes. An example for an IMultiShape is the Region. A Region represents the area that results from composing multiple Rectangles. Accordingly, a Ring represents the area that results from composing multiple Polygons. It corresponds to the SWT Region.

The most general type in the hierarchy is the Path, because every geometric object can be transfered into it. Unfortunately, the Path is incompatible to the rest of the API in that it does not implement the different interfaces, it does not ensure a certain precision for the results of its test and manipulation methods, and it cannot be transferred back into compatible objects.

Important functionality

As you can see in this diagram, an ICurve can be approximated by a number of BezierCurves using the toBezier() method. The outline of an IShape can be retrieved using its getOutline() method. Additionally, you can split an IShape into a number of ICurves -- which form the outline -- using the getOutlineSegments() method. IMultiShape provides a getShapes() method to get the individual IShapes that are combined by the IMultiShape. It does provide a getOutlineSegments() method, too, which is used to split the IMultiShape into several ICurves. These transfer methods allow the decomposition of any geometric object into a bunch of BezierCurves:

BezierCurve[] fromCurve = curve.toBezier();
BezierCurve[] fromShape = shape.getOutline().toBezier();
 
ICurve[] fromPolyShape = polyShape.getOutlineSegments();
List<BezierCurve> beziers = new ArrayList<BezierCurve>();
for (ICurve c : fromPolyShape)
    beziers.addAll(Arrays.asList(c.toBezier()));

An important part of a geometry API in general, is the possibility to test the relationship of two geometric objects. The GEF 4 Geometry API provides four methods that perform relation tests. Universally usable is the touches() method for planar objects. It tests if two objects have at least one point in common. Additionally, ICurves can be tested for points of intersection using the intersects() method and for an overlap using the overlaps() method, among each other. An IShape provides a contains() method to test if it fully contains a given planar object. Moreover, the point test is available for every geometric object. It tests if a given Point is incidental to the particular object. Supplementary to the intersects() test, a getIntersections() method is offered among ICurves. BezierCurves do also facilitate the extraction of overlapping segments via the getOverlap() method.

So, let us consider a few examples:

boolean contained = arc.contains(point);
boolean contained = pie.contains(point);
Point[] intersections = line1.getIntersections(line2);
Point[] intersections = line.getIntersections(polygon.getOutline());
Point[] intersections = polygon.getOutline().getIntersections(roundedRectangle.getOutline());
boolean contained = ellipse.contains(line);
boolean contained = rectangle.contains(ellipse);
boolean contained = region.contains(polygon);

Noticeably, the use of interfaces unifies similar operations on different types. Therefore, the fundamental interfaces (ICurve, IShape, etc.) are complemented by three transformation interfaces.

Transformation interfaces

You can either transform your geometric objects via instances of the AffineTransform class, or by using the short-cut methods provided by the ITranslatable, IScalable, and IRotatable interfaces. Transformations can either be directly applied to an object, modifying the object in-place, or to a copy of the original object. This distinction is represented by the names of the short-cut methods. All names starting with 'get' are applied to a copy of the original object. The other methods modify the object in-place.

Translating an object means moving the object. You can move an object in x- and y-direction. Scaling an object means resizing the object. You can individually scale the object in x- and y-direction. Additionally, scaling requires a relative Point to scale to/away from. If you omit this Point, the scaling method will appropriately choose the relative Point. Normally, this will be the center Point of the geometric object that you want to scale. Rotation is special in that not all geometric objects can be rotated in-place. Rectangles, for example, are always parallel to the x- and y-axes. That's why the IRotatable interface does only include the getRotated*() short-cut methods which are not directly applied. However, some geometric objects do provide in-place rotation methods. As with scaling, rotation is performed around a relative Point. If you omit this Point, the rotation method will appropriately choose it. Normally, this will be the center Point of the geometric object that you want to rotate.

Polygon rhomb = new Rectangle(10, 10, 10, 10).getRotatedCCW(Angle.fromDeg(45));
PolyBezier slanted = new Ellipse(100, 100, 100, 50).getRotatedCCW(Angle.fromDeg(30));
Ring rotatedClippingArea = region.getRotatedCCW(Angle.fromDeg(300));

Augmenting the interface hierarchy, all concrete classes are based on abstract geometry classes, depending on the type of geometry used for constructing the objects (i.e. Ellipse is an AbstractRectangleBasedGeometry, because it is constructed by means of a Rectangle).

Inheritance hierarchy

This classification by the construction type of the individual geometry objects allows the generalization of many operations in a few abstract classes. Those abstract classes implement methods that should return an object of the same type as the inheriting class. Thus, type parameters are used to specify such return types.

Point

Point objects represent a point in 2-dimensional space. For the purpose of imagination, you can assume the coordinate system to be originated in the top left corner of your drawing area, expanding to the right and to the bottom. From a list of Point objects, you can build up most of the planar geometric objects:

Point p0 = new Point(); // defaults: x=0, y=0
Point p1 = new Point(5, 0);
Point p2 = new Point(0, 5);
Polygon triangle = new Polygon(p0, p1, p2);

Additionally, the Point class provides static utility methods to operate on a list of Points: getBounds(Point...), getCentroid(Point...), and getConvexHull(Point...). They construct a bounding box, the centroid, and a convex hull of the given Point list, respectively.

Polygon convexHull = Point.getConvexHull(points);

Dimension

The Dimension class is the pendant of the org.eclipse.draw2d.geometry.Dimension class. It decouples the location and the width and height of a rectangular object.

Rectangle bounds = new Rectangle(
    new Point(50, 50),
    new Dimension(80, 20)
);

Line

Line example

  • extends: BezierCurve
  • implements: ICurve, ITranslatable, IScalable, IRotatable

A Line is the straight connection of two Points:

Line line = new Line(p0, p1);

As it inherits from the BezierCurve class, all the operations for BezierCurves are available for Line objects, too. Because of its frequent use, Line overrides many of those operations to provide faster implementations for the Line/Line and Line/Point cases (equals(), touches(), contains(), intersects(), overlaps(), getIntersections(), and many more). If you want to display a Line using SWT, you can use the Geometry2SWT.toSWTPointArray() method as follows:

gc.drawPolyline(Geometry2SWT.toSWTPointArray(line));

Rectangle

Rectangle example

  • extends: AbstractRectangleBasedGeometry
  • implements: IShape, ITranslatable, IScalable, IRotatable

A Rectangle is the axes-parallel rectangle defined by a location (x- and y-coordinates) and a Dimension (width and height):

Rectangle rect = new Rectangle(x, y, w, h);

Rotating a Rectangle results in a Polygon:

Polygon slanted = rect.getRotatedCCW(Angle.fromDeg(30));

Rectangle objects are frequently used, that's why some operations are overridden to provide faster implementations for designated parameter types (equals(), contains(), touches()). If you want to display a Rectangle using SWT, you can use the Geometry2SWT.toSWTRectangle() method as follows:

gc.drawRectangle(Geometry2SWT.toSWTRectangle(rect));

Polyline

PolyLine example

  • extends: AbstractPointListBasedGeometry
  • implements: ICurve, ITranslatable, IScalable, IRotatable

A Polyline combines multiple Line segments to address them as a whole. Consecutive Line segments of a Polyline share at least one end Point. The outline of some of the IShape implementations can be represented by a Polyline (Rectangle and Polygon):

Polyline polyLine = new Polyline(new Line(p0, p1), new Line(p1, p2));
Polyline outline = Polygon.getOutline();

To render a Polyline with SWT, you can use the Geometry2SWT.toSWTPointArray() method as follows:

gc.drawPolyline(Geometry2SWT.toSWTPointArray(polyline));

Polygon

Polygon example

  • extends: AbstractPointListBasedGeometry
  • implements: IShape, ITranslatable, IScalable, IRotatable

A Polygon represents a simple polygon, i.e one that does not have intersecting sides:

Polygon rhomb = new Polygon(0, 0, 1, -1, 2, 0, 1, 1);

If you need to process self-intersecting polygons, you can use the Ring instead.

A Polygon can be rendered with SWT using the Geometry2SWT.toSWTPointArray() method as follows:

gc.drawPolyline(Geometry2SWT.toSWTPointArray(polygon));

Ellipse

Ellipse example

  • extends: AbstractRectangleBasedGeometry
  • implements: IShape, ITranslatable, IScalable, IRotatable

An Ellipse is the axes-symmetric oval that can be put into an axes-parallel Rectangle:

Ellipse ellipse = new Ellipse(rect);

Therefore, rotating an Ellipse does not result in another Ellipse, but in a PolyBezier which approximates the rotated Ellipse:

PolyBezier rotatedEllipse = ellipse.getRotatedCCW(Angle.fromDeg(45));

You can always transfrom a PolyBezier into an Ellipse by using the PolyBezier's bounds as the Ellipse's bounds:

Ellipse rotated = new Ellipse(rotatedEllipse.getBounds());

If you want to draw an Ellipse using SWT, you can directly use the GC's drawOval() method as follows:

gc.drawOval((int) ellipse.getX(), (int) ellipse.getY(), (int) ellipse.getWidth(), (int) ellipse.getHeight());

Arc

Arc example

  • extends: AbstractArcBasedGeometry (which extends AbstractRectangleBasedGeometry)
  • implements: ICurve, ITranslatable, IScalable, IRotatable

An Arc is an open segment of an Ellipse:

Arc arc = new Arc(ellipse, Angle.fromDeg(45), Angle.fromDeg(90));

Rotating an Arc does not necessarily result in another Arc, that's why the rotation methods return PolyBeziers instead:

PolyBezier polyBezier = arc.getRotatedCCW(Angle.fromDeg(15), new Point());

Unfortunately, it is impossible to transfrom a PolyBezier into an Arc.

Pie

Pie example

  • extends: AbstractArcBasedGeometry (which extends AbstractRectangleBasedGeometry)
  • implements: IShape, ITranslatable, IScalable, IRotatable

A Pie is a closed Arc. Closing the Arc is done by creating two segments: one from the mid Point of the related Ellipse to the start Point of the related Arc, the other from the mid Point of the Ellipse to the end Point of the Arc.

Pie pie = new Pie(arc);

Rotating a Pie results in a Path, which, unfortunately, cannot be transformed back into a Pie:

Path rotatedPie = pie.getRotatedCCW(Angle.fromDeg(15), new Point());#

RoundedRectangle

RoundedRectangle example

  • extends: AbstractRectangleBasedGeometry
  • implements: IShape, ITranslatable, IScalable, IRotatable

A RoundedRectangle is a rectangle with round corners. The corners are 90 degrees Arc objects:

RoundedRectangle rr = new RoundedRectangle(bounds, arcWidth, arcHeight);

Rotating a RoundedRectangle does not result in another RoundedRectangle, but rather in a PolyBezier describing the rotated outline:

PolyBezier rotated = rr.getRotatedCCW();

Unfortunately, it is impossible to transform a PolyBezier into a RoundedRectangle.

BezierCurve

BezierCurve example

  • extends: AbstractGeometry
  • implements: ICurve, ITranslatable, IScalable, IRotatable

A BezierCurve is constructed by a number of control Points: the start Point, an arbitrary number of handle Points, and the end Point. The curve approaches the handle Points. Therefore, the handle Points describe the flow of the curve. The more handle Points used, the more converges the BezierCurve to the Polyline through the control Points:

BezierCurve curve = new BezierCurve(pStart, pHandle0, pHandle1, pHandle2, ..., pEnd);

QuadraticCurve

QuadraticCurve example

  • extends: BezierCurve
  • implements: ICurve, ITranslatable, IScalable, IRotatable

A QuadraticCurve is a BezierCurve with three control Points: the start Point, one handle Point, and the end Point.

CubicCurve

CubicCurve example

  • extends: BezierCurve
  • implements: ICurve, ITranslatable, IScalable, IRotatable

A CubicCurve is a BezierCurve with four control Points: the start Point, two handle Points, and the end Point. Many geometry objects approximate their round outline segments using a number of CubicCurves (Ellipse, Arc, Pie, and RoundedRectangle).

PolyBezier

PolyBezier example

  • extends: AbstractGeometry
  • implements: ICurve, ITranslatable, IScalable, IRotatable

A PolyBezier combines multiple BezierCurve segments to address them as a whole:

PolyBezier polyBezier = new PolyBezier(line, quadCurve, cubicCurve, arbitraryBezierCurve);

Consecutive BezierCurves are connected with each other, i.e. the end Point of one BezierCurve is the start Point of the subsequent BezierCurve. The outline of several IShape implementations can be represented by a PolyBezier (Ellipse, Pie, and RoundedRectangle):

PolyBezier outline = pie.getOutline();

Besides, the PolyBezier class provides a method to interpolate a number of CubicCurves through a set of Points:

PolyBezier interpolation = PolyBezier.interpolateCubic(p0, p1, p2, p3, ...);

CurvedPolygon

CurvedPolygon example

  • extends: AbstractGeometry
  • implements: IShape, ITranslatable, IScalable, IRotatable

A CurvedPolygon is composed by a number of BezierCurves where two subsequent BezierCurves have to share one end Point. Moreover, a CurvedPolygon is always closed, so the end Point of the last BezierCurve has to be equal to the start Point of the first BezierCurve.

Region

Region example

  • extends: AbstractPolyShape
  • implements: IMultiShape, ITranslatable, IScalable, IRotatable

A Region is build up of multiple Rectangles to address their enclosing area as a unit. The Rectangles that build up the Region do not have to touch each other. If they intersect, the Rectangles are divided into a number of internal Rectangles that do not intersect:

Region region = new Region(rect0, rect1, rect2);

You can use a Region as a clipping area as in the example image above. For this purpose, it can be transfered into a SWT org.eclipse.swt.graphics.Region using the Geometry2SWT.toSWTRegion() method as follows:

gc.setClipping(Geometry2SWT.toSWTRegion(region));

Rotating a Region results in a Ring:

Ring rotatedRegion = region.getRotatedCCW(Angle.fromDeg(45));

Ring

Ring example

  • extends: AbstractPolyShape
  • implements: IMultiShape, ITranslatable, IScalable, IRotatable

A Ring is build up of multiple Polygons to address their enclosing area as a unit. The Polygons that build up the Ring do not have to touch each other. They are transfered into an internal number of triangles that do not intersect:

Ring ring = new Ring(poly0, poly1, poly2);

Path

Path example

  • extends: AbstractGeometry

Using a Path is like drawing the joker. You can transfer every other geometric object into a Path using the toPath() method. But the Path does not implement the GEF4 Geometry interfaces. It simply delegates to the java.awt.geom.Path2D. That's why you should try to avoid using the Path if you want to perform further computations. On the other hand, a Path is easy to render via SWT:

gc.drawPath(new org.eclipse.swt.graphics.Path(Display.getCurrent(), Geometry2SWT.toSWTPathData(gef4Path));
gc.fillPath(new org.eclipse.swt.graphics.Path(Display.getCurrent(), Geometry2SWT.toSWTPathData(gef4Path));

Euclidean

  • package: org.eclipse.gef4.geometry.euclidean

The euclidean package provides core abstractions (Vector, Straight, and Angle) to support calculations within 2-dimensional Euclidean space.

Angle, Vector, and Straight

Angle

Considering rotation and the angular relationship of two straight lines, Angle objects come into play. They abstract over the two commonly used angle units, degrees and radians. The user has to specify the unit of the value an Angle object is constructed from. Moreover, the user can read the value of an Angle object in either degrees or radians. Therefore, the use of Angle objects assures that correct values are used in calculations. This indirection is done due to an inconsistency of several APIs, for example, org.eclipse.swt.graphics.Transform vs. org.eclipse.draw2d.geometry.Transform.

// creates a 75% pie chart
Pie chart = new Pie(0, 0, 100, 100, Angle.fromDeg(15), Angle.fromDeg(270));

Vector

A Vector has two components x and y. It can be interpreted as a planar Point (toPoint()). The Vector class implements the common arithmetic operations for vectors: addition, multiplication with a scalar, dot product, cross product, and Angle calculation between two Vectors:

Vector u = new Vector(1, 0);
Vector v = new Vector(0, 1);
double zero = u.getDotProduct(v);

Straight

A Straight is an infinite planar line. You can build it up from either two Points which the Straight passes through, or by specifying a position and a direction Vector:

Straight diagonal = new Straight(new Point(1, 1), new Point(2, 2));
Straight diagonal = new Straight(new Vector(1, 1), new Vector(1, 1)); // exactly the same Straight

Projective

  • package: org.eclipse.gef4.geometry.projective

The projective package provides classes (Vector3D, Straight3D) to represent euclidean elements in the projective plane.

Vector3D and Straight3D

Projective geometry is an interesting perspective to (planar) geometry. A point and a line can both be represented by a (x, y, z) triple. And, in fact, people speak of the duality between points and lines, because for any relation between points and lines, the inverse relation holds if you substitute point by line and vice versa. To retain the semantic distinction of points and lines, both concepts are separated in the Vector3D and Straight3D classes. You may wonder why 2-dimensional objects are specified by three components. This is the case, because a planar projective point is really a three dimensional euclidean line, that passes through the origin of the three dimensional coordinate system. The x, y, and z values are the components of the direction vector of that line. Similarly, a planar projective line is really a three dimensional euclidean plane, that contains the origin of the three dimensional coordinate system. The x, y, and z components specify that plane's normal vector. Notice that the z = 1 plane is considered to be the 2-dimensional plane. Therefore, a Vector3D with the components (x, y, z) represents a Point with components (x/z, y/z).

This approach leads to elegant mathematical solutions to some of the basic planar geometric operations. You want to know if a point lies on a line? Simply substitute its coordinate values into the Straight3D's formula. You want to know the distance of a point to a line? If the Straight3D's vector is normalized (a^2 + b^2 = 1), the formula evaluates to the signed distance of the point to the line, i.e. on one side of the line it is positive and on the other side it is negative. You want to know where two lines are intersecting? Simply compute the cross product of two (x, y, z) triples. These operations are packed in appropriately named methods.

Straight3D s = Straight3D.through(new Vector3D(s0), new Vector3D(s1)); // s0, s1 are Points
double signedDistance = s.getSignedDistanceCW(p); // Math.abs() => absolute distance
Straight3D r = Straight3D.through(new Vector3D(r0), new Vector3D(r1)); // r0, r1 are Points
Vector3D intersection = s.getIntersection(r);
Point poi = intersection.toPoint();

Vector3D

A Vector3D consists of three components (x, y, z). It represents the Point (x/z, y/z) in 2-dimensional space. You can use the common arithmetic operations for vectors on a Vector3D object:

Vector3D v = new Vector3D(1, 2, 3);
Vector3D u = v.getAdded(new Vector3D(3, -6, 1));
double zero = v.getDotProduct(u);

Straight3D

A Straight3D consists of three components (x, y, z). It represents the line ax + by + z = 0 in 2-dimensional space, where (a, b) is a planar Point. You can use a Straight3D to calculate the distance of a Vector3D to the Straight3D. Moreover, you can compute the point of intersection of two Straight3Ds:

Straight3D s = Straight3D.through(new Vector3D(1, 1, 1), new Vector3D(2, 1, 1));
double one = s.getSignedDistanceCW(new Vector3D(1.5, 2, 1));

Convert.AWT

  • package: org.eclipse.gef4.geometry.convert.awt

The Convert.AWT package contains helper classes to transfer data from AWT/Geometry to one another.

AWT/Geometry conversions

Geometry2AWT

Point, Line, Rectangle, RoundedRectangle, and AffineTransform objects can be transfered into their AWT pendants using the toAWT*() methods of the Geometry2AWT class:

RoundRectangle2D rr2d = Geometry2AWT.toAWTRoundedRectangle(rr);

AWT2Geomety

Correspondingly, the AWT2Geometry class provides methods to transfer AWT objects into GEF 4 Geometry objects:

RoundedRectangle rr = AWT2Geometry.toRoundedRectangle(rr2d);

Geometry.Convert.FX

  • feature: org.eclipse.gef4.geometry.convert.fx
  • bundle: org.eclipse.gef4.geometry.convert.fx

The Geometry.Convert.FX bundle contains helper classes for the conversion of JavaFX/Geometry objects to one another.


Convert.FX

  • package: org.eclipse.gef4.geometry.convert.fx

The Convert.FX package contains helper classes to transfer data from JavaFX/Geometry to one another.

JavaFX/Geometry conversions

Geometry2JavaFX

AffineTransform, Path, Point, and Rectangle objects can be transfered into their JavaFX pendants using the toFX*() methods provided by the Geometry2JavaFX class:

Rectangle rect = new Rectangle(10, 10, 100, 50);
javafx.geometry.Bounds rectFx = Geometry2JavaFX.toFXBounds(rect);

Additionally, the #toPathElements(Path) method allows the conversion of a Path object into JavaFX PathElements.

JavaFX2Geometry

JavaFX Bounds, Transform, Path, and Point2D can be transfered into their Geometry pendants using the to*() methods provided by the JavaFX2Geometry class.


Geometry.Convert.SWT

  • feature: org.eclipse.gef4.geometry.convert.swt
  • bundle: org.eclipse.gef4.geometry.convert.swt

The Geometry.Convert.SWT bundle contains helper classes for the conversion of SWT/Geometry objects to one another and SWT/AWT objects to one another.


Convert.SWT

  • package: org.eclipse.gef4.geometry.convert.swt

The Convert.SWT package contains helper classes to transfer data from SWT/Geometry to one another and from SWT/AWT to one another.

SWT/Geometry conversions

Geometry2SWT

Path, Point, Line, Polygon, Polyline, Rectangle, Region, and Ring objects can be transfered into their SWT pendants using the toSWT*() methods provided by the Geometry2SWT class:

Rectangle rect = new Rectangle(10, 10, 100, 50);
org.eclipse.swt.graphics.Rectangle rectSWT = Geometry2SWT.toSWTRectangle(rect);

Using the IGeometry#toPath() method, you can easily convert any GEF4 Geometry object into an SWT PathData representation:

CubicCurve curve = new CubicCurve(0, 0, 50, 0, 0, 50, 50, 50);
PathData pd = Geometry2SWT.toSWTPathData(curve.toPath());

SWT2Geometry

The SWT2Geometry class contains methods to transfer SWT objects into GEF4 Geometry representations.

SWT2AWT

The SWT2AWT class contains a toPathIterator() method which transfers an SWT PathData into an java.awt.geom.PathIterator.

PathIterator pathIterator = SWT2AWT.toPathIterator(pathData, windingRule);

AWT2SWT

The AWT2SWT class contains a toSWTPathData() method which transfers an java.awt.geom.PathIterator into an org.eclipse.swt.graphics.PathData. Consider that the winding rule of the AWT PathIterator is not kept in the SWT PathData, because the latter does not store this information. Instead, it is provided by an SWT Path or by the SWT GC that is used to draw the SWT PathData object:

PathData pathData = AWT2SWT.toSWTPathData(pathIterator);

Back to the top