Skip to content

Commit

Permalink
Merge pull request #720 from hpinkos/polygonidl
Browse files Browse the repository at this point in the history
Polygonidl
  • Loading branch information
bagnell committed May 7, 2013
2 parents 6500fd2 + 3486a02 commit 7a657c4
Show file tree
Hide file tree
Showing 11 changed files with 579 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Apps/Sandcastle/gallery/Polygons.html
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,4 @@
});
</script>
</body>
</html>
</html>
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Beta Releases
* Added `czm_morphTime` automatic GLSL uniform.
* Added support for floating-point textures.
* Fixed polyline clipping artifact. [#728](https://github.com/AnalyticalGraphicsInc/cesium/issues/728).
* Added `IntersectionTests.trianglePlaneIntersection`.
* Fixed polygon crossing international date line for 2D and Columbus view

### b16 - 2013-05-01
* Breaking changes:
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/EllipsoidTangentPlane.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,4 @@ define([
};

return EllipsoidTangentPlane;
});
});
154 changes: 154 additions & 0 deletions Source/Core/IntersectionTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -418,5 +418,159 @@ define([
return result;
};

/**
* Computes the intersection of a triangle and a plane
* @memberof IntersectionTests
*
* @param {Cartesian3} p0 First point of the triangle
* @param {Cartesian3} p1 Second point of the triangle
* @param {Cartesian3} p2 Third point of the triangle
* @param {Plane} plane Intersection plane
*
* @returns {Object} An object with properties <code>positions</code> and <code>indices</code>, which are arrays that represent three triangles that do not cross the plane. (Undefined if no intersection exists)
*
* @exception {DeveloperError} p0, p1, p2, and plane are required.
*
* @example
* var origin = ellipsoid.cartographicToCartesian(Cartographic.fromDegrees(-75.59777, 40.03883, 0.0));
* var normal = ellipsoid.geodeticSurfaceNormal(origin);
* var plane = Plane.fromPointNormal(origin, normal);
*
* var p0 = new Cartesian3(...);
* var p1 = new Cartesian3(...);
* var p2 = new Cartesian3(...);
*
* // convert the triangle composed of points (p0, p1, p2) to three triangles that don't cross the plane
* var triangles = IntersectionTests.lineSegmentPlane(p0, p1, p2, plane);
*
*/
IntersectionTests.trianglePlaneIntersection = function(p0, p1, p2, plane) {
if ((typeof p0 === 'undefined') ||
(typeof p1 === 'undefined') ||
(typeof p2 === 'undefined') ||
(typeof plane === 'undefined')) {
throw new DeveloperError('p0, p1, p2, and plane are required.');
}

var planeNormal = plane.normal;
var planeD = plane.distance;
var p0Behind = (Cartesian3.dot(planeNormal, p0) + planeD) < 0.0;
var p1Behind = (Cartesian3.dot(planeNormal, p1) + planeD) < 0.0;
var p2Behind = (Cartesian3.dot(planeNormal, p2) + planeD) < 0.0;
// Given these dots products, the calls to lineSegmentPlaneIntersection
// always have defined results.

var numBehind = 0;
numBehind += p0Behind ? 1 : 0;
numBehind += p1Behind ? 1 : 0;
numBehind += p2Behind ? 1 : 0;

var u1, u2;
if (numBehind === 1 || numBehind === 2) {
u1 = new Cartesian3();
u2 = new Cartesian3();
}

if (numBehind === 1) {
if (p0Behind) {
IntersectionTests.lineSegmentPlane(p0, p1, plane, u1);
IntersectionTests.lineSegmentPlane(p0, p2, plane, u2);

return {
positions : [p0, p1, p2, u1, u2 ],
indices : [
// Behind
0, 3, 4,

// In front
1, 2, 4,
1, 4, 3
]
};
} else if (p1Behind) {
IntersectionTests.lineSegmentPlane(p1, p2, plane, u1);
IntersectionTests.lineSegmentPlane(p1, p0, plane, u2);

return {
positions : [p0, p1, p2, u1, u2 ],
indices : [
// Behind
1, 3, 4,

// In front
2, 0, 4,
2, 4, 3
]
};
} else if (p2Behind) {
IntersectionTests.lineSegmentPlane(p2, p0, plane, u1);
IntersectionTests.lineSegmentPlane(p2, p1, plane, u2);

return {
positions : [p0, p1, p2, u1, u2 ],
indices : [
// Behind
2, 3, 4,

// In front
0, 1, 4,
0, 4, 3
]
};
}
} else if (numBehind === 2) {
if (!p0Behind) {
IntersectionTests.lineSegmentPlane(p1, p0, plane, u1);
IntersectionTests.lineSegmentPlane(p2, p0, plane, u2);

return {
positions : [p0, p1, p2, u1, u2 ],
indices : [
// Behind
1, 2, 4,
1, 4, 3,

// In front
0, 3, 4
]
};
} else if (!p1Behind) {
IntersectionTests.lineSegmentPlane(p2, p1, plane, u1);
IntersectionTests.lineSegmentPlane(p0, p1, plane, u2);

return {
positions : [p0, p1, p2, u1, u2 ],
indices : [
// Behind
2, 0, 4,
2, 4, 3,

// In front
1, 3, 4
]
};
} else if (!p2Behind) {
IntersectionTests.lineSegmentPlane(p0, p2, plane, u1);
IntersectionTests.lineSegmentPlane(p1, p2, plane, u2);

return {
positions : [p0, p1, p2, u1, u2 ],
indices : [
// Behind
0, 1, 4,
0, 4, 3,

// In front
2, 3, 4
]
};
}
}

// if numBehind is 3, the triangle is completely behind the plane;
// otherwise, it is completely in front (numBehind is 0).
return undefined;
};

return IntersectionTests;
});
2 changes: 1 addition & 1 deletion Source/Core/Plane.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,4 @@ define([
};

return Plane;
});
});
136 changes: 135 additions & 1 deletion Source/Core/PolygonPipeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,24 @@ define([
return newPolygonVertices;
}

var c3 = new Cartesian3();
function getXZIntersectionOffsetPoints(p, p1, u1, v1) {
p.add(p1.subtract(p, c3).multiplyByScalar(p.y/(p.y-p1.y), c3), u1);
Cartesian3.clone(u1, v1);
offsetPointFromXZPlane(u1, true);
offsetPointFromXZPlane(v1, false);
}

function offsetPointFromXZPlane(p, isBehind) {
if (Math.abs(p.y) < CesiumMath.EPSILON11){
if (isBehind) {
p.y = -CesiumMath.EPSILON11;
} else {
p.y = CesiumMath.EPSILON11;
}
}
}

var scaleToGeodeticHeightN = new Cartesian3();
var scaleToGeodeticHeightP = new Cartesian3();

Expand Down Expand Up @@ -538,6 +556,122 @@ define([
return indices;
},

/**
* Subdivides a {@link Polygon} such that no triangles cross the &plusmn;180 degree meridian of an ellipsoid.
* @memberof PolygonPipeline
*
* @param {Array} positions The Cartesian positions of triangles that make up a polygon.
* @param {Array} indices The indices of positions in the positions array that make up triangles
*
* @returns {Object} The full set of indices, including those for positions added for newly created triangles
*
* @exception {DeveloperError} positions and indices are required
* @exception {DeveloperError} At least three indices are required.
* @exception {DeveloperError} The number of indices must be divisable by three.
*
* @see Polygon
*
* @example
* var positions = [new Cartesian3(-1, -1, 0), new Cartesian3(-1, 1, 2), new Cartesian3(-1, 2, 2)];
* var indices = [0, 1, 2];
* indices = PolygonPipeline.wrapLongitude(positions, indices);
*/

wrapLongitude : function(positions, indices) {
if ((typeof positions === 'undefined') ||
(typeof indices === 'undefined')) {
throw new DeveloperError('positions and indices are required.');
}

if (indices.length < 3) {
throw new DeveloperError('At least three indices are required.');
}

if (indices.length % 3 !== 0) {
throw new DeveloperError('The number of indices must be divisable by three.');
}

var newIndices = [];

var len = indices.length;
for (var i = 0; i < len; i += 3) {
var i0 = indices[i];
var i1 = indices[i + 1];
var i2 = indices[i + 2];
var p0 = positions[i0];
var p1 = positions[i1];
var p2 = positions[i2];

// In WGS84 coordinates, for a triangle approximately on the
// ellipsoid to cross the IDL, first it needs to be on the
// negative side of the plane x = 0.
if ((p0.x < 0.0) && (p1.x < 0.0) && (p2.x < 0.0)) {
var p0Behind = p0.y < 0.0;
var p1Behind = p1.y < 0.0;
var p2Behind = p2.y < 0.0;

offsetPointFromXZPlane(p0, p0Behind);
offsetPointFromXZPlane(p1, p1Behind);
offsetPointFromXZPlane(p2, p2Behind);

var numBehind = 0;
numBehind += p0Behind ? 1 : 0;
numBehind += p1Behind ? 1 : 0;
numBehind += p2Behind ? 1 : 0;

var u1, u2, v1, v2;

if (numBehind === 1 || numBehind === 2) {
u1 = new Cartesian3();
u2 = new Cartesian3();
v1 = new Cartesian3();
v2 = new Cartesian3();
}
var iu1 = positions.length;
if (numBehind === 1) {
if (p0Behind) {
getXZIntersectionOffsetPoints(p0, p1, u1, v1);
getXZIntersectionOffsetPoints(p0, p2, u2, v2);
positions.push(u1, u2, v1, v2);
newIndices.push(i0, iu1, iu1+1, i1, i2, iu1+3, i1, iu1+3, iu1+2);
} else if (p1Behind) {
getXZIntersectionOffsetPoints(p1, p0, u1, v1);
getXZIntersectionOffsetPoints(p1, p2, u2, v2);
positions.push(u1, u2, v1, v2);
newIndices.push(i1, iu1, iu1+1, i2, i0, iu1+3, i2, iu1+3, iu1+2);
} else if (p2Behind) {
getXZIntersectionOffsetPoints(p2, p0, u1, v1);
getXZIntersectionOffsetPoints(p2, p1, u2, v2);
positions.push(u1, u2, v1, v2);
newIndices.push(i2, iu1, iu1+1, i0, i1, iu1+3, i0, iu1+3, iu1+2);
}
} else if (numBehind === 2) {
if (!p0Behind) {
getXZIntersectionOffsetPoints(p0, p1, u1, v1);
getXZIntersectionOffsetPoints(p0, p2, u2, v2);
positions.push(u1, u2, v1, v2);
newIndices.push(i1, i2, iu1+1, i1, iu1+1, iu1, i0, iu1+2, iu1+3);
} else if (!p1Behind) {
getXZIntersectionOffsetPoints(p1, p2, u1, v1);
getXZIntersectionOffsetPoints(p1, p0, u2, v2);
positions.push(u1, u2, v1, v2);
newIndices.push(i2, i0, iu1+1, i2, iu1+1, iu1, i1, iu1+2, iu1+3);
} else if (!p2Behind) {
getXZIntersectionOffsetPoints(p2, p0, u1, v1);
getXZIntersectionOffsetPoints(p2, p1, u2, v2);
positions.push(u1, u2, v1, v2);
newIndices.push(i0, i1, iu1+1, i0, iu1+1, iu1, i2, iu1+2, iu1+3);
}
} else {
newIndices.push(i0, i1, i2);
}
} else {
newIndices.push(i0, i1, i2);
}
}
return newIndices;
},

/**
* DOC_TBA
*
Expand All @@ -552,7 +686,7 @@ define([
* @exception {DeveloperError} Granularity must be greater than zero.
*/
computeSubdivision : function(positions, indices, granularity) {
if (typeof positions === 'undefined') {
if (typeof positions === 'undefined') {
throw new DeveloperError('positions is required.');
}

Expand Down
3 changes: 2 additions & 1 deletion Source/Core/PolylinePipeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ define([
* @returns {Object} An object with a <code>positions</code> property that is an array of positions and a
* <code>segments</code> property.
*
* @see PolygonPipeline.wrapLongitude
* @see Polyline
* @see PolylineCollection
*
Expand Down Expand Up @@ -112,4 +113,4 @@ define([
};

return PolylinePipeline;
});
});
Loading

0 comments on commit 7a657c4

Please sign in to comment.