108void QGeoMapPolygonGeometry::updateSourcePoints(
const QGeoMap &map,
109 const QList<QList <QDoubleVector2D>> &basePaths,
110 MapBorderBehaviour wrapping)
116 const QGeoProjectionWebMercator &p =
static_cast<
const QGeoProjectionWebMercator&>(map.geoProjection());
117 srcPath_ = QPainterPath();
118 srcOrigin_ = p.mapProjectionToGeo(QDoubleVector2D(0.0, 0.0));
119 const QRectF cameraRect = QDeclarativeGeoMapItemUtils::boundingRectangleFromList(p.visibleGeometry());
121 QList<QList<QDoubleVector2D>> paths;
123 if (wrapping == WrapAround) {
126 paths.reserve(basePaths.size());
127 for (qsizetype j = 0; j< basePaths.size(); j++) {
128 const QList<QDoubleVector2D> &bp = basePaths[j];
131 paths << QList<QDoubleVector2D>({bp[0]});
132 QList<QDoubleVector2D> &pp = paths[j];
133 pp.reserve(bp.size());
134 for (qsizetype i = 1; i < bp.size(); i++) {
135 if (bp[i].x() > pp.last().x() + 0.5)
136 pp << bp[i] - QDoubleVector2D(1.0, 0.0);
137 else if (bp[i].x() < pp.last().x() - 0.5)
138 pp << bp[i] + QDoubleVector2D(1.0, 0.0);
145 for (qsizetype j = 0; j < paths.size(); j++) {
146 QList<QDoubleVector2D> &pp = paths[j];
148 if (pp.last().x() - pp.first().x() < -0.5) {
149 for (qsizetype i = 0; i < floor(pp.length()/2.); i++)
150 pp.swapItemsAt(i, pp.length() - i - 1);
152 if (pp.last().x() - pp.first().x() > 0.5) {
154 const double leftBorder = cameraRect.left();
155 const double rightBorder = cameraRect.right();
157 qsizetype originalPathLength = pp.length();
159 if (pp.last().x() < rightBorder) {
160 for (qsizetype i = 0; i < originalPathLength; i++)
161 pp.append(pp[i] + QDoubleVector2D(1.0, 0.0));
163 if (pp.first().x() > leftBorder) {
164 for (qsizetype i = 0; i < originalPathLength; i++)
165 pp.insert(i, pp[2*i] - QDoubleVector2D(1.0, 0.0));
167 const double newPoleLat = (pp.first().y() + pp.last().y() < 1.0) ? 0.0 : 1.0;
168 const QDoubleVector2D P1 = pp.first();
169 const QDoubleVector2D P2 = pp.last();
170 pp.push_front(QDoubleVector2D(P1.x(), newPoleLat));
171 pp.append(QDoubleVector2D(P2.x(), newPoleLat));
183 QList<QList<QDoubleVector2D>> wrappedPaths;
185 if (wrapping == Duplicate || wrapping == WrapAround) {
187 for (
const auto &path : paths)
188 itemRect |= QDeclarativeGeoMapItemUtils::boundingRectangleFromList(path);
190 for (
double xoffset : {-1.0, 0.0, 1.0}) {
191 if (!cameraRect.intersects(itemRect.translated(QPointF(xoffset, 0.0))))
193 for (
const auto &path : paths) {
194 wrappedPaths.append(QList<QDoubleVector2D>());
195 QList<QDoubleVector2D> &wP = wrappedPaths.last();
196 wP.reserve(path.size());
197 for (
const QDoubleVector2D &coord : path)
198 wP.append(coord+QDoubleVector2D(xoffset, 0.0));
202 wrappedPaths = paths;
205 if (wrappedPaths.isEmpty())
210 QList<QList<QDoubleVector2D>> clippedPaths;
211 const QList<QDoubleVector2D> &visibleRegion = p.visibleGeometryExpanded();
212 for (
const auto &path : wrappedPaths) {
213 if (visibleRegion.size()) {
214 QClipperUtils clipper;
215 clipper.addSubjectPath(path,
true);
216 clipper.addClipPolygon(visibleRegion);
217 clippedPaths << clipper.execute(QClipperUtils::Intersection, QClipperUtils::pftEvenOdd,
218 QClipperUtils::pftEvenOdd);
221 clippedPaths.append(path);
224 if (clippedPaths.isEmpty())
228 for (
const auto &path: clippedPaths)
229 bb |= QDeclarativeGeoMapItemUtils::boundingRectangleFromList(path);
231 srcOrigin_ = p.mapProjectionToGeo(QDoubleVector2D(bb.left(), bb.top()));
232 QDoubleVector2D origin = p.wrappedMapProjectionToItemPosition(p.geoToWrappedMapProjection(srcOrigin_));
234 for (
const auto &path: clippedPaths) {
235 QDoubleVector2D prevPoint = p.wrappedMapProjectionToItemPosition(path.at(0)) - origin;
236 QDoubleVector2D nextPoint = p.wrappedMapProjectionToItemPosition(path.at(1)) - origin;
237 srcPath_.moveTo(prevPoint.toPointF());
238 maxCoord_ = qMax(maxCoord_, qMax(prevPoint.x(), prevPoint.y()));
239 qsizetype pointsAdded = 1;
240 for (qsizetype i = 1; i < path.size(); ++i) {
241 const QDoubleVector2D point = nextPoint;
243 if (qMax(point.x(), point.y()) > maxCoord_)
244 maxCoord_ = qMax(point.x(), point.y());
246 if (i == path.size() - 1) {
247 srcPath_.lineTo(point.toPointF());
249 nextPoint = p.wrappedMapProjectionToItemPosition(path.at(i+1)) - origin;
251 bool addPoint = ( i > pointsAdded * 10 ||
254 const double tolerance = 0.1;
256 const double dsqr = QDeclarativeGeoMapItemUtils::distanceSqrPointLine(
257 point.x(), point.y(),
258 nextPoint.x(), nextPoint.y(),
259 prevPoint.x(), prevPoint.y());
260 addPoint = addPoint || (dsqr > (tolerance*tolerance));
264 srcPath_.lineTo(point.toPointF());
271 srcPath_.closeSubpath();
275 srcPath_ = srcPath_.simplified();
277 sourceBounds_ = srcPath_.boundingRect();
311void QDeclarativePolygonMapItemPrivateCPU::updatePolish()
313 if (m_poly.m_geopoly.perimeter().length() == 0) {
317 m_shape->setVisible(
false);
320 const QGeoMap *map = m_poly.map();
321 const qreal borderWidth = m_poly.m_border.width();
322 QScopedValueRollback<
bool> rollback(m_poly.m_updatingGeometry);
323 m_poly.m_updatingGeometry =
true;
325 m_geometry.updateSourcePoints(*map, m_geopathProjected,
326 m_poly.referenceSurface() == QLocation::ReferenceSurface::Globe ?
327 QGeoMapPolygonGeometry::WrapAround :
328 QGeoMapPolygonGeometry::Duplicate);
330 const QRectF bb = m_geometry.sourceBoundingBox();
332 m_poly.setShapeTriangulationScale(m_shape, m_geometry.maxCoord());
334 const bool hasBorder = m_poly.m_border.color().alpha() != 0 && m_poly.m_border.width() > 0;
335 m_shapePath->setStrokeColor(hasBorder ? m_poly.m_border.color() : Qt::transparent);
336 m_shapePath->setStrokeWidth(hasBorder ? borderWidth : -1.0f);
337 m_shapePath->setFillColor(m_poly.color());
339 QPainterPath path = m_geometry.srcPath();
340 path.translate(-bb.left() + borderWidth, -bb.top() + borderWidth);
342 m_painterPath->setPath(path);
344 m_poly.setSize(bb.size() + QSize(2 * borderWidth, 2 * borderWidth));
345 m_shape->setSize(m_poly.size());
346 m_shape->setOpacity(m_poly.zoomLevelOpacity());
347 m_shape->setVisible(
true);
349 m_poly.setPositionOnMap(m_geometry.origin(), -1 * bb.topLeft() + QPointF(borderWidth, borderWidth));
372QDeclarativePolygonMapItem::QDeclarativePolygonMapItem(QQuickItem *parent)
373: QDeclarativeGeoMapItemBase(parent), m_border(
this), m_color(Qt::transparent),
374 m_updatingGeometry(
false)
375 , m_d(
new QDeclarativePolygonMapItemPrivateCPU(*
this))
379 m_itemType = QGeoMap::MapPolygon;
380 m_geopoly = QGeoPolygonEager();
381 setFlag(ItemHasContents,
true);
383 QObject::connect(&m_border, &QDeclarativeMapLineProperties::colorChanged,
384 this, &QDeclarativePolygonMapItem::onLinePropertiesChanged);
385 QObject::connect(&m_border, &QDeclarativeMapLineProperties::widthChanged,
386 this, &QDeclarativePolygonMapItem::onLinePropertiesChanged);
387 QObject::connect(
this, &QDeclarativePolygonMapItem::referenceSurfaceChanged,
388 this, [
this]() { m_d->onGeoGeometryChanged(); });