mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
- changes to the line and polygon clipping code
- fix bug where clipping fails when zoomed in too far - many minor changes to reduce execution times - general code tidy up - still a bit slower in drawing than desired git-svn-id: http://svn.osgeo.org/qgis/trunk@3102 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
de34b95107
commit
3bbf810f64
@ -22,8 +22,7 @@
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
bool QgsClipper::trimLine(const QgsPoint& from, const QgsPoint& to,
|
||||
QgsPoint& tFrom, QgsPoint& tTo)
|
||||
bool QgsClipper::trimLine(QgsPoint& from, QgsPoint& to)
|
||||
{
|
||||
// To determine the intersection between a line given by the points
|
||||
// A and B, and the line given by the points C and D, calculate
|
||||
@ -57,7 +56,7 @@ bool QgsClipper::trimLine(const QgsPoint& from, const QgsPoint& to,
|
||||
//
|
||||
// Also do a check to see if the line segment is inside or outside
|
||||
// the limits. If outside, return false to let the caller know that
|
||||
// the shouldn't plot the line segment.
|
||||
// it shouldn't plot the line segment.
|
||||
//
|
||||
// This function has more than one exit point - as soon as the code
|
||||
// determines that it has trimmed the lines appropriately, it exits,
|
||||
@ -67,14 +66,12 @@ bool QgsClipper::trimLine(const QgsPoint& from, const QgsPoint& to,
|
||||
// point in doing further checks, so return from the function
|
||||
// if that occurs.
|
||||
bool toDone = false, fromDone = false;
|
||||
QgsPoint trimmedTo = to, trimmedFrom = from;
|
||||
|
||||
// Check for the need to trim first
|
||||
if (from.x() < minX || from.x() > maxX || to.x() < minX || to.x() > maxX ||
|
||||
from.y() < minY || from.y() > maxY || to.y() < minY || to.y() > maxY)
|
||||
{
|
||||
tFrom = from;
|
||||
tTo = to;
|
||||
|
||||
// Check the top boundary
|
||||
double r_n = (from.y() - minY) * (maxX - minX);
|
||||
double dTB = - (to.y() - from.y()) * (maxX - minX);
|
||||
@ -95,14 +92,14 @@ bool QgsClipper::trimLine(const QgsPoint& from, const QgsPoint& to,
|
||||
if (from.y() <= minY) // trim from
|
||||
{
|
||||
fromDone = true;
|
||||
tFrom.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
tFrom.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
trimmedFrom.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
trimmedFrom.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
}
|
||||
else // trim to
|
||||
{
|
||||
toDone = true;
|
||||
tTo.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
tTo.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
trimmedTo.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
trimmedTo.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -126,21 +123,25 @@ bool QgsClipper::trimLine(const QgsPoint& from, const QgsPoint& to,
|
||||
if (from.x() >= maxX) // trim from
|
||||
{
|
||||
fromDone = true;
|
||||
tFrom.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
tFrom.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
trimmedFrom.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
trimmedFrom.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
}
|
||||
else // trim to
|
||||
{
|
||||
toDone = true;
|
||||
tTo.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
tTo.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
trimmedTo.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
trimmedTo.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Done both ends of the line, so leave.
|
||||
if (toDone && fromDone)
|
||||
{
|
||||
to = trimmedTo;
|
||||
from = trimmedFrom;
|
||||
return true;
|
||||
}
|
||||
|
||||
// the left border
|
||||
r_n = - (from.x() - minX) * (maxY - minY);
|
||||
@ -162,21 +163,25 @@ bool QgsClipper::trimLine(const QgsPoint& from, const QgsPoint& to,
|
||||
if (from.x() <= minX) // trim from
|
||||
{
|
||||
fromDone = true;
|
||||
tFrom.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
tFrom.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
trimmedFrom.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
trimmedFrom.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
}
|
||||
else // trim to
|
||||
{
|
||||
toDone = true;
|
||||
tTo.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
tTo.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
trimmedTo.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
trimmedTo.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Done both ends of the line, so leave.
|
||||
if (toDone && fromDone)
|
||||
{
|
||||
to = trimmedTo;
|
||||
from = trimmedFrom;
|
||||
return true;
|
||||
}
|
||||
|
||||
// the bottom border
|
||||
r_n = (from.y() - maxY) * (maxX - minX);
|
||||
@ -197,27 +202,25 @@ bool QgsClipper::trimLine(const QgsPoint& from, const QgsPoint& to,
|
||||
if (from.y() >= maxY) // trim from
|
||||
{
|
||||
fromDone = true;
|
||||
tFrom.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
tFrom.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
trimmedFrom.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
trimmedFrom.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
}
|
||||
else // trim to
|
||||
{
|
||||
toDone = true;
|
||||
tTo.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
tTo.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
trimmedTo.setX(from.x() + r_nOverd*(to.x() - from.x()));
|
||||
trimmedTo.setY(from.y() + r_nOverd*(to.y() - from.y()));
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the line hasn't been trimmed yet, it is entirely outside the
|
||||
// boundary, so tell the calling code.
|
||||
if (!toDone && !fromDone)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The entire line is visible on screen, so do nothing.
|
||||
tFrom = from;
|
||||
tTo = to;
|
||||
{
|
||||
to = trimmedTo;
|
||||
from = trimmedFrom;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Too verbose for QGISDEBUG, but handy sometimes.
|
||||
@ -227,6 +230,9 @@ bool QgsClipper::trimLine(const QgsPoint& from, const QgsPoint& to,
|
||||
<< "Point 2 trimmed from " << to.x() << ", " << to.y()
|
||||
<< " to " << tTo.x() << ", " << tTo.y() << "\n\n";
|
||||
*/
|
||||
to = trimmedTo;
|
||||
from = trimmedFrom;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -241,26 +247,22 @@ bool QgsClipper::trimLine(const QgsPoint& from, const QgsPoint& to,
|
||||
// one (the only?) that is guaranteed to always give the correct
|
||||
// result.
|
||||
|
||||
void QgsClipper::trimPolygon(QPointArray* pa)
|
||||
void QgsClipper::trimPolygon(std::vector<QgsPoint>& polygon)
|
||||
{
|
||||
// std::cerr << "Trimming polygon...\n";
|
||||
// Not the most efficient way - needs to be redone. Efficiency is
|
||||
// important here, so std::vector<> might not be the most
|
||||
// appropriate data structure.
|
||||
|
||||
// Trim the polygon against the four boundaries in turn.
|
||||
QPointArray* tmp = new QPointArray();
|
||||
trimPolygonToBoundary(pa, tmp, Xmax);
|
||||
pa->resize(0);
|
||||
trimPolygonToBoundary(tmp, pa, Ymax);
|
||||
tmp->resize(0);
|
||||
trimPolygonToBoundary(pa, tmp, Xmin);
|
||||
pa->resize(0);
|
||||
trimPolygonToBoundary(tmp, pa, Ymin);
|
||||
delete tmp;
|
||||
/*
|
||||
for (int i = 0; i < pa->size(); ++i)
|
||||
std::cerr << pa->point(i).x() << ", "
|
||||
<< pa->point(i).y() << "; ";
|
||||
std::cerr <<'\n';
|
||||
*/
|
||||
std::vector<QgsPoint> tmp1;
|
||||
std::vector<QgsPoint> tmp2;
|
||||
std::vector<QgsPoint> tmp3;
|
||||
std::vector<QgsPoint> tmp4;
|
||||
|
||||
trimPolygonToBoundary(polygon, tmp1, Xmax);
|
||||
trimPolygonToBoundary(tmp1, tmp2, Ymax);
|
||||
trimPolygonToBoundary(tmp2, tmp3, Xmin);
|
||||
trimPolygonToBoundary(tmp3, tmp4, Ymin);
|
||||
polygon = tmp4;
|
||||
}
|
||||
|
||||
// An auxilary function that is part of the polygon trimming
|
||||
@ -268,64 +270,56 @@ void QgsClipper::trimPolygon(QPointArray* pa)
|
||||
// the trimmed polygon in the out pointer. Uses Sutherland and
|
||||
// Hodgman's polygon-clipping algorithm.
|
||||
|
||||
void QgsClipper::trimPolygonToBoundary(QPointArray* in,
|
||||
QPointArray* out, boundary b)
|
||||
void QgsClipper::trimPolygonToBoundary(const std::vector<QgsPoint>& in,
|
||||
std::vector<QgsPoint>& out, boundary b)
|
||||
{
|
||||
QPoint i;
|
||||
|
||||
int i1 = in->size()-1; // start with last point
|
||||
int i1 = in.size()-1; // start with last point
|
||||
|
||||
// and compare to the first point initially.
|
||||
for (int i2 = 0; i2 < in->size() ; ++i2)
|
||||
{ // look at each edge of the polygon in turn
|
||||
for (int i2 = 0; i2 < in.size() ; ++i2)
|
||||
{ // look at each edge of the polygon in turn
|
||||
if (inside(in, i2, b)) // end point of edge is inside boundary
|
||||
{
|
||||
if (inside(in, i1, b)) // edge is entirely inside boundary, so pass-thru
|
||||
out->putPoints(out->size(), 1, in->point(i2).x(), in->point(i2).y());
|
||||
out.push_back(in[i2]);
|
||||
else
|
||||
{
|
||||
// edge crosses into the boundary, so trim back to the boundary, and
|
||||
// store both ends of the new edge
|
||||
i = intersect(in, i1, i2, b);
|
||||
out->putPoints(out->size(), 1, i.x(), i.y());
|
||||
out->putPoints(out->size(), 1, in->point(i2).x(), in->point(i2).y());
|
||||
out.push_back( intersect(in, i1, i2, b) );
|
||||
out.push_back( in[i2] );
|
||||
}
|
||||
}
|
||||
else // end point of edge is outside boundary
|
||||
{
|
||||
if (inside(in, i1, b))
|
||||
{ // start point is in boundary, so need to trim back
|
||||
i = intersect(in, i1, i2, b);
|
||||
out->putPoints(out->size(), 1, i.x(), i.y());
|
||||
}
|
||||
if (inside(in, i1, b)) // start point is in boundary, so need to trim back
|
||||
out.push_back( intersect(in, i1, i2, b) );
|
||||
}
|
||||
i1 = i2;
|
||||
}
|
||||
// std::cerr << in->size() << " -> " << out->size() << '\n';
|
||||
}
|
||||
|
||||
|
||||
// An auxilary function to trimPolygonToBoundarY() that returns
|
||||
// whether a point is inside or outside the given boundary.
|
||||
|
||||
bool QgsClipper::inside(QPointArray* pa, int p, boundary b)
|
||||
bool QgsClipper::inside(const std::vector<QgsPoint>& pa, int p, boundary b)
|
||||
{
|
||||
switch (b)
|
||||
{
|
||||
case Xmax: // x < maxX is inside
|
||||
if ((pa->point(p)).x() < maxX)
|
||||
if ((pa[p]).x() < maxX)
|
||||
return true;
|
||||
break;
|
||||
case Xmin: // x > minX is inside
|
||||
if ((pa->point(p)).x() > minX)
|
||||
if ((pa[p]).x() > minX)
|
||||
return true;
|
||||
break;
|
||||
case Ymax: // y < maxY is inside
|
||||
if ((pa->point(p)).y() < maxY)
|
||||
if ((pa[p]).y() < maxY)
|
||||
return true;
|
||||
break;
|
||||
case Ymin: // y > minY is inside
|
||||
if ((pa->point(p)).y() > minY)
|
||||
if ((pa[p]).y() > minY)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
@ -337,21 +331,15 @@ bool QgsClipper::inside(QPointArray* pa, int p, boundary b)
|
||||
// returns the intersection of the line defined by the given points
|
||||
// and the given boundary.
|
||||
|
||||
QPoint QgsClipper::intersect(QPointArray* pa, int i1, int i2, boundary b)
|
||||
QgsPoint QgsClipper::intersect(const std::vector<QgsPoint>& pa, int i1, int i2, boundary b)
|
||||
{
|
||||
// This function assumes that the two given points cross the given
|
||||
// boundary. Making this assumption allows some optimisations.
|
||||
|
||||
QPoint p1 = pa->point(i1);
|
||||
QPoint p2 = pa->point(i2);
|
||||
QPoint p;
|
||||
QgsPoint p1 = pa[i1];
|
||||
QgsPoint p2 = pa[i2];
|
||||
double r_n, r_d;
|
||||
|
||||
/*
|
||||
std::cerr << pa->point(i1).x() << ", " << pa->point(i1).y() << ", "
|
||||
<< pa->point(i2).x() << ", " << pa->point(i2).y() << '\n';
|
||||
*/
|
||||
|
||||
switch (b)
|
||||
{
|
||||
case Xmax: // x = maxX boundary
|
||||
@ -372,11 +360,12 @@ QPoint QgsClipper::intersect(QPointArray* pa, int i1, int i2, boundary b)
|
||||
break;
|
||||
}
|
||||
|
||||
QgsPoint p;
|
||||
|
||||
if (std::abs(r_d) > SMALL_NUM && std::abs(r_n) > SMALL_NUM)
|
||||
{ // they cross
|
||||
double r = r_n / r_d;
|
||||
p.setX(static_cast<int>(round(p1.x() + r*(p2.x() - p1.x()))));
|
||||
p.setY(static_cast<int>(round(p1.y() + r*(p2.y() - p1.y()))));
|
||||
p.set(p1.x() + r*(p2.x() - p1.x()), p1.y() + r*(p2.y() - p1.y()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "qgspoint.h"
|
||||
#include "qpointarray.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
// The functions in this class are likely to be called from within a
|
||||
// render loop and hence need to as CPU efficient as possible.
|
||||
|
||||
@ -53,27 +55,28 @@ class QgsClipper
|
||||
|
||||
// Trims the given line segment to a rectangular box. Returns the
|
||||
// trimmed line segement in tFrom and tTo.
|
||||
static bool trimLine(const QgsPoint& from, const QgsPoint& to,
|
||||
QgsPoint& tFrom, QgsPoint& tTo);
|
||||
static bool trimLine(QgsPoint& from, QgsPoint& to);
|
||||
|
||||
// Trims the given polygon to a rectangular box. Returns the trimmed
|
||||
// polygon in the given QPointArray.
|
||||
static void trimPolygon(QPointArray* pa);
|
||||
// static void trimPolygon(QPointArray* pa);
|
||||
|
||||
static void trimPolygon(std::vector<QgsPoint>& polygon);
|
||||
|
||||
private:
|
||||
|
||||
// Trims the given polygon to the given boundary. Returns the
|
||||
// trimmed polygon in the out pointer.
|
||||
static void trimPolygonToBoundary(QPointArray* in,
|
||||
QPointArray* out,
|
||||
static void trimPolygonToBoundary(const std::vector<QgsPoint>& in,
|
||||
std::vector<QgsPoint>& out,
|
||||
boundary b);
|
||||
|
||||
// Determines if a point is inside or outside a boundary
|
||||
static bool inside(QPointArray* pa, int p, boundary b);
|
||||
static bool inside(const std::vector<QgsPoint>& pa, int p, boundary b);
|
||||
|
||||
// Calculates the intersection point between a line defined by a
|
||||
// line segment and a boundary
|
||||
static QPoint intersect(QPointArray* pa, int i1, int i2, boundary b);
|
||||
static QgsPoint intersect(const std::vector<QgsPoint>& pa, int i1, int i2, boundary b);
|
||||
|
||||
};
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
// for htonl
|
||||
#ifdef WIN32
|
||||
@ -408,7 +409,6 @@ void QgsVectorLayer::draw(QPainter * p, QgsRect * viewExtent, QgsMapToPixel * th
|
||||
int numLineStrings;
|
||||
int idx, jdx, kdx;
|
||||
unsigned char *ptr;
|
||||
char lsb;
|
||||
QgsPoint pt;
|
||||
QPointArray *pa;
|
||||
int wkbType;
|
||||
@ -2091,46 +2091,43 @@ bool QgsVectorLayer::snapPoint(QgsPoint& point, double tolerance)
|
||||
void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * theMapToPixelTransform,
|
||||
QPicture* marker, double markerScaleFactor, bool projectionsEnabledFlag)
|
||||
{
|
||||
unsigned char *feature;
|
||||
bool attributesneeded = m_renderer->needsAttributes();
|
||||
// Only have variables, etc outside the switch() statement that are
|
||||
// used in all cases of the statement (otherwise they may get
|
||||
// executed, but never used, in a bit of code where performance is
|
||||
// critical).
|
||||
|
||||
double *x;
|
||||
double *y;
|
||||
int wkbType;
|
||||
QgsPoint pt,myProjectedPoint;
|
||||
QgsPoint ptFrom, ptTo;
|
||||
QgsPoint trimmedFrom, trimmedTo;
|
||||
#if defined(Q_WS_X11)
|
||||
bool needToTrim = false;
|
||||
#endif
|
||||
|
||||
unsigned char* feature = fet->getGeometry();
|
||||
|
||||
QPen pen;
|
||||
|
||||
feature = fet->getGeometry();
|
||||
|
||||
unsigned int wkbType;
|
||||
memcpy(&wkbType, (feature+1), sizeof(wkbType));
|
||||
|
||||
switch (wkbType)
|
||||
{
|
||||
case WKBPoint:
|
||||
{
|
||||
x = (double *) (feature + 5);
|
||||
y = (double *) (feature + 5 + sizeof(double));
|
||||
QgsPoint myProjectedPoint;
|
||||
double *x = (double *) (feature + 5);
|
||||
double *y = (double *) (feature + 5 + sizeof(double));
|
||||
// std::cout << "transforming point\n";
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
QgsPoint pt(*x, *y);
|
||||
if (projectionsEnabledFlag)
|
||||
{
|
||||
//reproject the point to the map coordinate system
|
||||
try {
|
||||
myProjectedPoint=mCoordinateTransform->transform(pt);
|
||||
}
|
||||
catch (QgsCsException &e)
|
||||
{
|
||||
qDebug( "Transform error caught in %s line %d:\n%s", __FILE__, __LINE__, e.what());
|
||||
}
|
||||
//transform from projected coordinate system to pixel position on map canvas
|
||||
try
|
||||
{
|
||||
myProjectedPoint=mCoordinateTransform->transform(pt);
|
||||
}
|
||||
catch (QgsCsException &e)
|
||||
{
|
||||
qDebug( "Transform error caught in %s line %d:\n%s",
|
||||
__FILE__, __LINE__, e.what());
|
||||
}
|
||||
// transform from projected coordinate system to pixel position
|
||||
// on map canvas
|
||||
theMapToPixelTransform->transform(&myProjectedPoint);
|
||||
}
|
||||
else
|
||||
@ -2142,40 +2139,45 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
//
|
||||
p->save();
|
||||
p->scale(markerScaleFactor,markerScaleFactor);
|
||||
p->drawPicture((int)(static_cast<int>(myProjectedPoint.x()) / markerScaleFactor - marker->boundingRect().x() - marker->boundingRect().width() / 2),
|
||||
(int)(static_cast<int>(myProjectedPoint.y()) / markerScaleFactor - marker->boundingRect().y() - marker->boundingRect().height() / 2),
|
||||
p->drawPicture((int)(static_cast<int>(myProjectedPoint.x())
|
||||
/ markerScaleFactor - marker->boundingRect().x()
|
||||
- marker->boundingRect().width() / 2),
|
||||
(int)(static_cast<int>(myProjectedPoint.y())
|
||||
/ markerScaleFactor - marker->boundingRect().y()
|
||||
- marker->boundingRect().height() / 2),
|
||||
*marker);
|
||||
p->restore();
|
||||
|
||||
// p->resetXForm(); // Don't use this, some transformations must be keept !
|
||||
|
||||
break;
|
||||
}
|
||||
case WKBMultiPoint:
|
||||
{
|
||||
std::cerr << "Qgis doesn't draw multipoints yet.\n";
|
||||
|
||||
break;
|
||||
}
|
||||
case WKBLineString:
|
||||
{
|
||||
unsigned char *ptr;
|
||||
int *nPoints;
|
||||
int idx;
|
||||
#if defined(Q_WS_X11)
|
||||
needToTrim = false;
|
||||
#endif
|
||||
|
||||
// get number of points in the line
|
||||
ptr = feature + 5;
|
||||
nPoints = (int *) ptr;
|
||||
QgsPoint ptFrom, ptTo;
|
||||
unsigned char *ptr = feature + 5;
|
||||
unsigned int nPoints = *((int*)ptr);
|
||||
ptr = feature + 1 + 2 * sizeof(int);
|
||||
for (idx = 0; idx < *nPoints; idx++)
|
||||
double *x, *y;
|
||||
|
||||
for (unsigned int idx = 0; idx < nPoints; idx++)
|
||||
{
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
// transform the point
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
QgsPoint pt(*x, *y);
|
||||
if (projectionsEnabledFlag)
|
||||
{
|
||||
//reproject the point to the map coordinate system
|
||||
// reproject the point to the map coordinate system
|
||||
try
|
||||
{
|
||||
ptTo=mCoordinateTransform->transform(pt);
|
||||
@ -2185,18 +2187,17 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
qDebug( "Transform error caught in %s line %d:\n%s",
|
||||
__FILE__, __LINE__, e.what());
|
||||
}
|
||||
//transform from projected coordinate system to pixel
|
||||
// transform from projected coordinate system to pixel
|
||||
// position on map canvas
|
||||
theMapToPixelTransform->transform(&ptTo);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptTo=theMapToPixelTransform->transform(pt);
|
||||
//std::cerr << theMapToPixelTransform->showParameters() << '\n';
|
||||
}
|
||||
#if defined(Q_WS_X11)
|
||||
if (std::abs(ptTo.x()) > QgsClipper::maxX ||
|
||||
std::abs(ptTo.y()) > QgsClipper::maxY)
|
||||
if (std::abs(ptTo.x()) > QgsClipper::maxX ||
|
||||
std::abs(ptTo.y()) > QgsClipper::maxY)
|
||||
needToTrim = true;
|
||||
#endif
|
||||
if (idx == 0)
|
||||
@ -2207,11 +2208,11 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
// Work around a +/- 32768 limitation on coordinates in X11
|
||||
if (needToTrim)
|
||||
{
|
||||
if (QgsClipper::trimLine(ptFrom, ptTo, trimmedFrom, trimmedTo))
|
||||
p->drawLine(static_cast<int>(trimmedFrom.x()),
|
||||
static_cast<int>(trimmedFrom.y()),
|
||||
static_cast<int>(trimmedTo.x()),
|
||||
static_cast<int>(trimmedTo.y()));
|
||||
if (QgsClipper::trimLine(ptFrom, ptTo))
|
||||
p->drawLine(static_cast<int>(ptFrom.x()),
|
||||
static_cast<int>(ptFrom.y()),
|
||||
static_cast<int>(ptTo.x()),
|
||||
static_cast<int>(ptTo.y()));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -2226,32 +2227,25 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
}
|
||||
case WKBMultiLineString:
|
||||
{
|
||||
unsigned char *ptr;
|
||||
int idx, jdx, numLineStrings;
|
||||
int *nPoints;
|
||||
char lsb;
|
||||
#if defined(Q_WS_X11)
|
||||
needToTrim = false;
|
||||
#endif
|
||||
QgsPoint pt, ptFrom, ptTo;
|
||||
unsigned int numLineStrings = *((int*)feature[5]);
|
||||
unsigned char *ptr = feature + 9;
|
||||
double *x, *y;
|
||||
|
||||
numLineStrings = (int) (feature[5]);
|
||||
ptr = feature + 9;
|
||||
for (jdx = 0; jdx < numLineStrings; jdx++)
|
||||
for (unsigned int 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 += 5; // skip type since we know it's 2
|
||||
unsigned int nPoints = *((int*)ptr);
|
||||
ptr += sizeof(int);
|
||||
for (idx = 0; idx < *nPoints; idx++)
|
||||
for (unsigned int idx = 0; idx < nPoints; idx++)
|
||||
{
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
// transform the point
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
pt.set(*x, *y);
|
||||
if (projectionsEnabledFlag)
|
||||
{
|
||||
//reproject the point to the map coordinate system
|
||||
@ -2273,8 +2267,8 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
ptTo=theMapToPixelTransform->transform(pt);
|
||||
}
|
||||
#if defined(Q_WS_X11)
|
||||
if (std::abs(ptTo.x()) > QgsClipper::maxX ||
|
||||
std::abs(ptTo.y()) > QgsClipper::maxY)
|
||||
if (std::abs(ptTo.x()) > QgsClipper::maxX ||
|
||||
std::abs(ptTo.y()) > QgsClipper::maxY)
|
||||
needToTrim = true;
|
||||
#endif
|
||||
if (idx == 0)
|
||||
@ -2284,13 +2278,11 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
#if defined(Q_WS_X11)
|
||||
// Work around a +/- 32768 limitation on coordinates in X11
|
||||
if (needToTrim)
|
||||
{
|
||||
if(QgsClipper::trimLine(ptFrom, ptTo, trimmedFrom, trimmedTo))
|
||||
p->drawLine(static_cast<int>(trimmedFrom.x()),
|
||||
static_cast<int>(trimmedFrom.y()),
|
||||
static_cast<int>(trimmedTo.x()),
|
||||
static_cast<int>(trimmedTo.y()));
|
||||
}
|
||||
if (QgsClipper::trimLine(ptFrom, ptTo))
|
||||
p->drawLine(static_cast<int>(ptFrom.x()),
|
||||
static_cast<int>(ptFrom.y()),
|
||||
static_cast<int>(ptTo.x()),
|
||||
static_cast<int>(ptTo.y()));
|
||||
else
|
||||
#endif
|
||||
p->drawLine(static_cast<int>(ptFrom.x()),
|
||||
@ -2304,63 +2296,49 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
break;
|
||||
}
|
||||
case WKBPolygon:
|
||||
|
||||
{
|
||||
unsigned char *ptr;
|
||||
int idx, jdx;
|
||||
int *numRings, *nPoints;
|
||||
QPointArray *pa;
|
||||
#if defined(Q_WS_X11)
|
||||
needToTrim = false;
|
||||
#endif
|
||||
|
||||
double *x, *y;
|
||||
// get number of rings in the polygon
|
||||
numRings = (int *) (feature + 1 + sizeof(int));
|
||||
unsigned int numRings = *((int*)(feature + 1 + sizeof(int)));
|
||||
|
||||
if ( ! *numRings ) // sanity check for zero rings in polygon
|
||||
if ( numRings == 0 ) // sanity check for zero rings in polygon
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int *ringStart; // index of first point for each ring
|
||||
int *ringNumPoints; // number of points in each ring
|
||||
ringStart = new int[*numRings];
|
||||
ringNumPoints = new int[*numRings];
|
||||
// index of first point for each ring
|
||||
unsigned int *ringStart = new unsigned int[numRings];
|
||||
// number of points in each ring
|
||||
unsigned int *ringNumPoints = new unsigned int[numRings];
|
||||
|
||||
int x0, y0, pdx;
|
||||
pdx = 0;
|
||||
ptr = feature + 1 + 2 * sizeof(int); // set pointer to the first ring
|
||||
for (idx = 0; idx < *numRings; idx++)
|
||||
std::vector<QgsPoint> polygon;
|
||||
int pdx = 0;
|
||||
QgsPoint pt, outerRingPt, myProjectedPoint;
|
||||
|
||||
unsigned char* ptr = feature + 1 + 2 * sizeof(int); // set pointer to the first ring
|
||||
for (unsigned int idx = 0; idx < numRings; idx++)
|
||||
{
|
||||
// get number of points in the ring
|
||||
nPoints = (int *) ptr;
|
||||
int nPoints = *((int*)ptr);
|
||||
ringStart[idx] = pdx;
|
||||
ringNumPoints[idx] = *nPoints;
|
||||
ringNumPoints[idx] = nPoints;
|
||||
ptr += 4;
|
||||
if ( idx == 0 )
|
||||
{
|
||||
pa = new QPointArray(*nPoints);
|
||||
}
|
||||
else
|
||||
{
|
||||
// better to calc size for all rings before?
|
||||
pa->resize ( pa->size() + *nPoints + 1 );
|
||||
}
|
||||
for (jdx = 0; jdx < *nPoints; jdx++)
|
||||
|
||||
// better to calc size for all rings before?
|
||||
polygon.resize(polygon.size() + nPoints + 1);
|
||||
|
||||
for (unsigned int jdx = 0; jdx < nPoints; jdx++)
|
||||
{
|
||||
// add points to a point array for drawing the polygon
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
#ifdef QGISX11DEBUG
|
||||
std::cout << "Transforming " << *x << "," << *y << " to ";
|
||||
#endif
|
||||
ptr += sizeof(double);
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
pt.set(*x, *y);
|
||||
|
||||
if (projectionsEnabledFlag)
|
||||
{
|
||||
//reproject the point to the map coordinate system
|
||||
// reproject the point to the map coordinate system
|
||||
try
|
||||
{
|
||||
myProjectedPoint=mCoordinateTransform->transform(pt);
|
||||
@ -2370,7 +2348,7 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
qDebug( "Transform error caught in %s line %d:\n%s",
|
||||
__FILE__, __LINE__, e.what());
|
||||
}
|
||||
//transform from projected coordinate system to pixel
|
||||
// transform from projected coordinate system to pixel
|
||||
// position on map canvas
|
||||
theMapToPixelTransform->transform(&myProjectedPoint);
|
||||
}
|
||||
@ -2383,30 +2361,35 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
std::abs(myProjectedPoint.y()) > QgsClipper::maxY)
|
||||
needToTrim = true;
|
||||
#endif
|
||||
pa->setPoint(pdx++, static_cast<int>(myProjectedPoint.x()),
|
||||
static_cast<int>(myProjectedPoint.y()));
|
||||
polygon[pdx++] = myProjectedPoint;
|
||||
}
|
||||
if ( idx == 0 )
|
||||
{ // remember last outer ring point
|
||||
x0 = static_cast<int>(myProjectedPoint.x());
|
||||
y0 = static_cast<int>(myProjectedPoint.y());
|
||||
outerRingPt = myProjectedPoint;
|
||||
}
|
||||
else
|
||||
{ // return to x0,y0 (inner rings - islands)
|
||||
pa->setPoint(pdx++, x0, y0);
|
||||
polygon[pdx++] = outerRingPt;
|
||||
}
|
||||
}
|
||||
|
||||
// draw the polygon fill
|
||||
pen = p->pen(); // store current pen
|
||||
QPen pen = p->pen(); // store current pen
|
||||
p->setPen ( Qt::NoPen ); // no boundary
|
||||
#if defined(Q_WS_X11)
|
||||
// Work around a +/- 32768 limitation on coordinates in X11
|
||||
if (needToTrim)
|
||||
QgsClipper::trimPolygon(pa);
|
||||
QgsClipper::trimPolygon(polygon);
|
||||
#endif
|
||||
|
||||
QPointArray *pa = new QPointArray(polygon.size());
|
||||
for (int i = 0; i < polygon.size(); ++i)
|
||||
pa->setPoint(i, static_cast<int>(round(polygon[i].x())),
|
||||
static_cast<int>(round(polygon[i].y())));
|
||||
|
||||
p->drawPolygon(*pa);
|
||||
|
||||
/*
|
||||
// draw outline
|
||||
p->setPen ( pen );
|
||||
p->setBrush ( Qt::NoBrush );
|
||||
@ -2414,7 +2397,7 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
{
|
||||
p->drawPolygon( *pa, FALSE, ringStart[idx], ringNumPoints[idx]);
|
||||
}
|
||||
|
||||
*/
|
||||
delete pa;
|
||||
delete [] ringStart;
|
||||
delete [] ringNumPoints;
|
||||
@ -2424,32 +2407,27 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
}
|
||||
case WKBMultiPolygon:
|
||||
{
|
||||
unsigned char *ptr;
|
||||
int idx, jdx, kdx;
|
||||
int *numPolygons, *numRings, *nPoints;
|
||||
QPointArray *pa;
|
||||
|
||||
QgsPoint pt, myProjectedPoint;
|
||||
double *x, *y;
|
||||
unsigned char *ptr = feature + 5;
|
||||
// get the number of polygons
|
||||
ptr = feature + 5;
|
||||
numPolygons = (int *) ptr;
|
||||
unsigned int numPolygons = *((int*)ptr);
|
||||
ptr = feature + 9;
|
||||
for (kdx = 0; kdx < *numPolygons; kdx++)
|
||||
for (int kdx = 0; kdx < numPolygons; kdx++)
|
||||
{
|
||||
//skip the endian and feature type info and
|
||||
// skip the endian and feature type info and
|
||||
// get number of rings in the polygon
|
||||
ptr+=5;
|
||||
numRings = (int *) ptr;
|
||||
ptr += 5;
|
||||
unsigned int numRings = *((int*)ptr);
|
||||
ptr += 4;
|
||||
for (idx = 0; idx < *numRings; idx++)
|
||||
for (unsigned int idx = 0; idx < numRings; idx++)
|
||||
{
|
||||
// get number of points in the ring
|
||||
nPoints = (int *) ptr;
|
||||
unsigned int nPoints = *((int*)ptr);
|
||||
ptr += 4;
|
||||
#if defined(Q_WS_X11)
|
||||
needToTrim = false;
|
||||
#endif
|
||||
pa = new QPointArray(*nPoints);
|
||||
for (jdx = 0; jdx < *nPoints; jdx++)
|
||||
std::vector<QgsPoint> polygon(nPoints);
|
||||
|
||||
for (unsigned int jdx = 0; jdx < nPoints; jdx++)
|
||||
{
|
||||
// add points to a point array for drawing the polygon
|
||||
x = (double *) ptr;
|
||||
@ -2459,11 +2437,10 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
#ifdef QGISX11DEBUG
|
||||
std::cout << "Transforming " << *x << "," << *y << " to ";
|
||||
#endif
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
pt.set(*x, *y);
|
||||
if (projectionsEnabledFlag)
|
||||
{
|
||||
//reproject the point to the map coordinate system
|
||||
// reproject the point to the map coordinate system
|
||||
try
|
||||
{
|
||||
myProjectedPoint=mCoordinateTransform->transform(pt);
|
||||
@ -2473,7 +2450,7 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
qDebug( "Transform error caught in %s line %d:\n%s",
|
||||
__FILE__, __LINE__, e.what());
|
||||
}
|
||||
//transform from projected coordinate system to
|
||||
// transform from projected coordinate system to
|
||||
// pixel position on map canvas
|
||||
theMapToPixelTransform->transform(&myProjectedPoint);
|
||||
}
|
||||
@ -2485,16 +2462,21 @@ void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsMapToPixel * t
|
||||
if (std::abs(myProjectedPoint.x()) > QgsClipper::maxX ||
|
||||
std::abs(myProjectedPoint.y()) > QgsClipper::maxY)
|
||||
needToTrim = true;
|
||||
|
||||
#endif
|
||||
pa->setPoint(jdx, static_cast<int>(myProjectedPoint.x()),
|
||||
static_cast<int>(myProjectedPoint.y()));
|
||||
polygon[jdx] = myProjectedPoint;
|
||||
}
|
||||
// draw the ring
|
||||
#if defined(Q_WS_X11)
|
||||
// Work around a +/- 32768 limitation on coordinates in X11
|
||||
if (needToTrim)
|
||||
QgsClipper::trimPolygon(pa);
|
||||
QgsClipper::trimPolygon(polygon);
|
||||
#endif
|
||||
QPointArray *pa = new QPointArray(polygon.size());
|
||||
for (int i = 0; i < polygon.size(); ++i)
|
||||
pa->setPoint(i, static_cast<int>(round(polygon[i].x())),
|
||||
static_cast<int>(round(polygon[i].y())));
|
||||
|
||||
p->drawPolygon(*pa);
|
||||
delete pa;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user