jsxgraph 1.4.5 → 1.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/Readme.md +17 -0
- package/build/bin/jsxcompressor.js +1 -0
- package/build/bin/jsxgraphcore-min.js +7 -0
- package/build/bin/jsxgraphcore.js +83017 -0
- package/build/bin/jsxgraphcore.min.js +67 -0
- package/build/compressor.build.json +14 -0
- package/build/compressor.deps.js +8 -0
- package/build/core-amd.build.json +14 -0
- package/build/core-amd.deps.js +81 -0
- package/build/core.build.json +14 -0
- package/build/core.deps.js +102 -0
- package/build/plot.build.json +15 -0
- package/distrib/geogebra.min.js +1 -1
- package/distrib/geonext.min.js +1 -1
- package/distrib/index.d.ts +1 -0
- package/distrib/intergeo.min.js +1 -1
- package/distrib/jsxgraph.css +6 -0
- package/distrib/jsxgraphcore.js +3 -3
- package/distrib/jsxgraphsrc.js +3326 -1816
- package/distrib/sketch.min.js +1 -1
- package/package.json +1 -1
- package/src/3d/box3d.js +43 -38
- package/src/3d/curve3d.js +157 -53
- package/src/3d/element3d.js +84 -0
- package/src/3d/linspace3d.js +427 -146
- package/src/3d/point3d.js +352 -153
- package/src/3d/surface3d.js +140 -42
- package/src/3d/view3d.js +319 -164
- package/src/base/board.js +42 -26
- package/src/base/constants.js +8 -1
- package/src/base/curve.js +51 -9
- package/src/base/polygon.js +111 -69
- package/src/base/text.js +125 -51
- package/src/base/ticks.js +11 -2
- package/src/element/button.js +7 -3
- package/src/element/checkbox.js +8 -4
- package/src/element/composition.js +7 -1
- package/src/element/conic.js +2 -2
- package/src/element/input.js +9 -5
- package/src/jsxgraph.js +2 -0
- package/src/loadjsxgraph.js +13 -8
- package/src/math/clip.js +34 -134
- package/src/math/geometry.js +204 -3
- package/src/math/math.js +1 -2
- package/src/math/nlp.js +789 -730
- package/src/options.js +159 -8
- package/src/options3d.js +24 -7
- package/src/parser/jessiecode.js +8 -2
- package/src/renderer/abstract.js +26 -15
- package/src/renderer/canvas.js +2 -2
- package/src/renderer/svg.js +15 -2
- package/src/utils/env.js +29 -46
- package/src/utils/type.js +75 -2
- package/src/3d/threed.js +0 -38
package/src/base/board.js
CHANGED
|
@@ -334,7 +334,7 @@ define([
|
|
|
334
334
|
this.numObjects = 0;
|
|
335
335
|
|
|
336
336
|
/**
|
|
337
|
-
* An associative array to store the objects of the board by name.
|
|
337
|
+
* An associative array / dictionary to store the objects of the board by name. The name of the object is the key and value is a reference to the object.
|
|
338
338
|
* @type Object
|
|
339
339
|
*/
|
|
340
340
|
this.elementsByName = {};
|
|
@@ -819,7 +819,7 @@ define([
|
|
|
819
819
|
// In ownerDoc we need the "real" document object.
|
|
820
820
|
// The first version is used in the case of shadowDom,
|
|
821
821
|
// the second case in the "normal" case.
|
|
822
|
-
ownerDoc = this.document.ownerDocument || this.document,
|
|
822
|
+
ownerDoc = this.document.ownerDocument || this.document,
|
|
823
823
|
docElement = ownerDoc.documentElement || this.document.body.parentNode,
|
|
824
824
|
docBody = ownerDoc.body,
|
|
825
825
|
container = this.containerObj,
|
|
@@ -5345,7 +5345,7 @@ define([
|
|
|
5345
5345
|
return s;
|
|
5346
5346
|
}
|
|
5347
5347
|
|
|
5348
|
-
//
|
|
5348
|
+
// It's a string, most likely an id or a name.
|
|
5349
5349
|
if (Type.isString(s) && s !== '') {
|
|
5350
5350
|
// Search by ID
|
|
5351
5351
|
if (Type.exists(this.objects[s])) {
|
|
@@ -5357,7 +5357,8 @@ define([
|
|
|
5357
5357
|
} else if (Type.exists(this.groups[s])) {
|
|
5358
5358
|
s = this.groups[s];
|
|
5359
5359
|
}
|
|
5360
|
-
|
|
5360
|
+
|
|
5361
|
+
// It's a function or an object, but not an element
|
|
5361
5362
|
} else if (!onlyByIdOrName &&
|
|
5362
5363
|
(Type.isFunction(s) ||
|
|
5363
5364
|
(Type.isObject(s) && !Type.isFunction(s.setAttribute))
|
|
@@ -5370,7 +5371,8 @@ define([
|
|
|
5370
5371
|
olist[flist[i].id] = flist[i];
|
|
5371
5372
|
}
|
|
5372
5373
|
s = new Composition(olist);
|
|
5373
|
-
|
|
5374
|
+
|
|
5375
|
+
// It's an element which has been deleted (and still hangs around, e.g. in an attractor list
|
|
5374
5376
|
} else if (Type.isObject(s) && Type.exists(s.id) && !Type.exists(this.objects[s.id])) {
|
|
5375
5377
|
s = null;
|
|
5376
5378
|
}
|
|
@@ -6006,7 +6008,7 @@ define([
|
|
|
6006
6008
|
*/
|
|
6007
6009
|
toFullscreen: function (id) {
|
|
6008
6010
|
var wrap_id, wrap_node, inner_node,
|
|
6009
|
-
doc = this.document;
|
|
6011
|
+
doc = this.document, fullscreenElement;
|
|
6010
6012
|
|
|
6011
6013
|
id = id || this.container;
|
|
6012
6014
|
this._fullscreen_inner_id = id;
|
|
@@ -6026,7 +6028,7 @@ define([
|
|
|
6026
6028
|
|
|
6027
6029
|
// Get the real width and height of the JSXGraph div
|
|
6028
6030
|
// and determine the scaling and vertical shift amount
|
|
6029
|
-
this._fullscreen_res = Env._getScaleFactors(inner_node);
|
|
6031
|
+
// this._fullscreen_res = Env._getScaleFactors(inner_node);
|
|
6030
6032
|
|
|
6031
6033
|
// Trigger fullscreen mode
|
|
6032
6034
|
wrap_node.requestFullscreen = wrap_node.requestFullscreen ||
|
|
@@ -6034,14 +6036,24 @@ define([
|
|
|
6034
6036
|
wrap_node.mozRequestFullScreen ||
|
|
6035
6037
|
wrap_node.msRequestFullscreen;
|
|
6036
6038
|
|
|
6037
|
-
if (doc.fullscreenElement
|
|
6039
|
+
if (doc.fullscreenElement !== undefined) {
|
|
6040
|
+
fullscreenElement = doc.fullscreenElement;
|
|
6041
|
+
} else if (doc.webkitFullscreenElement !== undefined) {
|
|
6042
|
+
fullscreenElement = doc.webkitFullscreenElement;
|
|
6043
|
+
} else {
|
|
6044
|
+
fullscreenElement = doc.msFullscreenElement;
|
|
6045
|
+
}
|
|
6046
|
+
if (fullscreenElement === null) {
|
|
6038
6047
|
// Start fullscreen mode
|
|
6039
6048
|
if (wrap_node.requestFullscreen) {
|
|
6040
6049
|
wrap_node.requestFullscreen();
|
|
6041
6050
|
}
|
|
6042
6051
|
} else {
|
|
6043
|
-
|
|
6044
|
-
|
|
6052
|
+
if (Type.exists(document.exitFullscreen)) {
|
|
6053
|
+
document.exitFullscreen();
|
|
6054
|
+
} else if (Type.exists(document.webkitExitFullscreen)) {
|
|
6055
|
+
document.webkitExitFullscreen();
|
|
6056
|
+
}
|
|
6045
6057
|
}
|
|
6046
6058
|
|
|
6047
6059
|
return this;
|
|
@@ -6055,7 +6067,7 @@ define([
|
|
|
6055
6067
|
* @param {Object} evt fullscreen event object (unused)
|
|
6056
6068
|
*/
|
|
6057
6069
|
fullscreenListener: function (evt) {
|
|
6058
|
-
var
|
|
6070
|
+
var inner_id, inner_node, fullscreenElement, // res,
|
|
6059
6071
|
doc = this.document;
|
|
6060
6072
|
|
|
6061
6073
|
inner_id = this._fullscreen_inner_id;
|
|
@@ -6063,20 +6075,23 @@ define([
|
|
|
6063
6075
|
return;
|
|
6064
6076
|
}
|
|
6065
6077
|
|
|
6066
|
-
doc.fullscreenElement
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6078
|
+
if (doc.fullscreenElement !== undefined) {
|
|
6079
|
+
fullscreenElement = doc.fullscreenElement;
|
|
6080
|
+
} else if (doc.webkitFullscreenElement !== undefined) {
|
|
6081
|
+
fullscreenElement = doc.webkitFullscreenElement;
|
|
6082
|
+
} else {
|
|
6083
|
+
fullscreenElement = doc.msFullscreenElement;
|
|
6084
|
+
}
|
|
6070
6085
|
|
|
6071
6086
|
inner_node = doc.getElementById(inner_id);
|
|
6072
6087
|
// If full screen mode is started we have to remove CSS margin around the JSXGraph div.
|
|
6073
6088
|
// Otherwise, the positioning of the fullscreen div will be false.
|
|
6074
6089
|
// When leaving the fullscreen mode, the margin is put back in.
|
|
6075
|
-
if (
|
|
6090
|
+
if (fullscreenElement) {
|
|
6076
6091
|
// Just entered fullscreen mode
|
|
6077
6092
|
|
|
6078
6093
|
// Get the data computed in board.toFullscreen()
|
|
6079
|
-
res = this._fullscreen_res;
|
|
6094
|
+
// res = this._fullscreen_res;
|
|
6080
6095
|
|
|
6081
6096
|
// Store the scaling data.
|
|
6082
6097
|
// It is used in AbstractRenderer.updateText to restore the scaling matrix
|
|
@@ -6084,25 +6099,26 @@ define([
|
|
|
6084
6099
|
// Further, the CSS margin has to be removed when in fullscreen mode,
|
|
6085
6100
|
// and must be restored later.
|
|
6086
6101
|
inner_node._cssFullscreenStore = {
|
|
6087
|
-
id:
|
|
6102
|
+
id: fullscreenElement.id,
|
|
6088
6103
|
isFullscreen: true,
|
|
6089
6104
|
margin: inner_node.style.margin,
|
|
6090
|
-
width: inner_node.style.width
|
|
6091
|
-
scale: res.scale,
|
|
6092
|
-
vshift: res.vshift
|
|
6105
|
+
// width: inner_node.style.width
|
|
6106
|
+
// scale: res.scale,
|
|
6107
|
+
// vshift: res.vshift
|
|
6093
6108
|
};
|
|
6094
6109
|
|
|
6095
6110
|
inner_node.style.margin = '';
|
|
6096
|
-
inner_node.style.width = res.width + 'px';
|
|
6111
|
+
// inner_node.style.width = res.width + 'px';
|
|
6097
6112
|
|
|
6098
6113
|
// Do the shifting and scaling via CSS pseudo rules
|
|
6099
6114
|
// We do this after fullscreen mode has been established to get the correct size
|
|
6100
6115
|
// of the JSXGraph div.
|
|
6101
|
-
Env.scaleJSXGraphDiv(
|
|
6116
|
+
// Env.scaleJSXGraphDiv(fullscreenElement.id, inner_id, res.scale, res.vshift, res.ratio, doc);
|
|
6117
|
+
Env.scaleJSXGraphDiv(fullscreenElement.id, inner_id, doc);
|
|
6102
6118
|
|
|
6103
|
-
// Clear this.
|
|
6119
|
+
// Clear this.doc.fullscreenElement, because Safari doesn't to it and
|
|
6104
6120
|
// when leaving full screen mode it is still set.
|
|
6105
|
-
|
|
6121
|
+
fullscreenElement = null;
|
|
6106
6122
|
|
|
6107
6123
|
} else if (Type.exists(inner_node._cssFullscreenStore)) {
|
|
6108
6124
|
// Just left the fullscreen mode
|
|
@@ -6116,7 +6132,7 @@ define([
|
|
|
6116
6132
|
|
|
6117
6133
|
inner_node._cssFullscreenStore.isFullscreen = false;
|
|
6118
6134
|
inner_node.style.margin = inner_node._cssFullscreenStore.margin;
|
|
6119
|
-
inner_node.style.width = inner_node._cssFullscreenStore.width;
|
|
6135
|
+
// inner_node.style.width = inner_node._cssFullscreenStore.width;
|
|
6120
6136
|
}
|
|
6121
6137
|
|
|
6122
6138
|
this.updateCSSTransforms();
|
package/src/base/constants.js
CHANGED
|
@@ -42,7 +42,7 @@ define(['jxg'], function (JXG) {
|
|
|
42
42
|
|
|
43
43
|
var major = 1,
|
|
44
44
|
minor = 4,
|
|
45
|
-
patch =
|
|
45
|
+
patch = 6,
|
|
46
46
|
add = '', //'dev'
|
|
47
47
|
version = major + '.' + minor + '.' + patch + (add ? '-' + add : ''),
|
|
48
48
|
constants;
|
|
@@ -111,7 +111,13 @@ define(['jxg'], function (JXG) {
|
|
|
111
111
|
OBJECT_TYPE_BUTTON: 29,
|
|
112
112
|
OBJECT_TYPE_TRANSFORMATION: 30,
|
|
113
113
|
OBJECT_TYPE_FOREIGNOBJECT: 31,
|
|
114
|
+
|
|
114
115
|
OBJECT_TYPE_VIEW3D: 32,
|
|
116
|
+
OBJECT_TYPE_POINT3D: 33,
|
|
117
|
+
OBJECT_TYPE_LINE3D: 34,
|
|
118
|
+
OBJECT_TYPE_PLANE3D: 35,
|
|
119
|
+
OBJECT_TYPE_CURVE3D: 36,
|
|
120
|
+
OBJECT_TYPE_SURFACE3D: 37,
|
|
115
121
|
|
|
116
122
|
// IMPORTANT:
|
|
117
123
|
// ----------
|
|
@@ -127,6 +133,7 @@ define(['jxg'], function (JXG) {
|
|
|
127
133
|
OBJECT_CLASS_AREA: 5,
|
|
128
134
|
OBJECT_CLASS_OTHER: 6,
|
|
129
135
|
OBJECT_CLASS_TEXT: 7,
|
|
136
|
+
OBJECT_CLASS_3D: 8,
|
|
130
137
|
|
|
131
138
|
// SketchReader constants
|
|
132
139
|
GENTYPE_ABC: 1, // unused
|
package/src/base/curve.js
CHANGED
|
@@ -235,7 +235,7 @@ define([
|
|
|
235
235
|
*/
|
|
236
236
|
hasPoint: function (x, y, start) {
|
|
237
237
|
var t, checkPoint, len, invMat, c,
|
|
238
|
-
i, tX, tY,
|
|
238
|
+
i, tX, tY, isIn,
|
|
239
239
|
res = [],
|
|
240
240
|
points, qdt,
|
|
241
241
|
steps = Type.evaluate(this.visProp.numberpointslow),
|
|
@@ -255,10 +255,20 @@ define([
|
|
|
255
255
|
// 'inherit'
|
|
256
256
|
prec = this.board.options.precision.hasPoint;
|
|
257
257
|
}
|
|
258
|
+
|
|
259
|
+
// From now on, x,y are usrCoords
|
|
258
260
|
checkPoint = new Coords(Const.COORDS_BY_SCREEN, [x, y], this.board, false);
|
|
259
261
|
x = checkPoint.usrCoords[1];
|
|
260
262
|
y = checkPoint.usrCoords[2];
|
|
261
263
|
|
|
264
|
+
// Handle inner points of the curve
|
|
265
|
+
if (this.bezierDegree === 1 && Type.evaluate(this.visProp.hasinnerpoints)) {
|
|
266
|
+
isIn = Geometry.windingNumber([1, x, y], this.points, true);
|
|
267
|
+
if (isIn !== 0) {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
262
272
|
// We use usrCoords. Only in the final distance calculation
|
|
263
273
|
// screen coords are used
|
|
264
274
|
prec += Type.evaluate(this.visProp.strokewidth) * 0.5;
|
|
@@ -276,11 +286,11 @@ define([
|
|
|
276
286
|
|
|
277
287
|
ev_ct = Type.evaluate(this.visProp.curvetype);
|
|
278
288
|
if (ev_ct === 'parameter' || ev_ct === 'polar') {
|
|
289
|
+
|
|
290
|
+
// Transform the mouse/touch coordinates
|
|
291
|
+
// back to the original position of the curve.
|
|
292
|
+
// This is needed, because we work with the function terms, not the points.
|
|
279
293
|
if (this.transformations.length > 0) {
|
|
280
|
-
/**
|
|
281
|
-
* Transform the mouse/touch coordinates
|
|
282
|
-
* back to the original position of the curve.
|
|
283
|
-
*/
|
|
284
294
|
this.updateTransformMatrix();
|
|
285
295
|
invMat = Mat.inverse(this.transformMat);
|
|
286
296
|
c = Mat.matVecMult(invMat, [1, x, y]);
|
|
@@ -304,6 +314,9 @@ define([
|
|
|
304
314
|
} else if (ev_ct === 'plot' ||
|
|
305
315
|
ev_ct === 'functiongraph') {
|
|
306
316
|
|
|
317
|
+
// Here, we can ignore transformations of the curve,
|
|
318
|
+
// since we are working directly with the points.
|
|
319
|
+
|
|
307
320
|
if (!Type.exists(start) || start < 0) {
|
|
308
321
|
start = 0;
|
|
309
322
|
}
|
|
@@ -1209,8 +1222,37 @@ define([
|
|
|
1209
1222
|
}
|
|
1210
1223
|
}
|
|
1211
1224
|
return [isTransformed, curve_org];
|
|
1225
|
+
},
|
|
1226
|
+
|
|
1227
|
+
pnpoly: function(x_in, y_in, coord_type) {
|
|
1228
|
+
var i, j, len,
|
|
1229
|
+
x, y, crds,
|
|
1230
|
+
v = this.points,
|
|
1231
|
+
isIn = false;
|
|
1232
|
+
|
|
1233
|
+
if (coord_type === Const.COORDS_BY_USER) {
|
|
1234
|
+
crds = new Coords(Const.COORDS_BY_USER, [x_in, y_in], this.board);
|
|
1235
|
+
x = crds.scrCoords[1];
|
|
1236
|
+
y = crds.scrCoords[2];
|
|
1237
|
+
} else {
|
|
1238
|
+
x = x_in;
|
|
1239
|
+
y = y_in;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
len = this.points.length;
|
|
1243
|
+
for (i = 0, j = len - 2; i < len - 1; j = i++) {
|
|
1244
|
+
if (((v[i].scrCoords[2] > y) !== (v[j].scrCoords[2] > y)) &&
|
|
1245
|
+
(x < (v[j].scrCoords[1] - v[i].scrCoords[1]) *
|
|
1246
|
+
(y - v[i].scrCoords[2]) / (v[j].scrCoords[2] - v[i].scrCoords[2]) + v[i].scrCoords[1])
|
|
1247
|
+
) {
|
|
1248
|
+
isIn = !isIn;
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
return isIn;
|
|
1212
1253
|
}
|
|
1213
1254
|
|
|
1255
|
+
|
|
1214
1256
|
});
|
|
1215
1257
|
|
|
1216
1258
|
/**
|
|
@@ -1378,13 +1420,13 @@ define([
|
|
|
1378
1420
|
attr = Type.copyAttributes(attributes, board.options, 'curve');
|
|
1379
1421
|
|
|
1380
1422
|
obj = board.select(parents[0], true);
|
|
1381
|
-
if (Type.
|
|
1423
|
+
if (Type.isTransformationOrArray(parents[1]) &&
|
|
1424
|
+
Type.isObject(obj) &&
|
|
1382
1425
|
(obj.type === Const.OBJECT_TYPE_CURVE ||
|
|
1383
1426
|
obj.type === Const.OBJECT_TYPE_ANGLE ||
|
|
1384
1427
|
obj.type === Const.OBJECT_TYPE_ARC ||
|
|
1385
1428
|
obj.type === Const.OBJECT_TYPE_CONIC ||
|
|
1386
|
-
obj.type === Const.OBJECT_TYPE_SECTOR)
|
|
1387
|
-
Type.isTransformationOrArray(parents[1])) {
|
|
1429
|
+
obj.type === Const.OBJECT_TYPE_SECTOR) ) {
|
|
1388
1430
|
|
|
1389
1431
|
if (obj.type === Const.OBJECT_TYPE_SECTOR) {
|
|
1390
1432
|
attr = Type.copyAttributes(attributes, board.options, 'sector');
|
|
@@ -2326,7 +2368,7 @@ define([
|
|
|
2326
2368
|
/**
|
|
2327
2369
|
* @ignore
|
|
2328
2370
|
*/
|
|
2329
|
-
|
|
2371
|
+
c.updateDataArray = function () {
|
|
2330
2372
|
var i, j = 0,
|
|
2331
2373
|
len = this.xterm.length;
|
|
2332
2374
|
|
package/src/base/polygon.js
CHANGED
|
@@ -80,6 +80,14 @@ define([
|
|
|
80
80
|
this.vertices = [];
|
|
81
81
|
for (i = 0; i < vertices.length; i++) {
|
|
82
82
|
this.vertices[i] = this.board.select(vertices[i]);
|
|
83
|
+
|
|
84
|
+
// The _is_new flag is replaced by _is_new_pol.
|
|
85
|
+
// Otherwise, the polygon would disappear if the last border element
|
|
86
|
+
// is removed (and the point has been provided by coordinates)
|
|
87
|
+
if (this.vertices[i]._is_new) {
|
|
88
|
+
delete this.vertices[i]._is_new;
|
|
89
|
+
this.vertices[i]._is_new_pol = true;
|
|
90
|
+
}
|
|
83
91
|
}
|
|
84
92
|
|
|
85
93
|
// Close the polygon
|
|
@@ -127,9 +135,9 @@ define([
|
|
|
127
135
|
// - add points (supplied as coordinate arrays by the user and created by Type.providePoints) as children to the polygon
|
|
128
136
|
for (i = 0; i < this.vertices.length - 1; i++) {
|
|
129
137
|
p = this.board.select(this.vertices[i]);
|
|
130
|
-
if (Type.exists(p.
|
|
138
|
+
if (Type.exists(p._is_new_pol)) {
|
|
131
139
|
this.addChild(p);
|
|
132
|
-
delete p.
|
|
140
|
+
delete p._is_new_pol;
|
|
133
141
|
} else {
|
|
134
142
|
p.addChild(this);
|
|
135
143
|
}
|
|
@@ -165,10 +173,7 @@ define([
|
|
|
165
173
|
JXG.extend(JXG.Polygon.prototype, /** @lends JXG.Polygon.prototype */ {
|
|
166
174
|
|
|
167
175
|
/**
|
|
168
|
-
*
|
|
169
|
-
* Implements W. Randolf Franklin's pnpoly method.
|
|
170
|
-
*
|
|
171
|
-
* See <a href="https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html">https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html</a>.
|
|
176
|
+
* Wrapper for JXG.Math.Geometry.pnpoly.
|
|
172
177
|
*
|
|
173
178
|
* @param {Number} x_in x-coordinate (screen or user coordinates)
|
|
174
179
|
* @param {Number} y_in y-coordinate (screen or user coordinates)
|
|
@@ -176,7 +181,9 @@ define([
|
|
|
176
181
|
* Possible values are <b>JXG.COORDS_BY_USER</b> and <b>JXG.COORDS_BY_SCREEN</b>.
|
|
177
182
|
* Default value is JXG.COORDS_BY_SCREEN
|
|
178
183
|
*
|
|
179
|
-
* @returns {Boolean} if (
|
|
184
|
+
* @returns {Boolean} if (x_in, y_in) is inside of the polygon.
|
|
185
|
+
* @see JXG.Math.Geometry#pnpoly
|
|
186
|
+
*
|
|
180
187
|
* @example
|
|
181
188
|
* var pol = board.create('polygon', [[-1,2], [2,2], [-1,4]]);
|
|
182
189
|
* var p = board.create('point', [4, 3]);
|
|
@@ -202,31 +209,7 @@ define([
|
|
|
202
209
|
*
|
|
203
210
|
*/
|
|
204
211
|
pnpoly: function(x_in, y_in, coord_type) {
|
|
205
|
-
|
|
206
|
-
x, y, crds,
|
|
207
|
-
v = this.vertices,
|
|
208
|
-
isIn = false;
|
|
209
|
-
|
|
210
|
-
if (coord_type === Const.COORDS_BY_USER) {
|
|
211
|
-
crds = new Coords(Const.COORDS_BY_USER, [x_in, y_in], this.board);
|
|
212
|
-
x = crds.scrCoords[1];
|
|
213
|
-
y = crds.scrCoords[2];
|
|
214
|
-
} else {
|
|
215
|
-
x = x_in;
|
|
216
|
-
y = y_in;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
len = this.vertices.length;
|
|
220
|
-
for (i = 0, j = len - 2; i < len - 1; j = i++) {
|
|
221
|
-
if (((v[i].coords.scrCoords[2] > y) !== (v[j].coords.scrCoords[2] > y)) &&
|
|
222
|
-
(x < (v[j].coords.scrCoords[1] - v[i].coords.scrCoords[1]) *
|
|
223
|
-
(y - v[i].coords.scrCoords[2]) / (v[j].coords.scrCoords[2] - v[i].coords.scrCoords[2]) + v[i].coords.scrCoords[1])
|
|
224
|
-
) {
|
|
225
|
-
isIn = !isIn;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
return isIn;
|
|
212
|
+
return Geometry.pnpoly(x_in, y_in, this.vertices, coord_type);
|
|
230
213
|
},
|
|
231
214
|
|
|
232
215
|
/**
|
|
@@ -590,9 +573,14 @@ define([
|
|
|
590
573
|
*
|
|
591
574
|
*/
|
|
592
575
|
addPoints: function (p) {
|
|
593
|
-
var args = Array.prototype.slice.call(arguments);
|
|
576
|
+
var idx, args = Array.prototype.slice.call(arguments);
|
|
594
577
|
|
|
595
|
-
|
|
578
|
+
if (this.elType === 'polygonalchain') {
|
|
579
|
+
idx = this.vertices.length - 1;
|
|
580
|
+
} else {
|
|
581
|
+
idx = this.vertices.length - 2;
|
|
582
|
+
}
|
|
583
|
+
return this.insertPoints.apply(this, [idx].concat(args));
|
|
596
584
|
},
|
|
597
585
|
|
|
598
586
|
/**
|
|
@@ -630,38 +618,65 @@ define([
|
|
|
630
618
|
*
|
|
631
619
|
*/
|
|
632
620
|
insertPoints: function (idx, p) {
|
|
633
|
-
var i, le;
|
|
621
|
+
var i, le, last, start, q;
|
|
634
622
|
|
|
635
623
|
if (arguments.length === 0) {
|
|
636
624
|
return this;
|
|
637
625
|
}
|
|
638
626
|
|
|
627
|
+
last = this.vertices.length - 1;
|
|
628
|
+
if (this.elType === 'polygon') {
|
|
629
|
+
last--;
|
|
630
|
+
}
|
|
639
631
|
|
|
640
|
-
|
|
632
|
+
// Wrong insertion index, get out of here
|
|
633
|
+
if (idx < -1 || idx > last) {
|
|
641
634
|
return this;
|
|
642
635
|
}
|
|
643
636
|
|
|
644
637
|
le = arguments.length - 1;
|
|
645
638
|
for (i = 1; i < le + 1; i++) {
|
|
646
|
-
this.
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
639
|
+
q = Type.providePoints(this.board, [arguments[i]], {}, 'polygon', ['vertices'])[0];
|
|
640
|
+
if (q._is_new) {
|
|
641
|
+
// Add the point as child of the polygon, but not of the borders.
|
|
642
|
+
this.addChild(q);
|
|
643
|
+
delete q._is_new;
|
|
644
|
+
}
|
|
645
|
+
this.vertices.splice(idx + i, 0, q);
|
|
652
646
|
}
|
|
647
|
+
|
|
653
648
|
if (this.withLines) {
|
|
654
|
-
|
|
655
|
-
|
|
649
|
+
start = idx + 1;
|
|
650
|
+
if (this.elType === 'polygon') {
|
|
651
|
+
if (idx < 0) {
|
|
652
|
+
// Add point(s) in the front
|
|
653
|
+
this.vertices[this.vertices.length - 1] = this.vertices[0];
|
|
654
|
+
this.borders[this.borders.length - 1].point2 = this.vertices[this.vertices.length - 1];
|
|
655
|
+
} else {
|
|
656
|
+
// Insert point(s) (middle or end)
|
|
657
|
+
this.borders[idx].point2 = this.vertices[start];
|
|
658
|
+
}
|
|
656
659
|
} else {
|
|
657
|
-
|
|
660
|
+
// Add point(s) in the front: do nothing
|
|
661
|
+
// Else:
|
|
662
|
+
if (idx >= 0) {
|
|
663
|
+
if (idx < this.borders.length) {
|
|
664
|
+
// Insert point(s) in the middle
|
|
665
|
+
this.borders[idx].point2 = this.vertices[start];
|
|
666
|
+
} else {
|
|
667
|
+
// Add point at the end
|
|
668
|
+
start = idx;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
658
671
|
}
|
|
659
|
-
for (i =
|
|
672
|
+
for (i = start; i < start + le; i++) {
|
|
660
673
|
this.borders.splice(i, 0,
|
|
661
674
|
this.board.create('segment', [this.vertices[i], this.vertices[i + 1]], this.attr_line)
|
|
662
675
|
);
|
|
663
676
|
}
|
|
664
677
|
}
|
|
678
|
+
this.inherits = [];
|
|
679
|
+
this.inherits.push(this.vertices, this.borders);
|
|
665
680
|
this.board.update();
|
|
666
681
|
|
|
667
682
|
return this;
|
|
@@ -673,7 +688,8 @@ define([
|
|
|
673
688
|
* @returns {JXG.Polygon} Reference to the polygon
|
|
674
689
|
*/
|
|
675
690
|
removePoints: function (p) {
|
|
676
|
-
var i, j,
|
|
691
|
+
var i, j, j0, idx, firstPoint,
|
|
692
|
+
nvertices = [], nborders = [],
|
|
677
693
|
nidx = [], partition = [];
|
|
678
694
|
|
|
679
695
|
// Partition:
|
|
@@ -684,8 +700,11 @@ define([
|
|
|
684
700
|
// this gives us the borders, that can be removed and the borders we have to create.
|
|
685
701
|
|
|
686
702
|
|
|
687
|
-
//
|
|
688
|
-
|
|
703
|
+
// In case of polygon: remove the last vertex from the list of vertices since
|
|
704
|
+
// it is identical to the first
|
|
705
|
+
if (this.elType === 'polygon') {
|
|
706
|
+
firstPoint = this.vertices.pop();
|
|
707
|
+
}
|
|
689
708
|
|
|
690
709
|
// Collect all valid parameters as indices in nidx
|
|
691
710
|
for (i = 0; i < arguments.length; i++) {
|
|
@@ -693,12 +712,19 @@ define([
|
|
|
693
712
|
if (Type.isPoint(idx)) {
|
|
694
713
|
idx = this.findPoint(idx);
|
|
695
714
|
}
|
|
696
|
-
|
|
697
715
|
if (Type.isNumber(idx) && idx > -1 && idx < this.vertices.length && Type.indexOf(nidx, idx) === -1) {
|
|
698
716
|
nidx.push(idx);
|
|
699
717
|
}
|
|
700
718
|
}
|
|
701
719
|
|
|
720
|
+
if (nidx.length === 0) {
|
|
721
|
+
// Wrong index, get out of here
|
|
722
|
+
if (this.elType === 'polygon') {
|
|
723
|
+
this.vertices.push(firstPoint);
|
|
724
|
+
}
|
|
725
|
+
return this;
|
|
726
|
+
}
|
|
727
|
+
|
|
702
728
|
// Remove the polygon from each removed point's children
|
|
703
729
|
for (i = 0; i < nidx.length; i++) {
|
|
704
730
|
this.vertices[nidx[i]].removeChild(this);
|
|
@@ -709,7 +735,7 @@ define([
|
|
|
709
735
|
nvertices = this.vertices.slice();
|
|
710
736
|
nborders = this.borders.slice();
|
|
711
737
|
|
|
712
|
-
// Initialize the partition
|
|
738
|
+
// Initialize the partition with an array containing the last point to be removed
|
|
713
739
|
if (this.withLines) {
|
|
714
740
|
partition.push([nidx[nidx.length - 1]]);
|
|
715
741
|
}
|
|
@@ -719,7 +745,9 @@ define([
|
|
|
719
745
|
for (i = nidx.length - 1; i > -1; i--) {
|
|
720
746
|
nvertices[nidx[i]] = -1;
|
|
721
747
|
|
|
722
|
-
|
|
748
|
+
// Find gaps between the list of points to be removed.
|
|
749
|
+
// In this case a new partition is added.
|
|
750
|
+
if (this.withLines && nidx.length > 1 && (nidx[i] - 1 > nidx[i - 1])) {
|
|
723
751
|
partition[partition.length - 1][1] = nidx[i];
|
|
724
752
|
partition.push([nidx[i - 1]]);
|
|
725
753
|
}
|
|
@@ -737,7 +765,11 @@ define([
|
|
|
737
765
|
this.vertices.push(nvertices[i]);
|
|
738
766
|
}
|
|
739
767
|
}
|
|
740
|
-
|
|
768
|
+
|
|
769
|
+
// Close the polygon again
|
|
770
|
+
if (this.elType === 'polygon' &&
|
|
771
|
+
this.vertices.length > 1 &&
|
|
772
|
+
this.vertices[this.vertices.length - 1].id !== this.vertices[0].id) {
|
|
741
773
|
this.vertices.push(this.vertices[0]);
|
|
742
774
|
}
|
|
743
775
|
|
|
@@ -747,23 +779,28 @@ define([
|
|
|
747
779
|
for (j = partition[i][1] - 1; j < partition[i][0] + 1; j++) {
|
|
748
780
|
// special cases
|
|
749
781
|
if (j < 0) {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
782
|
+
if (this.elType === 'polygon') {
|
|
783
|
+
// First vertex is removed, so the last border has to be removed, too
|
|
784
|
+
this.board.removeObject(this.borders[nborders.length - 1]);
|
|
785
|
+
nborders[nborders.length - 1] = -1;
|
|
786
|
+
}
|
|
787
|
+
} else if (j < nborders.length) {
|
|
788
|
+
this.board.removeObject(this.borders[j]);
|
|
789
|
+
nborders[j] = -1;
|
|
756
790
|
}
|
|
757
|
-
|
|
758
|
-
this.board.removeObject(this.borders[j]);
|
|
759
|
-
nborders[j] = -1;
|
|
760
791
|
}
|
|
761
792
|
|
|
762
|
-
//
|
|
763
|
-
//
|
|
764
|
-
// just to be sure...
|
|
793
|
+
// Only create the new segment if it's not the closing border.
|
|
794
|
+
// The closing border is getting a special treatment at the end.
|
|
765
795
|
if (partition[i][1] !== 0 && partition[i][0] !== nvertices.length - 1) {
|
|
766
|
-
nborders[partition[i][0] - 1] = this.board.create('segment', [
|
|
796
|
+
// nborders[partition[i][0] - 1] = this.board.create('segment', [
|
|
797
|
+
// nvertices[Math.max(partition[i][1] - 1, 0)],
|
|
798
|
+
// nvertices[Math.min(partition[i][0] + 1, this.vertices.length - 1)]
|
|
799
|
+
// ], this.attr_line);
|
|
800
|
+
nborders[partition[i][0] - 1] = this.board.create('segment', [
|
|
801
|
+
nvertices[partition[i][1] - 1],
|
|
802
|
+
nvertices[partition[i][0] + 1]
|
|
803
|
+
], this.attr_line);
|
|
767
804
|
}
|
|
768
805
|
}
|
|
769
806
|
|
|
@@ -775,10 +812,16 @@ define([
|
|
|
775
812
|
}
|
|
776
813
|
|
|
777
814
|
// if the first and/or the last vertex is removed, the closing border is created at the end.
|
|
778
|
-
if (
|
|
779
|
-
this.
|
|
815
|
+
if (this.elType === 'polygon' &&
|
|
816
|
+
this.vertices.length > 2 && // Avoid trivial case of polygon with 1 vertex
|
|
817
|
+
(partition[0][1] === this.vertices.length - 1 || partition[partition.length - 1][1] === 0)) {
|
|
818
|
+
this.borders.push(this.board.create('segment',
|
|
819
|
+
[this.vertices[0], this.vertices[this.vertices.length - 2]],
|
|
820
|
+
this.attr_line));
|
|
780
821
|
}
|
|
781
822
|
}
|
|
823
|
+
this.inherits = [];
|
|
824
|
+
this.inherits.push(this.vertices, this.borders);
|
|
782
825
|
|
|
783
826
|
this.board.update();
|
|
784
827
|
|
|
@@ -1025,7 +1068,6 @@ define([
|
|
|
1025
1068
|
return this.sutherlandHodgman(polygon);
|
|
1026
1069
|
}
|
|
1027
1070
|
|
|
1028
|
-
|
|
1029
1071
|
});
|
|
1030
1072
|
|
|
1031
1073
|
|