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/math/clip.js
CHANGED
|
@@ -126,114 +126,6 @@ define([
|
|
|
126
126
|
return components;
|
|
127
127
|
},
|
|
128
128
|
|
|
129
|
-
/**
|
|
130
|
-
* Determinant of three points in the Euclidean plane.
|
|
131
|
-
* Zero, if the points are collinear. Used to determine of a point q is left or
|
|
132
|
-
* right to a segment defined by points p1 and p2.
|
|
133
|
-
* @private
|
|
134
|
-
* @param {Array} p1 Coordinates of the first point of the segment. Array of length 3. First coordinate is equal to 1.
|
|
135
|
-
* @param {Array} p2 Coordinates of the second point of the segment. Array of length 3. First coordinate is equal to 1.
|
|
136
|
-
* @param {Array} q Coordinates of the point. Array of length 3. First coordinate is equal to 1.
|
|
137
|
-
* @return {Number} Signed area of the triangle formed by these three points.
|
|
138
|
-
*/
|
|
139
|
-
det: function(p1, p2, q) {
|
|
140
|
-
return (p1[1] - q[1]) * (p2[2] - q[2]) - (p2[1] - q[1]) * (p1[2] - q[2]);
|
|
141
|
-
},
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Winding number of a point in respect to a polygon path.
|
|
145
|
-
*
|
|
146
|
-
* The point is regarded outside if the winding number is zero,
|
|
147
|
-
* inside otherwise. The algorithm tries to find degenerate cases, i.e.
|
|
148
|
-
* if the point is on the path. This is regarded as "outside".
|
|
149
|
-
* If the point is a vertex of the path, it is regarded as "inside".
|
|
150
|
-
*
|
|
151
|
-
* Implementation of algorithm 7 from "The point in polygon problem for
|
|
152
|
-
* arbitrary polygons" by Kai Hormann and Alexander Agathos, Computational Geometry,
|
|
153
|
-
* Volume 20, Issue 3, November 2001, Pages 131-144.
|
|
154
|
-
*
|
|
155
|
-
* @param {Array} usrCoords Homogenous coordinates of the point
|
|
156
|
-
* @param {Array} path Array of points determining a path, i.e. the vertices of the polygon. The array elements
|
|
157
|
-
* do not have to be full points, but have to have a subobject "coords".
|
|
158
|
-
* @return {Number} Winding number of the point. The point is
|
|
159
|
-
* regarded outside if the winding number is zero,
|
|
160
|
-
* inside otherwise.
|
|
161
|
-
*/
|
|
162
|
-
windingNumber: function(usrCoords, path) {
|
|
163
|
-
var wn = 0,
|
|
164
|
-
le = path.length,
|
|
165
|
-
x = usrCoords[1],
|
|
166
|
-
y = usrCoords[2],
|
|
167
|
-
p1, p2, d, sign, i;
|
|
168
|
-
|
|
169
|
-
if (le === 0) {
|
|
170
|
-
return 0;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Infinite points are declared outside
|
|
174
|
-
if (isNaN(x) || isNaN(y)) {
|
|
175
|
-
return 1;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Handle the case if the point is a vertex of the path
|
|
179
|
-
if (path[0].coords.usrCoords[1] === x &&
|
|
180
|
-
path[0].coords.usrCoords[2] === y) {
|
|
181
|
-
|
|
182
|
-
// console.log('<<<<<<< Vertex 1');
|
|
183
|
-
return 1;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
for (i = 0; i < le; i++) {
|
|
187
|
-
// Consider the edge from p1 = path[i] to p2 = path[i+1]
|
|
188
|
-
p1 = path[i].coords.usrCoords;
|
|
189
|
-
p2 = path[(i + 1) % le].coords.usrCoords;
|
|
190
|
-
if (p1[0] === 0 || p2[0] === 0 ||
|
|
191
|
-
isNaN(p1[1]) || isNaN(p2[1]) ||
|
|
192
|
-
isNaN(p1[2]) || isNaN(p2[2])) {
|
|
193
|
-
|
|
194
|
-
continue;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (p2[2] === y) {
|
|
198
|
-
if (p2[1] === x) {
|
|
199
|
-
// console.log('<<<<<<< Vertex 2');
|
|
200
|
-
return 1;
|
|
201
|
-
}
|
|
202
|
-
if (p1[2] === y && ((p2[1] > x) === (p1[1] < x))) {
|
|
203
|
-
// console.log('<<<<<<< Edge 1', p1, p2, [x, y]);
|
|
204
|
-
return 0;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if ((p1[2] < y) !== (p2[2] < y)) {
|
|
209
|
-
sign = 2 * ((p2[2] > p1[2]) ? 1 : 0) - 1;
|
|
210
|
-
if (p1[1] >= x) {
|
|
211
|
-
if (p2[1] > x) {
|
|
212
|
-
wn += sign;
|
|
213
|
-
} else {
|
|
214
|
-
d = this.det(p1, p2, usrCoords);
|
|
215
|
-
if (d === 0) {
|
|
216
|
-
// console.log('<<<<<<< Edge 2');
|
|
217
|
-
return 0;
|
|
218
|
-
}
|
|
219
|
-
if ((d > 0) === (p2[2] > p1[2])) {
|
|
220
|
-
wn += sign;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
} else {
|
|
224
|
-
if (p2[1] > x) {
|
|
225
|
-
d = this.det(p1, p2, usrCoords);
|
|
226
|
-
if ((d > 0 + Mat.eps) === (p2[2] > p1[2])) {
|
|
227
|
-
wn += sign;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return wn;
|
|
235
|
-
},
|
|
236
|
-
|
|
237
129
|
/**
|
|
238
130
|
* JavaScript object containing the intersection of two paths. Every intersection point is on one path, but
|
|
239
131
|
* comes with a neighbour point having the same coordinates and being on the other path.
|
|
@@ -655,9 +547,9 @@ define([
|
|
|
655
547
|
* @private
|
|
656
548
|
*/
|
|
657
549
|
_getPosition: function(q, p1, p2, p3) {
|
|
658
|
-
var s1 =
|
|
659
|
-
s2 =
|
|
660
|
-
s3 =
|
|
550
|
+
var s1 = Geometry.det3p(q, p1, p2),
|
|
551
|
+
s2 = Geometry.det3p(q, p2, p3),
|
|
552
|
+
s3 = Geometry.det3p(p1, p2, p3);
|
|
661
553
|
|
|
662
554
|
// Left turn
|
|
663
555
|
if (s3 >= 0) {
|
|
@@ -687,7 +579,7 @@ define([
|
|
|
687
579
|
*/
|
|
688
580
|
_classifyDegenerateIntersections: function(P) {
|
|
689
581
|
var Pp, Pm, Qp, Qm, Q, side,
|
|
690
|
-
cnt, tmp,
|
|
582
|
+
cnt, tmp, det,
|
|
691
583
|
oppositeDir,
|
|
692
584
|
s1, s2, s3, s4,
|
|
693
585
|
DEBUG = false;
|
|
@@ -695,6 +587,7 @@ define([
|
|
|
695
587
|
if (DEBUG) {
|
|
696
588
|
console.log("\n-------------- _classifyDegenerateIntersections()", (Type.exists(P.data))?P.data.pathname:' ');
|
|
697
589
|
}
|
|
590
|
+
det = Geometry.det3p;
|
|
698
591
|
cnt = 0;
|
|
699
592
|
P._tours = 0;
|
|
700
593
|
while (true) {
|
|
@@ -737,20 +630,20 @@ define([
|
|
|
737
630
|
console.log("Pp", this._getPosition(Pp, Qm, Q.coords.usrCoords, Qp));
|
|
738
631
|
}
|
|
739
632
|
|
|
740
|
-
s1 =
|
|
741
|
-
s2 =
|
|
742
|
-
s3 =
|
|
743
|
-
s4 =
|
|
633
|
+
s1 = det(P.coords.usrCoords, Pm, Qm);
|
|
634
|
+
s2 = det(P.coords.usrCoords, Pp, Qp);
|
|
635
|
+
s3 = det(P.coords.usrCoords, Pm, Qp);
|
|
636
|
+
s4 = det(P.coords.usrCoords, Pp, Qm);
|
|
744
637
|
|
|
745
638
|
if (s1 === 0 && s2 === 0 && s3 === 0 && s4 === 0) {
|
|
746
639
|
P.coords.usrCoords[1] *= 1 + Math.random() * Mat.eps;
|
|
747
640
|
P.coords.usrCoords[2] *= 1 + Math.random() * Mat.eps;
|
|
748
641
|
Q.coords.usrCoords[1] = P.coords.usrCoords[1];
|
|
749
642
|
Q.coords.usrCoords[2] = P.coords.usrCoords[2];
|
|
750
|
-
s1 =
|
|
751
|
-
s2 =
|
|
752
|
-
s3 =
|
|
753
|
-
s4 =
|
|
643
|
+
s1 = det(P.coords.usrCoords, Pm, Qm);
|
|
644
|
+
s2 = det(P.coords.usrCoords, Pp, Qp);
|
|
645
|
+
s3 = det(P.coords.usrCoords, Pm, Qp);
|
|
646
|
+
s4 = det(P.coords.usrCoords, Pp, Qm);
|
|
754
647
|
if (DEBUG) {
|
|
755
648
|
console.log("Random shift", P.coords.usrCoords);
|
|
756
649
|
console.log(s1, s2, s3, s4, s2 === 0);
|
|
@@ -952,14 +845,14 @@ define([
|
|
|
952
845
|
*/
|
|
953
846
|
_handleFullyDegenerateCase: function(S, C, board) {
|
|
954
847
|
var P, Q, l, M, crds, q1, q2, node,
|
|
955
|
-
i, j,
|
|
848
|
+
i, j, leP, leQ, is_on_Q, tmp,
|
|
956
849
|
is_fully_degenerated,
|
|
957
850
|
arr = [S, C];
|
|
958
851
|
|
|
959
852
|
for (l = 0; l < 2; l++) {
|
|
960
853
|
P = arr[l];
|
|
961
|
-
|
|
962
|
-
for (i = 0, is_fully_degenerated = true; i <
|
|
854
|
+
leP = P.length;
|
|
855
|
+
for (i = 0, is_fully_degenerated = true; i < leP; i++) {
|
|
963
856
|
if (!P[i].intersection) {
|
|
964
857
|
is_fully_degenerated = false;
|
|
965
858
|
break;
|
|
@@ -969,22 +862,23 @@ define([
|
|
|
969
862
|
if (is_fully_degenerated) {
|
|
970
863
|
// All nodes of P are also on the other path.
|
|
971
864
|
Q = arr[(l + 1) % 2];
|
|
972
|
-
|
|
865
|
+
leQ = Q.length;
|
|
973
866
|
|
|
974
867
|
// We search for a midpoint of one edge of P which is not the other path and
|
|
975
868
|
// we add that midpoint to P.
|
|
976
|
-
for (i = 0; i <
|
|
869
|
+
for (i = 0; i < leP; i++) {
|
|
977
870
|
q1 = P[i].coords.usrCoords;
|
|
978
|
-
q2 = P[
|
|
979
|
-
|
|
871
|
+
q2 = P[i]._next.coords.usrCoords;
|
|
872
|
+
|
|
873
|
+
// M is the midpoint
|
|
980
874
|
M = [(q1[0] + q2[0]) * 0.5,
|
|
981
875
|
(q1[1] + q2[1]) * 0.5,
|
|
982
876
|
(q1[2] + q2[2]) * 0.5];
|
|
983
877
|
|
|
984
878
|
// Test if M is on path Q. If this is not the case,
|
|
985
879
|
// we take M as additional point of P.
|
|
986
|
-
for (j = 0, is_on_Q = false; j <
|
|
987
|
-
if (Math.abs(
|
|
880
|
+
for (j = 0, is_on_Q = false; j < leQ; j++) {
|
|
881
|
+
if (Math.abs(Geometry.det3p(Q[j].coords.usrCoords, Q[(j + 1) % leQ].coords.usrCoords, M)) < Mat.eps) {
|
|
988
882
|
is_on_Q = true;
|
|
989
883
|
break;
|
|
990
884
|
}
|
|
@@ -998,10 +892,14 @@ define([
|
|
|
998
892
|
coords: crds,
|
|
999
893
|
elementClass: Const.OBJECT_CLASS_POINT
|
|
1000
894
|
};
|
|
895
|
+
|
|
896
|
+
tmp = P[i]._next;
|
|
1001
897
|
P[i]._next = node;
|
|
1002
898
|
node._prev = P[i];
|
|
1003
|
-
|
|
1004
|
-
|
|
899
|
+
node._next = tmp;
|
|
900
|
+
tmp._prev = node;
|
|
901
|
+
|
|
902
|
+
|
|
1005
903
|
if (P[i]._end) {
|
|
1006
904
|
P[i]._end = false;
|
|
1007
905
|
node._end = true;
|
|
@@ -1022,12 +920,14 @@ define([
|
|
|
1022
920
|
}
|
|
1023
921
|
P = P._next;
|
|
1024
922
|
}
|
|
1025
|
-
if (
|
|
923
|
+
if (Geometry.windingNumber(P.coords.usrCoords, path) === 0) {
|
|
1026
924
|
// Outside
|
|
1027
925
|
status = 'entry';
|
|
926
|
+
// console.log(P.coords.usrCoords, ' is outside')
|
|
1028
927
|
} else {
|
|
1029
928
|
// Inside
|
|
1030
929
|
status = 'exit';
|
|
930
|
+
// console.log(P.coords.usrCoords, ' is inside')
|
|
1031
931
|
}
|
|
1032
932
|
|
|
1033
933
|
return [P, status];
|
|
@@ -1477,10 +1377,10 @@ define([
|
|
|
1477
1377
|
}
|
|
1478
1378
|
|
|
1479
1379
|
// Test if one curve is contained by the other
|
|
1480
|
-
if (
|
|
1380
|
+
if (Geometry.windingNumber(P.coords.usrCoords, C) === 0) {
|
|
1481
1381
|
// P is outside of C:
|
|
1482
1382
|
// Either S is disjoint from C or C is inside of S
|
|
1483
|
-
if (
|
|
1383
|
+
if (Geometry.windingNumber(Q.coords.usrCoords, S) !== 0) {
|
|
1484
1384
|
// C is inside of S, i.e. C subset of S
|
|
1485
1385
|
|
|
1486
1386
|
if (clip_type === 'union') {
|
package/src/math/geometry.js
CHANGED
|
@@ -1042,6 +1042,208 @@ define([
|
|
|
1042
1042
|
return r;
|
|
1043
1043
|
},
|
|
1044
1044
|
|
|
1045
|
+
/**
|
|
1046
|
+
* Determinant of three points in the Euclidean plane.
|
|
1047
|
+
* Zero, if the points are collinear. Used to determine of a point q is left or
|
|
1048
|
+
* right to a segment defined by points p1 and p2.
|
|
1049
|
+
*
|
|
1050
|
+
* @param {Array} p1 Coordinates of the first point of the segment. Array of length 3. First coordinate is equal to 1.
|
|
1051
|
+
* @param {Array} p2 Coordinates of the second point of the segment. Array of length 3. First coordinate is equal to 1.
|
|
1052
|
+
* @param {Array} q Coordinates of the point. Array of length 3. First coordinate is equal to 1.
|
|
1053
|
+
* @return {Number} Signed area of the triangle formed by these three points.
|
|
1054
|
+
*
|
|
1055
|
+
* @see #windingNumber
|
|
1056
|
+
*/
|
|
1057
|
+
det3p: function(p1, p2, q) {
|
|
1058
|
+
return (p1[1] - q[1]) * (p2[2] - q[2]) - (p2[1] - q[1]) * (p1[2] - q[2]);
|
|
1059
|
+
},
|
|
1060
|
+
|
|
1061
|
+
/**
|
|
1062
|
+
* Winding number of a point in respect to a polygon path.
|
|
1063
|
+
*
|
|
1064
|
+
* The point is regarded outside if the winding number is zero,
|
|
1065
|
+
* inside otherwise. The algorithm tries to find degenerate cases, i.e.
|
|
1066
|
+
* if the point is on the path. This is regarded as "outside".
|
|
1067
|
+
* If the point is a vertex of the path, it is regarded as "inside".
|
|
1068
|
+
*
|
|
1069
|
+
* Implementation of algorithm 7 from "The point in polygon problem for
|
|
1070
|
+
* arbitrary polygons" by Kai Hormann and Alexander Agathos, Computational Geometry,
|
|
1071
|
+
* Volume 20, Issue 3, November 2001, Pages 131-144.
|
|
1072
|
+
*
|
|
1073
|
+
* @param {Array} usrCoords Homogenous coordinates of the point
|
|
1074
|
+
* @param {Array} path Array of points / coords determining a path, i.e. the vertices of the polygon / path. The array elements
|
|
1075
|
+
* do not have to be full points, but have to have a subobject "coords" or should be of type JXG.Coords.
|
|
1076
|
+
* @param {Boolean} [doNotClosePath=false] If true the last point of the path is not connected to the first point.
|
|
1077
|
+
* This is necessary if the path consists of two or more closed subpaths, e.g. if the figure has a hole.
|
|
1078
|
+
*
|
|
1079
|
+
* @return {Number} Winding number of the point. The point is
|
|
1080
|
+
* regarded outside if the winding number is zero,
|
|
1081
|
+
* inside otherwise.
|
|
1082
|
+
*/
|
|
1083
|
+
windingNumber: function(usrCoords, path, doNotClosePath) {
|
|
1084
|
+
var wn = 0,
|
|
1085
|
+
le = path.length,
|
|
1086
|
+
x = usrCoords[1],
|
|
1087
|
+
y = usrCoords[2],
|
|
1088
|
+
p0, p1, p2, d, sign, i, off = 0;
|
|
1089
|
+
|
|
1090
|
+
if (le === 0) {
|
|
1091
|
+
return 0;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
doNotClosePath = doNotClosePath || false;
|
|
1095
|
+
if (doNotClosePath) {
|
|
1096
|
+
off = 1;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
// Infinite points are declared outside
|
|
1100
|
+
if (isNaN(x) || isNaN(y)) {
|
|
1101
|
+
return 1;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
if (Type.exists(path[0].coords)) {
|
|
1105
|
+
p0 = path[0].coords;
|
|
1106
|
+
p1 = path[le - 1].coords;
|
|
1107
|
+
} else {
|
|
1108
|
+
p0 = path[0];
|
|
1109
|
+
p1 = path[le - 1];
|
|
1110
|
+
}
|
|
1111
|
+
// Handle the case if the point is the first vertex of the path, i.e. inside.
|
|
1112
|
+
if (p0.usrCoords[1] === x && p0.usrCoords[2] === y) {
|
|
1113
|
+
return 1;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
for (i = 0; i < le - off; i++) {
|
|
1117
|
+
// Consider the edge from p1 = path[i] to p2 = path[i+1]isClosedPath
|
|
1118
|
+
if (Type.exists(path[i].coords)) {
|
|
1119
|
+
p1 = path[i].coords.usrCoords;
|
|
1120
|
+
p2 = path[(i + 1) % le].coords.usrCoords;
|
|
1121
|
+
} else {
|
|
1122
|
+
p1 = path[i].usrCoords;
|
|
1123
|
+
p2 = path[(i + 1) % le].usrCoords;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
// If one of the two points p1, p2 is undefined or infinite,
|
|
1127
|
+
// move on.
|
|
1128
|
+
if (p1[0] === 0 || p2[0] === 0 ||
|
|
1129
|
+
isNaN(p1[1]) || isNaN(p2[1]) ||
|
|
1130
|
+
isNaN(p1[2]) || isNaN(p2[2])) {
|
|
1131
|
+
continue;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
if (p2[2] === y) {
|
|
1135
|
+
if (p2[1] === x) {
|
|
1136
|
+
return 1;
|
|
1137
|
+
}
|
|
1138
|
+
if (p1[2] === y && ((p2[1] > x) === (p1[1] < x))) {
|
|
1139
|
+
return 0;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
if ((p1[2] < y) !== (p2[2] < y)) { // Crossing
|
|
1144
|
+
sign = 2 * ((p2[2] > p1[2]) ? 1 : 0) - 1;
|
|
1145
|
+
if (p1[1] >= x) {
|
|
1146
|
+
if (p2[1] > x) {
|
|
1147
|
+
wn += sign;
|
|
1148
|
+
} else {
|
|
1149
|
+
d = this.det3p(p1, p2, usrCoords);
|
|
1150
|
+
if (d === 0) { // Point is on line, i.e. outside
|
|
1151
|
+
return 0;
|
|
1152
|
+
}
|
|
1153
|
+
if ((d > 0 + Mat.eps) === (p2[2] > p1[2])) { // Right crossing
|
|
1154
|
+
wn += sign;
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
} else {
|
|
1158
|
+
if (p2[1] > x) {
|
|
1159
|
+
d = this.det3p(p1, p2, usrCoords);
|
|
1160
|
+
if ((d > 0 + Mat.eps) === (p2[2] > p1[2])) { // Right crossing
|
|
1161
|
+
wn += sign;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
return wn;
|
|
1169
|
+
},
|
|
1170
|
+
|
|
1171
|
+
/**
|
|
1172
|
+
* Decides if a point (x,y) is inside of a path / polygon.
|
|
1173
|
+
* Does not work correct if the path has hole. In this case, windingNumber is the preferred method.
|
|
1174
|
+
* Implements W. Randolf Franklin's pnpoly method.
|
|
1175
|
+
*
|
|
1176
|
+
* See <a href="https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html">https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html</a>.
|
|
1177
|
+
*
|
|
1178
|
+
* @param {Number} x_in x-coordinate (screen or user coordinates)
|
|
1179
|
+
* @param {Number} y_in y-coordinate (screen or user coordinates)
|
|
1180
|
+
* @param {Array} path Array of points / coords determining a path, i.e. the vertices of the polygon / path. The array elements
|
|
1181
|
+
* do not have to be full points, but have to have a subobject "coords" or should be of type JXG.Coords.
|
|
1182
|
+
* @param {Number} [coord_type=JXG.COORDS_BY_SCREEN] Type of coordinates used here.
|
|
1183
|
+
* Possible values are <b>JXG.COORDS_BY_USER</b> and <b>JXG.COORDS_BY_SCREEN</b>.
|
|
1184
|
+
* Default value is JXG.COORDS_BY_SCREEN.
|
|
1185
|
+
*
|
|
1186
|
+
* @returns {Boolean} if (x_in, y_in) is inside of the polygon.
|
|
1187
|
+
* @see JXG.Polygon.hasPoint
|
|
1188
|
+
* @see JXG.Polygon.pnpoly
|
|
1189
|
+
* @see #windingNumber
|
|
1190
|
+
*
|
|
1191
|
+
* @example
|
|
1192
|
+
* var pol = board.create('polygon', [[-1,2], [2,2], [-1,4]]);
|
|
1193
|
+
* var p = board.create('point', [4, 3]);
|
|
1194
|
+
* var txt = board.create('text', [-1, 0.5, function() {
|
|
1195
|
+
* return 'Point A is inside of the polygon = ' +
|
|
1196
|
+
* JXG.Math.Geometry.pnpoly(p.X(), p.Y(), JXG.COORDS_BY_USER, pol.vertices);
|
|
1197
|
+
* }]);
|
|
1198
|
+
*
|
|
1199
|
+
* </pre><div id="JXG4656ed42-f965-4e35-bb66-c334a4529683" class="jxgbox" style="width: 300px; height: 300px;"></div>
|
|
1200
|
+
* <script type="text/javascript">
|
|
1201
|
+
* (function() {
|
|
1202
|
+
* var board = JXG.JSXGraph.initBoard('JXG4656ed42-f965-4e35-bb66-c334a4529683',
|
|
1203
|
+
* {boundingbox: [-2, 5, 5,-2], axis: true, showcopyright: false, shownavigation: false});
|
|
1204
|
+
* var pol = board.create('polygon', [[-1,2], [2,2], [-1,4]]);
|
|
1205
|
+
* var p = board.create('point', [4, 3]);
|
|
1206
|
+
* var txt = board.create('text', [-1, 0.5, function() {
|
|
1207
|
+
* return 'Point A is inside of the polygon = ' + JXG.Math.Geometry.pnpoly(p.X(), p.Y(), JXG.COORDS_BY_USER, pol.vertices);
|
|
1208
|
+
* }]);
|
|
1209
|
+
*
|
|
1210
|
+
* })();
|
|
1211
|
+
*
|
|
1212
|
+
* </script><pre>
|
|
1213
|
+
*
|
|
1214
|
+
*/
|
|
1215
|
+
pnpoly: function(x_in, y_in, path, coord_type) {
|
|
1216
|
+
var i, j, len,
|
|
1217
|
+
x, y, crds,
|
|
1218
|
+
v = path,
|
|
1219
|
+
vi, vj,
|
|
1220
|
+
isIn = false;
|
|
1221
|
+
|
|
1222
|
+
if (coord_type === Const.COORDS_BY_USER) {
|
|
1223
|
+
crds = new Coords(Const.COORDS_BY_USER, [x_in, y_in], this.board);
|
|
1224
|
+
x = crds.scrCoords[1];
|
|
1225
|
+
y = crds.scrCoords[2];
|
|
1226
|
+
} else {
|
|
1227
|
+
x = x_in;
|
|
1228
|
+
y = y_in;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
len = path.length;
|
|
1232
|
+
for (i = 0, j = len - 2; i < len - 1; j = i++) {
|
|
1233
|
+
vi = (Type.exists(v[i].coords)) ? v[i].coords : v[i];
|
|
1234
|
+
vj = (Type.exists(v[j].coords)) ? v[j].coords : v[j];
|
|
1235
|
+
|
|
1236
|
+
if (((vi.scrCoords[2] > y) !== (vj.scrCoords[2] > y)) &&
|
|
1237
|
+
(x < (vj.scrCoords[1] - vi.scrCoords[1]) *
|
|
1238
|
+
(y - vi.scrCoords[2]) / (vj.scrCoords[2] - vi.scrCoords[2]) + vi.scrCoords[1])
|
|
1239
|
+
) {
|
|
1240
|
+
isIn = !isIn;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
return isIn;
|
|
1245
|
+
},
|
|
1246
|
+
|
|
1045
1247
|
/****************************************/
|
|
1046
1248
|
/**** INTERSECTIONS ****/
|
|
1047
1249
|
/****************************************/
|
|
@@ -2566,7 +2768,7 @@ define([
|
|
|
2566
2768
|
for (i = 0; i < steps; i++) {
|
|
2567
2769
|
f_new = minfunc(t_new);
|
|
2568
2770
|
|
|
2569
|
-
if (f_new < f_old || f_old === Infinity) {
|
|
2771
|
+
if (f_new < f_old || f_old === Infinity || isNaN(f_old)) {
|
|
2570
2772
|
t = t_new;
|
|
2571
2773
|
f_old = f_new;
|
|
2572
2774
|
}
|
|
@@ -2831,7 +3033,6 @@ define([
|
|
|
2831
3033
|
return p;
|
|
2832
3034
|
},
|
|
2833
3035
|
|
|
2834
|
-
|
|
2835
3036
|
meetPlanePlane: function (v11, v12, v21, v22) {
|
|
2836
3037
|
var i, no1, no2,
|
|
2837
3038
|
v = [0, 0, 0],
|
|
@@ -2891,7 +3092,7 @@ define([
|
|
|
2891
3092
|
return [s1, e1, s2, e2];
|
|
2892
3093
|
}
|
|
2893
3094
|
return null;
|
|
2894
|
-
}
|
|
3095
|
+
}
|
|
2895
3096
|
|
|
2896
3097
|
});
|
|
2897
3098
|
|
package/src/math/math.js
CHANGED
|
@@ -39,9 +39,8 @@
|
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* @fileoverview In this file the namespace JXG.Math is defined, which is the base namespace
|
|
42
|
-
* for namespaces like Math.Numerics, Math.
|
|
42
|
+
* for namespaces like JXG.Math.Numerics, JXG.Math.Plot, JXG.Math.Statistics, JXG.Math.Clip etc.
|
|
43
43
|
*/
|
|
44
|
-
|
|
45
44
|
define(['jxg', 'utils/type'], function (JXG, Type) {
|
|
46
45
|
|
|
47
46
|
"use strict";
|