@pie-element/graphing-solution-set 6.1.2-next.1 → 6.1.2
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/CHANGELOG.json +1 -0
- package/CHANGELOG.md +856 -0
- package/LICENSE.md +5 -0
- package/README.md +20 -0
- package/configure/CHANGELOG.json +1 -0
- package/configure/CHANGELOG.md +816 -0
- package/configure/lib/configure.js +312 -0
- package/configure/lib/configure.js.map +1 -0
- package/configure/lib/correct-response.js +435 -0
- package/configure/lib/correct-response.js.map +1 -0
- package/configure/lib/defaults.js +357 -0
- package/configure/lib/defaults.js.map +1 -0
- package/configure/lib/graphing-config.js +408 -0
- package/configure/lib/graphing-config.js.map +1 -0
- package/configure/lib/index.js +163 -0
- package/configure/lib/index.js.map +1 -0
- package/configure/lib/utils.js +630 -0
- package/configure/lib/utils.js.map +1 -0
- package/configure/package.json +29 -0
- package/controller/CHANGELOG.json +1 -0
- package/controller/CHANGELOG.md +675 -0
- package/controller/lib/defaults.js +69 -0
- package/controller/lib/defaults.js.map +1 -0
- package/controller/lib/index.js +351 -0
- package/controller/lib/index.js.map +1 -0
- package/controller/lib/utils.js +212 -0
- package/controller/lib/utils.js.map +1 -0
- package/controller/package.json +22 -0
- package/demo-gss.gif +0 -0
- package/docs/config-schema.json +1560 -0
- package/docs/config-schema.json.md +1114 -0
- package/docs/demo/config.js +8 -0
- package/docs/demo/generate.js +54 -0
- package/docs/demo/index.html +1 -0
- package/docs/demo/session.js +6 -0
- package/docs/pie-schema.json +1800 -0
- package/docs/pie-schema.json.md +952 -0
- package/lib/index.js +164 -0
- package/lib/index.js.map +1 -0
- package/lib/main.js +355 -0
- package/lib/main.js.map +1 -0
- package/lib/utils.js +515 -0
- package/lib/utils.js.map +1 -0
- package/package.json +23 -86
- package/configure.js +0 -2
- package/controller.js +0 -1
- package/dist/author/configure.d.ts +0 -26
- package/dist/author/configure.js +0 -190
- package/dist/author/correct-response.d.ts +0 -33
- package/dist/author/correct-response.js +0 -206
- package/dist/author/defaults.d.ts +0 -238
- package/dist/author/defaults.js +0 -339
- package/dist/author/graphing-config.d.ts +0 -33
- package/dist/author/graphing-config.js +0 -237
- package/dist/author/index.d.ts +0 -62
- package/dist/author/index.js +0 -87
- package/dist/author/utils.d.ts +0 -46
- package/dist/author/utils.js +0 -474
- package/dist/browser/author/index.js +0 -1942
- package/dist/browser/author/index.js.map +0 -1
- package/dist/browser/browser-pUycHh7Y.js +0 -348
- package/dist/browser/browser-pUycHh7Y.js.map +0 -1
- package/dist/browser/controller/index.js +0 -193
- package/dist/browser/controller/index.js.map +0 -1
- package/dist/browser/delivery/index.js +0 -782
- package/dist/browser/delivery/index.js.map +0 -1
- package/dist/browser/dist-BxTk7Laj.js +0 -57671
- package/dist/browser/dist-BxTk7Laj.js.map +0 -1
- package/dist/browser/graphing-solution-set.css +0 -2
- package/dist/controller/defaults.d.ts +0 -64
- package/dist/controller/defaults.js +0 -54
- package/dist/controller/index.d.ts +0 -24
- package/dist/controller/index.js +0 -110
- package/dist/controller/utils.d.ts +0 -20
- package/dist/controller/utils.js +0 -39
- package/dist/delivery/index.d.ts +0 -22
- package/dist/delivery/index.js +0 -62
- package/dist/delivery/main.d.ts +0 -31
- package/dist/delivery/main.js +0 -198
- package/dist/delivery/utils.d.ts +0 -12
- package/dist/delivery/utils.js +0 -220
- package/dist/graphing-solution-set.css +0 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.iife.d.ts +0 -8
- package/dist/index.iife.js +0 -405
- package/dist/index.js +0 -2
- package/dist/runtime-support.d.ts +0 -12
- package/dist/runtime-support.js +0 -12
|
@@ -0,0 +1,630 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.pointInsidePolygon = exports.getLabelValues = exports.getGridValues = exports.findSectionsInSolutionSet = exports.filterPlotableMarks = exports.checkIfLinesAreAdded = exports.applyConstraints = exports.VALID_LABEL_VALUES = void 0;
|
|
7
|
+
var _lodashEs = require("lodash-es");
|
|
8
|
+
/*Valid grid values*/
|
|
9
|
+
const VALID_GRID_VALUES = [0.01, 0.02, 0.04, 0.05, 0.0625, 0.1, 0.125, 0.2, 0.25, 0.5, 1, 2, 3, 4, 5, 8, 10, 12, 15, 20, 40, 50, 64, 100, 500, 1000];
|
|
10
|
+
|
|
11
|
+
// same as VALID_GRID_VALUES but next values are excluded: 0.04, 0.0625, 0.125, 3, 4, 8, 12, 15, 40, 64
|
|
12
|
+
const PREFERRED_VALID_GRID_VALUES = [0.01, 0.02, 0.05, 0.1, 0.2, 0.25, 0.5, 1, 2, 5, 10, 20, 50, 100, 500, 1000];
|
|
13
|
+
|
|
14
|
+
/*Valid label values*/
|
|
15
|
+
const VALID_LABEL_VALUES = exports.VALID_LABEL_VALUES = {
|
|
16
|
+
0.01: [0, 0.01, 0.02, 0.04, 0.05, 0.1],
|
|
17
|
+
0.02: [0, 0.02, 0.04, 0.1],
|
|
18
|
+
0.04: [0, 0.04, 0.08, 0.16, 0.2],
|
|
19
|
+
0.05: [0, 0.05, 0.1, 0.2, 0.25],
|
|
20
|
+
0.0625: [0, 0.0625, 0.125, 0.25, 0.5],
|
|
21
|
+
0.1: [0, 0.1, 0.2, 0.4, 0.5, 1],
|
|
22
|
+
0.125: [0, 0.125, 0.25, 0.5, 1],
|
|
23
|
+
0.2: [0, 0.2, 0.5, 0.1],
|
|
24
|
+
0.25: [0, 0.25, 0.5, 1, 2],
|
|
25
|
+
0.5: [0, 0.5, 1, 2],
|
|
26
|
+
1: [0, 1, 2, 4, 5, 10],
|
|
27
|
+
2: [0, 2, 4, 8, 10],
|
|
28
|
+
3: [0, 3, 6, 12, 15],
|
|
29
|
+
4: [0, 4, 8, 16, 20],
|
|
30
|
+
5: [0, 5, 10, 20, 25],
|
|
31
|
+
8: [0, 8, 16, 32, 40, 64],
|
|
32
|
+
10: [0, 10, 20, 40, 50, 100],
|
|
33
|
+
12: [0, 12, 24],
|
|
34
|
+
15: [0, 15, 30, 60],
|
|
35
|
+
20: [0, 20, 40, 80, 100],
|
|
36
|
+
40: [0, 40, 80, 160, 200],
|
|
37
|
+
50: [0, 50, 100, 200, 250],
|
|
38
|
+
64: [0, 64, 128],
|
|
39
|
+
100: [0, 100, 200, 400, 500],
|
|
40
|
+
500: [0, 500, 1000, 2500],
|
|
41
|
+
1000: [0, 1000, 2000, 4000, 5000]
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/*
|
|
45
|
+
* Function to get grid values
|
|
46
|
+
* @param {Object} axis - axis object
|
|
47
|
+
* @param {Number} size - size of the axis
|
|
48
|
+
* @param {Boolean} prefferedValues - flag to get preffered values
|
|
49
|
+
* */
|
|
50
|
+
const getGridValues = (axis, size, prefferedValues = false) => {
|
|
51
|
+
const minValue = 10 * (axis.max - axis.min) / size;
|
|
52
|
+
const maxValue = minValue * 10;
|
|
53
|
+
const values = prefferedValues ? PREFERRED_VALID_GRID_VALUES : VALID_GRID_VALUES;
|
|
54
|
+
return values.filter(value => value >= minValue && value <= maxValue);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/*
|
|
58
|
+
* Function to get label values
|
|
59
|
+
* @param {Number} value - value of the axis step
|
|
60
|
+
* */
|
|
61
|
+
exports.getGridValues = getGridValues;
|
|
62
|
+
const getLabelValues = value => VALID_LABEL_VALUES[value] || [];
|
|
63
|
+
|
|
64
|
+
/*
|
|
65
|
+
* Function to apply constraints
|
|
66
|
+
* @param {Object} axis - axis object
|
|
67
|
+
* @param {Number} size - size of the axis
|
|
68
|
+
* @param {Array} oldGridValues - old grid values
|
|
69
|
+
* @param {Array} oldLabelValues - old label values
|
|
70
|
+
* */
|
|
71
|
+
exports.getLabelValues = getLabelValues;
|
|
72
|
+
const applyConstraints = (axis, size, oldGridValues, oldLabelValues) => {
|
|
73
|
+
const gridValues = getGridValues(axis, size);
|
|
74
|
+
let labelValues = getLabelValues(axis.step);
|
|
75
|
+
if (!(0, _lodashEs.isEqual)(oldGridValues, gridValues) && !gridValues.includes(axis.step)) {
|
|
76
|
+
const preferredValues = getGridValues(axis, size, true);
|
|
77
|
+
const lowestValue = preferredValues[0] || 1;
|
|
78
|
+
axis.step = lowestValue;
|
|
79
|
+
labelValues = getLabelValues(lowestValue);
|
|
80
|
+
if (!labelValues.includes(axis.labelStep)) {
|
|
81
|
+
axis.labelStep = lowestValue;
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
gridValues,
|
|
85
|
+
labelValues
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (!(0, _lodashEs.isEqual)(oldLabelValues, labelValues) && !labelValues.includes(axis.labelStep)) {
|
|
89
|
+
axis.labelStep = axis.step;
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
gridValues,
|
|
93
|
+
labelValues
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// also used in pie-lib/graphing/utils as 'getTickValues'
|
|
98
|
+
/*
|
|
99
|
+
* Function to get plotable points
|
|
100
|
+
* @param {Object} prop - axis object
|
|
101
|
+
* */
|
|
102
|
+
exports.applyConstraints = applyConstraints;
|
|
103
|
+
const getPlotablePoints = prop => {
|
|
104
|
+
const tickValues = [];
|
|
105
|
+
let tickVal = 0;
|
|
106
|
+
while (tickVal >= prop.min && tickValues.indexOf(tickVal) < 0) {
|
|
107
|
+
tickValues.push(tickVal);
|
|
108
|
+
tickVal = Math.round((tickVal - prop.step) * 10000) / 10000;
|
|
109
|
+
}
|
|
110
|
+
tickVal = Math.round(prop.step * 10000) / 10000;
|
|
111
|
+
while (tickVal <= prop.max && tickValues.indexOf(tickVal) < 0) {
|
|
112
|
+
tickValues.push(tickVal);
|
|
113
|
+
tickVal = Math.round((tickVal + prop.step) * 10000) / 10000;
|
|
114
|
+
}
|
|
115
|
+
// return only ticks that are inside the min-max interval
|
|
116
|
+
if (tickValues) {
|
|
117
|
+
return tickValues.filter(tV => tV >= prop.min && tV <= prop.max);
|
|
118
|
+
}
|
|
119
|
+
return [];
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/*
|
|
123
|
+
* Function to get plotable marks
|
|
124
|
+
* @param {Object} domain - domain object
|
|
125
|
+
* @param {Object} range - range object
|
|
126
|
+
* @param {Object} answers - answers object
|
|
127
|
+
* */
|
|
128
|
+
const filterPlotableMarks = (domain, range, answers) => {
|
|
129
|
+
const domainValues = getPlotablePoints(domain);
|
|
130
|
+
const rangeValues = getPlotablePoints(range);
|
|
131
|
+
const isPointPlotable = (x, y) => domainValues.includes(x) && rangeValues.includes(y);
|
|
132
|
+
return Object.entries(answers || {}).reduce((newAnswers, [key, answer]) => {
|
|
133
|
+
newAnswers[key] = {
|
|
134
|
+
...answer,
|
|
135
|
+
marks: (answer.marks || []).filter(mark => {
|
|
136
|
+
if (mark.type === 'point') {
|
|
137
|
+
return isPointPlotable(mark.x, mark.y);
|
|
138
|
+
}
|
|
139
|
+
if (mark.type === 'polygon') {
|
|
140
|
+
return !mark.points.find(point => !isPointPlotable(point.x, point.y));
|
|
141
|
+
}
|
|
142
|
+
const from = mark.from || mark.root;
|
|
143
|
+
const to = mark.to || mark.edge;
|
|
144
|
+
return mark.building ? isPointPlotable(from.x, from.y) : isPointPlotable(from.x, from.y) && isPointPlotable(to.x, to.y);
|
|
145
|
+
})
|
|
146
|
+
};
|
|
147
|
+
return newAnswers;
|
|
148
|
+
}, {});
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
//////////////////////////////////////////////////////////////////////////////////
|
|
152
|
+
// BELOW FUNCTIONS ARE USED IN src/utils as well
|
|
153
|
+
//////////////////////////////////////////////////////////////////////////////////
|
|
154
|
+
|
|
155
|
+
/*
|
|
156
|
+
* Function to calculate the distance between two points
|
|
157
|
+
* @param {Object} a - point a
|
|
158
|
+
* @param {Object} b - point b
|
|
159
|
+
* */
|
|
160
|
+
exports.filterPlotableMarks = filterPlotableMarks;
|
|
161
|
+
const distance = (a, b) => {
|
|
162
|
+
return Number(Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2).toFixed(3));
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/*
|
|
166
|
+
* Function to check if a point lies on edges of a polygon
|
|
167
|
+
* @param {Object} point - point object
|
|
168
|
+
* @param {Array} polygon - polygon points array
|
|
169
|
+
* */
|
|
170
|
+
const pointInPolygon = (point, polygon) => {
|
|
171
|
+
let c = point;
|
|
172
|
+
let inside = false;
|
|
173
|
+
let clonePolygon = [...polygon];
|
|
174
|
+
clonePolygon.push(polygon[0]);
|
|
175
|
+
for (let i = 0; i < clonePolygon.length - 1; i++) {
|
|
176
|
+
let a = clonePolygon[i];
|
|
177
|
+
let b = clonePolygon[i + 1];
|
|
178
|
+
// check if point is on the edge
|
|
179
|
+
if (distance(a, c) + distance(c, b) === distance(a, b)) {
|
|
180
|
+
inside = true;
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return inside;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/*
|
|
188
|
+
* Function to get the intersection point of two lines
|
|
189
|
+
* @param {Number} x1 - x coordinate of point 1 of line 1
|
|
190
|
+
* @param {Number} y1 - y coordinate of point 1 of line 1
|
|
191
|
+
* @param {Number} x2 - x coordinate of point 2 of line 1
|
|
192
|
+
* @param {Number} y2 - y coordinate of point 2 of line 1
|
|
193
|
+
* @param {Number} x3 - x coordinate of point 1 of line 2
|
|
194
|
+
* @param {Number} y3 - y coordinate of point 1 of line 2
|
|
195
|
+
* @param {Number} x4 - x coordinate of point 2 of line 2
|
|
196
|
+
* @param {Number} y4 - y coordinate of point 2 of line 2
|
|
197
|
+
* */
|
|
198
|
+
const lineIntersect = (x1, y1, x2, y2, x3, y3, x4, y4) => {
|
|
199
|
+
let ua,
|
|
200
|
+
denominator = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
|
|
201
|
+
if (denominator === 0) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator;
|
|
205
|
+
return {
|
|
206
|
+
x: Number((x1 + ua * (x2 - x1)).toFixed(3)),
|
|
207
|
+
y: Number((y1 + ua * (y2 - y1)).toFixed(3))
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
/*
|
|
212
|
+
* Check if a point is inside the graph
|
|
213
|
+
* @param {Object} point - point object
|
|
214
|
+
* @param {Object} domain - domain object
|
|
215
|
+
* @param {Object} range - range object
|
|
216
|
+
* */
|
|
217
|
+
const isPointInsideGraph = (point, domain, range) => {
|
|
218
|
+
return point.x > domain.min && point.x < domain.max && point.y > range.min && point.y < range.max;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
/*
|
|
222
|
+
* Check if a point is on or inside the graph
|
|
223
|
+
* @param {Object} point - point object
|
|
224
|
+
* @param {Object} domain - domain object
|
|
225
|
+
* @param {Object} range - range object
|
|
226
|
+
* */
|
|
227
|
+
const isPointOnOrInsideGraph = (point, domain, range) => {
|
|
228
|
+
return point.x >= domain.min && point.x <= domain.max && point.y >= range.min && point.y <= range.max;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/*
|
|
232
|
+
* Find the intersection point of a mark with the graph
|
|
233
|
+
* @param {Object} mark - mark object
|
|
234
|
+
* @param {Object} domain - domain object
|
|
235
|
+
* @param {Object} range - range object
|
|
236
|
+
* */
|
|
237
|
+
const findIntersectionPointForMark = (mark, domain, range) => {
|
|
238
|
+
let intersectionPoint = [];
|
|
239
|
+
let tempData = [[domain.max, range.max, domain.max, range.min], [domain.min, range.max, domain.min, range.min], [domain.min, range.max, domain.max, range.max], [domain.min, range.min, domain.max, range.min]];
|
|
240
|
+
for (let i = 0; i < tempData.length; i++) {
|
|
241
|
+
let intersection = lineIntersect(mark.from.x, mark.from.y, mark.to.x, mark.to.y, tempData[i][0], tempData[i][1], tempData[i][2], tempData[i][3]);
|
|
242
|
+
if (intersection && isPointOnOrInsideGraph(intersection, domain, range)) {
|
|
243
|
+
intersectionPoint.push(intersection);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return intersectionPoint;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
/*
|
|
250
|
+
* Sort points in clockwise direction for a polygon
|
|
251
|
+
* @param {Array} points - points array
|
|
252
|
+
* */
|
|
253
|
+
const sortPointsClockWise = points => {
|
|
254
|
+
// Find min max to get center and Sort from top to bottom
|
|
255
|
+
points.sort((a, b) => a.y - b.y);
|
|
256
|
+
// Get center y
|
|
257
|
+
const cy = (points[0].y + points[points.length - 1].y) / 2;
|
|
258
|
+
// Sort from right to left
|
|
259
|
+
points.sort((a, b) => b.x - a.x);
|
|
260
|
+
// Get center x
|
|
261
|
+
const cx = (points[0].x + points[points.length - 1].x) / 2;
|
|
262
|
+
// Center point
|
|
263
|
+
const center = {
|
|
264
|
+
x: cx,
|
|
265
|
+
y: cy
|
|
266
|
+
};
|
|
267
|
+
// As the points are sorted from right to left the first point is the rightmost Starting angle used to reference other angles
|
|
268
|
+
let startAng;
|
|
269
|
+
points.forEach(point => {
|
|
270
|
+
let ang = Math.atan2(point.y - center.y, point.x - center.x);
|
|
271
|
+
if (!startAng) {
|
|
272
|
+
startAng = ang;
|
|
273
|
+
} else {
|
|
274
|
+
if (ang < startAng) {
|
|
275
|
+
// ensure that all points are clockwise of the start point
|
|
276
|
+
ang += Math.PI * 2;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
point.angle = ang; // add the angle to the point
|
|
280
|
+
});
|
|
281
|
+
// first sort clockwise
|
|
282
|
+
points.sort((a, b) => a.angle - b.angle);
|
|
283
|
+
// then reverse the order
|
|
284
|
+
const ccwPoints = points.reverse();
|
|
285
|
+
// move the last point back to the start
|
|
286
|
+
ccwPoints.unshift(ccwPoints.pop());
|
|
287
|
+
return ccwPoints.map(({
|
|
288
|
+
angle,
|
|
289
|
+
...attr
|
|
290
|
+
}) => attr);
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
/*
|
|
294
|
+
* Function to calculate the dot product of two vectors
|
|
295
|
+
* @param {Object} v1 - point 1
|
|
296
|
+
* @param {Object} v2 - point 2
|
|
297
|
+
* */
|
|
298
|
+
const dotProduct = (v1, v2) => {
|
|
299
|
+
return v1.x * v2.x + v1.y * v2.y;
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
/*
|
|
303
|
+
* Function to calculate the magnitude of a vector
|
|
304
|
+
* @param {Object} v - point object
|
|
305
|
+
* */
|
|
306
|
+
const magnitude = v => {
|
|
307
|
+
return Math.sqrt(v.x * v.x + v.y * v.y);
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
/*
|
|
311
|
+
* Function to calculate the angle between two vectors in radians
|
|
312
|
+
* @param {Object} v1 - point 1
|
|
313
|
+
* @param {Object} v2 - point 2
|
|
314
|
+
* */
|
|
315
|
+
const angleBetweenVectors = (v1, v2) => {
|
|
316
|
+
const dot = dotProduct(v1, v2);
|
|
317
|
+
const magV1 = magnitude(v1);
|
|
318
|
+
const magV2 = magnitude(v2);
|
|
319
|
+
// Ensure the dot product is within the domain of the acos function
|
|
320
|
+
return Math.acos(dot / (magV1 * magV2));
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
/*
|
|
324
|
+
* Function to check if a point lies between the angle formed by two lines
|
|
325
|
+
* @param {Object} commonPoint - common point of the two lines
|
|
326
|
+
* @param {Object} point1 - point 1 of cone
|
|
327
|
+
* @param {Object} point2 - point 2 of cone
|
|
328
|
+
* @param {Object} testPoint - point to be tested
|
|
329
|
+
* */
|
|
330
|
+
const pointInAngle = (commonPoint, point1, point2, testPoint) => {
|
|
331
|
+
const vector1 = {
|
|
332
|
+
x: point1.x - commonPoint.x,
|
|
333
|
+
y: point1.y - commonPoint.y
|
|
334
|
+
};
|
|
335
|
+
const vector2 = {
|
|
336
|
+
x: point2.x - commonPoint.x,
|
|
337
|
+
y: point2.y - commonPoint.y
|
|
338
|
+
};
|
|
339
|
+
const testVector = {
|
|
340
|
+
x: testPoint.x - commonPoint.x,
|
|
341
|
+
y: testPoint.y - commonPoint.y
|
|
342
|
+
};
|
|
343
|
+
const angle1 = angleBetweenVectors(vector1, testVector);
|
|
344
|
+
const angle2 = angleBetweenVectors(vector2, testVector);
|
|
345
|
+
const angleSum = angle1 + angle2;
|
|
346
|
+
// Check if the sum of angles is approximately equal to the angle between the two lines
|
|
347
|
+
// You may need to adjust the tolerance (e.g., 0.0001) based on your specific requirements
|
|
348
|
+
const tolerance = 0.0001;
|
|
349
|
+
return Math.abs(angleSum - angleBetweenVectors(vector1, vector2)) < tolerance;
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
/*
|
|
353
|
+
* Function to remove duplicate points from an array
|
|
354
|
+
* @param {Array} array - array of points
|
|
355
|
+
* */
|
|
356
|
+
const removeDuplicatesFromArray = array => {
|
|
357
|
+
return array.filter((obj, index) => {
|
|
358
|
+
return index === array.findIndex(o => obj.x === o.x && obj.y === o.y);
|
|
359
|
+
});
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
/*
|
|
363
|
+
* Function to remove duplicate points and filter sections
|
|
364
|
+
* @param {Array} sections - array of sections
|
|
365
|
+
* */
|
|
366
|
+
const removeDuplicateAndFilterSections = sections => {
|
|
367
|
+
//removing duplicate points.
|
|
368
|
+
for (let i = 0; i < sections.length; i++) {
|
|
369
|
+
sections[i] = sections[i].filter((obj, index) => {
|
|
370
|
+
return index === sections[i].findIndex(o => obj.x === o.x && obj.y === o.y);
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
//removing arrays with two points
|
|
374
|
+
sections = sections.filter(section => section.length > 2);
|
|
375
|
+
//sorting the points in clockwise direction
|
|
376
|
+
for (let i = 0; i < sections.length; i++) {
|
|
377
|
+
sections[i] = sortPointsClockWise(sections[i]);
|
|
378
|
+
}
|
|
379
|
+
return sections;
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
/*
|
|
383
|
+
* Function to find sections in solution set for one line
|
|
384
|
+
* @param {Array} intersectionPoint - intersection point
|
|
385
|
+
* @param {Object} domain - domain object
|
|
386
|
+
* @param {Object} range - range object
|
|
387
|
+
* */
|
|
388
|
+
const findSectionsInSolutionSetForOneLine = (intersectionPoint, domain, range) => {
|
|
389
|
+
let sections = [];
|
|
390
|
+
sections.push([].concat(intersectionPoint));
|
|
391
|
+
sections.push([].concat(intersectionPoint));
|
|
392
|
+
if (intersectionPoint[0].x === domain.max && intersectionPoint[1].y === range.max || intersectionPoint[1].x === domain.max && intersectionPoint[0].y === range.max) {
|
|
393
|
+
sections[0].push({
|
|
394
|
+
x: domain.max,
|
|
395
|
+
y: range.max
|
|
396
|
+
});
|
|
397
|
+
sections[1].push({
|
|
398
|
+
x: domain.min,
|
|
399
|
+
y: range.max
|
|
400
|
+
}, {
|
|
401
|
+
x: domain.min,
|
|
402
|
+
y: range.min
|
|
403
|
+
}, {
|
|
404
|
+
x: domain.max,
|
|
405
|
+
y: range.min
|
|
406
|
+
});
|
|
407
|
+
} else if (intersectionPoint[0].x === domain.min && intersectionPoint[1].y === range.max || intersectionPoint[1].x === domain.min && intersectionPoint[0].y === range.max) {
|
|
408
|
+
sections[0].push({
|
|
409
|
+
x: domain.min,
|
|
410
|
+
y: range.max
|
|
411
|
+
});
|
|
412
|
+
sections[1].push({
|
|
413
|
+
x: domain.max,
|
|
414
|
+
y: range.max
|
|
415
|
+
}, {
|
|
416
|
+
x: domain.max,
|
|
417
|
+
y: range.min
|
|
418
|
+
}, {
|
|
419
|
+
x: domain.min,
|
|
420
|
+
y: range.min
|
|
421
|
+
});
|
|
422
|
+
} else if (intersectionPoint[0].x === domain.min && intersectionPoint[1].y === range.min || intersectionPoint[1].x === domain.min && intersectionPoint[0].y === range.min) {
|
|
423
|
+
sections[0].push({
|
|
424
|
+
x: domain.min,
|
|
425
|
+
y: range.min
|
|
426
|
+
});
|
|
427
|
+
sections[1].push({
|
|
428
|
+
x: domain.max,
|
|
429
|
+
y: range.min
|
|
430
|
+
}, {
|
|
431
|
+
x: domain.max,
|
|
432
|
+
y: range.max
|
|
433
|
+
}, {
|
|
434
|
+
x: domain.min,
|
|
435
|
+
y: range.max
|
|
436
|
+
});
|
|
437
|
+
} else if (intersectionPoint[0].x === domain.max && intersectionPoint[1].y === range.min || intersectionPoint[1].x === domain.max && intersectionPoint[0].y === range.min) {
|
|
438
|
+
sections[0].push({
|
|
439
|
+
x: domain.max,
|
|
440
|
+
y: range.min
|
|
441
|
+
});
|
|
442
|
+
sections[1].push({
|
|
443
|
+
x: domain.min,
|
|
444
|
+
y: range.min
|
|
445
|
+
}, {
|
|
446
|
+
x: domain.min,
|
|
447
|
+
y: range.max
|
|
448
|
+
}, {
|
|
449
|
+
x: domain.max,
|
|
450
|
+
y: range.max
|
|
451
|
+
});
|
|
452
|
+
} else if (intersectionPoint[0].x === domain.min && intersectionPoint[1].x === domain.max || intersectionPoint[0].x === domain.max && intersectionPoint[1].x === domain.min) {
|
|
453
|
+
sections[0].push({
|
|
454
|
+
x: domain.min,
|
|
455
|
+
y: range.max
|
|
456
|
+
}, {
|
|
457
|
+
x: domain.max,
|
|
458
|
+
y: range.max
|
|
459
|
+
});
|
|
460
|
+
sections[1].push({
|
|
461
|
+
x: domain.min,
|
|
462
|
+
y: range.min
|
|
463
|
+
}, {
|
|
464
|
+
x: domain.max,
|
|
465
|
+
y: range.min
|
|
466
|
+
});
|
|
467
|
+
} else if (intersectionPoint[0].y === range.min && intersectionPoint[1].y === range.max || intersectionPoint[0].y === range.max && intersectionPoint[1].y === range.min) {
|
|
468
|
+
sections[0].push({
|
|
469
|
+
x: domain.min,
|
|
470
|
+
y: range.min
|
|
471
|
+
}, {
|
|
472
|
+
x: domain.min,
|
|
473
|
+
y: range.max
|
|
474
|
+
});
|
|
475
|
+
sections[1].push({
|
|
476
|
+
x: domain.max,
|
|
477
|
+
y: range.min
|
|
478
|
+
}, {
|
|
479
|
+
x: domain.max,
|
|
480
|
+
y: range.max
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
return removeDuplicateAndFilterSections(sections);
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
/*
|
|
487
|
+
* Function to find sections in solution set for two lines
|
|
488
|
+
* @param {Object} gssLineData - graphing solution set line data
|
|
489
|
+
* @param {Array} answers - answers array
|
|
490
|
+
* @param {Object} domain - domain object
|
|
491
|
+
* @param {Object} range - range object
|
|
492
|
+
* */
|
|
493
|
+
const findSectionsInSolutionSetForTwoLines = (gssLineData, answers, domain, range) => {
|
|
494
|
+
let mark1 = answers[0];
|
|
495
|
+
let mark2 = answers[1];
|
|
496
|
+
let cornerPoints = [{
|
|
497
|
+
x: domain.min,
|
|
498
|
+
y: range.min
|
|
499
|
+
}, {
|
|
500
|
+
x: domain.min,
|
|
501
|
+
y: range.max
|
|
502
|
+
}, {
|
|
503
|
+
x: domain.max,
|
|
504
|
+
y: range.min
|
|
505
|
+
}, {
|
|
506
|
+
x: domain.max,
|
|
507
|
+
y: range.max
|
|
508
|
+
}];
|
|
509
|
+
let intersectPoint = lineIntersect(mark1.from.x, mark1.from.y, mark1.to.x, mark1.to.y, mark2.from.x, mark2.from.y, mark2.to.x, mark2.to.y);
|
|
510
|
+
let sections = [];
|
|
511
|
+
let intersectionPoint1 = findIntersectionPointForMark(mark1, domain, range);
|
|
512
|
+
intersectionPoint1 = removeDuplicatesFromArray(intersectionPoint1);
|
|
513
|
+
let intersectionPoint2 = findIntersectionPointForMark(mark2, domain, range);
|
|
514
|
+
intersectionPoint2 = removeDuplicatesFromArray(intersectionPoint2);
|
|
515
|
+
if (intersectPoint && isPointInsideGraph(intersectPoint, domain, range)) {
|
|
516
|
+
for (let i = 0; i < intersectionPoint1.length; i++) {
|
|
517
|
+
for (let j = 0; j < intersectionPoint2.length; j++) {
|
|
518
|
+
let bucket = [];
|
|
519
|
+
let newCornerPoints = [];
|
|
520
|
+
bucket.push(intersectPoint);
|
|
521
|
+
bucket.push(intersectionPoint1[i]);
|
|
522
|
+
bucket.push(intersectionPoint2[j]);
|
|
523
|
+
for (let k = 0; k < cornerPoints.length; k++) {
|
|
524
|
+
if (pointInAngle(intersectPoint, intersectionPoint1[i], intersectionPoint2[j], cornerPoints[k])) {
|
|
525
|
+
bucket.push(cornerPoints[k]);
|
|
526
|
+
} else {
|
|
527
|
+
newCornerPoints.push(cornerPoints[k]);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
cornerPoints = newCornerPoints;
|
|
531
|
+
sections.push(bucket);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
} else {
|
|
535
|
+
let sections1 = findSectionsInSolutionSetForOneLine(intersectionPoint1, domain, range);
|
|
536
|
+
let sections2 = findSectionsInSolutionSetForOneLine(intersectionPoint2, domain, range);
|
|
537
|
+
for (let i = 0; i < sections1.length; i++) {
|
|
538
|
+
if (!(pointInPolygon(intersectionPoint2[0], sections1[i]) && pointInPolygon(intersectionPoint2[1], sections1[i]))) {
|
|
539
|
+
sections.push(sections1[i]);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
for (let i = 0; i < sections2.length; i++) {
|
|
543
|
+
if (!(pointInPolygon(intersectionPoint1[0], sections2[i]) && pointInPolygon(intersectionPoint1[1], sections2[i]))) {
|
|
544
|
+
sections.push(sections2[i]);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
for (let i = 0; i < sections.length; i++) {
|
|
548
|
+
cornerPoints = cornerPoints.filter(function (o1) {
|
|
549
|
+
return !sections[i].some(function (o2) {
|
|
550
|
+
return o1.x === o2.x && o1.y === o2.y;
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
let sections3 = cornerPoints.concat(intersectionPoint1, intersectionPoint2);
|
|
555
|
+
sections.push(sections3);
|
|
556
|
+
}
|
|
557
|
+
return removeDuplicateAndFilterSections(sections);
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
/*
|
|
561
|
+
* Function to find sections in solution set
|
|
562
|
+
* @param {Object} gssLineData - graphing solution set line data
|
|
563
|
+
* @param {Array} answers - answers array
|
|
564
|
+
* @param {Object} domain - domain object
|
|
565
|
+
* @param {Object} range - range object
|
|
566
|
+
* */
|
|
567
|
+
const findSectionsInSolutionSet = (gssLineData, answers, domain, range) => {
|
|
568
|
+
if (gssLineData.numberOfLines === 1) {
|
|
569
|
+
const intersectionPoint = findIntersectionPointForMark(answers[0], domain, range);
|
|
570
|
+
gssLineData.sections = findSectionsInSolutionSetForOneLine(intersectionPoint, domain, range);
|
|
571
|
+
} else {
|
|
572
|
+
gssLineData.sections = findSectionsInSolutionSetForTwoLines(gssLineData, answers, domain, range);
|
|
573
|
+
}
|
|
574
|
+
return gssLineData;
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
/*
|
|
578
|
+
* Function to check if a point is inside a polygon
|
|
579
|
+
* @param {Object} point - point to be checked
|
|
580
|
+
* @param {Array} polygon - polygon points array
|
|
581
|
+
* */
|
|
582
|
+
exports.findSectionsInSolutionSet = findSectionsInSolutionSet;
|
|
583
|
+
const pointInsidePolygon = (point, polygon) => {
|
|
584
|
+
const num_vertices = polygon.length;
|
|
585
|
+
const x = point.x;
|
|
586
|
+
const y = point.y;
|
|
587
|
+
let inside = false;
|
|
588
|
+
let p1 = polygon[0];
|
|
589
|
+
let p2;
|
|
590
|
+
for (let i = 1; i <= num_vertices; i++) {
|
|
591
|
+
p2 = polygon[i % num_vertices];
|
|
592
|
+
if (y > Math.min(p1.y, p2.y)) {
|
|
593
|
+
if (y <= Math.max(p1.y, p2.y)) {
|
|
594
|
+
if (x <= Math.max(p1.x, p2.x)) {
|
|
595
|
+
const x_intersection = (y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
|
|
596
|
+
if (p1.x === p2.x || x <= x_intersection) {
|
|
597
|
+
inside = !inside;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
p1 = p2;
|
|
603
|
+
}
|
|
604
|
+
return inside;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
/*
|
|
608
|
+
* Function to check if lines are added in the graph
|
|
609
|
+
* @param {Object} gssLineData - graphing solution set line data
|
|
610
|
+
* @param {Array} answer - answer array
|
|
611
|
+
* */
|
|
612
|
+
exports.pointInsidePolygon = pointInsidePolygon;
|
|
613
|
+
const checkIfLinesAreAdded = (gssLineData, answer) => {
|
|
614
|
+
if (answer.length === 0) {
|
|
615
|
+
return false;
|
|
616
|
+
}
|
|
617
|
+
if (gssLineData.numberOfLines === 1) {
|
|
618
|
+
if (answer.length === 1) {
|
|
619
|
+
return !answer[0].building;
|
|
620
|
+
}
|
|
621
|
+
} else {
|
|
622
|
+
if (answer.length !== 2) {
|
|
623
|
+
return false;
|
|
624
|
+
} else {
|
|
625
|
+
return !answer[1].building;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
exports.checkIfLinesAreAdded = checkIfLinesAreAdded;
|
|
630
|
+
//# sourceMappingURL=utils.js.map
|