summaryrefslogtreecommitdiffstats
path: root/rasodmg/polygon.hh
diff options
context:
space:
mode:
authorConstantin Jucovschi <cj@ubuntu.localdomain>2009-04-24 07:20:22 -0400
committerConstantin Jucovschi <cj@ubuntu.localdomain>2009-04-24 07:20:22 -0400
commit8f27e65bddd7d4b8515ce620fb485fdd78fcdf89 (patch)
treebd328a4dd4f92d32202241b5e3a7f36177792c5f /rasodmg/polygon.hh
downloadrasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.gz
rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.xz
rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.zip
Initial commitv8.0
Diffstat (limited to 'rasodmg/polygon.hh')
-rw-r--r--rasodmg/polygon.hh287
1 files changed, 287 insertions, 0 deletions
diff --git a/rasodmg/polygon.hh b/rasodmg/polygon.hh
new file mode 100644
index 0000000..ebed9ea
--- /dev/null
+++ b/rasodmg/polygon.hh
@@ -0,0 +1,287 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: polygon.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Polygon
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_POLYGON_
+#define _R_POLYGON_
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include "raslib/point.hh"
+#include "raslib/minterval.hh"
+
+class r_GMarray;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The class r_Edge is used to represent edges of 2-D polygons
+ represented in class r_Polygon. Edges cannot be modified. This does
+ not make sense, as a polygon always has to consist out of connecting
+ edges. Modifications should always be done on the polygon.
+
+*/
+
+class r_Edge
+{
+public:
+ /// constructor getting a 2-D start and end point.
+ r_Edge(const r_Point& newStart, const r_Point& newEnd);
+
+ /// retrieve 2-D start point of edge.
+ const r_Point& getStart() const;
+
+ /// retrieve 2-D end point of edge.
+ const r_Point& getEnd() const;
+
+ /// calculate inverse slope of the edge. Note: may throw exception due to division by 0.
+ double getInvSlope() const;
+
+ /// calculate slope of the edge. Note: may throw exception due to division by 0.
+ double getSlope() const;
+
+ /// retrieve x for a given y on a line with the slope of the edge. Calls getInvSlope().
+ double getCurrX(r_Range y) const;
+
+ /// retrieve y for a given x on a line with the slope of the edge. Calls getSlope().
+ double getCurrY(r_Range x) const;
+
+ /// print start and end point of the edge.
+ void print_status( std::ostream& s = std::cout ) const;
+
+ /// returns true if the edge is parallel to the first axis
+ bool isHorizontal() const;
+
+private:
+ /// start point of the edge.
+ r_Point start;
+
+ /// end point of the edge.
+ r_Point end;
+};
+
+/*@Doc:
+
+ The class r_Polygon is used to represent 2-D polygons in
+ RasDaMan. Polygons are always constructed by specifying a set of
+ points. This class is mainly used for doing polygonal cutouts on
+ r_Marray objects, it offers the relevant methods for that purpose.
+
+ The construction of a r_Polygon with addPoint has to finish with a
+ call to close(). A open polygon is not a legal polygon! Currently no
+ exceptions are thrown if a polygon is open and methods besides
+ addPointXY or close are called. The results are undefined, if the
+ polygon is not closed.
+
+*/
+
+class r_Polygon
+{
+public:
+
+ /// FIXME current we support only 2 dimensional polygon
+ static const r_Dimension polyPointDim;
+
+ /// enum used to clasify one polygon
+ enum r_Polygon_Type{
+ UNKNOWN,
+ CONCAVE,
+ CONVEX
+ };
+
+ /// constructor to initialize polygon from a string
+ r_Polygon(const char* init) throw (r_Error);
+
+ /// constructor getting x and y of the first point in the polygon.
+ r_Polygon(r_Range x, r_Range y);
+
+ /// copy constructor
+ r_Polygon(const r_Polygon&);
+
+ /// default constructor.
+ r_Polygon();
+
+ /// asignment opertor
+ r_Polygon& operator=(const r_Polygon&);
+
+ /// add a point to the polygon.
+ void addPoint(const r_Point& newPoint) throw(r_Error);
+
+ /// add a point to the polygon specifying x and y.
+ void addPointXY(r_Range x, r_Range y) throw(r_Error);
+
+ /// close a polygon after creation with addPointXY.
+ void close();
+
+ /// retrieve the set of all edges of the polygon.
+ const std::vector<r_Edge>& getEdges() const throw(r_Error);
+
+ /// determine the polygon type for an polygon in 2D
+ r_Polygon::r_Polygon_Type detectPolygonType() const throw(r_Error);
+ /**
+ It is assumed that the polygon is simple (does not intersect itself or have holes)
+ Returns UNKNOWN for incomputables eg: polygon with colinear points, polygon with less then 3 points
+ */
+
+ /// retrieve a vector of all points in the polygon.
+ std::vector<r_Point> getPoints() const throw(r_Error);
+ /**
+ Each point is connected with its successor. The last point is connected to the first one.
+ */
+
+ /// print all edges of the polygon.
+ void print_status( std::ostream& s = std::cout ) const;
+
+ /// Fill the 2-D array myArray according to the polygon.
+ void fillMArray( r_GMarray& myArray, bool fillInside = false, const std::string& bgr = "") const throw(r_Error);
+ /** The polygon has to be completely in the domain of the array. Should this not be the case,
+ then the polygon must be clipped according to the domain of the array. Filling is done
+ so that the data in the array is overwritten byte by byte with 0 which is not inside
+ the polygon.
+ */
+
+ /// retrieve the bounding box of the polygon.
+ r_Minterval getBoundingBox() const throw(r_Error);
+
+ /// clip the polygon according to the bounding box specified in clipDom.
+ void clip(const r_Minterval& clipDom) throw(r_Error);
+ /** Note that the r_Polygon object is modified! So after calling clip you will generally
+ have a different polygon represented by your object. */
+
+ /// scale the points of the polygon according to scaleFactor.
+ void scale(const r_Point& origin, const r_Minterval& mddDom,
+ const r_Minterval& clipDom, const double& scaleFactor) throw(r_Error);
+ /** This function is used when using a polygon to extract part of an image retrieved
+ with r_Fast_Scale. The scaling is done like in r_Fast_Base_Scale::get_scaled_domain().
+ origin is the point of origin for the scaling. mddDom is the domain of the MDD which
+ will later be filled with the polygon. Problem is, that the domain of this MDD is
+ currently not created by simply scaling the domain of the original MDD. Instead it
+ is made sure that the origin of the scaled domain stays the same. clipDom is used
+ to do the same when scaling the polygon, it contains the scaled domain of the MDD
+ without shifting it to origin of the domain of the MDD before scaling. It is a
+ bit complicated, I know. scaleFactor is trivially the scaleFactor used. */
+
+ /// scale the points of the polygon according to scaleFactor.
+ void scale(const r_Point& origin, const double& scaleFactor) throw(r_Error);
+ /** This function is used used when we scale a polygon to extract part of an image retrieved
+ with r_Fast_Scale. The scaling is done like in r_Fast_Base_Scale::get_scaled_domain().
+ origin is the point of origin for the scaling. scaleFactor is the scale factor used. */
+
+ /// mirrors a polygon along the y-axes point by point.
+ void mirror(const r_Minterval& mddDom) throw(r_Error);
+ /** The mirroring is done along the middle of mddDom. It is done like that to be coherent
+ with the mirroring commonly done when inserting TIFF image, e.g. in insertlva.cc. */
+
+ /// get "middle" point by averaging all x and y values.
+ r_Point getMiddle() const throw(r_Error);
+
+ /// "shrink" polygon by moving all points towards the middle by pixelCount pixels.
+ void shrinkPoly(int pixelCount) throw(r_Error);
+
+ /// returns the number of edges
+ int countEdges() const;
+
+ /// returns the number of horizontal edges (used by polygon cut out)
+ int countHorizontalEdges() const;
+
+private:
+
+ /// check if the current point is the first point to close the polygon
+ void checkFistPoint();
+
+ /// clipping is done side by side. This enum is used to tell functions which side to clip.
+ enum Side {
+ top, bottom, left, right
+ };
+
+ /// overwrite this with a polygon create from a vector of points.
+ void fromPoints(const std::vector<r_Point>& newPoints) throw(r_Error);
+
+ /// erase the area in myArray outside of the polygon for one scanline.
+ void eraseLine( r_Range x1, r_Range x2, r_Range y, r_GMarray& myArray, const std::string& bgr ) const throw(r_Error);
+
+ /// return the polygon clipped on the specified side as a list of points.
+ std::vector<r_Point> clip1Side(const r_Minterval& b, r_Polygon::Side s);
+
+ /// determine if a point is inside a bounding line on a certain side.
+ bool inside(const r_Minterval& b, const r_Point& p, r_Polygon::Side s);
+
+ /// intersect an edge with a bounding line on a certain side.
+ r_Point intersect(const r_Minterval& b, const r_Edge& e, r_Polygon::Side s);
+
+ /// flag if the polygon is closed.
+ bool closed;
+
+ /// flag if firstPoint has been set.
+ bool firstPointSet;
+
+ /// vector of all edges of the polygon.
+ std::vector<r_Edge> edges;
+ /// remember first point. Used when constructing the polygon.
+
+ r_Point firstPoint;
+
+ /// remember last added point. Used when constructing the polygon.
+ r_Point currPoint;
+};
+
+extern std::ostream& operator<<( std::ostream& s, const r_Polygon& d );
+
+// The following classes are STL function objects which can be used to make
+// sorted collection of r_Edge. In the current implementation only the first
+// one is needed.
+
+class EdgeSortCriterion
+{
+public:
+ // This is needed for keeping a sorted set of edges (sorted by start coordinate y,
+ // then start coordinate x).
+ bool operator() (const r_Edge& e1, const r_Edge& e2) const {
+ return e1.getStart()[1] < e2.getStart()[1] ||
+ (!(e2.getStart()[1] < e1.getStart()[1]) && e1.getStart()[0] < e2.getStart()[0]);
+ }
+};
+
+class ActiveEdgeSortCriterion
+{
+public:
+ // This is needed for keeping a sorted set of active edges (sorted by start coordinate x,
+ // then start coordinate y).
+ bool operator() (const r_Edge& e1, const r_Edge& e2) const {
+ return e1.getStart()[0] < e2.getStart()[0] ||
+ (!(e2.getStart()[0] < e1.getStart()[0]) && e1.getStart()[1] < e2.getStart()[1]);
+ }
+};
+
+#endif