Skip to content

Commit 423fa0b

Browse files
author
morb_au
committed
* In Vertex editing, restore the rubberbanding to moving verticies, which was broken in r5550.
* Bonus bugfix: If two adjacent verticies were moved in succession, the second vertex would show a rubberband from the *old* position of the first vertex instead of the moved-to position of the first vertex. This should now be fixed. * Bonus function: New "get_at()" function in QgsGeometryVertexIndex. Should be fairly self-explanitory. git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@5568 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent dd2b966 commit 423fa0b

7 files changed

+372
-48
lines changed

src/core/qgsgeometry.cpp

+237
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,243 @@ QgsPoint QgsGeometry::closestVertex(const QgsPoint& point, QgsGeometryVertexInde
457457
}
458458

459459

460+
void QgsGeometry::adjacentVerticies(const QgsGeometryVertexIndex& atVertex, int& beforeVertex, int& afterVertex) const
461+
{
462+
if(mDirtyWkb)
463+
{
464+
exportGeosToWkb();
465+
}
466+
467+
beforeVertex = -1;
468+
afterVertex = -1;
469+
470+
if (mGeometry)
471+
{
472+
int vertexcounter = 0;
473+
474+
int wkbType;
475+
476+
memcpy(&wkbType, (mGeometry+1), sizeof(int));
477+
478+
switch (wkbType)
479+
{
480+
case QGis::WKBPoint:
481+
{
482+
// NOOP - Points do not have adjacent verticies
483+
break;
484+
}
485+
486+
case QGis::WKBLineString:
487+
{
488+
unsigned char* ptr = mGeometry+5;
489+
int* npoints = (int*) ptr;
490+
491+
const int index = atVertex.back();
492+
493+
// assign the rubber band indices
494+
495+
if(index == 0)
496+
{
497+
beforeVertex = -1;
498+
}
499+
else
500+
{
501+
beforeVertex = index-1;
502+
}
503+
504+
if(index == (*npoints - 1))
505+
{
506+
afterVertex = -1;
507+
}
508+
else
509+
{
510+
afterVertex = index+1;
511+
}
512+
513+
break;
514+
}
515+
case QGis::WKBPolygon:
516+
{
517+
int* nrings=(int*)(mGeometry+5);
518+
int* npoints;
519+
unsigned char* ptr=mGeometry+9;
520+
521+
// Walk through the POLYGON WKB
522+
523+
for (int index0 = 0; index0 < *nrings; ++index0)
524+
{
525+
npoints=(int*)ptr;
526+
ptr+=sizeof(int);
527+
528+
for (int index1 = 0; index1 < *npoints; ++index1)
529+
{
530+
ptr += sizeof(double);
531+
ptr += sizeof(double);
532+
533+
if (vertexcounter == atVertex.back())
534+
// TODO: The above is deprecated as it doesn't allow for multiple linear rings in the polygon.
535+
// replace with the below when the rest of QgsGeometry is migrated to a GEOS back-end.
536+
//if (
537+
// (index0 == atVertex.get_at(0)) &&
538+
// (index1 == atVertex.get_at(1))
539+
// )
540+
{
541+
// Found the vertex of the linear-ring we were looking for.
542+
543+
// assign the rubber band indices
544+
545+
if(index1 == 0)
546+
{
547+
beforeVertex = vertexcounter+(*npoints-2);
548+
afterVertex = vertexcounter+1;
549+
}
550+
else if(index1 == (*npoints-1))
551+
{
552+
beforeVertex = vertexcounter-1;
553+
afterVertex = vertexcounter - (*npoints-2);
554+
}
555+
else
556+
{
557+
beforeVertex = vertexcounter-1;
558+
afterVertex = vertexcounter+1;
559+
}
560+
}
561+
562+
++vertexcounter;
563+
}
564+
}
565+
break;
566+
}
567+
568+
case QGis::WKBMultiPoint:
569+
{
570+
// NOOP - Points do not have adjacent verticies
571+
break;
572+
}
573+
574+
case QGis::WKBMultiLineString:
575+
{
576+
unsigned char* ptr=mGeometry+5;
577+
int* nlines=(int*)ptr;
578+
int* npoints = 0;
579+
ptr+=sizeof(int);
580+
581+
for (int index0 = 0; index0 < *nlines; ++index0)
582+
{
583+
ptr += (sizeof(int) + 1);
584+
npoints = (int*)ptr;
585+
ptr += sizeof(int);
586+
587+
for (int index1 = 0; index1 < *npoints; ++index1)
588+
{
589+
ptr+=sizeof(double);
590+
ptr+=sizeof(double);
591+
592+
if (vertexcounter == atVertex.back())
593+
// TODO: The above is deprecated as it doesn't allow for account for all ends of lines.
594+
// replace with the below when the rest of QgsGeometry is migrated to a GEOS back-end.
595+
//if (
596+
// (index0 == atVertex.get_at(0)) &&
597+
// (index1 == atVertex.get_at(1))
598+
// )
599+
{
600+
// Found the vertex of the linestring we were looking for.
601+
602+
// assign the rubber band indices
603+
604+
if(index1 == 0)
605+
{
606+
beforeVertex = -1;
607+
}
608+
else
609+
{
610+
beforeVertex = vertexcounter-1;
611+
}
612+
if(index1 == (*npoints)-1)
613+
{
614+
afterVertex = -1;
615+
}
616+
else
617+
{
618+
afterVertex = vertexcounter+1;
619+
}
620+
}
621+
++vertexcounter;
622+
}
623+
}
624+
625+
break;
626+
}
627+
628+
case QGis::WKBMultiPolygon:
629+
{
630+
unsigned char* ptr=mGeometry+5;
631+
int* npolys=(int*)ptr;
632+
int* nrings;
633+
int* npoints;
634+
ptr+=sizeof(int);
635+
636+
for (int index0 = 0; index0 < *npolys; ++index0)
637+
{
638+
ptr += (1 + sizeof(int)); //skip endian and polygon type
639+
nrings=(int*)ptr;
640+
ptr+=sizeof(int);
641+
642+
for (int index1 = 0; index1 < *nrings; ++index1)
643+
{
644+
npoints=(int*)ptr;
645+
ptr+=sizeof(int);
646+
647+
for (int index2 = 0; index2 < *npoints; ++index2)
648+
{
649+
ptr += sizeof(double);
650+
ptr += sizeof(double);
651+
652+
if (vertexcounter == atVertex.back())
653+
// TODO: The above is deprecated as it doesn't allow for multiple linear rings in the polygon.
654+
// replace with the below when the rest of QgsGeometry is migrated to a GEOS back-end.
655+
//if (
656+
// (index0 == atVertex.get_at(0)) &&
657+
// (index1 == atVertex.get_at(1)) &&
658+
// (index2 == atVertex.get_at(2))
659+
// )
660+
{
661+
// Found the vertex of the linear-ring of the polygon we were looking for.
662+
663+
// assign the rubber band indices
664+
665+
if(index2 == 0)
666+
{
667+
beforeVertex = vertexcounter+(*npoints-2);
668+
afterVertex = vertexcounter+1;
669+
}
670+
else if(index2 == (*npoints-1))
671+
{
672+
beforeVertex = vertexcounter-1;
673+
afterVertex = vertexcounter - (*npoints-2);
674+
}
675+
else
676+
{
677+
beforeVertex = vertexcounter-1;
678+
afterVertex = vertexcounter+1;
679+
}
680+
}
681+
++vertexcounter;
682+
}
683+
}
684+
}
685+
686+
break;
687+
}
688+
689+
default:
690+
break;
691+
} // switch (wkbType)
692+
693+
} // if (mGeometry)
694+
}
695+
696+
460697

461698
bool QgsGeometry::insertVertexBefore(double x, double y,
462699
int beforeVertex,

src/core/qgsgeometry.h

+18-1
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,27 @@ class QgsGeometry {
8383
void setGeos(geos::Geometry* geos);
8484

8585
/**
86-
Returns the vertex closest to the given point (and also vertex index, squared distance and indexes of the vertices before/after)
86+
Returns the vertex closest to the given point
87+
(and also vertex index, squared distance and indexes of the vertices before/after)
8788
*/
8889
QgsPoint closestVertex(const QgsPoint& point, QgsGeometryVertexIndex& atVertex, int& beforeVertex, int& afterVertex, double& sqrDist) const;
8990

91+
92+
/**
93+
Returns the indexes of the vertices before and after the given vertex index.
94+
95+
This function takes into account the following factors:
96+
97+
1. If the given vertex index is at the end of a linestring,
98+
the adjacent index will be -1 (for "no adjacent vertex")
99+
2. If the given vertex index is at the end of a linear ring
100+
(such as in a polygon), the adjacent index will take into
101+
account the first vertex is equal to the last vertex (and will
102+
skip equal vertex positions).
103+
*/
104+
void adjacentVerticies(const QgsGeometryVertexIndex& atVertex, int& beforeVertex, int& afterVertex) const;
105+
106+
90107
/** Insert a new vertex before the given vertex index,
91108
* ring and item (first number is index 0)
92109
* If the requested vertex number (beforeVertex.back()) is greater

src/core/qgsgeometryvertexindex.cpp

+24-5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ email : morb at ozemail dot com dot au
1616

1717
#include "qgsgeometryvertexindex.h"
1818

19+
#include <iostream>
20+
1921

2022
QgsGeometryVertexIndex::QgsGeometryVertexIndex()
2123
{
@@ -47,17 +49,34 @@ void QgsGeometryVertexIndex::push_back(int& i)
4749
mIndex.push_back(i);
4850
}
4951

50-
int QgsGeometryVertexIndex::back()
52+
int QgsGeometryVertexIndex::back() const
5153
{
5254
#ifdef QGISDEBUG
53-
for(std::vector<int>::iterator it = mIndex.begin(); it != mIndex.end(); ++it)
54-
{
55-
qWarning("mIndex contains: "+QString::number(*it));
56-
}
55+
std::cout << "QgsGeometryVertexIndex::back: mIndex contains:";
56+
for(std::vector<int>::const_iterator it = mIndex.begin(); it != mIndex.end(); ++it)
57+
{
58+
std::cout << " " << (*it);
59+
}
60+
std::cout << "." << std::endl;
5761
#endif
5862
return mIndex.back();
5963
}
6064

65+
66+
int QgsGeometryVertexIndex::get_at(int i) const
67+
{
68+
#ifdef QGISDEBUG
69+
std::cout << "QgsGeometryVertexIndex::get_at: mIndex contains:";
70+
for(std::vector<int>::const_iterator it = mIndex.begin(); it != mIndex.end(); ++it)
71+
{
72+
std::cout << " " << (*it);
73+
}
74+
std::cout << "." << std::endl;
75+
#endif
76+
return mIndex[i];
77+
}
78+
79+
6180
void QgsGeometryVertexIndex::clear()
6281
{
6382
mIndex.clear();

src/core/qgsgeometryvertexindex.h

+8-3
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,15 @@ class QgsGeometryVertexIndex {
5050

5151
/** Pushes an int onto the last (rightmost) element of the index */
5252
void push_back(int& i);
53-
53+
5454
/** Gets the last (rightmost) element of the index */
55-
int back();
56-
55+
int back() const;
56+
57+
/** Gets the i'th element of the index.
58+
i=0 refers to the "innermost" line-string or linear-ring.
59+
*/
60+
int get_at(int i) const;
61+
5762
/** Resets the index */
5863
void clear();
5964

0 commit comments

Comments
 (0)