107void QGeoMapPolygonGeometry::updateSourcePoints(
const QGeoMap &map,
108 const QList<QList <QDoubleVector2D>> &basePaths,
109 MapBorderBehaviour wrapping)
115 const QGeoProjectionWebMercator &p =
static_cast<
const QGeoProjectionWebMercator&>(map.geoProjection());
116 srcPath_ = QPainterPath();
117 srcOrigin_ = p.mapProjectionToGeo(QDoubleVector2D(0.0, 0.0));
118 const QRectF cameraRect = QDeclarativeGeoMapItemUtils::boundingRectangleFromList(p.visibleGeometry());
120 QList<QList<QDoubleVector2D>> paths;
122 if (wrapping == WrapAround) {
125 paths.reserve(basePaths.size());
126 for (qsizetype j = 0; j< basePaths.size(); j++) {
127 const QList<QDoubleVector2D> &bp = basePaths[j];
130 paths << QList<QDoubleVector2D>({bp[0]});
131 QList<QDoubleVector2D> &pp = paths[j];
132 pp.reserve(bp.size());
133 for (qsizetype i = 1; i < bp.size(); i++) {
134 if (bp[i].x() > pp.last().x() + 0.5)
135 pp << bp[i] - QDoubleVector2D(1.0, 0.0);
136 else if (bp[i].x() < pp.last().x() - 0.5)
137 pp << bp[i] + QDoubleVector2D(1.0, 0.0);
144 for (qsizetype j = 0; j < paths.size(); j++) {
145 QList<QDoubleVector2D> &pp = paths[j];
147 if (pp.last().x() - pp.first().x() < -0.5) {
148 for (qsizetype i = 0; i < floor(pp.length()/2.); i++)
149 pp.swapItemsAt(i, pp.length() - i - 1);
151 if (pp.last().x() - pp.first().x() > 0.5) {
153 const double leftBorder = cameraRect.left();
154 const double rightBorder = cameraRect.right();
156 qsizetype originalPathLength = pp.length();
158 if (pp.last().x() < rightBorder) {
159 for (qsizetype i = 0; i < originalPathLength; i++)
160 pp.append(pp[i] + QDoubleVector2D(1.0, 0.0));
162 if (pp.first().x() > leftBorder) {
163 for (qsizetype i = 0; i < originalPathLength; i++)
164 pp.insert(i, pp[2*i] - QDoubleVector2D(1.0, 0.0));
166 const double newPoleLat = (pp.first().y() + pp.last().y() < 1.0) ? 0.0 : 1.0;
167 const QDoubleVector2D P1 = pp.first();
168 const QDoubleVector2D P2 = pp.last();
169 pp.push_front(QDoubleVector2D(P1.x(), newPoleLat));
170 pp.append(QDoubleVector2D(P2.x(), newPoleLat));
182 QList<QList<QDoubleVector2D>> wrappedPaths;
184 if (wrapping == Duplicate || wrapping == WrapAround) {
186 for (
const auto &path : paths)
187 itemRect |= QDeclarativeGeoMapItemUtils::boundingRectangleFromList(path);
189 for (
double xoffset : {-1.0, 0.0, 1.0}) {
190 if (!cameraRect.intersects(itemRect.translated(QPointF(xoffset, 0.0))))
192 for (
const auto &path : paths) {
193 wrappedPaths.append(QList<QDoubleVector2D>());
194 QList<QDoubleVector2D> &wP = wrappedPaths.last();
195 wP.reserve(path.size());
196 for (
const QDoubleVector2D &coord : path)
197 wP.append(coord+QDoubleVector2D(xoffset, 0.0));
201 wrappedPaths = paths;
204 if (wrappedPaths.isEmpty())
209 QList<QList<QDoubleVector2D>> clippedPaths;
210 const QList<QDoubleVector2D> &visibleRegion = p.visibleGeometryExpanded();
211 for (
const auto &path : wrappedPaths) {
212 if (visibleRegion.size()) {
213 QClipperUtils clipper;
214 clipper.addSubjectPath(path,
true);
215 clipper.addClipPolygon(visibleRegion);
216 clippedPaths << clipper.execute(QClipperUtils::Intersection, QClipperUtils::pftEvenOdd,
217 QClipperUtils::pftEvenOdd);
220 clippedPaths.append(path);
223 if (clippedPaths.isEmpty())
227 for (
const auto &path: clippedPaths)
228 bb |= QDeclarativeGeoMapItemUtils::boundingRectangleFromList(path);
230 srcOrigin_ = p.mapProjectionToGeo(QDoubleVector2D(bb.left(), bb.top()));
231 QDoubleVector2D origin = p.wrappedMapProjectionToItemPosition(p.geoToWrappedMapProjection(srcOrigin_));
233 for (
const auto &path: clippedPaths) {
234 QDoubleVector2D prevPoint = p.wrappedMapProjectionToItemPosition(path.at(0)) - origin;
235 QDoubleVector2D nextPoint = p.wrappedMapProjectionToItemPosition(path.at(1)) - origin;
236 srcPath_.moveTo(prevPoint.toPointF());
237 maxCoord_ = qMax(maxCoord_, qMax(prevPoint.x(), prevPoint.y()));
238 qsizetype pointsAdded = 1;
239 for (qsizetype i = 1; i < path.size(); ++i) {
240 const QDoubleVector2D point = nextPoint;
242 if (qMax(point.x(), point.y()) > maxCoord_)
243 maxCoord_ = qMax(point.x(), point.y());
245 if (i == path.size() - 1) {
246 srcPath_.lineTo(point.toPointF());
248 nextPoint = p.wrappedMapProjectionToItemPosition(path.at(i+1)) - origin;
250 bool addPoint = ( i > pointsAdded * 10 ||
253 const double tolerance = 0.1;
255 const double dsqr = QDeclarativeGeoMapItemUtils::distanceSqrPointLine(
256 point.x(), point.y(),
257 nextPoint.x(), nextPoint.y(),
258 prevPoint.x(), prevPoint.y());
259 addPoint = addPoint || (dsqr > (tolerance*tolerance));
263 srcPath_.lineTo(point.toPointF());
270 srcPath_.closeSubpath();
274 srcPath_ = srcPath_.simplified();
276 sourceBounds_ = srcPath_.boundingRect();
310void QDeclarativePolygonMapItemPrivateCPU::updatePolish()
312 if (m_poly.m_geopoly.perimeter().length() == 0) {
316 m_shape->setVisible(
false);
319 const QGeoMap *map = m_poly.map();
320 const qreal borderWidth = m_poly.m_border.width();
321 QScopedValueRollback<
bool> rollback(m_poly.m_updatingGeometry);
322 m_poly.m_updatingGeometry =
true;
324 m_geometry.updateSourcePoints(*map, m_geopathProjected,
325 m_poly.referenceSurface() == QLocation::ReferenceSurface::Globe ?
326 QGeoMapPolygonGeometry::WrapAround :
327 QGeoMapPolygonGeometry::Duplicate);
329 const QRectF bb = m_geometry.sourceBoundingBox();
331 m_poly.setShapeTriangulationScale(m_shape, m_geometry.maxCoord());
333 const bool hasBorder = m_poly.m_border.color().alpha() != 0 && m_poly.m_border.width() > 0;
334 m_shapePath->setStrokeColor(hasBorder ? m_poly.m_border.color() : Qt::transparent);
335 m_shapePath->setStrokeWidth(hasBorder ? borderWidth : -1.0f);
336 m_shapePath->setFillColor(m_poly.color());
338 QPainterPath path = m_geometry.srcPath();
339 path.translate(-bb.left() + borderWidth, -bb.top() + borderWidth);
341 m_painterPath->setPath(path);
343 m_poly.setSize(bb.size() + QSize(2 * borderWidth, 2 * borderWidth));
344 m_shape->setSize(m_poly.size());
345 m_shape->setOpacity(m_poly.zoomLevelOpacity());
346 m_shape->setVisible(
true);
348 m_poly.setPositionOnMap(m_geometry.origin(), -1 * bb.topLeft() + QPointF(borderWidth, borderWidth));
371QDeclarativePolygonMapItem::QDeclarativePolygonMapItem(QQuickItem *parent)
372: QDeclarativeGeoMapItemBase(parent), m_border(
this), m_color(Qt::transparent),
373 m_updatingGeometry(
false)
374 , m_d(
new QDeclarativePolygonMapItemPrivateCPU(*
this))
378 m_itemType = QGeoMap::MapPolygon;
379 m_geopoly = QGeoPolygonEager();
380 setFlag(ItemHasContents,
true);
382 QObject::connect(&m_border, &QDeclarativeMapLineProperties::colorChanged,
383 this, &QDeclarativePolygonMapItem::onLinePropertiesChanged);
384 QObject::connect(&m_border, &QDeclarativeMapLineProperties::widthChanged,
385 this, &QDeclarativePolygonMapItem::onLinePropertiesChanged);
386 QObject::connect(
this, &QDeclarativePolygonMapItem::referenceSurfaceChanged,
387 this, [
this]() { m_d->onGeoGeometryChanged(); });