Skip to content

Commit

Permalink
Merge pull request #6819 from AnalyticalGraphicsInc/polygon-centroid
Browse files Browse the repository at this point in the history
Compute polygon centroid instead of average of positions
  • Loading branch information
bagnell authored Jul 19, 2018
2 parents 943fe93 + 23e383d commit 1f62bd9
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 88 deletions.
79 changes: 42 additions & 37 deletions Source/Core/EllipsoidTangentPlane.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ define([
'./Cartesian2',
'./Cartesian3',
'./Cartesian4',
'./Check',
'./defaultValue',
'./defined',
'./defineProperties',
Expand All @@ -18,6 +19,7 @@ define([
Cartesian2,
Cartesian3,
Cartesian4,
Check,
defaultValue,
defined,
defineProperties,
Expand Down Expand Up @@ -45,9 +47,7 @@ define([
*/
function EllipsoidTangentPlane(origin, ellipsoid) {
//>>includeStart('debug', pragmas.debug);
if (!defined(origin)) {
throw new DeveloperError('origin is required.');
}
Check.defined('origin', origin);
//>>includeEnd('debug');

ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
Expand Down Expand Up @@ -146,14 +146,12 @@ define([
* Creates a new instance from the provided ellipsoid and the center
* point of the provided Cartesians.
*
* @param {Ellipsoid} ellipsoid The ellipsoid to use.
* @param {Cartesian3} cartesians The list of positions surrounding the center point.
* @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid to use.
*/
EllipsoidTangentPlane.fromPoints = function(cartesians, ellipsoid) {
//>>includeStart('debug', pragmas.debug);
if (!defined(cartesians)) {
throw new DeveloperError('cartesians is required.');
}
Check.defined('cartesians', cartesians);
//>>includeEnd('debug');

var box = AxisAlignedBoundingBox.fromPoints(cartesians, tmp);
Expand All @@ -172,9 +170,7 @@ define([
*/
EllipsoidTangentPlane.prototype.projectPointOntoPlane = function(cartesian, result) {
//>>includeStart('debug', pragmas.debug);
if (!defined(cartesian)) {
throw new DeveloperError('cartesian is required.');
}
Check.defined('cartesian', cartesian);
//>>includeEnd('debug');

var ray = scratchProjectPointOntoPlaneRay;
Expand Down Expand Up @@ -214,9 +210,7 @@ define([
*/
EllipsoidTangentPlane.prototype.projectPointsOntoPlane = function(cartesians, result) {
//>>includeStart('debug', pragmas.debug);
if (!defined(cartesians)) {
throw new DeveloperError('cartesians is required.');
}
Check.defined('cartesians', cartesians);
//>>includeEnd('debug');

if (!defined(result)) {
Expand Down Expand Up @@ -245,9 +239,7 @@ define([
*/
EllipsoidTangentPlane.prototype.projectPointToNearestOnPlane = function(cartesian, result) {
//>>includeStart('debug', pragmas.debug);
if (!defined(cartesian)) {
throw new DeveloperError('cartesian is required.');
}
Check.defined('cartesian', cartesian);
//>>includeEnd('debug');

if (!defined(result)) {
Expand Down Expand Up @@ -284,9 +276,7 @@ define([
*/
EllipsoidTangentPlane.prototype.projectPointsToNearestOnPlane = function(cartesians, result) {
//>>includeStart('debug', pragmas.debug);
if (!defined(cartesians)) {
throw new DeveloperError('cartesians is required.');
}
Check.defined('cartesians', cartesians);
//>>includeEnd('debug');

if (!defined(result)) {
Expand All @@ -302,6 +292,37 @@ define([
};

var projectPointsOntoEllipsoidScratch = new Cartesian3();
/**
* Computes the projection of the provided 2D position onto the 3D ellipsoid.
*
* @param {Cartesian2} cartesian The points to project.
* @param {Cartesian3} [result] The Cartesian3 instance to store result.
* @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if none was provided.
*/
EllipsoidTangentPlane.prototype.projectPointOntoEllipsoid = function(cartesian, result) {
//>>includeStart('debug', pragmas.debug);
Check.defined('cartesian', cartesian);
//>>includeEnd('debug');

if (!defined(result)) {
result = new Cartesian3();
}

var ellipsoid = this._ellipsoid;
var origin = this._origin;
var xAxis = this._xAxis;
var yAxis = this._yAxis;
var tmp = projectPointsOntoEllipsoidScratch;

Cartesian3.multiplyByScalar(xAxis, cartesian.x, tmp);
result = Cartesian3.add(origin, tmp, result);
Cartesian3.multiplyByScalar(yAxis, cartesian.y, tmp);
Cartesian3.add(result, tmp, result);
ellipsoid.scaleToGeocentricSurface(result, result);

return result;
};

/**
* Computes the projection of the provided 2D positions onto the 3D ellipsoid.
*
Expand All @@ -311,9 +332,7 @@ define([
*/
EllipsoidTangentPlane.prototype.projectPointsOntoEllipsoid = function(cartesians, result) {
//>>includeStart('debug', pragmas.debug);
if (!defined(cartesians)) {
throw new DeveloperError('cartesians is required.');
}
Check.defined('cartesians', cartesians);
//>>includeEnd('debug');

var length = cartesians.length;
Expand All @@ -323,22 +342,8 @@ define([
result.length = length;
}

var ellipsoid = this._ellipsoid;
var origin = this._origin;
var xAxis = this._xAxis;
var yAxis = this._yAxis;
var tmp = projectPointsOntoEllipsoidScratch;

for ( var i = 0; i < length; ++i) {
var position = cartesians[i];
Cartesian3.multiplyByScalar(xAxis, position.x, tmp);
if (!defined(result[i])) {
result[i] = new Cartesian3();
}
var point = Cartesian3.add(origin, tmp, result[i]);
Cartesian3.multiplyByScalar(yAxis, position.y, tmp);
Cartesian3.add(point, tmp, point);
ellipsoid.scaleToGeocentricSurface(point, point);
result[i] = this.projectPointOntoEllipsoid(cartesians[i], result[i]);
}

return result;
Expand Down
37 changes: 28 additions & 9 deletions Source/DataSources/PolygonGeometryUpdater.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
define([
'../Core/ApproximateTerrainHeights',
'../Core/Cartesian2',
'../Core/Cartesian3',
'../Core/Check',
'../Core/Color',
Expand All @@ -9,6 +10,7 @@ define([
'../Core/defined',
'../Core/DeveloperError',
'../Core/DistanceDisplayConditionGeometryInstanceAttribute',
'../Core/EllipsoidTangentPlane',
'../Core/GeometryInstance',
'../Core/GeometryOffsetAttribute',
'../Core/isArray',
Expand All @@ -30,6 +32,7 @@ define([
'./Property'
], function(
ApproximateTerrainHeights,
Cartesian2,
Cartesian3,
Check,
Color,
Expand All @@ -39,6 +42,7 @@ define([
defined,
DeveloperError,
DistanceDisplayConditionGeometryInstanceAttribute,
EllipsoidTangentPlane,
GeometryInstance,
GeometryOffsetAttribute,
isArray,
Expand All @@ -64,6 +68,8 @@ define([
var defaultOffset = Cartesian3.ZERO;
var offsetScratch = new Cartesian3();
var scratchRectangle = new Rectangle();
var scratch2DPositions = [];
var cart2Scratch = new Cartesian2();

function PolygonGeometryOptions(entity) {
this.id = entity;
Expand Down Expand Up @@ -216,17 +222,30 @@ define([
if (positions.length === 0) {
return;
}
var ellipsoid = this._scene.mapProjection.ellipsoid;

var centroid = Cartesian3.clone(Cartesian3.ZERO, result);
var length = positions.length;
for (var i = 0; i < length; i++) {
centroid = Cartesian3.add(positions[i], centroid, centroid);
}
centroid = Cartesian3.multiplyByScalar(centroid, 1 / length, centroid);
if (defined(this._scene.globe)) {
centroid = this._scene.globe.ellipsoid.scaleToGeodeticSurface(centroid, centroid);
var tangentPlane = EllipsoidTangentPlane.fromPoints(positions, ellipsoid);
var positions2D = tangentPlane.projectPointsOntoPlane(positions, scratch2DPositions);

var length = positions2D.length;
var area = 0;
var j = length - 1;
var centroid2D = new Cartesian2();
for (var i = 0; i < length; j = i++) {
var p1 = positions2D[i];
var p2 = positions2D[j];
var f = p1.x * p2.y - p2.x * p1.y;

var sum = Cartesian2.add(p1, p2, cart2Scratch);
sum = Cartesian2.multiplyByScalar(sum, f, sum);
centroid2D = Cartesian2.add(centroid2D, sum, centroid2D);

area += f;
}
return centroid;

var a = 1.0 / (area * 3.0);
centroid2D = Cartesian2.multiplyByScalar(centroid2D, a, centroid2D);
return tangentPlane.projectPointOntoEllipsoid(centroid2D, result);
};

PolygonGeometryUpdater.prototype._isHidden = function(entity, polygon) {
Expand Down
Loading

0 comments on commit 1f62bd9

Please sign in to comment.