Skip to content

Commit e8843b4

Browse files
authored
Merge pull request #12650 from CesiumGS/improve-clipping-polygon-performance
Improve clipping polygon performance
2 parents b04b592 + 2d9d6f7 commit e8843b4

File tree

1 file changed

+91
-2
lines changed

1 file changed

+91
-2
lines changed

packages/engine/Source/Scene/ClippingPolygon.js

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,90 @@ function ClippingPolygon(options) {
4646
//>>includeEnd('debug');
4747

4848
this._ellipsoid = options.ellipsoid ?? Ellipsoid.default;
49-
this._positions = [...options.positions];
49+
this._positions = copyArrayCartesian3(options.positions);
50+
51+
/**
52+
* A copy of the input positions.
53+
*
54+
* This is used to detect modifications of the positions in
55+
* <code>coputeRectangle</code>: The rectangle only has
56+
* to be re-computed when these positions have changed.
57+
*
58+
* @type {Cartesian3[]|undefined}
59+
* @private
60+
*/
61+
this._cachedPositions = undefined;
62+
63+
/**
64+
* A cached version of the rectangle that is computed in
65+
* <code>computeRectangle</code>.
66+
*
67+
* This is only re-computed when the positions have changed, as
68+
* determined by comparing the <code>_positions</code> to the
69+
* <code>_cachedPositions</code>
70+
*
71+
* @type {Rectangle|undefined}
72+
* @private
73+
*/
74+
this._cachedRectangle = undefined;
75+
}
76+
77+
/**
78+
* Returns a deep copy of the given array.
79+
*
80+
* If the input is undefined, then <code>undefined</code> is returned.
81+
*
82+
* Otherwise, the result will be a copy of the given array, where
83+
* each element is copied with <code>Cartesian3.clone</code>.
84+
*
85+
* @param {Cartesian3[]|undefined} input The input array
86+
* @returns {Cartesian3[]|undefined} The copy
87+
*/
88+
function copyArrayCartesian3(input) {
89+
if (!defined(input)) {
90+
return undefined;
91+
}
92+
const n = input.length;
93+
const output = Array(n);
94+
for (let i = 0; i < n; i++) {
95+
output[i] = Cartesian3.clone(input[i]);
96+
}
97+
return output;
98+
}
99+
100+
/**
101+
* Returns whether the given arrays are component-wise equal.
102+
*
103+
* When both arrays are undefined, then <code>true</code> is returned.
104+
* When only one array is defined, or they are both defined but have
105+
* different lengths, then <code>false</code> is returned.
106+
*
107+
* Otherwise, returns whether the corresponding elements of the arrays
108+
* are equal, as of <code>Cartesian3.equals</code>.
109+
*
110+
* @param {Cartesian3[]|undefined} a The first array
111+
* @param {Cartesian3[]|undefined} b The second array
112+
* @returns {boolean} Whether the arrays are equal
113+
*/
114+
function equalsArrayCartesian3(a, b) {
115+
if (!defined(a) && !defined(b)) {
116+
return true;
117+
}
118+
if (defined(a) !== defined(b)) {
119+
return false;
120+
}
121+
if (a.length !== b.length) {
122+
return false;
123+
}
124+
const n = a.length;
125+
for (let i = 0; i < n; i++) {
126+
const ca = a[i];
127+
const cb = b[i];
128+
if (!Cartesian3.equals(ca, cb)) {
129+
return false;
130+
}
131+
}
132+
return true;
50133
}
51134

52135
Object.defineProperties(ClippingPolygon.prototype, {
@@ -138,12 +221,18 @@ ClippingPolygon.equals = function (left, right) {
138221
* @returns {Rectangle} The result rectangle
139222
*/
140223
ClippingPolygon.prototype.computeRectangle = function (result) {
141-
return PolygonGeometry.computeRectangleFromPositions(
224+
if (equalsArrayCartesian3(this._positions, this._cachedPositions)) {
225+
return Rectangle.clone(this._cachedRectangle, result);
226+
}
227+
const rectangle = PolygonGeometry.computeRectangleFromPositions(
142228
this.positions,
143229
this.ellipsoid,
144230
undefined,
145231
result,
146232
);
233+
this._cachedPositions = copyArrayCartesian3(this._positions);
234+
this._cachedRectangle = Rectangle.clone(rectangle);
235+
return rectangle;
147236
};
148237

149238
const scratchRectangle = new Rectangle();

0 commit comments

Comments
 (0)