1 /* 2 * libpal - Automated Placement of Labels Library 3 * 4 * Copyright (C) 2008 Maxence Laurent, MIS-TIC, HEIG-VD 5 * University of Applied Sciences, Western Switzerland 6 * http://www.hes-so.ch 7 * 8 * Contact: 9 * maxence.laurent <at> heig-vd <dot> ch 10 * or 11 * eric.taillard <at> heig-vd <dot> ch 12 * 13 * This file is part of libpal. 14 * 15 * libpal is free software: you can redistribute it and/or modify 16 * it under the terms of the GNU General Public License as published by 17 * the Free Software Foundation, either version 3 of the License, or 18 * (at your option) any later version. 19 * 20 * libpal is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * GNU General Public License for more details. 24 * 25 * You should have received a copy of the GNU General Public License 26 * along with libpal. If not, see <http://www.gnu.org/licenses/>. 27 * 28 */ 29 30 #ifndef POINTSET_H 31 #define POINTSET_H 32 33 #define SIP_NO_FILE 34 35 36 #include <cfloat> 37 #include <cmath> 38 #include <QLinkedList> 39 #include <geos_c.h> 40 #include <memory> 41 #include <vector> 42 43 #include "qgis_core.h" 44 #include "qgsrectangle.h" 45 46 namespace pal 47 { 48 49 class Pal; 50 class Projection; 51 class LabelPosition; 52 53 class PointSet; 54 55 /** 56 * Represents the minimum area, oriented bounding box surrounding a convex hull. 57 */ 58 struct OrientedConvexHullBoundingBox 59 { 60 double x[4]; 61 double y[4]; 62 63 double alpha; 64 65 double width; 66 double length; 67 }; 68 69 /** 70 * \class pal::PointSet 71 * \brief The underlying raw pal geometry class. 72 * \note not available in Python bindings 73 * \ingroup core 74 */ 75 class CORE_EXPORT PointSet 76 { 77 friend class FeaturePart; 78 friend class LabelPosition; 79 friend class CostCalculator; 80 friend class PolygonCostCalculator; 81 friend class Layer; 82 83 public: 84 PointSet(); 85 PointSet( int nbPoints, double *x, double *y ); 86 virtual ~PointSet(); 87 88 /** 89 * Does... something completely inscrutable. 90 */ 91 std::unique_ptr< PointSet > extractShape( int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty ); 92 93 /** 94 * Returns a copy of the point set. 95 */ 96 std::unique_ptr< PointSet > clone() const; 97 98 /** 99 * Tests whether point set contains a specified point. 100 * \param x x-coordinate of point 101 * \param y y-coordinate of point 102 * \returns TRUE if point set contains a specified point 103 */ 104 bool containsPoint( double x, double y ) const; 105 106 /** 107 * Tests whether a possible label candidate will fit completely within the shape. 108 * \param x x-coordinate of label candidate 109 * \param y y-coordinate of label candidate 110 * \param width label width 111 * \param height label height 112 * \param alpha label angle 113 * \returns TRUE if point set completely contains candidate label 114 */ 115 bool containsLabelCandidate( double x, double y, double width, double height, double alpha = 0 ) const; 116 117 /** 118 * Computes an oriented bounding box for the shape's convex hull. 119 */ 120 OrientedConvexHullBoundingBox computeConvexHullOrientedBoundingBox( bool &ok ); 121 122 /** 123 * Split a concave shape into several convex shapes. 124 */ 125 static void splitPolygons( QLinkedList<PointSet *> &inputShapes, 126 QLinkedList<PointSet *> &outputShapes, 127 double xrm, double yrm ); 128 129 /** 130 * Extends linestrings by the specified amount at the start and end of the line, 131 * by extending the existing lines following the same direction as the original line 132 * start or end. 133 * 134 * The \a smoothDistance argument specifies the distance over which to smooth the direction 135 * of the line at its start and end points. 136 */ 137 void extendLineByDistance( double startDistance, double endDistance, double smoothDistance ); 138 139 /** 140 * Returns the squared minimum distance between the point set geometry and the point (px,py) 141 * Optionally, the nearest point is stored in (rx,ry). 142 * \param px x coordinate of the point 143 * \param py y coordinate of the points 144 * \param rx pointer to x coorinates of the nearest point (can be NULL) 145 * \param ry pointer to y coorinates of the nearest point (can be NULL) 146 * \returns minimum distance 147 */ 148 double minDistanceToPoint( double px, double py, double *rx = nullptr, double *ry = nullptr ) const; 149 150 void getCentroid( double &px, double &py, bool forceInside = false ) const; 151 getGeosType()152 int getGeosType() const { return type; } 153 154 /** 155 * Returns the point set bounding box. 156 */ boundingBox()157 QgsRectangle boundingBox() const 158 { 159 return QgsRectangle( xmin, ymin, xmax, ymax ); 160 } 161 162 /** 163 * Returns TRUE if the bounding box of this pointset intersects the bounding box 164 * of another pointset. 165 */ 166 bool boundingBoxIntersects( const PointSet *other ) const; 167 168 //! Returns NULLPTR if this isn't a hole. Otherwise returns pointer to parent pointset. getHoleOf()169 PointSet *getHoleOf() const { return holeOf; } 170 getNumPoints()171 int getNumPoints() const { return nbPoints; } 172 173 /** 174 * Gets a point a set distance along a line geometry. 175 * \param d array of distances between points 176 * \param ad cumulative total distance from pt0 to each point (ad0 = pt0->pt0) 177 * \param dl distance to traverse along line 178 * \param px final x coord on line 179 * \param py final y coord on line 180 */ 181 void getPointByDistance( double *d, double *ad, double dl, double *px, double *py ); 182 183 /** 184 * Returns the point set's GEOS geometry. 185 */ 186 const GEOSGeometry *geos() const; 187 188 /** 189 * Returns length of line geometry. 190 */ 191 double length() const; 192 193 /** 194 * Returns area of polygon geometry. 195 */ 196 double area() const; 197 198 /** 199 * Returns TRUE if pointset is closed. 200 */ 201 bool isClosed() const; 202 203 int nbPoints; 204 std::vector< double > x; 205 std::vector< double > y; // points order is counterclockwise 206 207 protected: 208 mutable GEOSGeometry *mGeos = nullptr; 209 mutable bool mOwnsGeom = false; 210 211 int *cHull = nullptr; 212 int cHullSize = 0; 213 214 int type; 215 216 PointSet *holeOf = nullptr; 217 PointSet *parent = nullptr; 218 219 mutable double mArea = -1; 220 mutable double mLength = -1; 221 222 223 PointSet( double x, double y ); 224 225 PointSet( const PointSet &ps ); 226 227 void deleteCoords(); 228 void createGeosGeom() const; 229 const GEOSPreparedGeometry *preparedGeom() const; 230 void invalidateGeos(); 231 232 double xmin = std::numeric_limits<double>::max(); 233 double xmax = std::numeric_limits<double>::lowest(); 234 double ymin = std::numeric_limits<double>::max(); 235 double ymax = std::numeric_limits<double>::lowest(); 236 237 private: 238 239 mutable const GEOSPreparedGeometry *mPreparedGeom = nullptr; 240 241 PointSet &operator= ( const PointSet & ) = delete; 242 243 }; 244 245 } // namespace pal 246 247 #endif 248 249