3636< body >
3737 <!-- <pre></pre> -->
3838 < canvas > </ canvas >
39- < script src ="code/bundle.js "> </ script >
39+ <!-- <script src="code/bundle.js"></script> -->
40+
41+ < script >
42+
43+ // Find intersection of RAY & SEGMENT
44+ function getIntersection ( ray , segment ) {
45+ // RAY in parametric: Point + Delta*T1
46+ var r_px = ray . a . x ;
47+ var r_py = ray . a . y ;
48+ var r_dx = ray . b . x - ray . a . x ;
49+ var r_dy = ray . b . y - ray . a . y ;
50+
51+ // SEGMENT in parametric: Point + Delta*T2
52+ var s_px = segment . a . x ;
53+ var s_py = segment . a . y ;
54+ var s_dx = segment . b . x - segment . a . x ;
55+ var s_dy = segment . b . y - segment . a . y ;
56+
57+ // Are they parallel? If so, no intersect
58+ var r_mag = Math . sqrt ( r_dx * r_dx + r_dy * r_dy ) ;
59+ var s_mag = Math . sqrt ( s_dx * s_dx + s_dy * s_dy ) ;
60+ if ( r_dx / r_mag == s_dx / s_mag && r_dy / r_mag == s_dy / s_mag ) {
61+ // Unit vectors are the same.
62+ return null ;
63+ }
64+
65+ // SOLVE FOR T1 & T2
66+ // r_px+r_dx*T1 = s_px+s_dx*T2 && r_py+r_dy*T1 = s_py+s_dy*T2
67+ // ==> T1 = (s_px+s_dx*T2-r_px)/r_dx = (s_py+s_dy*T2-r_py)/r_dy
68+ // ==> s_px*r_dy + s_dx*T2*r_dy - r_px*r_dy = s_py*r_dx + s_dy*T2*r_dx - r_py*r_dx
69+ // ==> T2 = (r_dx*(s_py-r_py) + r_dy*(r_px-s_px))/(s_dx*r_dy - s_dy*r_dx)
70+ var T2 = ( r_dx * ( s_py - r_py ) + r_dy * ( r_px - s_px ) ) / ( s_dx * r_dy - s_dy * r_dx ) ;
71+ var T1 = ( s_px + s_dx * T2 - r_px ) / r_dx ;
72+
73+ // Must be within parametic whatevers for RAY/SEGMENT
74+ if ( T1 < 0 ) return null ;
75+ if ( T2 < 0 || T2 > 1 ) return null ;
76+
77+ // Return the POINT OF INTERSECTION
78+ return {
79+ x : r_px + r_dx * T1 ,
80+ y : r_py + r_dy * T1 ,
81+ param : T1
82+ } ;
83+ }
84+
85+ function getSightPolygon ( sightX , sightY ) {
86+ // Get all unique points
87+ var points = ( function ( segments ) {
88+ var a = [ ] ;
89+ segments . forEach ( function ( seg ) {
90+ a . push ( seg . a , seg . b ) ;
91+ } ) ;
92+ return a ;
93+ } ) ( segments ) ;
94+
95+ var uniquePoints = ( function ( points ) {
96+ var set = { } ;
97+ return points . filter ( function ( p ) {
98+ var key = p . x + "," + p . y ;
99+ if ( key in set ) {
100+ return false ;
101+ } else {
102+ set [ key ] = true ;
103+ return true ;
104+ }
105+ } ) ;
106+ } ) ( points ) ;
107+
108+ // Get all angles
109+ var uniqueAngles = [ ] ;
110+ for ( var j = 0 ; j < uniquePoints . length ; j ++ ) {
111+ var uniquePoint = uniquePoints [ j ] ;
112+ var angle = Math . atan2 ( uniquePoint . y - sightY , uniquePoint . x - sightX ) ;
113+ uniquePoint . angle = angle ;
114+ uniqueAngles . push ( angle - 0.00001 , angle , angle + 0.00001 ) ;
115+ }
116+
117+ // RAYS IN ALL DIRECTIONS
118+ var intersects = [ ] ;
119+ for ( var j = 0 ; j < uniqueAngles . length ; j ++ ) {
120+ var angle = uniqueAngles [ j ] ;
121+ // Calculate dx & dy from angle
122+ var dx = Math . cos ( angle ) ;
123+ var dy = Math . sin ( angle ) ;
124+
125+ // Ray from light coord to point coord
126+ var ray = {
127+ a : { x : sightX , y : sightY } ,
128+ b : { x : sightX + dx , y : sightY + dy }
129+ } ;
130+
131+ // Find CLOSEST intersection
132+ var closestIntersect = null ;
133+ for ( var i = 0 ; i < segments . length ; i ++ ) {
134+ var intersect = getIntersection ( ray , segments [ i ] ) ;
135+ if ( ! intersect ) continue ;
136+
137+ // param (aka distance)
138+ if ( ! closestIntersect || intersect . param < closestIntersect . param ) {
139+ closestIntersect = intersect ;
140+ }
141+ }
142+
143+ // Intersect angle
144+ if ( ! closestIntersect ) continue ;
145+ closestIntersect . angle = angle ;
146+
147+ // Add to list of intersects
148+ intersects . push ( closestIntersect ) ;
149+ }
150+
151+ // Sort intersects by angle
152+ intersects = intersects . sort ( function ( a , b ) {
153+ return a . angle - b . angle ;
154+ } ) ;
155+
156+ // Polygon is intersects, in order of angle
157+ return intersects ;
158+ }
159+
160+ ///////////////////////////////////////////////////////
161+ // DRAWING
162+ var canvas = document . querySelector ( "canvas" ) ;
163+ canvas . width = window . innerWidth ;
164+ canvas . height = window . innerHeight ;
165+
166+ var ctx = canvas . getContext ( "2d" ) ;
167+
168+ function draw ( ) {
169+ // Clear canvas
170+ ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
171+
172+ ctx . fillStyle = '#000' ;
173+ ctx . fillRect ( 0 , 0 , canvas . width , canvas . height ) ;
174+
175+ // Draw segments
176+ ctx . strokeStyle = "#999" ;
177+ for ( var i = 0 ; i < segments . length ; i ++ ) {
178+ var seg = segments [ i ] ;
179+ ctx . beginPath ( ) ;
180+ ctx . moveTo ( seg . a . x , seg . a . y ) ;
181+ ctx . lineTo ( seg . b . x , seg . b . y ) ;
182+ ctx . stroke ( ) ;
183+ }
184+
185+ var lightsCount = 5 ;
186+
187+
188+ performance . mark ( 'getSightPolygonStart' ) ;
189+
190+ // Sight Polygons
191+ var fuzzyRadius = 10 ;
192+ var polygons = [ getSightPolygon ( Mouse . x , Mouse . y ) ] ;
193+ for ( var angle = 0 ; angle < Math . PI * 2 ; angle += ( Math . PI * 2 ) / lightsCount ) {
194+ var dx = Math . cos ( angle ) * fuzzyRadius ;
195+ var dy = Math . sin ( angle ) * fuzzyRadius ;
196+ polygons . push ( getSightPolygon ( Mouse . x + dx , Mouse . y + dy ) ) ;
197+ } ;
198+
199+ performance . mark ( 'getSightPolygonEnd' ) ;
200+ performance . measure ( 'getSightPolygon' , 'getSightPolygonStart' , 'getSightPolygonEnd' ) ;
201+
202+
203+ // DRAW AS A GIANT POLYGON
204+ for ( var i = 1 ; i < polygons . length ; i ++ ) {
205+ drawPolygon ( polygons [ i ] , ctx , `rgba(255, 255, 255, ${ 1 / lightsCount } )` ) ;
206+ }
207+ drawPolygon ( polygons [ 0 ] , ctx , "#fff" ) ;
208+
209+
210+ // Draw red dots
211+ ctx . fillStyle = "#dd3838" ;
212+ ctx . beginPath ( ) ;
213+ ctx . arc ( Mouse . x , Mouse . y , 2 , 0 , 2 * Math . PI , false ) ;
214+ ctx . fill ( ) ;
215+ for ( var angle = 0 ; angle < Math . PI * 2 ; angle += ( Math . PI * 2 ) / lightsCount ) {
216+ var dx = Math . cos ( angle ) * fuzzyRadius ;
217+ var dy = Math . sin ( angle ) * fuzzyRadius ;
218+ ctx . beginPath ( ) ;
219+ ctx . arc ( Mouse . x + dx , Mouse . y + dy , 2 , 0 , 2 * Math . PI , false ) ;
220+ ctx . fill ( ) ;
221+ }
222+ }
223+
224+ function drawPolygon ( polygon , ctx , fillStyle ) {
225+ ctx . fillStyle = fillStyle ;
226+ ctx . beginPath ( ) ;
227+ ctx . moveTo ( polygon [ 0 ] . x , polygon [ 0 ] . y ) ;
228+ for ( var i = 1 ; i < polygon . length ; i ++ ) {
229+ var intersect = polygon [ i ] ;
230+ ctx . lineTo ( intersect . x , intersect . y ) ;
231+ }
232+ ctx . fill ( ) ;
233+ }
234+
235+ // LINE SEGMENTS
236+ var segments = [
237+ // Border
238+ { a : { x : 0 , y : 0 } , b : { x : 640 , y : 0 } } ,
239+ { a : { x : 640 , y : 0 } , b : { x : 640 , y : 360 } } ,
240+ { a : { x : 640 , y : 360 } , b : { x : 0 , y : 360 } } ,
241+ { a : { x : 0 , y : 360 } , b : { x : 0 , y : 0 } } ,
242+ // Polygon #1
243+ { a : { x : 100 , y : 150 } , b : { x : 120 , y : 50 } } ,
244+ { a : { x : 120 , y : 50 } , b : { x : 200 , y : 80 } } ,
245+ { a : { x : 200 , y : 80 } , b : { x : 140 , y : 210 } } ,
246+ { a : { x : 140 , y : 210 } , b : { x : 100 , y : 150 } } ,
247+ // Polygon #2
248+ { a : { x : 100 , y : 200 } , b : { x : 120 , y : 250 } } ,
249+ { a : { x : 120 , y : 250 } , b : { x : 60 , y : 300 } } ,
250+ { a : { x : 60 , y : 300 } , b : { x : 100 , y : 200 } } ,
251+ // Polygon #3
252+ { a : { x : 200 , y : 260 } , b : { x : 220 , y : 150 } } ,
253+ { a : { x : 220 , y : 150 } , b : { x : 300 , y : 200 } } ,
254+ { a : { x : 300 , y : 200 } , b : { x : 350 , y : 320 } } ,
255+ { a : { x : 350 , y : 320 } , b : { x : 200 , y : 260 } } ,
256+ // Polygon #4
257+ { a : { x : 340 , y : 60 } , b : { x : 360 , y : 40 } } ,
258+ { a : { x : 360 , y : 40 } , b : { x : 370 , y : 70 } } ,
259+ { a : { x : 370 , y : 70 } , b : { x : 340 , y : 60 } } ,
260+ // Polygon #5
261+ { a : { x : 450 , y : 190 } , b : { x : 560 , y : 170 } } ,
262+ { a : { x : 560 , y : 170 } , b : { x : 540 , y : 270 } } ,
263+ { a : { x : 540 , y : 270 } , b : { x : 430 , y : 290 } } ,
264+ { a : { x : 430 , y : 290 } , b : { x : 450 , y : 190 } } ,
265+ // Polygon #6
266+ { a : { x : 400 , y : 95 } , b : { x : 580 , y : 50 } } ,
267+ { a : { x : 580 , y : 50 } , b : { x : 480 , y : 150 } } ,
268+ { a : { x : 480 , y : 150 } , b : { x : 400 , y : 95 } }
269+ ] ;
270+ // DRAW LOOP
271+
272+ var updateCanvas = true ;
273+
274+ function drawLoop ( ) {
275+ requestAnimationFrame ( drawLoop ) ;
276+ if ( updateCanvas ) {
277+ draw ( ) ;
278+ updateCanvas = false ;
279+ }
280+ }
281+ window . onload = function ( ) {
282+ drawLoop ( ) ;
283+ } ;
284+ // MOUSE
285+ var Mouse = {
286+ x : canvas . width / 2 ,
287+ y : canvas . height / 2
288+ } ;
289+ canvas . onmousemove = function ( event ) {
290+ Mouse . x = event . clientX ;
291+ Mouse . y = event . clientY ;
292+ updateCanvas = true ;
293+ } ;
294+
295+ </ script >
40296</ body >
41297
42298</ html >
0 commit comments