QDebug operator<<(QDebug dbg, const QDoubleVector3D &vector) { QDebugStateSaver saver(dbg); dbg.nospace() << "QDoubleVector3D(" << vector.x() << ", " << vector.y() << ", " << vector.z() << ')'; return dbg; }
void QGeoCameraTilesPrivate::appendZIntersects(const QDoubleVector3D &start, const QDoubleVector3D &end, double z, QVector<QDoubleVector3D> &results) const { if (start.z() == end.z()) { if (start.z() == z) { results.append(start); results.append(end); } } else { double f = (start.z() - z) / (start.z() - end.z()); if ((0 <= f) && (f <= 1.0)) { results.append((1 - f) * start + f * end); } } }
// Returns the intersection of the plane of the map and the camera frustum as a right handed polygon Polygon QGeoCameraTilesPrivate::frustumFootprint(const Frustum &frustum) const { Polygon points; points.reserve(24); appendZIntersects(frustum.topLeftNear, frustum.topLeftFar, 0.0, points); appendZIntersects(frustum.topRightNear, frustum.topRightFar, 0.0, points); appendZIntersects(frustum.bottomLeftNear, frustum.bottomLeftFar, 0.0, points); appendZIntersects(frustum.bottomRightNear, frustum.bottomRightFar, 0.0, points); appendZIntersects(frustum.topLeftNear, frustum.bottomLeftNear, 0.0, points); appendZIntersects(frustum.bottomLeftNear, frustum.bottomRightNear, 0.0, points); appendZIntersects(frustum.bottomRightNear, frustum.topRightNear, 0.0, points); appendZIntersects(frustum.topRightNear, frustum.topLeftNear, 0.0, points); appendZIntersects(frustum.topLeftFar, frustum.bottomLeftFar, 0.0, points); appendZIntersects(frustum.bottomLeftFar, frustum.bottomRightFar, 0.0, points); appendZIntersects(frustum.bottomRightFar, frustum.topRightFar, 0.0, points); appendZIntersects(frustum.topRightFar, frustum.topLeftFar, 0.0, points); if (points.isEmpty()) return points; // sort points into a right handed polygon LengthSorter sorter; // - initial sort to remove duplicates sorter.base = points.first(); qSort(points.begin(), points.end(), sorter); for (int i = points.size() - 1; i > 0; --i) { if (points.at(i) == points.at(i - 1)) points.remove(i); } // - proper sort // - start with the first point, put it in the sorted part of the list // - add the nearest unsorted point to the last sorted point to the end // of the sorted points Polygon::iterator i; for (i = points.begin(); i != points.end(); ++i) { sorter.base = *i; if (i + 1 != points.end()) qSort(i + 1, points.end(), sorter); } // - determine if what we have is right handed int size = points.size(); if (size >= 3) { QDoubleVector3D normal = QDoubleVector3D::normal(points.at(1) - points.at(0), points.at(2) - points.at(1)); // - if not, reverse the list if (normal.z() < 0.0) { int halfSize = size / 2; for (int i = 0; i < halfSize; ++i) { QDoubleVector3D spare = points.at(i); points[i] = points[size - 1 - i]; points[size - 1 - i] = spare; } } } return points; }