-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathShape.js
More file actions
159 lines (127 loc) · 4.5 KB
/
Shape.js
File metadata and controls
159 lines (127 loc) · 4.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
function Shape() {}
Shape.prototype.intersectRay = function(ray, shape) {
//ray
const angleRadians = Math.atan2(ray.to.y - ray.from.y, ray.to.x - ray.from.x);
const tinyMovement = 0.1; // Define a very small movement value
const x1 = ray.from.x + tinyMovement * Math.cos(angleRadians); // Move x1 slightly closer to x2
const y1 = ray.from.y + tinyMovement * Math.sin(angleRadians); // Move y1 slightly closer to y2
const x2 = ray.to.x;
const y2 = ray.to.y;
//shape
const points = shape.points;
const n = points.length;
let intersections = [];
if (n > 2) {
//loop through all the edges
let _x1, _y1, _x2, _y2,
_x3, _y3, _x4, _y4;
for (let i = 0; i < n; i++) {
_x1 = points[i].x;
_y1 = points[i].y;
_x2 = points[(i + 1) % n].x;
_y2 = points[(i + 1) % n].y;
_x3 = x1;
_y3 = y1;
_x4 = x2;
_y4 = y2;
const intersection = VectorIntersectsVector(_x1, _y1, _x2, _y2, _x3, _y3, _x4, _y4);
if (intersection) intersections.push(intersection);
}
}
if (n === 2) {
//loop through all the edges
let _x1, _y1, _x2, _y2,
_x3, _y3, _x4, _y4;
_x1 = points[0].x;
_y1 = points[0].y;
_x2 = points[1].x;
_y2 = points[1].y;
_x3 = x1;
_y3 = y1;
_x4 = x2;
_y4 = y2;
const intersection = VectorIntersectsVector(_x1, _y1, _x2, _y2, _x3, _y3, _x4, _y4);
if (intersection) intersections.push(intersection);
}
if (intersections.length === 0) {
return;
}
let closestIntersection = null;
let closestDistance = 10000;
intersections.forEach((intersection) => {
const distance = Math.sqrt(Math.pow(intersection.x - x1, 2) + Math.pow(intersection.y - y1, 2));
if (distance < closestDistance) {
closestIntersection = intersection;
closestDistance = distance;
}
});
//get the of the ray from [closestIntersection] to [from]
const angleOfRay = normalizeDegreeAngle(RadiansToDegrees(Math.atan2(y1 - closestIntersection.y, x1 - closestIntersection.x)));
const normal1 = normalizeDegreeAngle(closestIntersection.normals[0]);
const normal2 = normalizeDegreeAngle(closestIntersection.normals[1]);
//check which is closer and set closestIntersection.normals to that
if (getClosestNumber(angleOfRay, [normal1, normal2]) === normal1) {
closestIntersection.normals = normal1;
} else {
closestIntersection.normals = normal2;
}
//check if the ray is hitting the shape from the inside
return {
from: {
x: x1,
y: y1
},
to: {
x: closestIntersection.x,
y: closestIntersection.y
},
shape: shape,
normal: closestIntersection.normals
};
function VectorIntersectsVector(x1, y1, x2, y2, x3, y3, x4, y4) {
const den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
if (den === 0) {
return;
}
const t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / den;
const u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / den;
const angleDegrees1 = RadiansToDegrees(Math.atan2(y2 - y1, x2 - x1)) + 90;
const angleDegrees2 = RadiansToDegrees(Math.atan2(y2 - y1, x2 - x1)) - 90;
if (t >= 0 && t <= 1 && u >= 0 && u <= 1) {
return {
x: x1 + t * (x2 - x1),
y: y1 + t * (y2 - y1),
normals: [
angleDegrees1,
angleDegrees2
]
};
}
}
}
Shape.prototype.contains = function(mx, my) {
// Check if a point (mx, my) is inside a polygon defined by an array of points
const points = this.points;
let isInside = false;
const n = points.length;
for (let i = 0, j = n - 1; i < n; j = i++) {
const xi = points[i].x;
const yi = points[i].y;
const xj = points[j].x;
const yj = points[j].y;
const intersect =
((yi > my) !== (yj > my)) &&
(mx < (xj - xi) * (my - yi) / (yj - yi) + xi);
if (intersect) {
isInside = !isInside;
}
}
return isInside;
}
Shape.prototype.stroke = function(ctx, strokeStyle, lineWidth) {
console.log("general Stroke")
ctx.strokeStyle = strokeStyle;
ctx.lineWidth = lineWidth;
this.draw(ctx);
ctx.stroke();
}