| 119 | } |
| 120 | |
| 121 | glm::dvec2 computeProjectedRectangleSize( |
| 122 | const Projection& projection, |
| 123 | const CesiumGeometry::Rectangle& rectangle, |
| 124 | double maxHeight, |
| 125 | const Ellipsoid& ellipsoid) { |
| 126 | glm::dvec3 ll = ellipsoid.cartographicToCartesian(unprojectPosition( |
| 127 | projection, |
| 128 | glm::dvec3(rectangle.getLowerLeft(), maxHeight))); |
| 129 | glm::dvec3 lr = ellipsoid.cartographicToCartesian(unprojectPosition( |
| 130 | projection, |
| 131 | glm::dvec3(rectangle.getLowerRight(), maxHeight))); |
| 132 | glm::dvec3 ul = ellipsoid.cartographicToCartesian(unprojectPosition( |
| 133 | projection, |
| 134 | glm::dvec3(rectangle.getUpperLeft(), maxHeight))); |
| 135 | glm::dvec3 ur = ellipsoid.cartographicToCartesian(unprojectPosition( |
| 136 | projection, |
| 137 | glm::dvec3(rectangle.getUpperRight(), maxHeight))); |
| 138 | |
| 139 | double lowerDistance = glm::distance(ll, lr); |
| 140 | double upperDistance = glm::distance(ul, ur); |
| 141 | double leftDistance = glm::distance(ll, ul); |
| 142 | double rightDistance = glm::distance(lr, ur); |
| 143 | |
| 144 | double x = glm::max(lowerDistance, upperDistance); |
| 145 | double y = glm::max(leftDistance, rightDistance); |
| 146 | |
| 147 | // A rectangle that wraps around the whole globe might have an upper and lower |
| 148 | // distance that are very small even though the rectangle is huge, because the |
| 149 | // left and right edges of the rectangle are nearly on top of each other. |
| 150 | // Detect that just by measuring the distance to a midpoint. |
| 151 | // The bigger problem here is that we're measuring the Cartesian distance, |
| 152 | // rather than the distance over the globe surface. But it's close enough |
| 153 | // for our purposes except in this extreme case. |
| 154 | glm::dvec3 lc = ellipsoid.cartographicToCartesian(unprojectPosition( |
| 155 | projection, |
| 156 | glm::dvec3(rectangle.getCenter().x, rectangle.minimumY, maxHeight))); |
| 157 | glm::dvec3 uc = ellipsoid.cartographicToCartesian(unprojectPosition( |
| 158 | projection, |
| 159 | glm::dvec3(rectangle.getCenter().x, rectangle.maximumY, maxHeight))); |
| 160 | |
| 161 | double halfDistanceLA = glm::distance(ll, lc); |
| 162 | double halfDistanceLB = glm::distance(lc, lr); |
| 163 | double halfDistanceUA = glm::distance(ul, uc); |
| 164 | double halfDistanceUB = glm::distance(uc, ur); |
| 165 | |
| 166 | if (halfDistanceLA > x || halfDistanceLB > x || halfDistanceUA > x || |
| 167 | halfDistanceUB > x) { |
| 168 | x = glm::max( |
| 169 | halfDistanceLA + halfDistanceLB, |
| 170 | halfDistanceUA + halfDistanceUB); |
| 171 | } |
| 172 | |
| 173 | // If either projected coordinate crosses zero, also check the distance at |
| 174 | // zero. This is not completely robust, but works well enough for |
| 175 | // currently supported projections at least. |
| 176 | if (glm::sign(rectangle.minimumX) != glm::sign(rectangle.maximumX)) { |
| 177 | glm::dvec3 top = ellipsoid.cartographicToCartesian(unprojectPosition( |
| 178 | projection, |
no test coverage detected