Edge.cpp 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. Edge& Edge::divNormalized(C Matrix3 &m)
  6. {
  7. p[0].divNormalized(m);
  8. p[1].divNormalized(m);
  9. return T;
  10. }
  11. Edge& Edge::divNormalized(C Matrix &m)
  12. {
  13. p[0].divNormalized(m);
  14. p[1].divNormalized(m);
  15. return T;
  16. }
  17. Edge& Edge::div(C Matrix3 &m)
  18. {
  19. p[0].divNormalized(m);
  20. p[1].divNormalized(m);
  21. Flt x=m.x.length2(); p[0].x/=x; p[1].x/=x;
  22. Flt y=m.y.length2(); p[0].y/=y; p[1].y/=y;
  23. Flt z=m.z.length2(); p[0].z/=z; p[1].z/=z;
  24. return T;
  25. }
  26. Edge& Edge::div(C Matrix &m)
  27. {
  28. p[0].divNormalized(m);
  29. p[1].divNormalized(m);
  30. Flt x=m.x.length2(); p[0].x/=x; p[1].x/=x;
  31. Flt y=m.y.length2(); p[0].y/=y; p[1].y/=y;
  32. Flt z=m.z.length2(); p[0].z/=z; p[1].z/=z;
  33. return T;
  34. }
  35. /******************************************************************************/
  36. void Edge2::draw(C Color &color)C
  37. {
  38. VI.color (color);
  39. VI.setType(VI_2D_FLAT, VI_LINE);
  40. if(Vtx2DFlat *v=(Vtx2DFlat*)VI.addVtx(2))
  41. {
  42. v[0].pos=p[0];
  43. v[1].pos=p[1];
  44. }
  45. VI.end();
  46. }
  47. void Edge2::draw(C Color &color0, C Color &color1)C
  48. {
  49. VI.setType(VI_2D_COL, VI_LINE);
  50. if(Vtx2DCol *v=(Vtx2DCol*)VI.addVtx(2))
  51. {
  52. v[0].pos=p[0]; v[0].color=color0;
  53. v[1].pos=p[1]; v[1].color=color1;
  54. }
  55. VI.end();
  56. }
  57. void Edge2::draw(C Color &color, Flt width)C
  58. {
  59. Vec2 perp=T.perp(); perp.setLength(width);
  60. VI.color (color);
  61. VI.setType(VI_2D_FLAT, VI_STRIP);
  62. if(Vtx2DFlat *v=(Vtx2DFlat*)VI.addVtx(4))
  63. {
  64. v[0].pos.set(p[0].x-perp.x, p[0].y-perp.y);
  65. v[1].pos.set(p[1].x-perp.x, p[1].y-perp.y);
  66. v[3].pos.set(p[1].x+perp.x, p[1].y+perp.y);
  67. v[2].pos.set(p[0].x+perp.x, p[0].y+perp.y);
  68. }
  69. VI.end();
  70. }
  71. /******************************************************************************/
  72. void Edge::draw(C Color &color)C
  73. {
  74. VI.color (color);
  75. VI.setType(VI_3D_FLAT, VI_LINE);
  76. if(Vtx3DFlat *v=(Vtx3DFlat*)VI.addVtx(2))
  77. {
  78. v[0].pos=p[0];
  79. v[1].pos=p[1];
  80. }
  81. VI.end();
  82. }
  83. void Edge::draw(C Color &color0, C Color &color1)C
  84. {
  85. VI.setType(VI_3D_COL, VI_LINE);
  86. if(Vtx3DCol *v=(Vtx3DCol*)VI.addVtx(2))
  87. {
  88. v[0].pos=p[0]; v[0].color=color0;
  89. v[1].pos=p[1]; v[1].color=color1;
  90. }
  91. VI.end();
  92. }
  93. void Edge::draw(C Color &color, Flt width)C
  94. {
  95. Flt z0=((p[0]*ObjMatrix)*CamMatrixInv).z-D.viewFromActual(),
  96. z1=((p[1]*ObjMatrix)*CamMatrixInv).z-D.viewFromActual();
  97. if( z0>=0 && z1>=0)Edge2(PosToScreenM(p[0]), PosToScreenM(p[1] )).draw(color, width);else
  98. if( z0> 0 )Edge2(PosToScreenM(p[0]), PosToScreenM(PointOnPlane(p[0], p[1], z0, z1))).draw(color, width);else
  99. if( z1> 0 )Edge2(PosToScreenM(p[1]), PosToScreenM(PointOnPlane(p[0], p[1], z0, z1))).draw(color, width);
  100. }
  101. /******************************************************************************/
  102. void EdgeD2::draw(C Color &color )C {return Edge2(T).draw(color );}
  103. void EdgeD2::draw(C Color &color , Flt width )C {return Edge2(T).draw(color , width );}
  104. void EdgeD2::draw(C Color &color0, C Color &color1)C {return Edge2(T).draw(color0, color1);}
  105. void EdgeD ::draw(C Color &color )C {return Edge (T).draw(color );}
  106. void EdgeD ::draw(C Color &color , Flt width )C {return Edge (T).draw(color , width );}
  107. void EdgeD ::draw(C Color &color0, C Color &color1)C {return Edge (T).draw(color0, color1);}
  108. /******************************************************************************/
  109. void Edge2_I::set(C Vec2 &a, C Vec2 &b, C Vec2 *normal)
  110. {
  111. p[0]=a;
  112. p[1]=b;
  113. if(normal)
  114. {
  115. T.normal=*normal;
  116. dir.x =-T.normal.y;
  117. dir.y = T.normal.x;
  118. length= DistPointPlane(b, a, dir);
  119. }else
  120. {
  121. dir = delta();
  122. length = dir.normalize();
  123. T.normal.x= dir.y;
  124. T.normal.y=-dir.x;
  125. }
  126. }
  127. void EdgeD2_I::set(C VecD2 &a, C VecD2 &b, C VecD2 *normal)
  128. {
  129. p[0]=a;
  130. p[1]=b;
  131. if(normal)
  132. {
  133. T.normal=*normal;
  134. dir.x =-T.normal.y;
  135. dir.y = T.normal.x;
  136. length= DistPointPlane(b, a, dir);
  137. }else
  138. {
  139. dir = delta();
  140. length = dir.normalize();
  141. T.normal.x= dir.y;
  142. T.normal.y=-dir.x;
  143. }
  144. }
  145. void Edge_I::set(C Vec &a, C Vec &b)
  146. {
  147. p[0] =a;
  148. p[1] =b;
  149. dir =b-a;
  150. length=dir.normalize();
  151. }
  152. void EdgeD_I::set(C VecD &a, C VecD &b)
  153. {
  154. p[0] =a;
  155. p[1] =b;
  156. dir =b-a;
  157. length=dir.normalize();
  158. }
  159. /******************************************************************************/
  160. // PIXEL WALKER
  161. /******************************************************************************/
  162. void PixelWalker::start(C VecI2 &start, C VecI2 &end)
  163. {
  164. VecI2 delta=end-start, adelta=Abs(delta);
  165. _active =true;
  166. _side_step=false;
  167. _axis =(adelta.maxI()==1);
  168. _steps = adelta.max ();
  169. _main_sign=Sign(delta.c[_axis]);
  170. _pos =start;
  171. _posr =start+0.5f;
  172. _step =delta; if(_steps)_step/=_steps;
  173. _pos_temp =_pos;
  174. }
  175. void PixelWalker::start(C Vec2 &start, C Vec2 &end)
  176. {
  177. _pos =Floor(start);
  178. _posr= start ;
  179. VecI2 delta=Floor(end)-_pos, adelta=Abs(delta);
  180. _active =true;
  181. _side_step=false;
  182. _axis =(adelta.maxI()==1);
  183. _steps = adelta.max (); // Abs(delta.c[_axis]);
  184. _main_sign=Sign(delta.c[_axis]);
  185. _step =end-start; if(_steps)_step/=_steps;
  186. _pos_temp =_pos;
  187. }
  188. void PixelWalker::step()
  189. {
  190. if(_active)
  191. {
  192. if(_side_step)
  193. {
  194. _pos_temp =_pos;
  195. _side_step= false;
  196. }else
  197. if(_steps-- <= 0)
  198. {
  199. _active=false;
  200. }else
  201. {
  202. Vec2 posr_next=_posr+_step;
  203. VecI2 pos_next;
  204. if(_axis==0) // horizontal
  205. {
  206. pos_next.set(_pos.x+_main_sign, Floor(posr_next.y));
  207. if(_pos.y!=pos_next.y) // we've changed Y, we need to check if additional step is required
  208. {
  209. Clamp(pos_next.y, _pos.y-1, _pos.y+1); // due to numerical precision issues the position can move more than 1, if for example the end is located at 0.0 coordinates and we would slightly cross the border, this is be cause in each step we accumulate '_step' which introduces some error
  210. // check which pixel was crossed first
  211. Flt dest;
  212. dest=Max(_pos.x, pos_next.x); Flt d0=(dest-_posr.x)/_step.x;
  213. dest=Max(_pos.y, pos_next.y); Flt d1=(dest-_posr.y)/_step.y;
  214. if(d0<d1){_pos_temp.x=pos_next.x; _side_step=true;}else // move in _axis first
  215. if(d0>d1){_pos_temp.y=pos_next.y; _side_step=true;} // move in !_axis first
  216. }
  217. }else // vertical
  218. {
  219. pos_next.set(Floor(posr_next.x), _pos.y+_main_sign);
  220. if(_pos.x!=pos_next.x) // we've changed X, we need to check if additional step is required
  221. {
  222. Clamp(pos_next.x, _pos.x-1, _pos.x+1); // due to numerical precision issues the position can move more than 1, if for example the end is located at 0.0 coordinates and we would slightly cross the border, this is be cause in each step we accumulate '_step' which introduces some error
  223. // check which pixel was crossed first
  224. Flt dest;
  225. dest=Max(_pos.y, pos_next.y); Flt d0=(dest-_posr.y)/_step.y;
  226. dest=Max(_pos.x, pos_next.x); Flt d1=(dest-_posr.x)/_step.x;
  227. if(d0<d1){_pos_temp.y=pos_next.y; _side_step=true;}else // move in _axis first
  228. if(d0>d1){_pos_temp.x=pos_next.x; _side_step=true;} // move in !_axis first
  229. }
  230. }
  231. _posr=posr_next;
  232. _pos = pos_next;
  233. if(!_side_step)_pos_temp=_pos;
  234. }
  235. }
  236. }
  237. /******************************************************************************/
  238. void PixelWalkerMask::start(C VecI2 &start, C VecI2 &end, C RectI &mask) {T.start(start+0.5f, end+0.5f, mask);}
  239. void PixelWalkerMask::start(C Vec2 &start, C Vec2 &end, C RectI &mask)
  240. {
  241. //Edge2 edge(start, end); if(Clip(edge, Rect(mask.min, mask.max+1))) no need to clip 'end' because we have to do it anyway in 'step'
  242. Vec2 start_clamp; if(SweepPointRect(start, end-start, Rect(mask.min, mask.max+1), null, null, &start_clamp))
  243. {
  244. //super::start(edge.p[0], edge.p[1]);
  245. super::start(start_clamp, end);
  246. T._mask=mask;
  247. for(; !mask.includes(T.pos()) && _active; )super::step(); // if not at the start, have to check multiple times in case we hit the mask rect at the edge, but it needs multiple steps to cross that border
  248. }else _active=false;
  249. }
  250. void PixelWalkerMask::step()
  251. {
  252. super::step();
  253. if(!_mask.includes(T.pos()))_active=false; // have to check mask in each step, because there's no easy way to prevent the end from going out of range, can't just decrease '_steps' because last valid pixel could be a side step before a position that is out of range
  254. }
  255. /******************************************************************************/
  256. void PixelWalkerEdge::start(C Vec2 &start, C Vec2 &end)
  257. {
  258. VecI2 pos=Floor(start), endi=Floor(end), delta=endi-pos;
  259. Bool frac_start_x=(start.x-pos.x!=0), frac_end_x=(end.x-endi.x!=0),
  260. frac_start_y=(start.y-pos.y!=0), frac_end_y=(end.y-endi.y!=0);
  261. if(end.x<start.x && !frac_start_x && frac_end_x)delta.x++;else
  262. if(end.x>start.x && frac_start_x && !frac_end_x)delta.x--;
  263. if(end.y<start.y && !frac_start_y && frac_end_y)delta.y++;else
  264. if(end.y>start.y && frac_start_y && !frac_end_y)delta.y--;
  265. VecI2 adelta=Abs(delta);
  266. _active =true;
  267. _side_step=false;
  268. _axis =((adelta.x>adelta.y) ? 0 : (adelta.y>adelta.x) ? 1 : (Abs(end-start).maxI()==1)); // _axis=(adelta.maxI()==1);
  269. _steps =adelta.max(); // Abs(delta.c[_axis]);
  270. _posr = start;
  271. _pos_end =end ;
  272. _step =end-start;
  273. if(_axis==0) // horizontal
  274. {
  275. if(frac_start_x)
  276. {
  277. Flt dest=pos.x+(end.x>start.x);
  278. _pos_next.set(dest, start.y+(dest-start.x)/_step.x*_step.y);
  279. }else
  280. {
  281. _pos_next=start;
  282. }
  283. _pos=pos.y;
  284. _step/=Max(1, Abs(_step.x)); // "Max(1" solves problem for start(-0.5, -0.5) end(0.0, 0.0) generating 2 points, because of this, when calculating if side-step is needed, 'd' will get 1.0 value and not qualify
  285. if(!frac_start_x || !frac_end_x)_steps++;
  286. }else // vertical
  287. {
  288. if(frac_start_y)
  289. {
  290. Flt dest=pos.y+(end.y>start.y);
  291. _pos_next.set(start.x+(dest-start.y)/_step.y*_step.x, dest);
  292. }else
  293. {
  294. _pos_next=start;
  295. }
  296. _pos=pos.x;
  297. _step/=Max(1, Abs(_step.y)); // "Max(1" solves problem for start(-0.5, -0.5) end(0.0, 0.0) generating 2 points, because of this, when calculating if side-step is needed, 'd' will get 1.0 value and not qualify
  298. if(!frac_start_y || !frac_end_y)_steps++;
  299. }
  300. step();
  301. }
  302. void PixelWalkerEdge::step()
  303. {
  304. if(_active)
  305. {
  306. if(_steps<=0)
  307. {
  308. if(_steps==0) // if this is the last step, then check if we have to perform a side-step
  309. {
  310. _pos_next=_pos_end;
  311. _steps= 1; step();
  312. _steps=-1; // make sure we will not make any more attempts
  313. if(sideStep())return;
  314. }
  315. _active=false;
  316. }else
  317. if(_side_step)
  318. {
  319. _side_step= false;
  320. _posr =_pos_next; _pos_next+=_step;
  321. _steps--;
  322. }else
  323. {
  324. if(_axis==0) // horizontal
  325. {
  326. Int pos_y=Floor(_pos_next.y);
  327. if(_pos!=pos_y) // we've changed Y, we need to check if additional step is required
  328. {
  329. Flt dest=Max(_pos, pos_y), d=(dest-_posr.y)/_step.y; if(d>EPS && d<1-EPS) // EPS needed to avoid generating duplicate points at the same position due to numerical precision issues
  330. {
  331. _posr.x+=d*_step.x;
  332. _posr.y =dest; _side_step=true;
  333. }
  334. _pos=pos_y;
  335. }
  336. }else // vertical
  337. {
  338. Int pos_x=Floor(_pos_next.x);
  339. if(_pos!=pos_x) // we've changed X, we need to check if additional step is required
  340. {
  341. Flt dest=Max(_pos, pos_x), d=(dest-_posr.x)/_step.x; if(d>EPS && d<1-EPS) // EPS needed to avoid generating duplicate points at the same position due to numerical precision issues
  342. {
  343. _posr.y+=d*_step.y;
  344. _posr.x =dest; _side_step=true;
  345. }
  346. _pos=pos_x;
  347. }
  348. }
  349. if(!_side_step)
  350. {
  351. _posr=_pos_next; _pos_next+=_step;
  352. _steps--;
  353. }
  354. }
  355. }
  356. }
  357. /******************************************************************************/
  358. void PixelWalkerEdgeMask::start(C Vec2 &start, C Vec2 &end, C RectI &mask)
  359. {
  360. //_mask.set(mask.min, mask.max+1).extend(EPS); // extend to make sure we will process positions at the borders, due to numerical precision issues
  361. _mask.set(mask.min-EPS, mask.max+(1+EPS)); // extend to make sure we will process positions at the borders, due to numerical precision issues
  362. //Edge2 edge(start, end); if(Clip(edge, _mask)) no need to clip 'end' because we have to do it anyway in 'step'
  363. Vec2 start_clamp; if(SweepPointRect(start, end-start, _mask, null, null, &start_clamp))
  364. {
  365. //super::start(edge.p[0], edge.p[1]);
  366. super::start(start_clamp, end);
  367. for(; !_mask.includes(T.pos()) && _active; )super::step(); // if not at the start, have to check multiple times in case we hit the mask rect at the edge, but it needs multiple steps to cross that border
  368. }else _active=false;
  369. }
  370. void PixelWalkerEdgeMask::step()
  371. {
  372. super::step();
  373. if(!_mask.includes(T.pos()))_active=false; // have to check mask in each step, because there's no easy way to prevent the end from going out of range, can't just decrease '_steps' because last valid pixel could be a side step before a position that is out of range
  374. }
  375. /******************************************************************************/
  376. // VOXEL WALKER
  377. /******************************************************************************/
  378. void VoxelWalker::start(C VecI &start, C VecI &end)
  379. {
  380. VecI delta=end-start, adelta=Abs(delta); _axis.set(0, 1, 2);
  381. if(adelta.y<adelta.z){Swap(_axis.y, _axis.z); Swap(adelta.y, adelta.z);}
  382. if(adelta.x<adelta.y){Swap(_axis.x, _axis.y); Swap(adelta.x, adelta.y);
  383. if(adelta.y<adelta.z){Swap(_axis.y, _axis.z); Swap(adelta.y, adelta.z);}} // this can happen only if XY were swapped
  384. _active =true;
  385. _side_step=false;
  386. _steps =adelta.max();
  387. _main_sign=Sign(delta.c[_axis.x]);
  388. _pos =start;
  389. _posr =start+0.5f;
  390. _step =delta; if(_steps)_step/=_steps;
  391. _pos_temp =_pos;
  392. }
  393. void VoxelWalker::start(C Vec &start, C Vec &end)
  394. {
  395. _pos =Floor(start);
  396. _posr= start ;
  397. VecI delta=Floor(end)-_pos, adelta=Abs(delta); _axis.set(0, 1, 2);
  398. if(adelta.y<adelta.z){Swap(_axis.y, _axis.z); Swap(adelta.y, adelta.z);}
  399. if(adelta.x<adelta.y){Swap(_axis.x, _axis.y); Swap(adelta.x, adelta.y);
  400. if(adelta.y<adelta.z){Swap(_axis.y, _axis.z); Swap(adelta.y, adelta.z);}} // this can happen only if XY were swapped
  401. _active =true;
  402. _side_step=false;
  403. _steps =adelta.max();
  404. _main_sign=Sign(delta.c[_axis.x]);
  405. _step =end-start; if(_steps)_step/=_steps;
  406. _pos_temp =_pos;
  407. }
  408. void VoxelWalker::step()
  409. {
  410. if(_active)
  411. {
  412. if(_side_step)
  413. {
  414. if(_side_step>=2)
  415. {
  416. Int axis=_side_step-2;
  417. _pos_temp.c[axis]=_pos.c[axis];
  418. _side_step=true;
  419. }else
  420. {
  421. _pos_temp =_pos;
  422. _side_step= false;
  423. }
  424. }else
  425. if(_steps-- <= 0)
  426. {
  427. _active=false;
  428. }else
  429. {
  430. Vec posr_next=_posr+_step;
  431. VecI pos_next;
  432. pos_next.c[_axis.x]= _pos .c[_axis.x]+_main_sign;
  433. pos_next.c[_axis.y]=Floor(posr_next.c[_axis.y]);
  434. pos_next.c[_axis.z]=Floor(posr_next.c[_axis.z]);
  435. VecI2 pos_changed(_pos.c[_axis.y]!=pos_next.c[_axis.y], // if we've changed second axis
  436. _pos.c[_axis.z]!=pos_next.c[_axis.z]); // if we've changed third axis
  437. if(pos_changed.all()) // both secondary axes changed
  438. {
  439. Clamp(pos_next.c[_axis.y], _pos.c[_axis.y]-1, _pos.c[_axis.y]+1); // due to numerical precision issues the position can move more than 1, if for example the end is located at 0.0 coordinates and we would slightly cross the border, this is be cause in each step we accumulate '_step' which introduces some error
  440. Clamp(pos_next.c[_axis.z], _pos.c[_axis.z]-1, _pos.c[_axis.z]+1); // due to numerical precision issues the position can move more than 1, if for example the end is located at 0.0 coordinates and we would slightly cross the border, this is be cause in each step we accumulate '_step' which introduces some error
  441. // check which voxel was crossed first
  442. Flt dest;
  443. dest=Max(_pos.c[_axis.x], pos_next.c[_axis.x]); Flt d0=(dest-_posr.c[_axis.x])/_step.c[_axis.x];
  444. dest=Max(_pos.c[_axis.y], pos_next.c[_axis.y]); Flt d1=(dest-_posr.c[_axis.y])/_step.c[_axis.y];
  445. dest=Max(_pos.c[_axis.z], pos_next.c[_axis.z]); Flt d2=(dest-_posr.c[_axis.z])/_step.c[_axis.z];
  446. VecI order=_axis;
  447. if(d1>d2){Swap(order.y, order.z); Swap(d1, d2);}
  448. if(d0>d1){Swap(order.x, order.y); Swap(d0, d1);
  449. if(d1>d2){Swap(order.y, order.z); Swap(d1, d2);}} // this can happen only if XY were swapped
  450. // following code is for ignoring voxels when crossing at the same time 01 instead of 01
  451. // 10 11
  452. Int same=0;
  453. if(d0==d1) // if both were crossed at the same time
  454. {
  455. if(d0==d2)same=2;else // all the same, then don't move at all
  456. {
  457. _pos_temp.c[order.y]=pos_next.c[order.y]; // move on order.y axis (this will be together with order.x)
  458. order.y=order.z; d1=d2; // remove d1, replace with d2
  459. same=1;
  460. }
  461. }else
  462. if(d1==d2)same=1;
  463. _pos_temp.c[order.x]=pos_next.c[order.x]; // move on order.x axis first
  464. _side_step=((same==0) ? 2+order.y : (same==1) ? true : false); // move on order.y axis next
  465. }else
  466. if(pos_changed.any()) // only one secondary axis was changed
  467. {
  468. Int main_axis= _axis.x ;
  469. Int sec_axis=(pos_changed.x ? _axis.y : _axis.z);
  470. Clamp(pos_next.c[sec_axis], _pos.c[sec_axis]-1, _pos.c[sec_axis]+1); // due to numerical precision issues the position can move more than 1, if for example the end is located at 0.0 coordinates and we would slightly cross the border, this is be cause in each step we accumulate '_step' which introduces some error
  471. // check which voxel was crossed first
  472. Flt dest;
  473. dest=Max(_pos.c[main_axis], pos_next.c[main_axis]); Flt d0=(dest-_posr.c[main_axis])/_step.c[main_axis];
  474. dest=Max(_pos.c[ sec_axis], pos_next.c[ sec_axis]); Flt d1=(dest-_posr.c[ sec_axis])/_step.c[ sec_axis];
  475. if(d0<d1){_pos_temp.c[main_axis]=pos_next.c[main_axis]; _side_step=true;}else // move in main_axis first
  476. if(d0>d1){_pos_temp.c[ sec_axis]=pos_next.c[ sec_axis]; _side_step=true;} // move in sec_axis first
  477. }
  478. _posr=posr_next;
  479. _pos = pos_next;
  480. if(!_side_step)_pos_temp=_pos;
  481. }
  482. }
  483. }
  484. /******************************************************************************/
  485. Flt DistPointStr(C Vec2 &point, C Vec2 &str, C Vec2 &dir) {return Abs(DistPointPlane(point, str, Perp(dir)) );}
  486. Dbl DistPointStr(C VecD2 &point, C VecD2 &str, C VecD2 &dir) {return Abs(DistPointPlane(point, str, Perp(dir)) );}
  487. Flt DistPointStr(C Vec &point, C Vec &str, C Vec &dir) {return Dist( PointOnPlane(point, str, dir ), str);}
  488. Dbl DistPointStr(C VecD &point, C Vec &str, C Vec &dir) {return Dist( PointOnPlane(point, str, dir ), str);}
  489. Dbl DistPointStr(C VecD &point, C VecD &str, C VecD &dir) {return Dist( PointOnPlane(point, str, dir ), str);}
  490. Flt DistStrStr(C Vec &pos_a, C Vec &dir_a, C Vec &pos_b, C Vec &dir_b)
  491. {
  492. Vec normal=Cross(dir_a, dir_b);
  493. if( normal.normalize())return Abs(DistPointPlane(pos_b, pos_a, normal));
  494. return Dist (pos_a, NearestPointOnStr(pos_a, pos_b, dir_b)); // if they're parallel, find closest point on straight 'pos_b' towards point 'pos_a' and return distance between them
  495. }
  496. Flt DistPointEdge(C Vec2 &point, C Vec2 &edge_a, C Vec2 &edge_b, DIST_TYPE *type) // safe in case 'edge' is zero length because 'd' would be zero, and 'DistPointPlane' would be zero
  497. {
  498. Vec2 d=edge_b-edge_a;
  499. if(DistPointPlane(point, edge_a, d)<=0){if(type)*type=DIST_POINT0; return Dist (point, edge_a );}
  500. if(DistPointPlane(point, edge_b, d)>=0){if(type)*type=DIST_POINT1; return Dist (point, edge_b );}
  501. if(type)*type=DIST_EDGE ; return DistPointStr(point, edge_a, !d);
  502. }
  503. Dbl DistPointEdge(C VecD2 &point, C VecD2 &edge_a, C VecD2 &edge_b, DIST_TYPE *type) // safe in case 'edge' is zero length because 'd' would be zero, and 'DistPointPlane' would be zero
  504. {
  505. VecD2 d=edge_b-edge_a;
  506. if(DistPointPlane(point, edge_a, d)<=0){if(type)*type=DIST_POINT0; return Dist (point, edge_a );}
  507. if(DistPointPlane(point, edge_b, d)>=0){if(type)*type=DIST_POINT1; return Dist (point, edge_b );}
  508. if(type)*type=DIST_EDGE ; return DistPointStr(point, edge_a, !d);
  509. }
  510. Flt DistPointEdge(C Vec &point, C Vec &edge_a, C Vec &edge_b, DIST_TYPE *type) // safe in case 'edge' is zero length because 'd' would be zero, and 'DistPointPlane' would be zero
  511. {
  512. Vec d=edge_b-edge_a;
  513. if(DistPointPlane(point, edge_a, d)<=0){if(type)*type=DIST_POINT0; return Dist (point, edge_a );}
  514. if(DistPointPlane(point, edge_b, d)>=0){if(type)*type=DIST_POINT1; return Dist (point, edge_b );}
  515. if(type)*type=DIST_EDGE ; return DistPointStr(point, edge_a, !d);
  516. }
  517. Dbl DistPointEdge(C VecD &point, C Vec &edge_a, C Vec &edge_b, DIST_TYPE *type) // safe in case 'edge' is zero length because 'd' would be zero, and 'DistPointPlane' would be zero
  518. {
  519. Vec d=edge_b-edge_a;
  520. if(DistPointPlane(point, edge_a, d)<=0){if(type)*type=DIST_POINT0; return Dist (point, edge_a );}
  521. if(DistPointPlane(point, edge_b, d)>=0){if(type)*type=DIST_POINT1; return Dist (point, edge_b );}
  522. if(type)*type=DIST_EDGE ; return DistPointStr(point, edge_a, !d);
  523. }
  524. Dbl DistPointEdge(C VecD &point, C VecD &edge_a, C VecD &edge_b, DIST_TYPE *type) // safe in case 'edge' is zero length because 'd' would be zero, and 'DistPointPlane' would be zero
  525. {
  526. VecD d=edge_b-edge_a;
  527. if(DistPointPlane(point, edge_a, d)<=0){if(type)*type=DIST_POINT0; return Dist (point, edge_a );}
  528. if(DistPointPlane(point, edge_b, d)>=0){if(type)*type=DIST_POINT1; return Dist (point, edge_b );}
  529. if(type)*type=DIST_EDGE ; return DistPointStr(point, edge_a, !d);
  530. }
  531. /******************************************************************************/
  532. Flt Dist(C Edge2 &a, C Edge2 &b)
  533. {
  534. // check if they're cutting each other
  535. Vec2 a_dir =a.delta(); Flt a_length=a_dir.normalize();
  536. Vec2 b_dir =b.dir (),
  537. a_perp=Perp(a_dir),
  538. b_perp=Perp(b_dir);
  539. Flt d0=DistPointPlane(b.p[0], a.p[0], a_perp); Int s0=Sign(d0);
  540. Flt d1=DistPointPlane(b.p[1], a.p[0], a_perp); Int s1=Sign(d1);
  541. if( s0==-s1 && s0)
  542. {
  543. Vec2 p=PointOnPlane (b.p[0], b.p[1], d0, d1);
  544. Flt d=DistPointPlane( p , a.p[0], a_dir );
  545. if(d>=0 && d<=a_length)return 0;
  546. }
  547. // they don't cut
  548. return Min(Dist(a.p[0], b),
  549. Dist(a.p[1], b),
  550. Dist(b.p[0], a),
  551. Dist(b.p[1], a));
  552. }
  553. Flt Dist(C Edge &a, C Edge &b) // safe in case 'a' or 'b' are zero length
  554. {
  555. // check if they're cutting each other
  556. Edge c;
  557. Vec a_dir=a.dir(),
  558. b_dir=b.dir();
  559. if(NearestPointOnStr(a.p[0], a_dir, b.p[0], b_dir, c)) // safe in case 'a' or 'b' are zero length
  560. {
  561. if(DistPointPlane(c.p[0], a.p[0], a_dir)>=0 && DistPointPlane(c.p[0], a.p[1], a_dir)<=0
  562. && DistPointPlane(c.p[1], b.p[0], b_dir)>=0 && DistPointPlane(c.p[1], b.p[1], b_dir)<=0)return c.length();
  563. }
  564. // they don't cut
  565. return Min(Dist(a.p[0], b),
  566. Dist(a.p[1], b),
  567. Dist(b.p[0], a),
  568. Dist(b.p[1], a));
  569. }
  570. /******************************************************************************/
  571. Flt Dist(C Edge &edge, C Plane &plane) // safe in case 'a' or 'b' are zero length
  572. {
  573. return Min(Dist(edge.p[0], plane),
  574. Dist(edge.p[1], plane));
  575. }
  576. /******************************************************************************/
  577. Vec2 NearestPointOnEdge(C Vec2 &point, C Vec2 &edge_a, C Vec2 &edge_b)
  578. {
  579. Vec2 dir=edge_b-edge_a;
  580. if(DistPointPlane(point, edge_a, dir)<=0)return edge_a;
  581. if(DistPointPlane(point, edge_b, dir)>=0)return edge_b;
  582. {
  583. dir.normalize();
  584. return edge_a + dir*DistPointPlane(point, edge_a, dir);
  585. }
  586. }
  587. Vec NearestPointOnEdge(C Vec &point, C Vec &edge_a, C Vec &edge_b)
  588. {
  589. Vec dir=edge_b-edge_a;
  590. if(DistPointPlane(point, edge_a, dir)<=0)return edge_a;
  591. if(DistPointPlane(point, edge_b, dir)>=0)return edge_b;
  592. {
  593. dir.normalize();
  594. return edge_a + dir*DistPointPlane(point, edge_a, dir);
  595. }
  596. }
  597. Vec NearestPointOnStr(C Vec &point, C Vec &str, C Vec &dir)
  598. {
  599. return str + dir*DistPointPlane(point, str, dir);
  600. }
  601. Bool NearestPointOnStr(C Vec &pos_a, C Vec &dir_a, C Vec &pos_b, C Vec &dir_b, Edge &out)
  602. {
  603. Vec normal=Cross(dir_a, dir_b);
  604. if( normal.normalize())
  605. {
  606. out.p[0]=PointOnPlaneRay(pos_a, pos_b, CrossN(normal, dir_b), dir_a);
  607. out.p[1]=PointOnPlaneRay(pos_b, pos_a, CrossN(normal, dir_a), dir_b);
  608. return true;
  609. }
  610. return false;
  611. }
  612. /******************************************************************************/
  613. Bool CutsPointEdge(C Vec2 &point, C Edge2_I &ei, Vec2 *cuts)
  614. {
  615. if(Abs(DistPointPlane(point, ei.p[0], ei.normal))<=EPS)
  616. {
  617. const Flt eps=EPS;
  618. Flt l=DistPointPlane(point, ei.p[0], ei.dir);
  619. if( l>=-eps && l<=ei.length+eps)
  620. {
  621. if(cuts)
  622. {
  623. const Flt eps2=EPS;
  624. if(l<= eps2)*cuts=ei.p[0];else
  625. if(l>=ei.length-eps2)*cuts=ei.p[1];else
  626. *cuts=point;
  627. }
  628. return true;
  629. }
  630. }
  631. return false;
  632. }
  633. Bool CutsPointEdge(C VecD2 &point, C EdgeD2_I &ei, VecD2 *cuts)
  634. {
  635. if(Abs(DistPointPlane(point, ei.p[0], ei.normal))<=EPSD)
  636. {
  637. const Dbl eps=EPSD;
  638. Dbl l=DistPointPlane(point, ei.p[0], ei.dir);
  639. if( l>=-eps && l<=ei.length+eps)
  640. {
  641. if(cuts)
  642. {
  643. const Dbl eps2=EPSD;
  644. if(l<= eps2)*cuts=ei.p[0];else
  645. if(l>=ei.length-eps2)*cuts=ei.p[1];else
  646. *cuts=point;
  647. }
  648. return true;
  649. }
  650. }
  651. return false;
  652. }
  653. Bool CutsPointEdge(C Vec &point, C Edge_I &ei, Vec *cuts)
  654. {
  655. if(DistPointStr(point, ei.p[0], ei.dir)<=EPS)
  656. {
  657. const Flt eps=EPS;
  658. Flt l=DistPointPlane(point, ei.p[0], ei.dir);
  659. if( l>=-eps && l<=ei.length+eps)
  660. {
  661. if(cuts)
  662. {
  663. const Flt eps2=EPS;
  664. if(l<= eps2)*cuts=ei.p[0];else
  665. if(l>=ei.length-eps2)*cuts=ei.p[1];else
  666. *cuts=point;
  667. }
  668. return true;
  669. }
  670. }
  671. return false;
  672. }
  673. Bool CutsPointEdge(C VecD &point, C EdgeD_I &ei, VecD *cuts)
  674. {
  675. if(DistPointStr(point, ei.p[0], ei.dir)<=EPSD)
  676. {
  677. const Dbl eps=EPSD;
  678. Dbl l=DistPointPlane(point, ei.p[0], ei.dir);
  679. if( l>=-eps && l<=ei.length+eps)
  680. {
  681. if(cuts)
  682. {
  683. const Dbl eps2=EPSD;
  684. if(l<= eps2)*cuts=ei.p[0];else
  685. if(l>=ei.length-eps2)*cuts=ei.p[1];else
  686. *cuts=point;
  687. }
  688. return true;
  689. }
  690. }
  691. return false;
  692. }
  693. /******************************************************************************/
  694. Int CutsEdgeEdge(C Edge2_I &a, C Edge2_I &b, Edge2 *cuts)
  695. {
  696. if(cuts)
  697. {
  698. Vec2 point[2];
  699. Int points=0;
  700. if(CutsPointEdge(b.p[0], a, &point[ 0]))points++;
  701. if(CutsPointEdge(b.p[1], a, &point[points]))points++;
  702. if(points==0)
  703. {
  704. if(CutsPointEdge(a.p[0], b, &point[ 0]))points++;
  705. if(CutsPointEdge(a.p[1], b, &point[points]))points++;
  706. }else
  707. if(points==1)
  708. {
  709. if(CutsPointEdge(a.p[0], b, &point[1]) && !Equal(point[0], point[1]))points++;else
  710. if(CutsPointEdge(a.p[1], b, &point[1]) && !Equal(point[0], point[1]))points++;
  711. }
  712. if(points)
  713. {
  714. cuts->p[0]=point[0];
  715. cuts->p[1]=point[1];
  716. return points;
  717. }
  718. Flt d0=DistPointPlane(b.p[0], a.p[0], a.normal); Int s0=Sign(d0);
  719. Flt d1=DistPointPlane(b.p[1], a.p[0], a.normal); Int s1=Sign(d1);
  720. if( s0==-s1 && s0)
  721. {
  722. Vec2 p=PointOnPlane (b.p[0], b.p[1], d0, d1);
  723. Flt d=DistPointPlane( p , a.p[0], a.dir );
  724. if(d>=0 && d<=a.length){cuts->p[0]=p; return 1;} // EPS doesn't need to be included because those cases have already been checked when testing points
  725. }
  726. }else
  727. {
  728. if(CutsPointEdge(a.p[0], b)
  729. || CutsPointEdge(a.p[1], b)
  730. || CutsPointEdge(b.p[0], a)
  731. || CutsPointEdge(b.p[1], a))return 1;
  732. Flt d0=DistPointPlane(b.p[0], a.p[0], a.normal); Int s0=Sign(d0);
  733. Flt d1=DistPointPlane(b.p[1], a.p[0], a.normal); Int s1=Sign(d1);
  734. if( s0==-s1 && s0)
  735. {
  736. Flt d=DistPointPlane(PointOnPlane(b.p[0], b.p[1], d0, d1), a.p[0], a.dir);
  737. if(d>=0 && d<=a.length)return 1; // EPS doesn't need to be included because those cases have already been checked when testing points
  738. }
  739. }
  740. return 0;
  741. }
  742. Int CutsEdgeEdge(C EdgeD2_I &a, C EdgeD2_I &b, EdgeD2 *cuts)
  743. {
  744. if(cuts)
  745. {
  746. VecD2 point[2];
  747. Int points=0;
  748. if(CutsPointEdge(b.p[0], a, &point[ 0]))points++;
  749. if(CutsPointEdge(b.p[1], a, &point[points]))points++;
  750. if(points==0)
  751. {
  752. if(CutsPointEdge(a.p[0], b, &point[ 0]))points++;
  753. if(CutsPointEdge(a.p[1], b, &point[points]))points++;
  754. }else
  755. if(points==1)
  756. {
  757. if(CutsPointEdge(a.p[0], b, &point[1]) && !Equal(point[0], point[1]))points++;else
  758. if(CutsPointEdge(a.p[1], b, &point[1]) && !Equal(point[0], point[1]))points++;
  759. }
  760. if(points)
  761. {
  762. cuts->p[0]=point[0];
  763. cuts->p[1]=point[1];
  764. return points;
  765. }
  766. Dbl d0=DistPointPlane(b.p[0], a.p[0], a.normal); Int s0=Sign(d0);
  767. Dbl d1=DistPointPlane(b.p[1], a.p[0], a.normal); Int s1=Sign(d1);
  768. if( s0==-s1 && s0)
  769. {
  770. VecD2 p=PointOnPlane (b.p[0], b.p[1], d0, d1);
  771. Dbl d=DistPointPlane( p , a.p[0], a.dir );
  772. if(d>=0 && d<=a.length){cuts->p[0]=p; return 1;} // EPS doesn't need to be included because those cases have already been checked when testing points
  773. }
  774. }else
  775. {
  776. if(CutsPointEdge(a.p[0], b)
  777. || CutsPointEdge(a.p[1], b)
  778. || CutsPointEdge(b.p[0], a)
  779. || CutsPointEdge(b.p[1], a))return 1;
  780. Dbl d0=DistPointPlane(b.p[0], a.p[0], a.normal); Int s0=Sign(d0);
  781. Dbl d1=DistPointPlane(b.p[1], a.p[0], a.normal); Int s1=Sign(d1);
  782. if( s0==-s1 && s0)
  783. {
  784. Dbl d=DistPointPlane(PointOnPlane(b.p[0], b.p[1], d0, d1), a.p[0], a.dir);
  785. if(d>=0 && d<=a.length)return 1; // EPS doesn't need to be included because those cases have already been checked when testing points
  786. }
  787. }
  788. return 0;
  789. }
  790. Int CutsEdgeEdge(C Edge_I &a, C Edge_I &b, Edge *cuts)
  791. {
  792. if(cuts)
  793. {
  794. Vec point[2];
  795. Int points=0;
  796. if(CutsPointEdge(b.p[0], a, &point[ 0]))points++;
  797. if(CutsPointEdge(b.p[1], a, &point[points]))points++;
  798. if(points==0)
  799. {
  800. if(CutsPointEdge(a.p[0], b, &point[ 0]))points++;
  801. if(CutsPointEdge(a.p[1], b, &point[points]))points++;
  802. }else
  803. if(points==1)
  804. {
  805. if(CutsPointEdge(a.p[0], b, &point[1]) && !Equal(point[0], point[1]))points++;else
  806. if(CutsPointEdge(a.p[1], b, &point[1]) && !Equal(point[0], point[1]))points++;
  807. }
  808. if(points)
  809. {
  810. cuts->p[0]=point[0];
  811. cuts->p[1]=point[1];
  812. return points;
  813. }
  814. Vec normal=Cross(a.dir, b.dir);
  815. if( normal.normalize() && Abs(DistPointPlane(b.p[0], a.p[0], normal))<=EPS)
  816. {
  817. Vec p=PointOnPlaneRay(a.p[0], b.p[0], CrossN(normal, b.dir), a.dir);
  818. Flt d=DistPointPlane (p , b.p[0], b.dir);
  819. if( d>=0 && d<=b.length) // EPS doesn't need to be included because those cases have already been checked when testing points
  820. {
  821. d=DistPointPlane(p, a.p[0], a.dir);
  822. if(d>=0 && d<=a.length){cuts->p[0]=p; return 1;} // EPS doesn't need to be included because those cases have already been checked when testing points
  823. }
  824. }
  825. }else
  826. {
  827. if(CutsPointEdge(a.p[0], b)
  828. || CutsPointEdge(a.p[1], b)
  829. || CutsPointEdge(b.p[0], a)
  830. || CutsPointEdge(b.p[1], a))return 1;
  831. Vec normal=Cross(a.dir, b.dir);
  832. if( normal.normalize() && Abs(DistPointPlane(b.p[0], a.p[0], normal))<=EPS)
  833. {
  834. Vec p=PointOnPlaneRay(a.p[0], b.p[0], CrossN(normal, b.dir), a.dir);
  835. Flt d=DistPointPlane (p , b.p[0], b.dir);
  836. if( d>=0 && d<=b.length) // EPS doesn't need to be included because those cases have already been checked when testing points
  837. {
  838. d=DistPointPlane(p, a.p[0], a.dir);
  839. if(d>=0 && d<=a.length)return 1; // EPS doesn't need to be included because those cases have already been checked when testing points
  840. }
  841. }
  842. }
  843. return 0;
  844. }
  845. Int CutsEdgeEdge(C EdgeD_I &a, C EdgeD_I &b, EdgeD *cuts)
  846. {
  847. if(cuts)
  848. {
  849. VecD point[2];
  850. Int points=0;
  851. if(CutsPointEdge(b.p[0], a, &point[ 0]))points++;
  852. if(CutsPointEdge(b.p[1], a, &point[points]))points++;
  853. if(points==0)
  854. {
  855. if(CutsPointEdge(a.p[0], b, &point[ 0]))points++;
  856. if(CutsPointEdge(a.p[1], b, &point[points]))points++;
  857. }else
  858. if(points==1)
  859. {
  860. if(CutsPointEdge(a.p[0], b, &point[1]) && !Equal(point[0], point[1]))points++;else
  861. if(CutsPointEdge(a.p[1], b, &point[1]) && !Equal(point[0], point[1]))points++;
  862. }
  863. if(points)
  864. {
  865. cuts->p[0]=point[0];
  866. cuts->p[1]=point[1];
  867. return points;
  868. }
  869. VecD normal=Cross(a.dir, b.dir);
  870. if( normal.normalize() && Abs(DistPointPlane(b.p[0], a.p[0], normal))<=EPSD)
  871. {
  872. VecD p=PointOnPlaneRay(a.p[0], b.p[0], CrossN(normal, b.dir), a.dir);
  873. Dbl d=DistPointPlane (p , b.p[0], b.dir);
  874. if( d>=0 && d<=b.length) // EPS doesn't need to be included because those cases have already been checked when testing points
  875. {
  876. d=DistPointPlane(p, a.p[0], a.dir);
  877. if(d>=0 && d<=a.length){cuts->p[0]=p; return 1;} // EPS doesn't need to be included because those cases have already been checked when testing points
  878. }
  879. }
  880. }else
  881. {
  882. if(CutsPointEdge(a.p[0], b)
  883. || CutsPointEdge(a.p[1], b)
  884. || CutsPointEdge(b.p[0], a)
  885. || CutsPointEdge(b.p[1], a))return 1;
  886. VecD normal=Cross(a.dir, b.dir);
  887. if( normal.normalize() && Abs(DistPointPlane(b.p[0], a.p[0], normal))<=EPSD)
  888. {
  889. VecD p=PointOnPlaneRay(a.p[0], b.p[0], CrossN(normal, b.dir), a.dir);
  890. Dbl d=DistPointPlane (p , b.p[0], b.dir);
  891. if( d>=0 && d<=b.length) // EPS doesn't need to be included because those cases have already been checked when testing points
  892. {
  893. d=DistPointPlane(p, a.p[0], a.dir);
  894. if(d>=0 && d<=a.length)return 1; // EPS doesn't need to be included because those cases have already been checked when testing points
  895. }
  896. }
  897. }
  898. return 0;
  899. }
  900. /******************************************************************************/
  901. Bool Cuts(C Edge &edge, C Plane &plane, Vec *cuts)
  902. {
  903. Flt d0=Dist(edge.p[0], plane),
  904. d1=Dist(edge.p[1], plane);
  905. if(Sign(d0)!=Sign(d1)){if(cuts)*cuts=PointOnPlane(edge.p[0], edge.p[1], d0, d1); return true;}
  906. if(Abs (d0)<=EPS ){if(cuts)*cuts= edge.p[0] ; return true;}
  907. if(Abs (d1)<=EPS ){if(cuts)*cuts= edge.p[1] ; return true;}
  908. return false;
  909. }
  910. Bool Cuts(C EdgeD &edge, C PlaneM &plane, VecD *cuts)
  911. {
  912. Dbl d0=Dist(edge.p[0], plane),
  913. d1=Dist(edge.p[1], plane);
  914. if(Sign(d0)!=Sign(d1)){if(cuts)*cuts=PointOnPlane(edge.p[0], edge.p[1], d0, d1); return true;}
  915. if(Abs (d0)<=EPSD ){if(cuts)*cuts= edge.p[0] ; return true;}
  916. if(Abs (d1)<=EPSD ){if(cuts)*cuts= edge.p[1] ; return true;}
  917. return false;
  918. }
  919. /******************************************************************************/
  920. Bool Clip(Edge2 &edge, C Plane2 &plane)
  921. {
  922. Flt d0=Dist(edge.p[0], plane),
  923. d1=Dist(edge.p[1], plane);
  924. if( d0>0 && d1>0)return false; // both outside
  925. if( d0>0 )edge.p[0]=PointOnPlane(edge.p[0], edge.p[1], d0, d1);else
  926. if( d1>0 )edge.p[1]=PointOnPlane(edge.p[0], edge.p[1], d0, d1);
  927. return true;
  928. }
  929. Bool Clip(EdgeD2 &edge, C PlaneD2 &plane)
  930. {
  931. Dbl d0=Dist(edge.p[0], plane),
  932. d1=Dist(edge.p[1], plane);
  933. if( d0>0 && d1>0)return false; // both outside
  934. if( d0>0 )edge.p[0]=PointOnPlane(edge.p[0], edge.p[1], d0, d1);else
  935. if( d1>0 )edge.p[1]=PointOnPlane(edge.p[0], edge.p[1], d0, d1);
  936. return true;
  937. }
  938. Bool Clip(Edge &edge, C Plane &plane)
  939. {
  940. Flt d0=Dist(edge.p[0], plane),
  941. d1=Dist(edge.p[1], plane);
  942. if( d0>0 && d1>0)return false; // both outside
  943. if( d0>0 )edge.p[0]=PointOnPlane(edge.p[0], edge.p[1], d0, d1);else
  944. if( d1>0 )edge.p[1]=PointOnPlane(edge.p[0], edge.p[1], d0, d1);
  945. return true;
  946. }
  947. Bool Clip(EdgeD &edge, C PlaneD &plane)
  948. {
  949. Dbl d0=Dist(edge.p[0], plane),
  950. d1=Dist(edge.p[1], plane);
  951. if( d0>0 && d1>0)return false; // both outside
  952. if( d0>0 )edge.p[0]=PointOnPlane(edge.p[0], edge.p[1], d0, d1);else
  953. if( d1>0 )edge.p[1]=PointOnPlane(edge.p[0], edge.p[1], d0, d1);
  954. return true;
  955. }
  956. /******************************************************************************/
  957. Bool ClipEps(Edge2 &edge, C Plane2 &plane)
  958. {
  959. Flt d0=Dist(edge.p[0], plane),
  960. d1=Dist(edge.p[1], plane);
  961. Int s0=SignEps(d0),
  962. s1=SignEps(d1);
  963. if( s0<=0 && s1<=0)return true;
  964. if( d0< 0 ){edge.p[1]=PointOnPlane(edge.p[0], edge.p[1], d0, d1); return true;}
  965. if( d1< 0 ){edge.p[0]=PointOnPlane(edge.p[0], edge.p[1], d0, d1); return true;}
  966. return false;
  967. }
  968. Bool ClipEps(EdgeD2 &edge, C PlaneD2 &plane)
  969. {
  970. Dbl d0=Dist(edge.p[0], plane),
  971. d1=Dist(edge.p[1], plane);
  972. Int s0=SignEps(d0),
  973. s1=SignEps(d1);
  974. if( s0<=0 && s1<=0)return true;
  975. if( d0< 0 ){edge.p[1]=PointOnPlane(edge.p[0], edge.p[1], d0, d1); return true;}
  976. if( d1< 0 ){edge.p[0]=PointOnPlane(edge.p[0], edge.p[1], d0, d1); return true;}
  977. return false;
  978. }
  979. Bool ClipEps(Edge &edge, C Plane &plane)
  980. {
  981. Flt d0=Dist(edge.p[0], plane),
  982. d1=Dist(edge.p[1], plane);
  983. Int s0=SignEps(d0),
  984. s1=SignEps(d1);
  985. if( s0<=0 && s1<=0)return true;
  986. if( d0< 0 ){edge.p[1]=PointOnPlane(edge.p[0], edge.p[1], d0, d1); return true;}
  987. if( d1< 0 ){edge.p[0]=PointOnPlane(edge.p[0], edge.p[1], d0, d1); return true;}
  988. return false;
  989. }
  990. Bool ClipEps(EdgeD &edge, C PlaneD &plane)
  991. {
  992. Dbl d0=Dist(edge.p[0], plane),
  993. d1=Dist(edge.p[1], plane);
  994. Int s0=SignEps(d0),
  995. s1=SignEps(d1);
  996. if( s0<=0 && s1<=0)return true;
  997. if( d0< 0 ){edge.p[1]=PointOnPlane(edge.p[0], edge.p[1], d0, d1); return true;}
  998. if( d1< 0 ){edge.p[0]=PointOnPlane(edge.p[0], edge.p[1], d0, d1); return true;}
  999. return false;
  1000. }
  1001. /******************************************************************************/
  1002. Bool Clip(Edge2 &edge, C Rect &rect)
  1003. {
  1004. Flt d0, d1;
  1005. // left
  1006. d0=rect.min.x-edge.p[0].x;
  1007. d1=rect.min.x-edge.p[1].x;
  1008. if(d0>0 && d1>0)return false;
  1009. if(d0>0 )edge.p[0].set(rect.min.x, PointOnPlane(edge.p[0].y, edge.p[1].y, d0, d1));else
  1010. if(d1>0 )edge.p[1].set(rect.min.x, PointOnPlane(edge.p[0].y, edge.p[1].y, d0, d1));
  1011. // right
  1012. d0=edge.p[0].x-rect.max.x;
  1013. d1=edge.p[1].x-rect.max.x;
  1014. if(d0>0 && d1>0)return false;
  1015. if(d0>0 )edge.p[0].set(rect.max.x, PointOnPlane(edge.p[0].y, edge.p[1].y, d0, d1));else
  1016. if(d1>0 )edge.p[1].set(rect.max.x, PointOnPlane(edge.p[0].y, edge.p[1].y, d0, d1));
  1017. // bottom
  1018. d0=rect.min.y-edge.p[0].y;
  1019. d1=rect.min.y-edge.p[1].y;
  1020. if(d0>0 && d1>0)return false;
  1021. if(d0>0 )edge.p[0].set(PointOnPlane(edge.p[0].x, edge.p[1].x, d0, d1), rect.min.y);else
  1022. if(d1>0 )edge.p[1].set(PointOnPlane(edge.p[0].x, edge.p[1].x, d0, d1), rect.min.y);
  1023. // top
  1024. d0=edge.p[0].y-rect.max.y;
  1025. d1=edge.p[1].y-rect.max.y;
  1026. if(d0>0 && d1>0)return false;
  1027. if(d0>0 )edge.p[0].set(PointOnPlane(edge.p[0].x, edge.p[1].x, d0, d1), rect.max.y);else
  1028. if(d1>0 )edge.p[1].set(PointOnPlane(edge.p[0].x, edge.p[1].x, d0, d1), rect.max.y);
  1029. return true;
  1030. }
  1031. Bool Clip(EdgeD2 &edge, C RectD &rect)
  1032. {
  1033. Dbl d0, d1;
  1034. // left
  1035. d0=rect.min.x-edge.p[0].x;
  1036. d1=rect.min.x-edge.p[1].x;
  1037. if(d0>0 && d1>0)return false;
  1038. if(d0>0 )edge.p[0].set(rect.min.x, PointOnPlane(edge.p[0].y, edge.p[1].y, d0, d1));else
  1039. if(d1>0 )edge.p[1].set(rect.min.x, PointOnPlane(edge.p[0].y, edge.p[1].y, d0, d1));
  1040. // right
  1041. d0=edge.p[0].x-rect.max.x;
  1042. d1=edge.p[1].x-rect.max.x;
  1043. if(d0>0 && d1>0)return false;
  1044. if(d0>0 )edge.p[0].set(rect.max.x, PointOnPlane(edge.p[0].y, edge.p[1].y, d0, d1));else
  1045. if(d1>0 )edge.p[1].set(rect.max.x, PointOnPlane(edge.p[0].y, edge.p[1].y, d0, d1));
  1046. // bottom
  1047. d0=rect.min.y-edge.p[0].y;
  1048. d1=rect.min.y-edge.p[1].y;
  1049. if(d0>0 && d1>0)return false;
  1050. if(d0>0 )edge.p[0].set(PointOnPlane(edge.p[0].x, edge.p[1].x, d0, d1), rect.min.y);else
  1051. if(d1>0 )edge.p[1].set(PointOnPlane(edge.p[0].x, edge.p[1].x, d0, d1), rect.min.y);
  1052. // top
  1053. d0=edge.p[0].y-rect.max.y;
  1054. d1=edge.p[1].y-rect.max.y;
  1055. if(d0>0 && d1>0)return false;
  1056. if(d0>0 )edge.p[0].set(PointOnPlane(edge.p[0].x, edge.p[1].x, d0, d1), rect.max.y);else
  1057. if(d1>0 )edge.p[1].set(PointOnPlane(edge.p[0].x, edge.p[1].x, d0, d1), rect.max.y);
  1058. return true;
  1059. }
  1060. /******************************************************************************/
  1061. Bool Clip(Edge &edge, C Box &box)
  1062. {
  1063. Flt d0, d1;
  1064. // left
  1065. d0=box.min.x-edge.p[0].x;
  1066. d1=box.min.x-edge.p[1].x;
  1067. if(d0>0 && d1>0)return false;
  1068. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(box.min.x, edge.lerpY(s), edge.lerpZ(s));}else
  1069. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(box.min.x, edge.lerpY(s), edge.lerpZ(s));}
  1070. // right
  1071. d0=edge.p[0].x-box.max.x;
  1072. d1=edge.p[1].x-box.max.x;
  1073. if(d0>0 && d1>0)return false;
  1074. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(box.max.x, edge.lerpY(s), edge.lerpZ(s));}else
  1075. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(box.max.x, edge.lerpY(s), edge.lerpZ(s));}
  1076. // bottom
  1077. d0=box.min.y-edge.p[0].y;
  1078. d1=box.min.y-edge.p[1].y;
  1079. if(d0>0 && d1>0)return false;
  1080. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(edge.lerpX(s), box.min.y, edge.lerpZ(s));}else
  1081. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(edge.lerpX(s), box.min.y, edge.lerpZ(s));}
  1082. // top
  1083. d0=edge.p[0].y-box.max.y;
  1084. d1=edge.p[1].y-box.max.y;
  1085. if(d0>0 && d1>0)return false;
  1086. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(edge.lerpX(s), box.max.y, edge.lerpZ(s));}else
  1087. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(edge.lerpX(s), box.max.y, edge.lerpZ(s));}
  1088. // back
  1089. d0=box.min.z-edge.p[0].z;
  1090. d1=box.min.z-edge.p[1].z;
  1091. if(d0>0 && d1>0)return false;
  1092. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(edge.lerpX(s), edge.lerpY(s), box.min.z);}else
  1093. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(edge.lerpX(s), edge.lerpY(s), box.min.z);}
  1094. // forward
  1095. d0=edge.p[0].z-box.max.z;
  1096. d1=edge.p[1].z-box.max.z;
  1097. if(d0>0 && d1>0)return false;
  1098. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(edge.lerpX(s), edge.lerpY(s), box.max.z);}else
  1099. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(edge.lerpX(s), edge.lerpY(s), box.max.z);}
  1100. return true;
  1101. }
  1102. Bool Clip(EdgeD &edge, C BoxD &box)
  1103. {
  1104. Dbl d0, d1;
  1105. // left
  1106. d0=box.min.x-edge.p[0].x;
  1107. d1=box.min.x-edge.p[1].x;
  1108. if(d0>0 && d1>0)return false;
  1109. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(box.min.x, edge.lerpY(s), edge.lerpZ(s));}else
  1110. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(box.min.x, edge.lerpY(s), edge.lerpZ(s));}
  1111. // right
  1112. d0=edge.p[0].x-box.max.x;
  1113. d1=edge.p[1].x-box.max.x;
  1114. if(d0>0 && d1>0)return false;
  1115. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(box.max.x, edge.lerpY(s), edge.lerpZ(s));}else
  1116. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(box.max.x, edge.lerpY(s), edge.lerpZ(s));}
  1117. // bottom
  1118. d0=box.min.y-edge.p[0].y;
  1119. d1=box.min.y-edge.p[1].y;
  1120. if(d0>0 && d1>0)return false;
  1121. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(edge.lerpX(s), box.min.y, edge.lerpZ(s));}else
  1122. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(edge.lerpX(s), box.min.y, edge.lerpZ(s));}
  1123. // top
  1124. d0=edge.p[0].y-box.max.y;
  1125. d1=edge.p[1].y-box.max.y;
  1126. if(d0>0 && d1>0)return false;
  1127. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(edge.lerpX(s), box.max.y, edge.lerpZ(s));}else
  1128. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(edge.lerpX(s), box.max.y, edge.lerpZ(s));}
  1129. // back
  1130. d0=box.min.z-edge.p[0].z;
  1131. d1=box.min.z-edge.p[1].z;
  1132. if(d0>0 && d1>0)return false;
  1133. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(edge.lerpX(s), edge.lerpY(s), box.min.z);}else
  1134. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(edge.lerpX(s), edge.lerpY(s), box.min.z);}
  1135. // forward
  1136. d0=edge.p[0].z-box.max.z;
  1137. d1=edge.p[1].z-box.max.z;
  1138. if(d0>0 && d1>0)return false;
  1139. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(edge.lerpX(s), edge.lerpY(s), box.max.z);}else
  1140. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(edge.lerpX(s), edge.lerpY(s), box.max.z);}
  1141. return true;
  1142. }
  1143. Bool Clip(Edge &edge, C Extent &ext)
  1144. {
  1145. Flt d0, d1, border;
  1146. // left
  1147. border=ext.minX();
  1148. d0=border-edge.p[0].x;
  1149. d1=border-edge.p[1].x;
  1150. if(d0>0 && d1>0)return false;
  1151. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(border, edge.lerpY(s), edge.lerpZ(s));}else
  1152. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(border, edge.lerpY(s), edge.lerpZ(s));}
  1153. // right
  1154. border=ext.maxX();
  1155. d0=edge.p[0].x-border;
  1156. d1=edge.p[1].x-border;
  1157. if(d0>0 && d1>0)return false;
  1158. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(border, edge.lerpY(s), edge.lerpZ(s));}else
  1159. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(border, edge.lerpY(s), edge.lerpZ(s));}
  1160. // bottom
  1161. border=ext.minY();
  1162. d0=border-edge.p[0].y;
  1163. d1=border-edge.p[1].y;
  1164. if(d0>0 && d1>0)return false;
  1165. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(edge.lerpX(s), border, edge.lerpZ(s));}else
  1166. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(edge.lerpX(s), border, edge.lerpZ(s));}
  1167. // top
  1168. border=ext.maxY();
  1169. d0=edge.p[0].y-border;
  1170. d1=edge.p[1].y-border;
  1171. if(d0>0 && d1>0)return false;
  1172. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(edge.lerpX(s), border, edge.lerpZ(s));}else
  1173. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(edge.lerpX(s), border, edge.lerpZ(s));}
  1174. // back
  1175. border=ext.minZ();
  1176. d0=border-edge.p[0].z;
  1177. d1=border-edge.p[1].z;
  1178. if(d0>0 && d1>0)return false;
  1179. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(edge.lerpX(s), edge.lerpY(s), border);}else
  1180. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(edge.lerpX(s), edge.lerpY(s), border);}
  1181. // forward
  1182. border=ext.maxZ();
  1183. d0=edge.p[0].z-border;
  1184. d1=edge.p[1].z-border;
  1185. if(d0>0 && d1>0)return false;
  1186. if(d0>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[0].set(edge.lerpX(s), edge.lerpY(s), border);}else
  1187. if(d1>0 ){Flt s=PointOnPlaneStep(d0, d1); edge.p[1].set(edge.lerpX(s), edge.lerpY(s), border);}
  1188. return true;
  1189. }
  1190. /******************************************************************************/
  1191. Bool SweepPointEdge(C Vec2 &point, C Vec2 &move, C Edge2_I &ei, Flt *hit_frac, Vec2 *hit_normal, Vec2 *hit_pos)
  1192. {
  1193. Vec2 hitp; if(SweepPointPlane(point, move, Plane2(ei.p[0], ei.normal), hit_frac, hit_normal, &hitp))
  1194. {
  1195. Flt d=DistPointPlane(hitp, ei.p[0], ei.dir);
  1196. if( d>=0 && d<=ei.length)
  1197. {
  1198. if(hit_pos)*hit_pos=hitp;
  1199. return true;
  1200. }
  1201. }
  1202. return false;
  1203. }
  1204. Bool SweepPointEdge(C VecD2 &point, C VecD2 &move, C EdgeD2_I &ei, Dbl *hit_frac, VecD2 *hit_normal, VecD2 *hit_pos)
  1205. {
  1206. VecD2 hitp; if(SweepPointPlane(point, move, PlaneD2(ei.p[0], ei.normal), hit_frac, hit_normal, &hitp))
  1207. {
  1208. Dbl d=DistPointPlane(hitp, ei.p[0], ei.dir);
  1209. if( d>=0 && d<=ei.length)
  1210. {
  1211. if(hit_pos)*hit_pos=hitp;
  1212. return true;
  1213. }
  1214. }
  1215. return false;
  1216. }
  1217. /******************************************************************************/
  1218. // DRAW
  1219. /******************************************************************************/
  1220. void DrawArrow(C Color &color, C Vec &start, C Vec &end, Flt tip_radius, Flt tip_length)
  1221. {
  1222. Matrix3 m;
  1223. Vec dir=end-start;
  1224. Flt len=dir.normalize();
  1225. m.setDir(dir);
  1226. m.x*= tip_radius*len;
  1227. m.y*= tip_radius*len;
  1228. m.z*=-tip_length*len;
  1229. VI.color(color);
  1230. VI.line (start, end);
  1231. Vec end2=end+m.z;
  1232. REP(3)
  1233. {
  1234. Flt c, s; CosSin(c, s, i*PI2/3);
  1235. VI.line(end, end2 + m.x*c + m.y*s);
  1236. }
  1237. VI.end();
  1238. }
  1239. void DrawArrow2(C Color &color, C Vec &start, C Vec &end, Flt width, Flt tip_radius, Flt tip_length)
  1240. {
  1241. Matrix3 m;
  1242. Vec dir=end-start;
  1243. Flt len=dir.normalize();
  1244. m.setDir(dir);
  1245. m.x*= tip_radius*len;
  1246. m.y*= tip_radius*len;
  1247. m.z*=-tip_length*len;
  1248. Edge(start, end).draw(color, width);
  1249. Vec end2=end+m.z;
  1250. REP(3)
  1251. {
  1252. Flt c, s; CosSin(c, s, i*PI2/3);
  1253. Edge(end, end2 + m.x*c + m.y*s).draw(color, width);
  1254. }
  1255. }
  1256. /******************************************************************************/
  1257. void SubdivideEdges(C MemPtr<Vec> &src, MemPtr<Vec> dest)
  1258. {
  1259. dest.setNum(Max(0, src.elms() + (src.elms()-1))); // original + edge points
  1260. // edge center points
  1261. REP(src.elms()-1)dest[i*2+1]=Avg(src[i], src[i+1]);
  1262. // original points
  1263. REPA(src)
  1264. {
  1265. Vec &d=dest[i*2];
  1266. if(i==0 || i==src.elms()-1)d=src[i];
  1267. else d=Avg(src[i], Avg(dest[i*2-1], dest[i*2+1]));
  1268. }
  1269. }
  1270. void SubdivideEdges(C MemPtr<VtxFull> &src, MemPtr<VtxFull> dest)
  1271. {
  1272. dest.setNum(Max(0, src.elms() + (src.elms()-1))); // original + edge points
  1273. // edge center points
  1274. REP(src.elms()-1)dest[i*2+1].avg(src[i], src[i+1]);
  1275. // original points
  1276. REPA(src)
  1277. {
  1278. VtxFull &d=dest[i*2];
  1279. if(i==0 || i==src.elms()-1)d=src[i];
  1280. else d.avg(src[i], d.avg(dest[i*2-1], dest[i*2+1]));
  1281. }
  1282. }
  1283. /******************************************************************************/
  1284. }
  1285. /******************************************************************************/