|
23 | 23 | #include "qgslogger.h"
|
24 | 24 | #include "qgsrenderer.h"
|
25 | 25 | #include "qgsexpressioncontextutils.h"
|
26 |
| - |
| 26 | +#include "qgslinestring.h" |
27 | 27 | #include <spatialindex/SpatialIndex.h>
|
28 | 28 |
|
29 | 29 | #include <QLinkedListIterator>
|
@@ -332,196 +332,48 @@ static QgsPointLocator::MatchList _geometrySegmentsInRect( QgsGeometry *geom, co
|
332 | 332 | // we need iterator for segments...
|
333 | 333 |
|
334 | 334 | QgsPointLocator::MatchList lst;
|
335 |
| - QByteArray wkb( geom->asWkb() ); |
336 |
| - if ( wkb.isEmpty() ) |
337 |
| - return lst; |
338 | 335 |
|
339 |
| - _CohenSutherland cs( rect ); |
| 336 | + // geom is converted to a MultiCurve |
| 337 | + QgsGeometry straightGeom = geom->convertToType( QgsWkbTypes::LineGeometry, true ); |
| 338 | + // and convert to straight segemnt / converts curve to linestring |
| 339 | + straightGeom.convertToStraightSegment(); |
340 | 340 |
|
341 |
| - QgsConstWkbPtr wkbPtr( wkb ); |
342 |
| - wkbPtr.readHeader(); |
| 341 | + // so, you must have multilinestring |
| 342 | + // |
| 343 | + // Special case: Intersections cannot be done on an empty linestring like |
| 344 | + // QgsGeometry(QgsLineString()) or QgsGeometry::fromWkt("LINESTRING EMPTY") |
| 345 | + if ( straightGeom.isEmpty() || ( ( straightGeom.type() != QgsWkbTypes::LineGeometry ) && ( !straightGeom.isMultipart() ) ) ) |
| 346 | + return lst; |
343 | 347 |
|
344 |
| - QgsWkbTypes::Type wkbType = geom->wkbType(); |
| 348 | + _CohenSutherland cs( rect ); |
345 | 349 |
|
346 |
| - bool hasZValue = false; |
347 |
| - switch ( wkbType ) |
| 350 | + int pointIndex = 0; |
| 351 | + for ( auto part = straightGeom.const_parts_begin(); part != straightGeom.const_parts_end(); ++part ) |
348 | 352 | {
|
349 |
| - case QgsWkbTypes::Point25D: |
350 |
| - case QgsWkbTypes::Point: |
351 |
| - case QgsWkbTypes::MultiPoint25D: |
352 |
| - case QgsWkbTypes::MultiPoint: |
353 |
| - { |
354 |
| - // Points have no lines |
355 |
| - return lst; |
356 |
| - } |
357 |
| - |
358 |
| - case QgsWkbTypes::LineString25D: |
359 |
| - hasZValue = true; |
360 |
| - //intentional fall-through |
361 |
| - FALLTHROUGH |
362 |
| - case QgsWkbTypes::LineString: |
363 |
| - { |
364 |
| - int nPoints; |
365 |
| - wkbPtr >> nPoints; |
366 |
| - |
367 |
| - double prevx = 0.0, prevy = 0.0; |
368 |
| - for ( int index = 0; index < nPoints; ++index ) |
369 |
| - { |
370 |
| - double thisx = 0.0, thisy = 0.0; |
371 |
| - wkbPtr >> thisx >> thisy; |
372 |
| - if ( hasZValue ) |
373 |
| - wkbPtr += sizeof( double ); |
374 |
| - |
375 |
| - if ( index > 0 ) |
376 |
| - { |
377 |
| - if ( cs.isSegmentInRect( prevx, prevy, thisx, thisy ) ) |
378 |
| - { |
379 |
| - QgsPointXY edgePoints[2]; |
380 |
| - edgePoints[0].set( prevx, prevy ); |
381 |
| - edgePoints[1].set( thisx, thisy ); |
382 |
| - lst << QgsPointLocator::Match( QgsPointLocator::Edge, vl, fid, 0, QgsPointXY(), index - 1, edgePoints ); |
383 |
| - } |
384 |
| - } |
385 |
| - |
386 |
| - prevx = thisx; |
387 |
| - prevy = thisy; |
388 |
| - } |
389 |
| - break; |
390 |
| - } |
391 |
| - |
392 |
| - case QgsWkbTypes::MultiLineString25D: |
393 |
| - hasZValue = true; |
394 |
| - //intentional fall-through |
395 |
| - FALLTHROUGH |
396 |
| - case QgsWkbTypes::MultiLineString: |
397 |
| - { |
398 |
| - int nLines; |
399 |
| - wkbPtr >> nLines; |
400 |
| - for ( int linenr = 0, pointIndex = 0; linenr < nLines; ++linenr ) |
401 |
| - { |
402 |
| - wkbPtr.readHeader(); |
403 |
| - int nPoints; |
404 |
| - wkbPtr >> nPoints; |
405 |
| - |
406 |
| - double prevx = 0.0, prevy = 0.0; |
407 |
| - for ( int pointnr = 0; pointnr < nPoints; ++pointnr ) |
408 |
| - { |
409 |
| - double thisx = 0.0, thisy = 0.0; |
410 |
| - wkbPtr >> thisx >> thisy; |
411 |
| - if ( hasZValue ) |
412 |
| - wkbPtr += sizeof( double ); |
413 |
| - |
414 |
| - if ( pointnr > 0 ) |
415 |
| - { |
416 |
| - if ( cs.isSegmentInRect( prevx, prevy, thisx, thisy ) ) |
417 |
| - { |
418 |
| - QgsPointXY edgePoints[2]; |
419 |
| - edgePoints[0].set( prevx, prevy ); |
420 |
| - edgePoints[1].set( thisx, thisy ); |
421 |
| - lst << QgsPointLocator::Match( QgsPointLocator::Edge, vl, fid, 0, QgsPointXY(), pointIndex - 1, edgePoints ); |
422 |
| - } |
423 |
| - } |
424 |
| - |
425 |
| - prevx = thisx; |
426 |
| - prevy = thisy; |
427 |
| - ++pointIndex; |
428 |
| - } |
429 |
| - } |
430 |
| - break; |
431 |
| - } |
| 353 | + // Checking for invalid linestrings |
| 354 | + // A linestring should/(must?) have at least two points |
| 355 | + if ( qgsgeometry_cast<QgsLineString *>( *part )->numPoints() < 2 ) |
| 356 | + continue; |
432 | 357 |
|
433 |
| - case QgsWkbTypes::Polygon25D: |
434 |
| - hasZValue = true; |
435 |
| - //intentional fall-through |
436 |
| - FALLTHROUGH |
437 |
| - case QgsWkbTypes::Polygon: |
| 358 | + QgsAbstractGeometry::vertex_iterator it = ( *part )->vertices_begin(); |
| 359 | + QgsPointXY prevPoint( *it ); |
| 360 | + it++; |
| 361 | + while ( it != ( *part )->vertices_end() ) |
438 | 362 | {
|
439 |
| - int nRings; |
440 |
| - wkbPtr >> nRings; |
441 |
| - |
442 |
| - for ( int ringnr = 0, pointIndex = 0; ringnr < nRings; ++ringnr )//loop over rings |
| 363 | + QgsPointXY thisPoint( *it ); |
| 364 | + if ( cs.isSegmentInRect( prevPoint.x(), prevPoint.y(), thisPoint.x(), thisPoint.y() ) ) |
443 | 365 | {
|
444 |
| - int nPoints; |
445 |
| - wkbPtr >> nPoints; |
446 |
| - |
447 |
| - double prevx = 0.0, prevy = 0.0; |
448 |
| - for ( int pointnr = 0; pointnr < nPoints; ++pointnr )//loop over points in a ring |
449 |
| - { |
450 |
| - double thisx = 0.0, thisy = 0.0; |
451 |
| - wkbPtr >> thisx >> thisy; |
452 |
| - if ( hasZValue ) |
453 |
| - wkbPtr += sizeof( double ); |
454 |
| - |
455 |
| - if ( pointnr > 0 ) |
456 |
| - { |
457 |
| - if ( cs.isSegmentInRect( prevx, prevy, thisx, thisy ) ) |
458 |
| - { |
459 |
| - QgsPointXY edgePoints[2]; |
460 |
| - edgePoints[0].set( prevx, prevy ); |
461 |
| - edgePoints[1].set( thisx, thisy ); |
462 |
| - lst << QgsPointLocator::Match( QgsPointLocator::Edge, vl, fid, 0, QgsPointXY(), pointIndex - 1, edgePoints ); |
463 |
| - } |
464 |
| - } |
465 |
| - |
466 |
| - prevx = thisx; |
467 |
| - prevy = thisy; |
468 |
| - ++pointIndex; |
469 |
| - } |
| 366 | + QgsPointXY edgePoints[2]; |
| 367 | + edgePoints[0] = prevPoint; |
| 368 | + edgePoints[1] = thisPoint; |
| 369 | + lst << QgsPointLocator::Match( QgsPointLocator::Edge, vl, fid, 0, QgsPointXY(), pointIndex - 1, edgePoints ); |
470 | 370 | }
|
471 |
| - break; |
472 |
| - } |
| 371 | + prevPoint = QgsPointXY( *it ); |
| 372 | + it++; |
| 373 | + pointIndex += 1; |
473 | 374 |
|
474 |
| - case QgsWkbTypes::MultiPolygon25D: |
475 |
| - hasZValue = true; |
476 |
| - //intentional fall-through |
477 |
| - FALLTHROUGH |
478 |
| - case QgsWkbTypes::MultiPolygon: |
479 |
| - { |
480 |
| - int nPolygons; |
481 |
| - wkbPtr >> nPolygons; |
482 |
| - for ( int polynr = 0, pointIndex = 0; polynr < nPolygons; ++polynr ) |
483 |
| - { |
484 |
| - wkbPtr.readHeader(); |
485 |
| - int nRings; |
486 |
| - wkbPtr >> nRings; |
487 |
| - for ( int ringnr = 0; ringnr < nRings; ++ringnr ) |
488 |
| - { |
489 |
| - int nPoints; |
490 |
| - wkbPtr >> nPoints; |
491 |
| - |
492 |
| - double prevx = 0.0, prevy = 0.0; |
493 |
| - for ( int pointnr = 0; pointnr < nPoints; ++pointnr ) |
494 |
| - { |
495 |
| - double thisx = 0.0, thisy = 0.0; |
496 |
| - wkbPtr >> thisx >> thisy; |
497 |
| - if ( hasZValue ) |
498 |
| - wkbPtr += sizeof( double ); |
499 |
| - |
500 |
| - if ( pointnr > 0 ) |
501 |
| - { |
502 |
| - if ( cs.isSegmentInRect( prevx, prevy, thisx, thisy ) ) |
503 |
| - { |
504 |
| - QgsPointXY edgePoints[2]; |
505 |
| - edgePoints[0].set( prevx, prevy ); |
506 |
| - edgePoints[1].set( thisx, thisy ); |
507 |
| - lst << QgsPointLocator::Match( QgsPointLocator::Edge, vl, fid, 0, QgsPointXY(), pointIndex - 1, edgePoints ); |
508 |
| - } |
509 |
| - } |
510 |
| - |
511 |
| - prevx = thisx; |
512 |
| - prevy = thisy; |
513 |
| - ++pointIndex; |
514 |
| - } |
515 |
| - } |
516 |
| - } |
517 |
| - break; |
518 | 375 | }
|
519 |
| - |
520 |
| - case QgsWkbTypes::Unknown: |
521 |
| - default: |
522 |
| - return lst; |
523 |
| - } // switch (wkbType) |
524 |
| - |
| 376 | + } |
525 | 377 | return lst;
|
526 | 378 | }
|
527 | 379 |
|
|
0 commit comments