Mshb Csg 2D.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. struct MC_POINT
  6. {
  7. Vec2 pos;
  8. Int sec_next;
  9. };
  10. struct MC_EDGE
  11. {
  12. VecI2 ind;
  13. Byte flag, solid;
  14. Rect rect;
  15. };
  16. struct SECT : Rects
  17. {
  18. Int *first;
  19. void create(C Rect &rect, Int vtx_num)
  20. {
  21. set(rect, vtx_num*4);
  22. Alloc(first, num());
  23. SetMemN(first, 0xFF, num());
  24. }
  25. void del()
  26. {
  27. Free(first);
  28. Zero(T);
  29. }
  30. };
  31. static struct CSG2D
  32. {
  33. SECT sec;
  34. Memc<MC_POINT> point;
  35. Memc<MC_EDGE > edge1,
  36. edge2,
  37. edgec;
  38. void create(Int vtx_num, C Rect &rect)
  39. {
  40. sec.create(rect, vtx_num);
  41. }
  42. void del()
  43. {
  44. edgec.del();
  45. edge2.del();
  46. edge1.del();
  47. point.del();
  48. sec .del();
  49. }
  50. }Csg2D;
  51. /******************************************************************************/
  52. // DRAW
  53. /******************************************************************************
  54. #if DEBUG
  55. static void draw_side(C Color &color, Vec2 &v1, Vec2 &v2, Bool hlt=false)
  56. {
  57. Flt length=Dist(v1, v2);
  58. Vec2 dir =!(v2-v1), nrm=Perp(dir);
  59. Flt teeth =0.03f;
  60. if(hlt)teeth=Sin(Time.appTime()*6)*0.015f+0.020f;
  61. for(Flt step=0; step<=length; step+=0.02f/D.draw_scale.x)
  62. {
  63. Vec2 pos=v1+dir*step;
  64. D.line(color, pos, pos+teeth*(dir+nrm)/D.draw_scale.x);
  65. }
  66. }
  67. static void draw_edge(C Color &color, MC_EDGE &edge)
  68. {
  69. Vec2 &v1=Csg2D.point[edge.ind.c[0]].pos,
  70. &v2=Csg2D.point[edge.ind.c[1]].pos;
  71. D.line(color, v1, v2);
  72. D.dot (color, v1, 0.005f/D.draw_scale.x);
  73. D.dot (color, v2, 0.005f/D.draw_scale.x);
  74. color=0; if(edge.solid&SOLID_AR)color|=GREEN; if(edge.solid&SOLID_BR)color|=BLUE; if(color)draw_side(color, v1, v2);
  75. color=0; if(edge.solid&SOLID_AL)color|=GREEN; if(edge.solid&SOLID_BL)color|=BLUE; if(color)draw_side(color, v2, v1);
  76. }
  77. static void disp(Memc<MC_EDGE> &medge)
  78. {
  79. FREPD(s,2)
  80. do{
  81. InpGet();
  82. DISPClr();
  83. Csg2D.sec.rect.draw(0xFF660066);
  84. Flt fx=Csg2D.sec.rect.min.x; REP(Csg2D.sec.cells.x+1){D.line(0xFF880088, fx, Csg2D.sec.rect.min.y, fx, Csg2D.sec.rect.max.y ); fx+=Csg2D.sec.size.x;}
  85. Flt fy=Csg2D.sec.rect.min.y; REP(Csg2D.sec.cells.y+1){D.line(0xFF880088, Csg2D.sec.rect.min.x, fy, Csg2D.sec.rect.max.x, fy); fy+=Csg2D.sec.size.y;}
  86. REPA(medge)draw_edge(TURQ, medge[i]);
  87. D.text(0, 0, StrF("xs:%d ys:%d", Csg2D.sec.cells.x, Csg2D.sec.cells.y));
  88. if(s>0)
  89. {
  90. REPD(x, Csg2D.sec.cells.x)
  91. REPD(y, Csg2D.sec.cells.y)
  92. {
  93. Flt fx=Csg2D.sec.rect.min.x+x*Csg2D.sec.size.x,
  94. fy=Csg2D.sec.rect.min.y+y*Csg2D.sec.size.y;
  95. for(Int i=Csg2D.sec.first[x+Csg2D.sec.cells.x*y]; i>=0; )
  96. {
  97. MC_POINT &point=Csg2D.point[i];
  98. D.dot(WHITE,point.pos,0.006f/D.draw_scale.x);
  99. i=point.sec_next;
  100. }
  101. }
  102. }
  103. DISPFlip();
  104. }while(!Kb.bp(KB_SPACE));
  105. }
  106. #endif
  107. /******************************************************************************/
  108. // ADD ELEMENTS
  109. /******************************************************************************/
  110. static UInt GetPoint(C Vec2 &pos)
  111. {
  112. // get sec
  113. VecI2 crd=Csg2D.sec.coords(pos);
  114. Int r =Csg2D.sec.index (crd);
  115. // find duplicate
  116. for(Int sy=-1; sy<=1; sy++)if(InRange(crd.y+sy, Csg2D.sec.cells.y))
  117. for(Int sx=-1; sx<=1; sx++)if(InRange(crd.x+sx, Csg2D.sec.cells.x))
  118. for(Int i=Csg2D.sec.first[r+sx+Csg2D.sec.cells.x*sy]; i>=0; )
  119. {
  120. MC_POINT &point=Csg2D.point[i];
  121. if(Equal(point.pos, pos))return i;
  122. i=point.sec_next;
  123. }
  124. // add new
  125. Int i =Csg2D.point.elms();
  126. MC_POINT &point=Csg2D.point.New();
  127. point.pos=pos;
  128. point.sec_next=Csg2D.sec.first[r];
  129. return Csg2D.sec.first[r]=i;
  130. }
  131. /******************************************************************************/
  132. static UInt MCEdgeSolidSwap(UInt solid)
  133. {
  134. UInt s=(solid&(~SOLID_ALL));
  135. if(solid&SOLID_AL )s|=SOLID_AR ;
  136. if(solid&SOLID_AR )s|=SOLID_AL ;
  137. if(solid&SOLID_BL )s|=SOLID_BR ;
  138. if(solid&SOLID_BR )s|=SOLID_BL ;
  139. if(solid&SOLID_NAL)s|=SOLID_NAR;
  140. if(solid&SOLID_NAR)s|=SOLID_NAL;
  141. if(solid&SOLID_NBL)s|=SOLID_NBR;
  142. if(solid&SOLID_NBR)s|=SOLID_NBL;
  143. return s;
  144. }
  145. static void AddEdge(UInt p0, UInt p1, UInt flag, UInt solid, Memc<MC_EDGE> &medge)
  146. {
  147. if(p0!=p1)
  148. {
  149. if(p1<p0)
  150. {
  151. Swap(p0, p1);
  152. flag = EtqFlagSwap(flag );
  153. solid=MCEdgeSolidSwap(solid);
  154. }
  155. MC_EDGE &edge=medge.New();
  156. edge.flag =flag;
  157. edge.solid=solid;
  158. edge.ind .set (p0, p1);
  159. edge.rect.from(Csg2D.point[p0].pos, Csg2D.point[p1].pos).extend(EPS);
  160. }
  161. }
  162. /******************************************************************************/
  163. static void AddMesh(C MeshBase &mshb, Memc<MC_EDGE> &medge, Bool type)
  164. {
  165. FREPA(mshb.edge)
  166. {
  167. C Int *p=mshb.edge.ind(i).c;
  168. UInt p0=GetPoint(mshb.vtx.pos(p[0]).xy),
  169. p1=GetPoint(mshb.vtx.pos(p[1]).xy);
  170. if(p0!=p1)
  171. {
  172. UInt flag =0,
  173. solid=0;
  174. if(mshb.edge.flag())
  175. {
  176. UInt mf=mshb.edge.flag(i);
  177. flag |=( mf&~ETQ_LR);
  178. if(type==TYPE_A) solid|=((mf& ETQ_L)?SOLID_AL:SOLID_NAL)|((mf&ETQ_R)?SOLID_AR:SOLID_NAR);else
  179. solid|=((mf& ETQ_L)?SOLID_BL:SOLID_NBL)|((mf&ETQ_R)?SOLID_BR:SOLID_NBR);
  180. }
  181. AddEdge(p0, p1, flag, solid, medge);
  182. }
  183. }
  184. }
  185. /******************************************************************************/
  186. // CUT
  187. /******************************************************************************/
  188. static void CutEdgeEdge(Memc<MC_EDGE> &edge0, Memc<MC_EDGE> &edge1, Memc<MC_EDGE> &edgec)
  189. {
  190. Flt *step_array=Alloc<Flt>(2*edge1.elms());
  191. FREPA(edge0)
  192. {
  193. MC_EDGE &e0=edge0[i];
  194. MC_POINT &p1=Csg2D.point[e0.ind.c[0]],
  195. &p2=Csg2D.point[e0.ind.c[1]];
  196. Edge2_I ei(p1.pos, p2.pos);
  197. Edge2 cuts;
  198. Int steps=0;
  199. FREPAD(j, edge1)
  200. {
  201. MC_EDGE &e1=edge1[j];
  202. if(Cuts(e0.rect, e1.rect))REPD(c, CutsEdgeEdge(ei, Edge2_I(Csg2D.point[e1.ind.c[0]].pos, Csg2D.point[e1.ind.c[1]].pos), &cuts))
  203. {
  204. Flt s=DistPointPlane(cuts.p[c], ei.p[0], ei.dir);
  205. if(s>EPS && s<ei.length-EPS)step_array[steps++]=s/ei.length;
  206. }
  207. }
  208. Int prev=e0.ind.c[0],
  209. next;
  210. Sort(step_array, steps); FREPD(j, steps)
  211. {
  212. next=GetPoint(Lerp(p1.pos, p2.pos, step_array[j])); AddEdge(prev, next, e0.flag, e0.solid, edgec);
  213. prev=next;
  214. } next=e0.ind.c[1];
  215. AddEdge(prev, next, e0.flag, e0.solid, edgec);
  216. }
  217. Free(step_array);
  218. }
  219. static void CutEdgePoint(Memc<MC_EDGE> &edge, Memc<MC_EDGE> &edgec)
  220. {
  221. Flt *step_array=Alloc<Flt>(Csg2D.point.elms());
  222. FREPA(edge)
  223. {
  224. MC_EDGE &e =edge[i];
  225. MC_POINT &p1=Csg2D.point[e.ind.c[0]],
  226. &p2=Csg2D.point[e.ind.c[1]];
  227. Edge2_I ei(p1.pos, p2.pos);
  228. Int steps=0;
  229. RectI secr;
  230. secr.from(Csg2D.sec.coords(p1.pos), Csg2D.sec.coords(p2.pos)).extend(1);
  231. Clamp(secr.min.x, 0, Csg2D.sec.cells.x-1); Clamp(secr.max.x, 0, Csg2D.sec.cells.x-1);
  232. Clamp(secr.min.y, 0, Csg2D.sec.cells.y-1); Clamp(secr.max.y, 0, Csg2D.sec.cells.y-1);
  233. for(Int y=secr.min.y; y<=secr.max.y; y++)
  234. for(Int x=secr.min.x; x<=secr.max.x; x++)
  235. for(Int tnum=Csg2D.sec.first[x+Csg2D.sec.cells.x*y]; tnum>=0; )
  236. {
  237. MC_POINT &tpoint=Csg2D.point[tnum];
  238. if(tnum!=e.ind.c[0] && tnum!=e.ind.c[1] && CutsPointEdge(tpoint.pos, ei))
  239. {
  240. Flt s=DistPointPlane(tpoint.pos, ei.p[0], ei.dir);
  241. if(s>EPS && s<ei.length-EPS)step_array[steps++]=s/ei.length;
  242. }
  243. tnum=tpoint.sec_next;
  244. }
  245. Int prev=e.ind.c[0],
  246. next;
  247. Sort(step_array, steps); FREPD(j, steps)
  248. {
  249. next=GetPoint(Lerp(p1.pos, p2.pos, step_array[j])); AddEdge(prev, next, e.flag, e.solid, edgec);
  250. prev=next;
  251. } next=e.ind.c[1];
  252. AddEdge(prev, next, e.flag, e.solid, edgec);
  253. }
  254. Free(step_array);
  255. }
  256. /******************************************************************************/
  257. // JOIN EDGES
  258. /******************************************************************************/
  259. static Int CompareEdge(C MC_EDGE &e0, C MC_EDGE &e1)
  260. {
  261. if(e0.ind.c[0]<e1.ind.c[0])return -1;
  262. if(e0.ind.c[0]>e1.ind.c[0])return +1;
  263. if(e0.ind.c[1]<e1.ind.c[1])return -1;
  264. if(e0.ind.c[1]>e1.ind.c[1])return +1;
  265. return 0;
  266. }
  267. static void JoinEdge(Memc<MC_EDGE> &medge, Bool grid)
  268. {
  269. Int edges =medge.elms();
  270. Bool *edge_is =Alloc<Bool >(edges); SetMem(edge_is, 1, edges);
  271. MC_EDGE *edge_sort=Alloc<MC_EDGE>(edges);
  272. medge.copyTo(edge_sort); Sort(edge_sort, edges, CompareEdge);
  273. medge.clear ();
  274. FREP(edges)if(edge_is[i])
  275. {
  276. MC_EDGE &edge =edge_sort[i];
  277. UInt flag =edge.flag;
  278. UInt solid =edge.solid;
  279. Int point0=edge.ind.c[0];
  280. for(Int j=i+1; j<edges; j++)if(edge_is[j])
  281. {
  282. MC_EDGE &tedge=edge_sort[j];
  283. if(tedge.ind.c[0]!=point0)break;
  284. if(tedge.ind.c[1]==edge.ind.c[1])
  285. {
  286. flag |=tedge.flag;
  287. solid|=tedge.solid;
  288. edge_is[j]=false;
  289. }
  290. }
  291. if(grid)solid|=SOLID_BL|SOLID_BR;
  292. if(solid&SOLID_AL)solid&=~SOLID_NAL;
  293. if(solid&SOLID_AR)solid&=~SOLID_NAR;
  294. if(solid&SOLID_BL)solid&=~SOLID_NBL;
  295. if(solid&SOLID_BR)solid&=~SOLID_NBR;
  296. MC_EDGE &edge_new=medge.New();
  297. edge_new.flag =flag;
  298. edge_new.solid=solid;
  299. edge_new.ind =edge.ind;
  300. }
  301. Free(edge_sort);
  302. Free(edge_is);
  303. }
  304. /******************************************************************************/
  305. // SET SOLID
  306. /******************************************************************************/
  307. static void LinkPointEdge(Memc<MC_EDGE> &medge, Index &point_edge)
  308. {
  309. Int *p;
  310. // link point->edges
  311. point_edge.create(Csg2D.point.elms());
  312. FREPA(medge){p=medge[i].ind.c; point_edge.incGroup(p[0] ); point_edge.incGroup(p[1] );} point_edge.set();
  313. FREPA(medge){p=medge[i].ind.c; point_edge.addElm (p[0], i); point_edge.addElm (p[1], i);}
  314. // sort point->edges depending on angles
  315. FloatIndex *fi=Alloc<FloatIndex>(point_edge.group_elms_max);
  316. FREPA(Csg2D.point)
  317. {
  318. Vec2 &center=Csg2D.point[i].pos;
  319. IndexGroup &ig =point_edge.group[i];
  320. FREPAD(e, ig)
  321. {
  322. Int edge_i=ig[e];
  323. MC_EDGE &edge =medge[edge_i];
  324. Int pi =edge.ind.c[0]; if(pi==i)pi=edge.ind.c[1];
  325. fi[e].f=AngleFast(Csg2D.point[pi].pos-center);
  326. fi[e].i=edge_i;
  327. }
  328. Sort(fi, ig.num);
  329. FREPAD(e, ig)ig[e]=fi[e].i;
  330. }
  331. Free(fi);
  332. }
  333. static UInt SolidNext(MC_EDGE &edge, Int point_ind, Bool type)
  334. {
  335. Bool solid, left=(edge.ind.c[0]==point_ind);
  336. if(type==TYPE_A)
  337. {
  338. if(left)solid=FlagTest(edge.solid, SOLID_AL);
  339. else solid=FlagTest(edge.solid, SOLID_AR);
  340. return solid ? (SOLID_AL|SOLID_AR) : (SOLID_NAL|SOLID_NAR);
  341. }else
  342. {
  343. if(left)solid=FlagTest(edge.solid, SOLID_BL);
  344. else solid=FlagTest(edge.solid, SOLID_BR);
  345. return solid ? (SOLID_BL|SOLID_BR) : (SOLID_NBL|SOLID_NBR);
  346. }
  347. }
  348. static struct SETSOLID
  349. {
  350. Bool type;
  351. UInt solid;
  352. Memc<MC_EDGE> *medge;
  353. Index *point_edge;
  354. }SS;
  355. static void SetSolid(MC_EDGE &e)
  356. {
  357. e.solid|=SS.solid;
  358. REPD(p, 2)
  359. {
  360. IndexGroup &ig=SS.point_edge->group[e.ind.c[p]];
  361. REPA(ig)
  362. {
  363. MC_EDGE &et=(*SS.medge)[ig[i]];
  364. if(!SolidT(et.solid, SS.type))SetSolid(et);
  365. }
  366. }
  367. }
  368. struct SETSOLIDNODE // point linking to owning edges
  369. {
  370. Int point_ind, edge_ofs, edge_cur, solid;
  371. };
  372. static void SetSolid(Memc<MC_EDGE> &medge, Bool grid, C MeshBase *mshb_a, C MeshBase *mshb_b)
  373. {
  374. // link point->edge
  375. Index point_edge;
  376. LinkPointEdge(medge, point_edge);
  377. // set solid
  378. Memb<SETSOLIDNODE> nodes(1024);
  379. SS. medge=& medge;
  380. SS.point_edge=&point_edge;
  381. FREPD(type, grid ? 1 : 2)
  382. {
  383. SS.type=(type!=0);
  384. FREPA(Csg2D.point) // for each vtx
  385. {
  386. IndexGroup &ig=point_edge.group[i];
  387. REPAD(j, ig)
  388. {
  389. MC_EDGE &edge=medge[ig[j]];
  390. if(SolidT(edge.solid, SS.type)) // find edge that has solid info
  391. {
  392. SETSOLIDNODE *node=&nodes.New();
  393. node->point_ind=i;
  394. node->edge_ofs =j;
  395. node->edge_cur =1;
  396. node->solid =SolidNext(edge, i, SS.type);
  397. for(; node; )
  398. {
  399. IndexGroup &ig=point_edge.group[node->point_ind];
  400. Bool recursive=false;
  401. for(; node->edge_cur<ig.num; ) // counter clockwising update solid
  402. {
  403. Int edge_num=ig[(node->edge_cur+node->edge_ofs)%ig.num]; node->edge_cur++;
  404. MC_EDGE &e=medge[edge_num];
  405. if(SolidT(e.solid, SS.type)) // update if solid already set
  406. {
  407. node->solid=SolidNext(e, node->point_ind, SS.type);
  408. }else // if not, do the recursive stepping to the next edges-nodes and filling solid info
  409. {
  410. e.solid|=node->solid;
  411. SETSOLIDNODE *prev=node;
  412. if(ig.num>2)node=&nodes.New();
  413. node->point_ind=((e.ind.c[0]==prev->point_ind) ? e.ind.c[1] : e.ind.c[0]);
  414. node->edge_cur =1;
  415. node->solid =prev->solid;
  416. IndexGroup &ig=point_edge.group[node->point_ind]; REPA(ig)if(edge_num==ig[i]){node->edge_ofs=i; break;}
  417. recursive =true; break;
  418. }
  419. }
  420. if(!recursive)
  421. {
  422. nodes.removeLast();
  423. node=(nodes.elms() ? &nodes.last() : null);
  424. }
  425. }
  426. break;
  427. }
  428. }
  429. }
  430. if(!grid && mshb_a && mshb_b)FREPA(medge)
  431. {
  432. MC_EDGE &e=medge[i];
  433. if(!SolidT(e.solid, SS.type))
  434. {
  435. Vec2 test_point=Avg(Csg2D.point[e.ind.c[0]].pos, Csg2D.point[e.ind.c[1]].pos);
  436. SS.solid=SolidTI(SS.type, CutsPointMesh(test_point, (SS.type==TYPE_A) ? *mshb_a : *mshb_b));
  437. SetSolid(e);
  438. }
  439. }
  440. }
  441. // free
  442. nodes.del();
  443. }
  444. /******************************************************************************/
  445. // CREATE MESH
  446. /******************************************************************************/
  447. static void CreateMesh(MeshBase &mshb, Memc<MC_EDGE> &medge, UInt sel)
  448. {
  449. Memt<Bool> is;
  450. is.setNum(medge.elms());
  451. FREPA(medge)
  452. {
  453. MC_EDGE &e=medge[i];
  454. UInt s=0;
  455. if((e.solid&SOLID_AL && e.solid&SOLID_BL ) || (e.solid&SOLID_AR && e.solid&SOLID_BR ))s|=SEL_AB;
  456. if((e.solid&SOLID_AL && e.solid&SOLID_NBL) || (e.solid&SOLID_AR && e.solid&SOLID_NBR))s|=SEL_A ;
  457. if((e.solid&SOLID_BL && e.solid&SOLID_NAL) || (e.solid&SOLID_BR && e.solid&SOLID_NAR))s|=SEL_B ;
  458. is[i]=((s&sel)!=0);
  459. }
  460. mshb.create(0, CountIs(is), 0, 0, EDGE_FLAG);
  461. Int n=0;
  462. FREPA(medge)if(is[i])
  463. {
  464. MC_EDGE &e=medge[i];
  465. UInt l=0, r=0;
  466. if(e.solid&SOLID_AL && e.solid&SOLID_BL )l|=SEL_AB; if(e.solid&SOLID_AR && e.solid&SOLID_BR )r|=SEL_AB;
  467. if(e.solid&SOLID_AL && e.solid&SOLID_NBL)l|=SEL_A ; if(e.solid&SOLID_AR && e.solid&SOLID_NBR)r|=SEL_A ;
  468. if(e.solid&SOLID_BL && e.solid&SOLID_NAL)l|=SEL_B ; if(e.solid&SOLID_BR && e.solid&SOLID_NAR)r|=SEL_B ;
  469. UInt flag=e.flag;
  470. if(l&sel)flag|=ETQ_L;
  471. if(r&sel)flag|=ETQ_R;
  472. mshb.edge.ind (n)=e.ind;
  473. mshb.edge.flag(n)=flag;
  474. n++;
  475. }
  476. is.clear().setNumZero(Csg2D.point.elms());
  477. FREPA(mshb.edge)
  478. {
  479. Int *p=mshb.edge.ind(i).c;
  480. is[p[0]]=1;
  481. is[p[1]]=1;
  482. }
  483. Memt<Int> point_remap;
  484. SetRemap( point_remap, is, Csg2D.point.elms());
  485. IndRemap( point_remap, mshb.edge.ind(), mshb.edges());
  486. mshb.vtx._elms=CountIs(is); mshb.include(VTX_POS);
  487. n=0; FREPA(Csg2D.point)if(is[i])mshb.vtx.pos(n++).set(Csg2D.point[i].pos, 0);
  488. }
  489. /******************************************************************************/
  490. // CUT & GRID & CSG
  491. /******************************************************************************/
  492. MeshBase& MeshBase::cut2D()
  493. {
  494. // create
  495. Csg2D.create(vtxs(), Rect(T));
  496. // add
  497. AddMesh(T, Csg2D.edge1, TYPE_A);
  498. // cut
  499. CutEdgeEdge(Csg2D.edge1, Csg2D.edge1, Csg2D.edgec);
  500. // join edges
  501. JoinEdge(Csg2D.edgec, true);
  502. // create
  503. del(); CreateMesh(T, Csg2D.edgec, SEL_A|SEL_AB);
  504. // free
  505. Csg2D.del();
  506. return T;
  507. }
  508. /******************************************************************************/
  509. static void CreateGrid(MeshBase &mesh, MeshBase &src, C Vec2 &scale, C Vec2 &offset, Bool fast)
  510. {
  511. Vec2 s=Abs(scale);
  512. MAX(s.x, EPS);
  513. MAX(s.y, EPS);
  514. Rect rect=Rect(src)-offset;
  515. rect.min.x=AlignFloor(rect.min.x, s.x); rect.min.y=AlignFloor(rect.min.y, s.y);
  516. rect.max.x=AlignCeil (rect.max.x, s.x); rect.max.y=AlignCeil (rect.max.y, s.y);
  517. Int xs=1+Round(rect.w()/s.x),
  518. ys=1+Round(rect.h()/s.y);
  519. mesh.createGrid(xs, ys, fast).scaleMove(Vec(rect.size(), 0), Vec(rect.min+offset, 0));
  520. }
  521. MeshBase& MeshBase::grid2D(C Vec2 &scale, C Vec2 &offset)
  522. {
  523. // create fast grid
  524. MeshBase temp; CreateGrid(temp, T, scale, offset, true);
  525. // create
  526. Csg2D.create((vtxs()+temp.vtxs())/2, Rect(temp));
  527. // add
  528. AddMesh(T , Csg2D.edge1, TYPE_A);
  529. AddMesh(temp, Csg2D.edge2, TYPE_B);
  530. // cut
  531. CutEdgeEdge(Csg2D.edge1, Csg2D.edge2, Csg2D.edgec);
  532. // grid up
  533. Csg2D.edge2.clear(); CreateGrid(temp, T, scale, offset, false);
  534. AddMesh (temp, Csg2D.edge2, TYPE_B);
  535. CutEdgePoint( Csg2D.edge2, Csg2D.edgec);
  536. // join edges
  537. JoinEdge(Csg2D.edgec, true);
  538. // set solid
  539. SetSolid(Csg2D.edgec, true, null, null);
  540. //disp(Csg2D.edgec);
  541. // create
  542. del(); CreateMesh(T, Csg2D.edgec, SEL_A|SEL_AB);
  543. // free
  544. Csg2D.del();
  545. return T;
  546. }
  547. /******************************************************************************/
  548. MeshBase& MeshBase::csg2D(C MeshBase &mshb, UInt sel)
  549. {
  550. // create
  551. Csg2D.create((vtxs()+mshb.vtxs())/2, Rect(T)|Rect(mshb));
  552. // add
  553. AddMesh(T , Csg2D.edge1, TYPE_A);
  554. AddMesh(mshb, Csg2D.edge2, TYPE_B);
  555. // cut
  556. CutEdgeEdge(Csg2D.edge1, Csg2D.edge2, Csg2D.edgec);
  557. CutEdgeEdge(Csg2D.edge2, Csg2D.edge1, Csg2D.edgec);
  558. // join edges
  559. JoinEdge(Csg2D.edgec, false);
  560. // set solid
  561. SetSolid(Csg2D.edgec, false, &T, &mshb);
  562. //disp(Csg2D.edgec);
  563. // create
  564. del(); CreateMesh(T, Csg2D.edgec, sel);
  565. // free
  566. Csg2D.del();
  567. return T;
  568. }
  569. /******************************************************************************/
  570. }
  571. /******************************************************************************/