mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-26 00:02:08 -05:00
fix for bug 1166086 plus consider not commited features in 'zoom to selection'
git-svn-id: http://svn.osgeo.org/qgis/trunk@3018 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
0910cdcd8a
commit
7c29714923
@ -42,7 +42,7 @@ QgsAttributeTableDisplay::QgsAttributeTableDisplay(QgsVectorLayer* layer):QgsAtt
|
||||
|
||||
edit->insertItem(tr("&Add Attribute..."), this, SLOT(addAttribute()), CTRL+Key_A,0);
|
||||
edit->insertItem(tr("&Delete Attributes..."), this, SLOT(deleteAttributes()), CTRL+Key_D,1);
|
||||
selection->insertItem(tr("&Bring selected to top"), this, SLOT(selectedToTop()), CTRL+Key_T);
|
||||
selection->insertItem(tr("&Bring selection to top"), this, SLOT(selectedToTop()), CTRL+Key_T);
|
||||
selection->insertItem(tr("&Invert selection"), this, SLOT(invertSelection()), CTRL+Key_I);
|
||||
mMenuBar->insertItem(tr("&Edit"), edit);
|
||||
mMenuBar->insertItem(tr("&Selection"),selection);
|
||||
|
@ -255,7 +255,7 @@ void QgsFeature::attributeDialog()
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsFeature::intersects(QgsRect* r)
|
||||
bool QgsFeature::intersects(QgsRect* r) const
|
||||
{
|
||||
bool returnval=false;
|
||||
|
||||
@ -532,7 +532,7 @@ bool QgsFeature::exportToWKT() const
|
||||
|
||||
}
|
||||
|
||||
QgsPoint QgsFeature::closestVertex(const QgsPoint& point)
|
||||
QgsPoint QgsFeature::closestVertex(const QgsPoint& point) const
|
||||
{
|
||||
if(geometry)
|
||||
{
|
||||
@ -682,3 +682,213 @@ QgsPoint QgsFeature::closestVertex(const QgsPoint& point)
|
||||
}
|
||||
return QgsPoint(0,0);
|
||||
}
|
||||
|
||||
QgsRect QgsFeature::boundingBox() const
|
||||
{
|
||||
double xmin=DBL_MAX;
|
||||
double ymin=DBL_MAX;
|
||||
double xmax=-DBL_MAX;
|
||||
double ymax=-DBL_MAX;
|
||||
|
||||
double *x;
|
||||
double *y;
|
||||
int *nPoints;
|
||||
int *numRings;
|
||||
int *numPolygons;
|
||||
int numPoints;
|
||||
int numLineStrings;
|
||||
int idx, jdx, kdx;
|
||||
unsigned char *ptr;
|
||||
char lsb;
|
||||
QgsPoint pt;
|
||||
QPointArray *pa;
|
||||
int wkbType;
|
||||
unsigned char *feature;
|
||||
|
||||
feature = this->getGeometry();
|
||||
if(feature)
|
||||
{
|
||||
wkbType=(int) feature[1];
|
||||
switch (wkbType)
|
||||
{
|
||||
case QGis::WKBPoint:
|
||||
x = (double *) (feature + 5);
|
||||
y = (double *) (feature + 5 + sizeof(double));
|
||||
if (*x < xmin)
|
||||
{
|
||||
xmin=*x;
|
||||
}
|
||||
if (*x > xmax)
|
||||
{
|
||||
xmax=*x;
|
||||
}
|
||||
if (*y < ymin)
|
||||
{
|
||||
ymin=*y;
|
||||
}
|
||||
if (*y > ymax)
|
||||
{
|
||||
ymax=*y;
|
||||
}
|
||||
break;
|
||||
|
||||
case QGis::WKBLineString:
|
||||
// get number of points in the line
|
||||
ptr = feature + 5;
|
||||
nPoints = (int *) ptr;
|
||||
ptr = feature + 1 + 2 * sizeof(int);
|
||||
for (idx = 0; idx < *nPoints; idx++)
|
||||
{
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
if (*x < xmin)
|
||||
{
|
||||
xmin=*x;
|
||||
}
|
||||
if (*x > xmax)
|
||||
{
|
||||
xmax=*x;
|
||||
}
|
||||
if (*y < ymin)
|
||||
{
|
||||
ymin=*y;
|
||||
}
|
||||
if (*y > ymax)
|
||||
{
|
||||
ymax=*y;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case QGis::WKBMultiLineString:
|
||||
numLineStrings = (int) (feature[5]);
|
||||
ptr = feature + 9;
|
||||
for (jdx = 0; jdx < numLineStrings; jdx++)
|
||||
{
|
||||
// each of these is a wbklinestring so must handle as such
|
||||
lsb = *ptr;
|
||||
ptr += 5; // skip type since we know its 2
|
||||
nPoints = (int *) ptr;
|
||||
ptr += sizeof(int);
|
||||
for (idx = 0; idx < *nPoints; idx++)
|
||||
{
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
if (*x < xmin)
|
||||
{
|
||||
xmin=*x;
|
||||
}
|
||||
if (*x > xmax)
|
||||
{
|
||||
xmax=*x;
|
||||
}
|
||||
if (*y < ymin)
|
||||
{
|
||||
ymin=*y;
|
||||
}
|
||||
if (*y > ymax)
|
||||
{
|
||||
ymax=*y;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case QGis::WKBPolygon:
|
||||
// get number of rings in the polygon
|
||||
numRings = (int *) (feature + 1 + sizeof(int));
|
||||
ptr = feature + 1 + 2 * sizeof(int);
|
||||
for (idx = 0; idx < *numRings; idx++)
|
||||
{
|
||||
// get number of points in the ring
|
||||
nPoints = (int *) ptr;
|
||||
ptr += 4;
|
||||
for (jdx = 0; jdx < *nPoints; jdx++)
|
||||
{
|
||||
// add points to a point array for drawing the polygon
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
if (*x < xmin)
|
||||
{
|
||||
xmin=*x;
|
||||
}
|
||||
if (*x > xmax)
|
||||
{
|
||||
xmax=*x;
|
||||
}
|
||||
if (*y < ymin)
|
||||
{
|
||||
ymin=*y;
|
||||
}
|
||||
if (*y > ymax)
|
||||
{
|
||||
ymax=*y;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case QGis::WKBMultiPolygon:
|
||||
// get the number of polygons
|
||||
ptr = feature + 5;
|
||||
numPolygons = (int *) ptr;
|
||||
for (kdx = 0; kdx < *numPolygons; kdx++)
|
||||
{
|
||||
//skip the endian and feature type info and
|
||||
// get number of rings in the polygon
|
||||
ptr = feature + 14;
|
||||
numRings = (int *) ptr;
|
||||
ptr += 4;
|
||||
for (idx = 0; idx < *numRings; idx++)
|
||||
{
|
||||
// get number of points in the ring
|
||||
nPoints = (int *) ptr;
|
||||
ptr += 4;
|
||||
for (jdx = 0; jdx < *nPoints; jdx++)
|
||||
{
|
||||
// add points to a point array for drawing the polygon
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
if (*x < xmin)
|
||||
{
|
||||
xmin=*x;
|
||||
}
|
||||
if (*x > xmax)
|
||||
{
|
||||
xmax=*x;
|
||||
}
|
||||
if (*y < ymin)
|
||||
{
|
||||
ymin=*y;
|
||||
}
|
||||
if (*y > ymax)
|
||||
{
|
||||
ymax=*y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef QGISDEBUG
|
||||
std::cout << "UNKNOWN WKBTYPE ENCOUNTERED\n";
|
||||
#endif
|
||||
break;
|
||||
|
||||
}
|
||||
return QgsRect(xmin,ymin,xmax,ymax);
|
||||
}
|
||||
else
|
||||
{
|
||||
return QgsRect(0,0,0,0);
|
||||
}
|
||||
}
|
||||
|
@ -122,10 +122,13 @@ class QgsFeature {
|
||||
void attributeDialog();
|
||||
|
||||
/**Test for intersection with a rectangle (uses GEOS)*/
|
||||
bool intersects(QgsRect* r);
|
||||
bool intersects(QgsRect* r) const;
|
||||
|
||||
/**Returns the Vertex closest to a given point*/
|
||||
QgsPoint closestVertex(const QgsPoint& point);
|
||||
QgsPoint closestVertex(const QgsPoint& point) const;
|
||||
|
||||
/**Returns the bounding box of this feature*/
|
||||
QgsRect boundingBox() const;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -1076,28 +1076,11 @@ void QgsMapCanvas::zoomToSelected()
|
||||
rect = lyr->bBoxOfSelected();
|
||||
}
|
||||
|
||||
// no selected features
|
||||
// XXX where is rectange set to "empty"? Shouldn't we use QgsRect::isEmpty()?
|
||||
if (rect.xMin() == DBL_MAX &&
|
||||
rect.yMin() == DBL_MAX &&
|
||||
rect.xMax() == -DBL_MAX &&
|
||||
rect.yMax() == -DBL_MAX)
|
||||
// no selected features, only one selected point feature
|
||||
//or two point features with the same x- or y-coordinates
|
||||
if(rect.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
//zoom to one single point
|
||||
else if (rect.xMin() == rect.xMax() &&
|
||||
rect.yMin() == rect.yMax())
|
||||
{
|
||||
mCanvasProperties->previousExtent = mCanvasProperties->currentExtent;
|
||||
mCanvasProperties->currentExtent.setXmin(rect.xMin() - 25);
|
||||
mCanvasProperties->currentExtent.setYmin(rect.yMin() - 25);
|
||||
mCanvasProperties->currentExtent.setXmax(rect.xMax() + 25);
|
||||
mCanvasProperties->currentExtent.setYmax(rect.yMax() + 25);
|
||||
emit extentsChanged(mCanvasProperties->currentExtent);
|
||||
clear();
|
||||
render();
|
||||
return;
|
||||
return;
|
||||
}
|
||||
//zoom to an area
|
||||
else
|
||||
|
@ -1033,214 +1033,68 @@ QPopupMenu *QgsVectorLayer::contextMenu()
|
||||
|
||||
QgsRect QgsVectorLayer::bBoxOfSelected()
|
||||
{
|
||||
QgsRect rect(DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX);
|
||||
if(mSelected.size()==0)//no selected features
|
||||
{
|
||||
return QgsRect(0,0,0,0);
|
||||
}
|
||||
|
||||
double xmin=DBL_MAX;
|
||||
double ymin=DBL_MAX;
|
||||
double xmax=-DBL_MAX;
|
||||
double ymax=-DBL_MAX;
|
||||
QgsRect r;
|
||||
QgsFeature* fet;
|
||||
dataProvider->reset();
|
||||
|
||||
QgsFeature *fet;
|
||||
unsigned char *feature;
|
||||
|
||||
double *x;
|
||||
double *y;
|
||||
int *nPoints;
|
||||
int *numRings;
|
||||
int *numPolygons;
|
||||
int numPoints;
|
||||
int numLineStrings;
|
||||
int idx, jdx, kdx;
|
||||
unsigned char *ptr;
|
||||
char lsb;
|
||||
QgsPoint pt;
|
||||
QPointArray *pa;
|
||||
int wkbType;
|
||||
|
||||
while ((fet = dataProvider->getNextFeature(false)))
|
||||
{
|
||||
if (mSelected.find(fet->featureId()) != mSelected.end())
|
||||
{
|
||||
feature = fet->getGeometry();
|
||||
wkbType = (int) feature[1];
|
||||
|
||||
|
||||
switch (wkbType)
|
||||
{
|
||||
case WKBPoint:
|
||||
x = (double *) (feature + 5);
|
||||
y = (double *) (feature + 5 + sizeof(double));
|
||||
if (*x < rect.xMin())
|
||||
{
|
||||
rect.setXmin(*x);
|
||||
}
|
||||
if (*x > rect.xMax())
|
||||
{
|
||||
rect.setXmax(*x);
|
||||
}
|
||||
if (*y < rect.yMin())
|
||||
{
|
||||
rect.setYmin(*y);
|
||||
}
|
||||
if (*y > rect.yMax())
|
||||
{
|
||||
rect.setYmax(*y);
|
||||
}
|
||||
break;
|
||||
|
||||
case WKBLineString:
|
||||
// get number of points in the line
|
||||
ptr = feature + 5;
|
||||
nPoints = (int *) ptr;
|
||||
ptr = feature + 1 + 2 * sizeof(int);
|
||||
for (idx = 0; idx < *nPoints; idx++)
|
||||
{
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
if (*x < rect.xMin())
|
||||
{
|
||||
rect.setXmin(*x);
|
||||
}
|
||||
if (*x > rect.xMax())
|
||||
{
|
||||
rect.setXmax(*x);
|
||||
}
|
||||
if (*y < rect.yMin())
|
||||
{
|
||||
rect.setYmin(*y);
|
||||
}
|
||||
if (*y > rect.yMax())
|
||||
{
|
||||
rect.setYmax(*y);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WKBMultiLineString:
|
||||
numLineStrings = (int) (feature[5]);
|
||||
ptr = feature + 9;
|
||||
for (jdx = 0; jdx < numLineStrings; jdx++)
|
||||
{
|
||||
// each of these is a wbklinestring so must handle as such
|
||||
lsb = *ptr;
|
||||
ptr += 5; // skip type since we know its 2
|
||||
nPoints = (int *) ptr;
|
||||
ptr += sizeof(int);
|
||||
for (idx = 0; idx < *nPoints; idx++)
|
||||
{
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
if (*x < rect.xMin())
|
||||
{
|
||||
rect.setXmin(*x);
|
||||
}
|
||||
if (*x > rect.xMax())
|
||||
{
|
||||
rect.setXmax(*x);
|
||||
}
|
||||
if (*y < rect.yMin())
|
||||
{
|
||||
rect.setYmin(*y);
|
||||
}
|
||||
if (*y > rect.yMax())
|
||||
{
|
||||
rect.setYmax(*y);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WKBPolygon:
|
||||
// get number of rings in the polygon
|
||||
numRings = (int *) (feature + 1 + sizeof(int));
|
||||
ptr = feature + 1 + 2 * sizeof(int);
|
||||
for (idx = 0; idx < *numRings; idx++)
|
||||
{
|
||||
// get number of points in the ring
|
||||
nPoints = (int *) ptr;
|
||||
ptr += 4;
|
||||
for (jdx = 0; jdx < *nPoints; jdx++)
|
||||
{
|
||||
// add points to a point array for drawing the polygon
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
if (*x < rect.xMin())
|
||||
{
|
||||
rect.setXmin(*x);
|
||||
}
|
||||
if (*x > rect.xMax())
|
||||
{
|
||||
rect.setXmax(*x);
|
||||
}
|
||||
if (*y < rect.yMin())
|
||||
{
|
||||
rect.setYmin(*y);
|
||||
}
|
||||
if (*y > rect.yMax())
|
||||
{
|
||||
rect.setYmax(*y);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WKBMultiPolygon:
|
||||
// get the number of polygons
|
||||
ptr = feature + 5;
|
||||
numPolygons = (int *) ptr;
|
||||
for (kdx = 0; kdx < *numPolygons; kdx++)
|
||||
{
|
||||
//skip the endian and feature type info and
|
||||
// get number of rings in the polygon
|
||||
ptr = feature + 14;
|
||||
numRings = (int *) ptr;
|
||||
ptr += 4;
|
||||
for (idx = 0; idx < *numRings; idx++)
|
||||
{
|
||||
// get number of points in the ring
|
||||
nPoints = (int *) ptr;
|
||||
ptr += 4;
|
||||
for (jdx = 0; jdx < *nPoints; jdx++)
|
||||
{
|
||||
// add points to a point array for drawing the polygon
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
if (*x < rect.xMin())
|
||||
{
|
||||
rect.setXmin(*x);
|
||||
}
|
||||
if (*x > rect.xMax())
|
||||
{
|
||||
rect.setXmax(*x);
|
||||
}
|
||||
if (*y < rect.yMin())
|
||||
{
|
||||
rect.setYmin(*y);
|
||||
}
|
||||
if (*y > rect.yMax())
|
||||
{
|
||||
rect.setYmax(*y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef QGISDEBUG
|
||||
std::cout << "UNKNOWN WKBTYPE ENCOUNTERED\n";
|
||||
#endif
|
||||
break;
|
||||
|
||||
}
|
||||
delete[]feature;
|
||||
r=fet->boundingBox();
|
||||
if(r.xMin()<xmin)
|
||||
{
|
||||
xmin=r.xMin();
|
||||
}
|
||||
if(r.yMin()<ymin)
|
||||
{
|
||||
ymin=r.yMin();
|
||||
}
|
||||
if(r.xMax()>xmax)
|
||||
{
|
||||
xmax=r.xMax();
|
||||
}
|
||||
if(r.yMax()>ymax)
|
||||
{
|
||||
ymax=r.yMax();
|
||||
}
|
||||
}
|
||||
delete fet;
|
||||
}
|
||||
return rect;
|
||||
//also go through the not commited features
|
||||
for(std::list<QgsFeature*>::iterator iter=mAddedFeatures.begin();iter!=mAddedFeatures.end();++iter)
|
||||
{
|
||||
if(mSelected.find((*iter)->featureId())!=mSelected.end())
|
||||
{
|
||||
r=(*iter)->boundingBox();
|
||||
if(r.xMin()<xmin)
|
||||
{
|
||||
xmin=r.xMin();
|
||||
}
|
||||
if(r.yMin()<ymin)
|
||||
{
|
||||
ymin=r.yMin();
|
||||
}
|
||||
if(r.xMax()>xmax)
|
||||
{
|
||||
xmax=r.xMax();
|
||||
}
|
||||
if(r.yMax()>ymax)
|
||||
{
|
||||
ymax=r.yMax();
|
||||
}
|
||||
}
|
||||
}
|
||||
return QgsRect(xmin,ymin,xmax,ymax);
|
||||
}
|
||||
|
||||
void QgsVectorLayer::setLayerProperties(QgsDlgVectorLayerProperties * properties)
|
||||
|
@ -133,7 +133,7 @@ public slots:
|
||||
QgsDlgVectorLayerProperties *propertiesDialog();
|
||||
/** Return the context menu for the layer */
|
||||
QPopupMenu *contextMenu();
|
||||
/**Returns the bounding box of the selected features. If there is no selection, the lower bounds are DBL_MAX and the upper bounds -DBL_MAX*/
|
||||
/**Returns the bounding box of the selected features. If there is no selection, QgsRect(0,0,0,0) is returned*/
|
||||
virtual QgsRect bBoxOfSelected();
|
||||
//! Return the provider type for this layer
|
||||
QString providerType();
|
||||
|
Loading…
x
Reference in New Issue
Block a user