Skip to content
Permalink
Browse files
* In Vertex editing, restore the rubberbanding to moving verticies, w…
…hich 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@5568 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
morb_au committed Jul 8, 2006
1 parent 6abc64b commit 002e57a020e9565a2243b766283d4af3d6e29dd8
Showing with 372 additions and 48 deletions.
  1. +237 −0 src/core/qgsgeometry.cpp
  2. +18 −1 src/core/qgsgeometry.h
  3. +24 −5 src/core/qgsgeometryvertexindex.cpp
  4. +8 −3 src/core/qgsgeometryvertexindex.h
  5. +52 −25 src/gui/qgsmaptoolvertexedit.cpp
  6. +10 −6 src/gui/qgsmaptoolvertexedit.h
  7. +23 −8 src/gui/qgsvectorlayer.cpp
@@ -457,6 +457,243 @@ QgsPoint QgsGeometry::closestVertex(const QgsPoint& point, QgsGeometryVertexInde
}


void QgsGeometry::adjacentVerticies(const QgsGeometryVertexIndex& atVertex, int& beforeVertex, int& afterVertex) const
{
if(mDirtyWkb)
{
exportGeosToWkb();
}

beforeVertex = -1;
afterVertex = -1;

if (mGeometry)
{
int vertexcounter = 0;

int wkbType;

memcpy(&wkbType, (mGeometry+1), sizeof(int));

switch (wkbType)
{
case QGis::WKBPoint:
{
// NOOP - Points do not have adjacent verticies
break;
}

case QGis::WKBLineString:
{
unsigned char* ptr = mGeometry+5;
int* npoints = (int*) ptr;

const int index = atVertex.back();

// assign the rubber band indices

if(index == 0)
{
beforeVertex = -1;
}
else
{
beforeVertex = index-1;
}

if(index == (*npoints - 1))
{
afterVertex = -1;
}
else
{
afterVertex = index+1;
}

break;
}
case QGis::WKBPolygon:
{
int* nrings=(int*)(mGeometry+5);
int* npoints;
unsigned char* ptr=mGeometry+9;

// Walk through the POLYGON WKB

for (int index0 = 0; index0 < *nrings; ++index0)
{
npoints=(int*)ptr;
ptr+=sizeof(int);

for (int index1 = 0; index1 < *npoints; ++index1)
{
ptr += sizeof(double);
ptr += sizeof(double);

if (vertexcounter == atVertex.back())
// TODO: The above is deprecated as it doesn't allow for multiple linear rings in the polygon.
// replace with the below when the rest of QgsGeometry is migrated to a GEOS back-end.
//if (
// (index0 == atVertex.get_at(0)) &&
// (index1 == atVertex.get_at(1))
// )
{
// Found the vertex of the linear-ring we were looking for.

// assign the rubber band indices

if(index1 == 0)
{
beforeVertex = vertexcounter+(*npoints-2);
afterVertex = vertexcounter+1;
}
else if(index1 == (*npoints-1))
{
beforeVertex = vertexcounter-1;
afterVertex = vertexcounter - (*npoints-2);
}
else
{
beforeVertex = vertexcounter-1;
afterVertex = vertexcounter+1;
}
}

++vertexcounter;
}
}
break;
}

case QGis::WKBMultiPoint:
{
// NOOP - Points do not have adjacent verticies
break;
}

case QGis::WKBMultiLineString:
{
unsigned char* ptr=mGeometry+5;
int* nlines=(int*)ptr;
int* npoints = 0;
ptr+=sizeof(int);

for (int index0 = 0; index0 < *nlines; ++index0)
{
ptr += (sizeof(int) + 1);
npoints = (int*)ptr;
ptr += sizeof(int);

for (int index1 = 0; index1 < *npoints; ++index1)
{
ptr+=sizeof(double);
ptr+=sizeof(double);

if (vertexcounter == atVertex.back())
// TODO: The above is deprecated as it doesn't allow for account for all ends of lines.
// replace with the below when the rest of QgsGeometry is migrated to a GEOS back-end.
//if (
// (index0 == atVertex.get_at(0)) &&
// (index1 == atVertex.get_at(1))
// )
{
// Found the vertex of the linestring we were looking for.

// assign the rubber band indices

if(index1 == 0)
{
beforeVertex = -1;
}
else
{
beforeVertex = vertexcounter-1;
}
if(index1 == (*npoints)-1)
{
afterVertex = -1;
}
else
{
afterVertex = vertexcounter+1;
}
}
++vertexcounter;
}
}

break;
}

case QGis::WKBMultiPolygon:
{
unsigned char* ptr=mGeometry+5;
int* npolys=(int*)ptr;
int* nrings;
int* npoints;
ptr+=sizeof(int);

for (int index0 = 0; index0 < *npolys; ++index0)
{
ptr += (1 + sizeof(int)); //skip endian and polygon type
nrings=(int*)ptr;
ptr+=sizeof(int);

for (int index1 = 0; index1 < *nrings; ++index1)
{
npoints=(int*)ptr;
ptr+=sizeof(int);

for (int index2 = 0; index2 < *npoints; ++index2)
{
ptr += sizeof(double);
ptr += sizeof(double);

if (vertexcounter == atVertex.back())
// TODO: The above is deprecated as it doesn't allow for multiple linear rings in the polygon.
// replace with the below when the rest of QgsGeometry is migrated to a GEOS back-end.
//if (
// (index0 == atVertex.get_at(0)) &&
// (index1 == atVertex.get_at(1)) &&
// (index2 == atVertex.get_at(2))
// )
{
// Found the vertex of the linear-ring of the polygon we were looking for.

// assign the rubber band indices

if(index2 == 0)
{
beforeVertex = vertexcounter+(*npoints-2);
afterVertex = vertexcounter+1;
}
else if(index2 == (*npoints-1))
{
beforeVertex = vertexcounter-1;
afterVertex = vertexcounter - (*npoints-2);
}
else
{
beforeVertex = vertexcounter-1;
afterVertex = vertexcounter+1;
}
}
++vertexcounter;
}
}
}

break;
}

default:
break;
} // switch (wkbType)

} // if (mGeometry)
}



bool QgsGeometry::insertVertexBefore(double x, double y,
int beforeVertex,
@@ -83,10 +83,27 @@ class QgsGeometry {
void setGeos(geos::Geometry* geos);

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


/**
Returns the indexes of the vertices before and after the given vertex index.
This function takes into account the following factors:
1. If the given vertex index is at the end of a linestring,
the adjacent index will be -1 (for "no adjacent vertex")
2. If the given vertex index is at the end of a linear ring
(such as in a polygon), the adjacent index will take into
account the first vertex is equal to the last vertex (and will
skip equal vertex positions).
*/
void adjacentVerticies(const QgsGeometryVertexIndex& atVertex, int& beforeVertex, int& afterVertex) const;


/** Insert a new vertex before the given vertex index,
* ring and item (first number is index 0)
* If the requested vertex number (beforeVertex.back()) is greater
@@ -16,6 +16,8 @@ email : morb at ozemail dot com dot au

#include "qgsgeometryvertexindex.h"

#include <iostream>


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

int QgsGeometryVertexIndex::back()
int QgsGeometryVertexIndex::back() const
{
#ifdef QGISDEBUG
for(std::vector<int>::iterator it = mIndex.begin(); it != mIndex.end(); ++it)
{
qWarning("mIndex contains: "+QString::number(*it));
}
std::cout << "QgsGeometryVertexIndex::back: mIndex contains:";
for(std::vector<int>::const_iterator it = mIndex.begin(); it != mIndex.end(); ++it)
{
std::cout << " " << (*it);
}
std::cout << "." << std::endl;
#endif
return mIndex.back();
}


int QgsGeometryVertexIndex::get_at(int i) const
{
#ifdef QGISDEBUG
std::cout << "QgsGeometryVertexIndex::get_at: mIndex contains:";
for(std::vector<int>::const_iterator it = mIndex.begin(); it != mIndex.end(); ++it)
{
std::cout << " " << (*it);
}
std::cout << "." << std::endl;
#endif
return mIndex[i];
}


void QgsGeometryVertexIndex::clear()
{
mIndex.clear();
@@ -50,10 +50,15 @@ class QgsGeometryVertexIndex {

/** Pushes an int onto the last (rightmost) element of the index */
void push_back(int& i);

/** Gets the last (rightmost) element of the index */
int back();

int back() const;

/** Gets the i'th element of the index.
i=0 refers to the "innermost" line-string or linear-ring.
*/
int get_at(int i) const;

/** Resets the index */
void clear();

0 comments on commit 002e57a

Please sign in to comment.