Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix mitering bug with ground polylines over long distances #7885

Merged
merged 4 commits into from
Jun 6, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ Change Log
##### Fixes :wrench:
* Fixed an edge case where Cesium would provide ion access token credentials to non-ion servers if the actual asset entrypoint was being hosted by ion. [#7839](https://github.com/AnalyticalGraphicsInc/cesium/pull/7839)
* Fixed a bug that caused Cesium to request non-existent tiles for terrain tilesets lacking tile availability, i.e. a `layer.json` file.
* Fixed memory leak when removing entities that had a `HeightReference` of `CLAMP_TO_GROUND` or `RELATIVE_TO_GROUND`. This includes when removing a `DataSource`.
* Fixed memory leak when removing entities that had a `HeightReference` of `CLAMP_TO_GROUND` or `RELATIVE_TO_GROUND`. This includes when removing a `DataSource`.
* Fixed 3D Tiles credits not being shown in the data attribution box. [#7877](https://github.com/AnalyticalGraphicsInc/cesium/pull/7877)
* Fixed a bug that caused missing segments for ground polylines with coplanar points over large distances. [#7855](https://github.com/AnalyticalGraphicsInc/cesium/issues/7855)

### 1.57 - 2019-05-01

Expand Down
45 changes: 23 additions & 22 deletions Source/Core/GroundPolylineGeometry.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,41 +353,42 @@ define([
return result;
}

function tangentDirection(target, origin, up, result) {
result = direction(target, origin, result);

// orthogonalize
result = Cartesian3.cross(result, up, result);
result = Cartesian3.normalize(result, result);
result = Cartesian3.cross(up, result, result);
return result;
}

var toPreviousScratch = new Cartesian3();
var toNextScratch = new Cartesian3();
var forwardScratch = new Cartesian3();
var coplanarNormalScratch = new Cartesian3();
var coplanarPlaneScratch = new Plane(Cartesian3.UNIT_X, 0.0);
var vertexUpScratch = new Cartesian3();
var cosine90 = 0.0;
var cosine180 = -1.0;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lilleyse for context, computeVertexMiterNormal is meant to compute a normal pointing to the "right" side of a join between two line segments defined by 3 points, eventually this is used to compute normals on the start and end faces of the volumes around polyline segments.

function computeVertexMiterNormal(previousBottom, vertexBottom, vertexTop, nextBottom, result) {
var up = direction(vertexTop, vertexBottom, vertexUpScratch);
var toPrevious = direction(previousBottom, vertexBottom, toPreviousScratch);
var toNext = direction(nextBottom, vertexBottom, toNextScratch);

// Check if points are coplanar in a right-side-pointing plane that contains "up."
// This is roughly equivalent to the points being colinear in cartographic space.
var coplanarNormal = Cartesian3.cross(up, toPrevious, coplanarNormalScratch);
coplanarNormal = Cartesian3.normalize(coplanarNormal, coplanarNormal);
var coplanarPlane = Plane.fromPointNormal(vertexBottom, coplanarNormal, coplanarPlaneScratch);
var nextBottomDistance = Plane.getPointDistance(coplanarPlane, nextBottom);
if (CesiumMath.equalsEpsilon(nextBottomDistance, 0.0, CesiumMath.EPSILON7)) {
// If the points are coplanar, point the normal in the direction of the plane
Cartesian3.clone(coplanarNormal, result);
return result;

// Compute vectors pointing towards neighboring points but tangent to this point on the ellipsoid
var toPrevious = tangentDirection(previousBottom, vertexBottom, up, toPreviousScratch);
var toNext = tangentDirection(nextBottom, vertexBottom, up, toNextScratch);

// Check if tangents are almost opposite - if so, no need to miter.
if (CesiumMath.equalsEpsilon(Cartesian3.dot(toPrevious, toNext), cosine180, CesiumMath.EPSILON5)) {
result = Cartesian3.cross(up, toPrevious, result);
result = Cartesian3.normalize(result, result);
return result;
}

// Average directions to previous and to next
// Average directions to previous and to next in the plane of Up
result = Cartesian3.add(toNext, toPrevious, result);
result = Cartesian3.normalize(result, result);

// Rotate this direction to be orthogonal to up
var forward = Cartesian3.cross(up, result, forwardScratch);
Cartesian3.normalize(forward, forward);
Cartesian3.cross(forward, up, result);
Cartesian3.normalize(result, result);

// Flip the normal if it isn't pointing roughly bound right (aka if forward is pointing more "backwards")
var forward = Cartesian3.cross(up, result, forwardScratch);
if (Cartesian3.dot(toNext, forward) < cosine90) {
result = Cartesian3.negate(result, result);
}
Expand Down
7 changes: 3 additions & 4 deletions Specs/Core/GroundPolylineGeometrySpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ defineSuite([
positions : Cartesian3.fromDegreesArray([
0.01, 0.0,
0.02, 0.0,
0.01, 0.0
0.01, CesiumMath.EPSILON7
]),
granularity : 0.0
});
Expand All @@ -299,11 +299,10 @@ defineSuite([

var miteredStartNormal = Cartesian3.unpack(startNormalAndForwardOffsetZvalues, 32);
var miteredEndNormal = Cartesian3.unpack(endNormalAndTextureCoordinateNormalizationXvalues, 0);
var reverseMiteredEndNormal = Cartesian3.multiplyByScalar(miteredEndNormal, -1.0, new Cartesian3());

expect(Cartesian3.equalsEpsilon(miteredStartNormal, reverseMiteredEndNormal, CesiumMath.EPSILON7)).toBe(true);
expect(Cartesian3.equalsEpsilon(miteredStartNormal, miteredEndNormal, CesiumMath.EPSILON7)).toBe(true);

var approximateExpectedMiterNormal = new Cartesian3(0.0, 1.0, 0.0);
var approximateExpectedMiterNormal = new Cartesian3(0.0, -1.0, 0.0);

Cartesian3.normalize(approximateExpectedMiterNormal, approximateExpectedMiterNormal);
expect(Cartesian3.equalsEpsilon(approximateExpectedMiterNormal, miteredStartNormal, CesiumMath.EPSILON2)).toBe(true);
Expand Down