@ALDParametrizedClass public class MTBPolygon2D extends de.unihalle.informatik.Alida.operator.ALDData implements Cloneable, MTBDataExportableToImageJROI
This class re-implements the class Polygon
.
The main reason for this is the awt-polygons are based on integer
points. However, in MiToBo we require double precision in snake
calculations.
Each polygon can be of complex or simple nature (i.e. does or does not intersect with itself), can be open or closed and is sorted either counter-clockwise or clockwise. Note that boundary points belongs to the polygon per definition.
The point of the polygon must have positive values for x- and y-coordinates. Negative coordinates can afford an undesirable behavior of some methods.
Note that some of the methods to be found here rely on the
GeoLib library. The library is accessed via the wrapper class
MTBPolygon2D_GeoPolygonsWrapper
.
Polygon
,
MTBPolygon2D_GeoPolygonsWrapper
Modifier and Type | Class and Description |
---|---|
private class |
MTBPolygon2D.IntersectionPoint2D
Helper class for function simplify().
|
Modifier and Type | Field and Description |
---|---|
protected boolean |
isClosed
Indicates if the polygon is closed or not.
|
protected Vector<Point2D.Double> |
points
List of polygon points.
|
Constructor and Description |
---|
MTBPolygon2D()
Default constructor.
|
MTBPolygon2D(double[] xp,
double[] yp,
boolean closed)
Construct polygon from coordinate arrays.
|
MTBPolygon2D(Vector<Point2D.Double> ps,
boolean closed)
Construct from point list.
|
Modifier and Type | Method and Description |
---|---|
void |
addPoint(double x,
double y)
Appends a new point to the end of the polygon.
|
MTBPolygon2D |
clone() |
boolean |
contains(double px,
double py,
int w,
int h)
Determines if a point lies inside a polygon or on its boundary.
|
boolean |
containsPoint(double x,
double y)
Checks if given point lies inside of the polygon.
|
ij.gui.PolygonRoi[] |
convertToImageJRoi()
Function to convert object to ImageJ ROI or set of ROIs.
|
void |
drawPolygon(MTBImage img)
Draw a polygon into an image (in red color).
|
void |
drawPolygon(MTBImage img,
int color)
Draw a polygon into an image.
|
void |
drawPolygonPoints(MTBImage img)
Draw polygon points into an image (in red color and as crosses).
|
void |
drawPolygonPoints(MTBImage img,
int color,
int mode)
Draw polygon points into an image.
|
boolean |
equals(Object obj) |
int[][] |
getBinaryMask(int w,
int h)
Generates binary mask for inside part of the polygon.
|
int[][] |
getBinaryMask(int w,
int h,
boolean includePolyPixels)
Generates binary mask for inside part of the polygon.
|
double[] |
getBoundingBox()
Calculates the axes-parallel bounding box of the snake.
|
double |
getLength()
Get the length of the polygon.
|
int |
getPointNum()
Get the number of points from the polygon.
|
Vector<Point2D.Double> |
getPoints()
Get polygon points.
|
MTBPolygon2D |
getPolygon()
Get a Polygon2D copy of this object.
|
double |
getSignedArea()
Calculates the signed area of simple (!)
|
boolean |
isClosed()
Returns true if the polygon forms a closed polygon.
|
boolean |
isConvex()
Check if polygon is convex.
|
boolean |
isOrderedClockwise()
Check if points are ordered clockwise.
|
boolean |
isOrderedCounterClockwise()
Check if points are ordered counter-clockwise.
|
boolean |
isSimple()
Check if polygon is simple, i.e. has no self-overlaps.
|
void |
makeSimple()
Makes the polygon simple, i.e. removes self-overlaps.
|
void |
resample(double segmentLength)
Method to re-sample the line segments of the polygon in a range of a given
segment length.
|
void |
reversePolypoints()
Changes the ordering of the polygon points.
|
void |
setClosed()
Set polygon closed.
|
void |
setOpen()
Set polygon opened (not closed).
|
void |
setPoints(Vector<Point2D.Double> ps)
Set all points of the polygon from the specified point vector object.
|
void |
shift(double shiftValue,
int imageSizeX,
int imageSizeY)
Method to shift the whole polygon outward (positive value) ore inward
(negative value) to its normal vector from every line segment.
|
boolean |
simplify()
Deprecated.
|
Point2D.Double |
standardization(Point2D.Double p) |
de.unihalle.informatik.MiToBo_xml.MTBXMLPolygon2DType |
toXMLType(de.unihalle.informatik.MiToBo_xml.MTBXMLPolygon2DType xmlPolygon)
Convert object to XML representation.
|
private Vector<Point2D.Double> |
traversePolygonPointList(Vector<Point2D.Double> pointlist,
int startPointID)
Helper function for simplify().
|
@ALDClassParameter(label="List of points") protected Vector<Point2D.Double> points
@ALDClassParameter(label="Polygon is closed") protected boolean isClosed
public MTBPolygon2D()
public MTBPolygon2D(double[] xp, double[] yp, boolean closed)
xp
- x coordinates of points.yp
- y coordinates of points.closed
- Should be true if polygon is closed.public MTBPolygon2D(Vector<Point2D.Double> ps, boolean closed)
ps
- List with points.closed
- Should be true if polygon is closed.public de.unihalle.informatik.MiToBo_xml.MTBXMLPolygon2DType toXMLType(de.unihalle.informatik.MiToBo_xml.MTBXMLPolygon2DType xmlPolygon)
Copy the information of this object into the corresponding xml
element xmlPolygon
. If xmlPolygon
is null, a new
object is created, otherwise the passed object filled.
xmlPolygon
- Object to be filled.public void setClosed()
public void setOpen()
public boolean isClosed()
public void setPoints(Vector<Point2D.Double> ps)
ps
- vector with new points of the polygonpublic Vector<Point2D.Double> getPoints()
public int getPointNum()
public MTBPolygon2D clone()
public MTBPolygon2D getPolygon()
public void addPoint(double x, double y)
x
- Point x coordinate.y
- Point y coordinate.public double getSignedArea()
The area is calculated according to the formulas found at
http://www.faqs.org/faqs/graphics/algorithms-faq/,
item 2.01. If the polygon points are ordered counter-clockwise the area will be larger than zero, otherwise smaller.
Note: if the polygon is complex, the result is undetermined! TODO Replace with JNI CGAL function.
public double getLength()
public double[] getBoundingBox()
The function extracts the coordinates of the upper left and lower right corner of the bounding box of the snake. Note that the there is at least one point of the snake lying on each side of the bounding box, i.e. the snake not just touches the box, but lies on it.
The result array contains the corner coordinates in the following order: [xmin, ymin, xmax, ymax]
public int[][] getBinaryMask(int w, int h)
w
- Image width.h
- Image height.public int[][] getBinaryMask(int w, int h, boolean includePolyPixels)
It is important to avoid negative coordinates in the polygon point list.
Note that this method internally uses a sweeping algorithm implemented in ImageJ. This algorithm seems to have some problems if the polygon is represented by a complete point list of all contour pixels, like in case of contours in MiToBo. In that case some polygon pixels are not automatically included in the final mask, but have to be added manually. This can be triggered by setting 'includePolyPixels' to true.
w
- Image width.h
- Image height.includePolyPixels
- Ensure that polygon pixels belong to mask.public boolean isOrderedClockwise()
public boolean isOrderedCounterClockwise()
public boolean isSimple()
public boolean isConvex()
public boolean containsPoint(double x, double y)
Note that the polygons boundary does not belong to the interior.
x
- x-coordinate of the point to test.y
- y-coordinate of the point to test.public void reversePolypoints()
If the polygon points are ordered clockwise afterwards they are ordered counter-clockwise and vice versa.
public boolean contains(double px, double py, int w, int h)
Use this method only for single point testing. If a couple of points should be tested, use the getBinaryMask method to get the region inside the polygon and test the points whether they are inside (value = 1) or outside (value = 0) the polygon.
px
- x coordinate of point to checkpy
- y coordinate of point to checkw
- width of the image where the polygon is includedh
- height of the image where the polygon is includedpublic void makeSimple()
@Deprecated public boolean simplify()
Given a polygon with points sorted counter-clockwise any self-intersection
is eliminated. Basically, at first all intersections are calculated and
then inserted into the point list, which results in a new pointlist
including all polygon points and the intersections in between.
In a second step the complete pointlist is traversed counter-clockwise.
Non-intersection points are directly added to the simplified polygon. If an
intersection point is found, its second counter-part in the list is
searched. Then the neighbor of that point with lies left of the current
segment is added to the simple polygon and traversal continues in the
direction of the recently added point.
The whole procedure stops when the starting point is reached again.
Complexity of the algorithm:
Searching for all intersection points requires to check each segment
against each other, yielding a complexity of O(N*N). During pointlist
traversal each point of the list is considered maximal once, however, the
list is traversed two times in two different directions to make sure that
we run in the correct direction on the polygon. Thus, traversal needs
O(2*|pointlist|).
Altogether this results in O(N*N + N), i.e. quadratic complexity.
IMPORTANT! It is strongly required that the polygon is sorted counter-clockwise!
private Vector<Point2D.Double> traversePolygonPointList(Vector<Point2D.Double> pointlist, int startPointID)
This function traverses a given point list in counter-clockwise ordering and eliminates all intersection points.
pointlist
- List of points to traverse.startPointID
- ID of point where to start.public void resample(double segmentLength)
Method to re-sample the line segments of the polygon in a range of a given segment length. The range is calculated from the given length of a segment by calculation: - minimum = segment length * 0.5 - maximum = segment length * 1.5 If a line segment (p,q) is too small, the point q is removed from the list. Then the new line segment (p,r) is observed, where r is the successor of q. If a line segment (p,q) is too large, new points will be added. The number of new points is calculated by the possible number of points (depending on the given segment length) that fit into the line segment between p and q.
segmentLength
- Target length of segments in resampling.public void shift(double shiftValue, int imageSizeX, int imageSizeY)
ATTENTION!!! After shifting a polygon, it can happen that the polygon is not simple !!!
shiftValue
- positive ore negative value to shift the polygonimageSizeX
- width of the image to test whether the coordinates of the shifted
polygon are validimageSizeY
- height of the image to test whether the coordinates of the shifted
polygon are validpublic Point2D.Double standardization(Point2D.Double p)
public void drawPolygon(MTBImage img)
img
- Image where to draw the polygon into.public void drawPolygon(MTBImage img, int color)
img
- Image where to draw the polygon into.color
- Color in which to draw the polygon.public void drawPolygonPoints(MTBImage img)
img
- Image where to draw the polygon points into.public void drawPolygonPoints(MTBImage img, int color, int mode)
img
- Image where to draw the polygon points into.color
- Color to be used.mode
- Shape to be drawn.public ij.gui.PolygonRoi[] convertToImageJRoi()
MTBDataExportableToImageJROI
convertToImageJRoi
in interface MTBDataExportableToImageJROI
Copyright © 2010–2020 Martin Luther University Halle-Wittenberg, Institute of Computer Science, Pattern Recognition and Bioinformatics. All rights reserved.