47 : nbPoints( nbPoints )
48 , type( GEOS_POLYGON )
103 bool needClose =
false;
109 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt,
nbPoints + ( needClose ? 1 : 0 ), 2 );
110 for (
int i = 0; i <
nbPoints; ++i )
112 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
113 GEOSCoordSeq_setXY_r( geosctxt, coord, i,
x[i],
y[i] );
115 GEOSCoordSeq_setX_r( geosctxt, coord, i,
x[i] );
116 GEOSCoordSeq_setY_r( geosctxt, coord, i,
y[i] );
123 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
124 GEOSCoordSeq_setXY_r( geosctxt, coord,
nbPoints,
x[0],
y[0] );
126 GEOSCoordSeq_setX_r( geosctxt, coord,
nbPoints,
x[0] );
127 GEOSCoordSeq_setY_r( geosctxt, coord,
nbPoints,
y[0] );
134 mGeos = GEOSGeom_createPolygon_r( geosctxt, GEOSGeom_createLinearRing_r( geosctxt, coord ),
nullptr, 0 );
137 case GEOS_LINESTRING:
138 mGeos = GEOSGeom_createLineString_r( geosctxt, coord );
142 mGeos = GEOSGeom_createPoint_r( geosctxt, coord );
154 if ( !mPreparedGeom )
158 return mPreparedGeom;
165 GEOSGeom_destroy_r( geosctxt,
mGeos );
171 GEOSPreparedGeom_destroy_r( geosctxt, mPreparedGeom );
172 mPreparedGeom =
nullptr;
175 if ( mGeosPreparedBoundary )
177 GEOSPreparedGeom_destroy_r( geosctxt, mGeosPreparedBoundary );
178 mGeosPreparedBoundary =
nullptr;
181 if ( mMultipartPreparedGeos )
183 GEOSPreparedGeom_destroy_r( geosctxt, mMultipartPreparedGeos );
184 mMultipartPreparedGeos =
nullptr;
186 if ( mMultipartGeos )
188 GEOSGeom_destroy_r( geosctxt, mMultipartGeos );
189 mMultipartGeos =
nullptr;
202 GEOSGeom_destroy_r( geosctxt,
mGeos );
205 GEOSPreparedGeom_destroy_r( geosctxt, mPreparedGeom );
207 if ( mGeosPreparedBoundary )
209 GEOSPreparedGeom_destroy_r( geosctxt, mGeosPreparedBoundary );
210 mGeosPreparedBoundary =
nullptr;
213 if ( mMultipartPreparedGeos )
215 GEOSPreparedGeom_destroy_r( geosctxt, mMultipartPreparedGeos );
216 mMultipartPreparedGeos =
nullptr;
218 if ( mMultipartGeos )
220 GEOSGeom_destroy_r( geosctxt, mMultipartGeos );
221 mMultipartGeos =
nullptr;
233 std::unique_ptr<PointSet>
PointSet::extractShape(
int nbPtSh,
int imin,
int imax,
int fps,
int fpe,
double fptx,
double fpty )
237 std::unique_ptr<PointSet> newShape = std::make_unique< PointSet >();
238 newShape->type = GEOS_POLYGON;
239 newShape->nbPoints = nbPtSh;
240 newShape->x.resize( newShape->nbPoints );
241 newShape->y.resize( newShape->nbPoints );
244 for ( j = 0, i = imin; i != ( imax + 1 ) %
nbPoints; i = ( i + 1 ) %
nbPoints, j++ )
246 newShape->x[j] =
x[i];
247 newShape->y[j] =
y[i];
253 newShape->x[j] = fptx;
254 newShape->y[j] = fpty;
262 return std::unique_ptr< PointSet>(
new PointSet( *
this ) );
270 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
273 GEOSCoordSequence *seq = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
274 GEOSCoordSeq_setX_r( geosctxt, seq, 0,
x );
275 GEOSCoordSeq_setY_r( geosctxt, seq, 0,
y );
278 const bool result = ( GEOSPreparedContainsProperly_r( geosctxt,
preparedGeom(), point.get() ) == 1 );
282 catch ( GEOSException &e )
284 qWarning(
"GEOS exception: %s", e.what() );
309 const double labelArea = labelWidth * labelHeight;
311 QLinkedList<PointSet *> inputShapes;
312 inputShapes.push_back( inputShape );
313 QLinkedList<PointSet *> outputShapes;
315 while ( !inputShapes.isEmpty() )
317 PointSet *shape = inputShapes.takeFirst();
319 const std::vector< double > &
x = shape->
x;
320 const std::vector< double > &
y = shape->
y;
322 std::vector< int > pts( nbp );
323 for (
int i = 0; i < nbp; i++ )
335 for ( std::size_t ihs = 0; ihs < shape->
convexHull.size(); ihs++ )
338 const std::size_t ihn = ( ihs + 1 ) % shape->
convexHull.size();
341 const int ipn = ( ips + 1 ) % nbp;
347 for (
int i = ips; i != shape->
convexHull[ihn]; i = ( i + 1 ) % nbp )
371 const double s = ( base + b +
c ) / 2;
372 double area = s * ( s - base ) * ( s - b ) * ( s -
c );
394 bestArea = std::sqrt( bestArea );
395 double cx, cy, dx, dy, ex, ey, fx, fy, seg_length, ptx = 0, pty = 0, fptx = 0, fpty = 0;
396 int ps = -1, pe = -1, fps = -1, fpe = -1;
397 if ( retainedPt >= 0 && bestArea > labelArea )
399 double c = std::numeric_limits<double>::max();
404 for (
int i = ( shape->
convexHull[holeE] + 1 ) % nbp; i != ( shape->
convexHull[holeS] - 1 + nbp ) % nbp; i = j )
412 cx = (
x[i] +
x[j] ) / 2.0;
413 cy = (
y[i] +
y[j] ) / 2.0;
451 double pointX, pointY;
474 if ( isValid && b <
c )
485 const int imin = retainedPt;
486 int imax = ( ( ( fps < retainedPt && fpe < retainedPt ) || ( fps > retainedPt && fpe > retainedPt ) ) ? std::min( fps, fpe ) : std::max( fps, fpe ) );
488 int nbPtSh1, nbPtSh2;
490 nbPtSh1 = imax - imin + 1 + ( fpe != fps );
492 nbPtSh1 = imax + nbp - imin + 1 + ( fpe != fps );
494 if ( ( imax == fps ? fpe : fps ) < imin )
495 nbPtSh2 = imin - ( imax == fps ? fpe : fps ) + 1 + ( fpe != fps );
497 nbPtSh2 = imin + nbp - ( imax == fps ? fpe : fps ) + 1 + ( fpe != fps );
499 if ( retainedPt == -1 || fps == -1 || fpe == -1 )
505 else if ( imax == imin || nbPtSh1 <= 2 || nbPtSh2 <= 2 || nbPtSh1 == nbp || nbPtSh2 == nbp )
507 outputShapes.append( shape );
512 PointSet *newShape = shape->
extractShape( nbPtSh1, imin, imax, fps, fpe, fptx, fpty ).release();
519 inputShapes.append( newShape );
526 newShape = shape->
extractShape( nbPtSh2, imax, imin, fps, fpe, fptx, fpty ).release();
533 inputShapes.append( newShape );
541 outputShapes.append( shape );
559 newGeos.reset( GEOSOffsetCurve_r( geosctxt,
mGeos, distance, 0, GEOSBUF_JOIN_MITRE, 2 ) );
564 if ( GEOSGeomTypeId_r( geosctxt, newGeos.get() ) == GEOS_MULTILINESTRING )
567 const int nParts = GEOSGetNumGeometries_r( geosctxt, newGeos.get() );
568 double maximumLength = -1;
569 const GEOSGeometry *longestPart =
nullptr;
570 for (
int i = 0; i < nParts; ++i )
572 const GEOSGeometry *part = GEOSGetGeometryN_r( geosctxt, newGeos.get(), i );
573 double partLength = -1;
574 if ( GEOSLength_r( geosctxt, part, &partLength ) == 1 )
576 if ( partLength > maximumLength )
578 maximumLength = partLength;
590 geos::unique_ptr longestPartClone( GEOSGeom_clone_r( geosctxt, longestPart ) );
591 newGeos = std::move( longestPartClone );
601 newGeos = std::move( reversed );
604 const int newNbPoints = GEOSGeomGetNumPoints_r( geosctxt, newGeos.get() );
605 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, newGeos.get() );
606 std::vector< double > newX;
607 std::vector< double > newY;
608 newX.resize( newNbPoints );
609 newY.resize( newNbPoints );
610 for (
int i = 0; i < newNbPoints; i++ )
612 GEOSCoordSeq_getX_r( geosctxt, coordSeq, i, &newX[i] );
613 GEOSCoordSeq_getY_r( geosctxt, coordSeq, i, &newY[i] );
619 catch ( GEOSException &e )
621 qWarning(
"GEOS exception: %s", e.what() );
627 mGeos = newGeos.release();
638 if ( startDistance > 0 )
644 double distanceConsumed = 0;
647 for (
int i = 1; i <
nbPoints; ++i )
649 const double thisX =
x[i];
650 const double thisY =
y[i];
651 const double thisSegmentLength = std::sqrt( ( thisX - lastX ) * ( thisX - lastX ) + ( thisY - lastY ) * ( thisY - lastY ) );
652 distanceConsumed += thisSegmentLength;
653 if ( distanceConsumed >= smoothDistance )
655 const double c = ( distanceConsumed - smoothDistance ) / thisSegmentLength;
656 x1 = lastX +
c * ( thisX - lastX );
657 y1 = lastY +
c * ( thisY - lastY );
664 const double distance = std::sqrt( ( x1 - x0 ) * ( x1 - x0 ) + ( y1 - y0 ) * ( y1 - y0 ) );
665 const double extensionFactor = ( startDistance + distance ) / distance;
672 if ( endDistance > 0 )
680 double distanceConsumed = 0;
683 for (
int i =
nbPoints - 2; i >= 0; --i )
685 const double thisX =
x[i];
686 const double thisY =
y[i];
687 const double thisSegmentLength = std::sqrt( ( thisX - lastX ) * ( thisX - lastX ) + ( thisY - lastY ) * ( thisY - lastY ) );
688 distanceConsumed += thisSegmentLength;
689 if ( distanceConsumed >= smoothDistance )
691 const double c = ( distanceConsumed - smoothDistance ) / thisSegmentLength;
692 xend1 = lastX +
c * ( thisX - lastX );
693 yend1 = lastY +
c * ( thisY - lastY );
700 const double distance = std::sqrt( ( xend1 - xend0 ) * ( xend1 - xend0 ) + ( yend1 - yend0 ) * ( yend1 - yend0 ) );
701 const double extensionFactor = ( endDistance + distance ) / distance;
703 x.emplace_back( newEnd.
x() );
704 y.emplace_back( newEnd.
y() );
708 if ( startDistance > 0 )
710 x.insert(
x.begin(), x0 );
711 y.insert(
y.begin(), y0 );
732 double best_area = std::numeric_limits<double>::max();
733 double best_alpha = -1;
735 double best_length = 0;
736 double best_width = 0;
739 bbox[0] = std::numeric_limits<double>::max();
740 bbox[1] = std::numeric_limits<double>::max();
741 bbox[2] = std::numeric_limits<double>::lowest();
742 bbox[3] = std::numeric_limits<double>::lowest();
744 for ( std::size_t i = 0; i <
convexHull.size(); i++ )
761 const double dref = bbox[2] - bbox[0];
768 for ( alpha_d = 0; alpha_d < 90; alpha_d++ )
770 alpha = alpha_d * M_PI / 180.0;
771 d1 = std::cos( alpha ) * dref;
772 d2 = std::sin( alpha ) * dref;
793 bb[14] = bb[12] + d2;
794 bb[15] = bb[13] - d1;
797 for (
int i = 0; i < 16; i += 4 )
800 alpha_seg = ( ( i / 4 > 0 ? ( i / 4 ) - 1 : 3 ) ) * M_PI_2 + alpha;
802 double best_cp = std::numeric_limits<double>::max();
804 for ( std::size_t j = 0; j <
convexHull.size(); j++ )
813 const double distNearestPoint = best_cp / dref;
815 d1 = std::cos( alpha_seg ) * distNearestPoint;
816 d2 = std::sin( alpha_seg ) * distNearestPoint;
840 memcpy( best_bb, bb,
sizeof(
double ) * 16 );
845 for (
int i = 0; i < 16; i = i + 4 )
848 best_bb[( i + 4 ) % 16], best_bb[( i + 5 ) % 16], best_bb[( i + 6 ) % 16], best_bb[( i + 7 ) % 16],
849 &finalBb.
x[int ( i / 4 )], &finalBb.
y[int ( i / 4 )] );
852 finalBb.
alpha = best_alpha;
853 finalBb.
width = best_width;
854 finalBb.
length = best_length;
871 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
872 geos::unique_ptr geosPt( GEOSGeom_createPointFromXY_r( geosctxt, px, py ) );
874 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
875 GEOSCoordSeq_setX_r( geosctxt, coord, 0, px );
876 GEOSCoordSeq_setY_r( geosctxt, coord, 0, py );
879 const int type = GEOSGeomTypeId_r( geosctxt,
mGeos );
880 const GEOSGeometry *extRing =
nullptr;
881 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=9
882 const GEOSPreparedGeometry *preparedExtRing =
nullptr;
885 if (
type != GEOS_POLYGON )
888 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=9
895 extRing = GEOSGetExteriorRing_r( geosctxt,
mGeos );
896 #if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 )
897 if ( ! mGeosPreparedBoundary )
899 mGeosPreparedBoundary = GEOSPrepare_r( geosctxt, extRing );
901 preparedExtRing = mGeosPreparedBoundary;
905 #if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=9 )
912 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
913 unsigned int nPoints = 0;
914 GEOSCoordSeq_getSize_r( geosctxt, nearestCoord.get(), &nPoints );
918 ( void )GEOSCoordSeq_getXY_r( geosctxt, nearestCoord.get(), 0, &nx, &ny );
920 ( void )GEOSCoordSeq_getX_r( geosctxt, nearestCoord.get(), 0, &nx );
921 ( void )GEOSCoordSeq_getY_r( geosctxt, nearestCoord.get(), 0, &ny );
931 catch ( GEOSException &e )
933 qWarning(
"GEOS exception: %s", e.what() );
953 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, centroidGeom.get() );
954 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
955 unsigned int nPoints = 0;
956 GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
959 GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
961 GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
962 GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py );
973 const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, pointGeom.get() );
974 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
975 unsigned int nPoints = 0;
976 GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
980 GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
982 GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
983 GEOSCoordSeq_getY_r( geosctxt, coordSeq, 0, &py );
988 catch ( GEOSException &e )
990 qWarning(
"GEOS exception: %s", e.what() );
1016 while ( i <
nbPoints && ad[i] <= dl ) i++;
1026 di = std::sqrt( dx * dx + dy * dy );
1030 dx =
x[i + 1] -
x[i];
1031 dy =
y[i + 1] -
y[i];
1036 *px =
x[i] + dx * distr / di;
1037 *py =
y[i] + dy * distr / di;
1048 const GEOSGeometry *thisGeos =
geos();
1057 catch ( GEOSException &e )
1059 qWarning(
"GEOS exception: %s", e.what() );
1066 const GEOSGeometry *thisGeos =
geos();
1070 double distance = -1;
1075 catch ( GEOSException &e )
1077 qWarning(
"GEOS exception: %s", e.what() );
1110 catch ( GEOSException &e )
1112 qWarning(
"GEOS exception: %s", e.what() );
1133 ( void )GEOSArea_r( geosctxt,
mGeos, &
mArea );
1137 catch ( GEOSException &e )
1139 qWarning(
"GEOS exception: %s", e.what() );
1159 GEOSWKTWriter *writer = GEOSWKTWriter_create_r( geosctxt );
1161 char *wkt = GEOSWKTWriter_write_r( geosctxt, writer,
mGeos );
1162 const QString res( wkt );
1164 GEOSFree_r( geosctxt, wkt );
1166 GEOSWKTWriter_destroy_r( geosctxt, writer );
1171 catch ( GEOSException &e )
1173 qWarning(
"GEOS exception: %s", e.what() );
1181 std::vector< double > distances(
nbPoints );
1182 double totalDistance = 0;
1183 double oldX = -1.0, oldY = -1.0;
1184 for (
int i = 0; i <
nbPoints; i++ )
1189 distances[i] = std::sqrt( std::pow( oldX -
x[i], 2 ) + std::pow( oldY -
y[i], 2 ) );
1193 totalDistance += distances[i];
1195 return std::make_tuple( std::move( distances ), totalDistance );