void tst_doubleVectors::constructor3dTest() { // empty constructor, since it sets to 0, we should check, in case people rely on it QDoubleVector3D v1; QCOMPARE(v1.x(), 0.0); QCOMPARE(v1.y(), 0.0); QCOMPARE(v1.z(), 0.0); QCOMPARE(v1.isNull(), true); v1 = QDoubleVector3D(1.1, -2.5, 3.2); // assignment and constructor QCOMPARE(v1.x(), 1.1); QCOMPARE(v1.y(), -2.5); QCOMPARE(v1.z(), 3.2); QDoubleVector3D v2(v1); // copy constructor QCOMPARE(v2.x(), 1.1); QCOMPARE(v2.y(), -2.5); QCOMPARE(v2.z(), 3.2); const QDoubleVector2D v2d(2.2, 3.3); QDoubleVector3D v3(v2d); // constructor from 3d vector, just copies x and y QCOMPARE(v3.x(), 2.2); QCOMPARE(v3.y(), 3.3); QCOMPARE(v3.z(), 0.0); QCOMPARE(v3.isNull(), false); const QDoubleVector2D v2d2(2.2, 3.3); QDoubleVector3D v4(v2d2, -13.6); // constructor from 2d vector QCOMPARE(v4.x(), 2.2); QCOMPARE(v4.y(), 3.3); QCOMPARE(v4.z(), -13.6); }
QT_BEGIN_NAMESPACE QDoubleVector3D QDoubleVector3D::normalized() const { // Need some extra precision if the length is very small. double len = double(xp) * double(xp) + double(yp) * double(yp) + double(zp) * double(zp); if (qFuzzyIsNull(len - 1.0)) return *this; else if (!qFuzzyIsNull(len)) return *this / (double)qSqrt(len); else return QDoubleVector3D(); }
QPair<Polygon, Polygon> QGeoCameraTilesPrivate::clipFootprintToMap(const Polygon &footprint) const { bool clipX0 = false; bool clipX1 = false; bool clipY0 = false; bool clipY1 = false; double side = 1.0 * sideLength_; typedef Polygon::const_iterator const_iter; const_iter i = footprint.constBegin(); const_iter end = footprint.constEnd(); for (; i != end; ++i) { QDoubleVector3D p = *i; if ((p.x() < 0.0) || (qFuzzyIsNull(p.x()))) clipX0 = true; if ((side < p.x()) || (qFuzzyCompare(side, p.x()))) clipX1 = true; if (p.y() < 0.0) clipY0 = true; if (side < p.y()) clipY1 = true; } Polygon results = footprint; if (clipY0) { results = splitPolygonAtAxisValue(results, 1, 0.0).second; } if (clipY1) { results = splitPolygonAtAxisValue(results, 1, side).first; } if (clipX0) { if (clipX1) { results = splitPolygonAtAxisValue(results, 0, 0.0).second; results = splitPolygonAtAxisValue(results, 0, side).first; return QPair<Polygon, Polygon>(results, Polygon()); } else { QPair<Polygon, Polygon> pair = splitPolygonAtAxisValue(results, 0, 0.0); if (pair.first.isEmpty()) { // if we touched the line but didn't cross it... for (int i = 0; i < pair.second.size(); ++i) { if (qFuzzyIsNull(pair.second.at(i).x())) pair.first.append(pair.second.at(i)); } if (pair.first.size() == 2) { double y0 = pair.first[0].y(); double y1 = pair.first[1].y(); pair.first.clear(); pair.first.append(QDoubleVector3D(side, y0, 0.0)); pair.first.append(QDoubleVector3D(side - 0.001, y0, 0.0)); pair.first.append(QDoubleVector3D(side - 0.001, y1, 0.0)); pair.first.append(QDoubleVector3D(side, y1, 0.0)); } else if (pair.first.size() == 1) { // FIXME this is trickier // - touching at one point on the tile boundary // - probably need to build a triangular polygon across the edge // - don't want to add another y tile if we can help it // - initial version doesn't care double y = pair.first.at(0).y(); pair.first.clear(); pair.first.append(QDoubleVector3D(side - 0.001, y, 0.0)); pair.first.append(QDoubleVector3D(side, y + 0.001, 0.0)); pair.first.append(QDoubleVector3D(side, y - 0.001, 0.0)); } } else { for (int i = 0; i < pair.first.size(); ++i) { pair.first[i].setX(pair.first.at(i).x() + side); } } return pair; } } else { if (clipX1) { QPair<Polygon, Polygon> pair = splitPolygonAtAxisValue(results, 0, side); if (pair.second.isEmpty()) { // if we touched the line but didn't cross it... for (int i = 0; i < pair.first.size(); ++i) { if (qFuzzyCompare(side, pair.first.at(i).x())) pair.second.append(pair.first.at(i)); } if (pair.second.size() == 2) { double y0 = pair.second[0].y(); double y1 = pair.second[1].y(); pair.second.clear(); pair.second.append(QDoubleVector3D(0, y0, 0.0)); pair.second.append(QDoubleVector3D(0.001, y0, 0.0)); pair.second.append(QDoubleVector3D(0.001, y1, 0.0)); pair.second.append(QDoubleVector3D(0, y1, 0.0)); } else if (pair.second.size() == 1) { // FIXME this is trickier // - touching at one point on the tile boundary // - probably need to build a triangular polygon across the edge // - don't want to add another y tile if we can help it // - initial version doesn't care double y = pair.second.at(0).y(); pair.second.clear(); pair.second.append(QDoubleVector3D(0.001, y, 0.0)); pair.second.append(QDoubleVector3D(0.0, y - 0.001, 0.0)); pair.second.append(QDoubleVector3D(0.0, y + 0.001, 0.0)); } } else { for (int i = 0; i < pair.second.size(); ++i) { pair.second[i].setX(pair.second.at(i).x() - side); } } return pair; } else { return QPair<Polygon, Polygon>(results, Polygon()); } } }
Frustum QGeoCameraTilesPrivate::frustum(double fieldOfViewGradient) const { QDoubleVector3D center = sideLength_ * QGeoProjection::coordToMercator(camera_.center()); center.setZ(0.0); double f = qMin(screenSize_.width(), screenSize_.height()) / (1.0 * tileSize_); double z = std::pow(2.0, camera_.zoomLevel() - intZoomLevel_); double altitude = f / (2.0 * z); QDoubleVector3D eye = center; eye.setZ(altitude); QDoubleVector3D view = eye - center; QDoubleVector3D side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); QDoubleVector3D up = QDoubleVector3D::normal(side, view); double nearPlane = sideLength_ / (1.0 * tileSize_ * (1 << maxZoom_)); double farPlane = 3.0; double aspectRatio = 1.0 * screenSize_.width() / screenSize_.height(); double hn = 0.0; double wn = 0.0; double hf = 0.0; double wf = 0.0; // fixes field of view at 45 degrees // this assumes that viewSize = 2*nearPlane x 2*nearPlane if (aspectRatio > 1.0) { hn = 2 * fieldOfViewGradient * nearPlane; wn = hn * aspectRatio; hf = 2 * fieldOfViewGradient * farPlane; wf = hf * aspectRatio; } else { wn = 2 * fieldOfViewGradient * nearPlane; hn = wn / aspectRatio; wf = 2 * fieldOfViewGradient * farPlane; hf = wf / aspectRatio; } QDoubleVector3D d = center - eye; d.normalize(); up.normalize(); QDoubleVector3D right = QDoubleVector3D::normal(d, up); QDoubleVector3D cf = eye + d * farPlane; QDoubleVector3D cn = eye + d * nearPlane; Frustum frustum; frustum.topLeftFar = cf + (up * hf / 2) - (right * wf / 2); frustum.topRightFar = cf + (up * hf / 2) + (right * wf / 2); frustum.bottomLeftFar = cf - (up * hf / 2) - (right * wf / 2); frustum.bottomRightFar = cf - (up * hf / 2) + (right * wf / 2); frustum.topLeftNear = cn + (up * hn / 2) - (right * wn / 2); frustum.topRightNear = cn + (up * hn / 2) + (right * wn / 2); frustum.bottomLeftNear = cn - (up * hn / 2) - (right * wn / 2); frustum.bottomRightNear = cn - (up * hn / 2) + (right * wn / 2); return frustum; }
QDoubleVector3D QDoubleVector2D::toVector3D() const { return QDoubleVector3D(xp, yp, 0.0); }