diff --git a/.gitattributes b/.gitattributes index ac4cd8d2a52..778363dc467 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3867,6 +3867,10 @@ Triangulation_3/doc_tex/TriangulationDS_3/topo-simplex4.pdf -text svneol=unset#a Triangulation_3/doc_tex/TriangulationDS_3/topo-simplex4.xml svneol=native#text/xml Triangulation_3/doc_tex/TriangulationDS_3_ref/flips.gif -text svneol=unset#image/gif Triangulation_3/doc_tex/TriangulationDS_3_ref/flips.pdf -text svneol=unset#application/pdf +Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.eps -text +Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.gif -text +Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.pdf -text +Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.png -text Triangulation_3/doc_tex/TriangulationDS_3_ref/topo-insert_outside_affine_hull.gif -text svneol=unset#image/gif Triangulation_3/doc_tex/TriangulationDS_3_ref/topo-insert_outside_affine_hull.pdf -text svneol=unset#application/pdf Triangulation_3/doc_tex/TriangulationDS_3_ref/utils.gif -text svneol=unset#image/gif diff --git a/.gitignore b/.gitignore index 29e9c8915eb..bd6ce4bb802 100644 --- a/.gitignore +++ b/.gitignore @@ -856,3 +856,4 @@ Triangulation_3/examples/Triangulation_3/regular Triangulation_3/test/Triangulation_3/Test??_triangulation_IO_3 Triangulation_3/test/Triangulation_3/Test?_triangulation_IO_3 Triangulation_3/test/Triangulation_3/Test_tds_IO_3 +Triangulation_3/test/Triangulation_3/makefile diff --git a/Triangulation_3/doc_tex/TriangulationDS_3_ref/TriangulationDataStructure_3.tex b/Triangulation_3/doc_tex/TriangulationDS_3_ref/TriangulationDataStructure_3.tex index 569f8aa0a37..4c1fb82fb1d 100644 --- a/Triangulation_3/doc_tex/TriangulationDS_3_ref/TriangulationDataStructure_3.tex +++ b/Triangulation_3/doc_tex/TriangulationDS_3_ref/TriangulationDataStructure_3.tex @@ -465,6 +465,36 @@ dimension 3, \ccVar.\ccc{insert_in_facet(v)} in dimension 2, and \ccPrecond{\ccVar.\ccc{degree(v)} $=$ \ccVar.\ccc{dimension()+1}.} } +\newpage + +\ccHeading{Dimension Manipulation} + +The following operation, \texttt{decrease\_dimension}, is necessary when the displacement of a vertex decreases +the dimension of the triangulation. + +\ccMethod{void decrease_dimension(Cell_handle c, int i);} +{The link of a vertex $v$ is formed by the facets +disjoint from $v$ that are included in the cells incident to $v$. When the link of \ccc{v = c->vertex(i)} contains all the other vertices, \ccc{decrease\_dimension} crushes the +triangulation of the sphere $S^d$ of $\R^{d+1}$ onto the the +triangulation of the sphere $S^{d-1}$ of $\R^{d}$ formed by the link of \ccc{v} +augmented with the vertex \ccc{v} itself, for $d$==2,3; this one is placed on the facet \ccc{(c, i)} +(see Fig. \ref{TDS3-dim_down}). +\ccPrecond{ The dimension must be 2 or 3. The degree of \ccc{v} must be equal to the total number of vertices of the triangulation data structure minus 1.} +} + +\begin{figure} +\begin{ccTexOnly} +\begin{center} +\includegraphics[width=1.0\textwidth]{TriangulationDS_3_ref/tds-dim_down} +\end{center} +\caption{From an $S^d$ data structure to an $S^{d-1}$ data structure (top: $d==2$, bottom: $d==3$).\label{TDS3-dim_down}} +\end{ccTexOnly} +\begin{ccHtmlOnly} +
+Lowering dimension from 3D to 2D +
+\end{ccHtmlOnly} +\end{figure} \begin{ccAdvanced} \ccHeading{Other modifiers} diff --git a/Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.eps b/Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.eps new file mode 100644 index 00000000000..e7144ce252f --- /dev/null +++ b/Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.eps @@ -0,0 +1,575 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 78 304 378 515 +%%HiResBoundingBox: 78.650000 304.112109 377.250000 514.150000 +%................................... +%%Creator: GPL Ghostscript 857 (epswrite) +%%CreationDate: 2010/04/26 13:46:43 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%EndComments +%%BeginProlog +% This copyright applies to everything between here and the %%EndProlog: +% Copyright (C) 2007 artofcode LLC, Benicia, CA. All rights reserved. +%%BeginResource: procset GS_epswrite_2_0_1001 +/GS_epswrite_2_0_1001 80 dict dup begin +/PageSize 2 array def/setpagesize{ PageSize aload pop 3 index eq exch +4 index eq and{ pop pop pop}{ PageSize dup 1 +5 -1 roll put 0 4 -1 roll put dup null eq {false} {dup where} ifelse{ exch get exec} +{ pop/setpagedevice where +{ pop 1 dict dup /PageSize PageSize put setpagedevice} +{ /setpage where{ pop PageSize aload pop pageparams 3 {exch pop} repeat +setpage}if}ifelse}ifelse}ifelse} bind def +/!{bind def}bind def/#{load def}!/N/counttomark # +/rG{3{3 -1 roll 255 div}repeat setrgbcolor}!/G{255 div setgray}!/K{0 G}! +/r6{dup 3 -1 roll rG}!/r5{dup 3 1 roll rG}!/r3{dup rG}! +/w/setlinewidth #/J/setlinecap # +/j/setlinejoin #/M/setmiterlimit #/d/setdash #/i/setflat # +/m/moveto #/l/lineto #/c/rcurveto # +/p{N 2 idiv{N -2 roll rlineto}repeat}! +/P{N 0 gt{N -2 roll moveto p}if}! +/h{p closepath}!/H{P closepath}! +/lx{0 rlineto}!/ly{0 exch rlineto}!/v{0 0 6 2 roll c}!/y{2 copy c}! +/re{4 -2 roll m exch dup lx exch ly neg lx h}! +/^{3 index neg 3 index neg}! +/f{P fill}!/f*{P eofill}!/s{H stroke}!/S{P stroke}! +/q/gsave #/Q/grestore #/rf{re fill}! +/Y{P clip newpath}!/Y*{P eoclip newpath}!/rY{re Y}! +/|={pop exch 4 1 roll 1 array astore cvx 3 array astore cvx exch 1 index def exec}! +/|{exch string readstring |=}! +/+{dup type/nametype eq{2 index 7 add -3 bitshift 2 index mul}if}! +/@/currentfile #/${+ @ |}! +/B{{2 copy string{readstring pop}aload pop 4 array astore cvx +3 1 roll}repeat pop pop true}! +/Ix{[1 0 0 1 11 -2 roll exch neg exch neg]exch}! +/,{true exch Ix imagemask}!/If{false exch Ix imagemask}!/I{exch Ix image}! +/Ic{exch Ix false 3 colorimage}! +/F{/Columns counttomark 3 add -2 roll/Rows exch/K -1/BlackIs1 true>> +/CCITTFaxDecode filter}!/FX{<+ +, +1395 4661 58 64 /2O +$C +-,RJ0cQF6,"1XK6;*,e2Q-Xhg^!O5QCKXpAb$)pAO`6hdjRZ#AlQZqqHI8 +gU?L]A=[RGL6]0$(ePW!8f36d'Gr4~> +, +12 w +2020.89 4825.31 491.13 0 S +2512.02 4825.31 -100 33.33 0 -66.66 f* +2512.02 4825.31 -100 33.33 0 -66.66 H +S +4 w +255 0 r6 +804.53 4472.31 637.23 646.34 S +1441.76 5118.65 641.79 -646.34 S +2083.55 4472.31 -1279.02 0 S +1287.01 4631.62 -477.93 -159.31 S +1441.76 4795.48 -632.68 -323.17 S +1605.62 4627.07 -801.09 -154.76 S +1441.76 4790.93 0 327.72 S +1441.76 4790.93 637.24 -314.07 S +1601.07 4627.07 482.48 -154.76 S +K +1823 4904 53 62 /7J +$C +-,kH?HkM'*-_U)g6Lpe%+S.l(e'dJFIo[)VYX-_V" +, +1884 4904 40 45 /2U +$C +.E%bXLdAn"*BGA+kR`&+\d@V,3aU>`Zp3"7%<:k97S`pY?aoE@>?bfG>VrN!9#kZ` +, +1936 4904 40 45 /7N +$C +.De@QKH)-!_K8(,i.8HGkr+aVPLcfe&+mX:s1A0mg&&Is!C@K_,UgSE~> +, +1980 4905 51 44 /2Y +$C +4:PMup85+ps8W-!s6p!&^V0"!p7<2`@u"]IL(..DHo9d-@79<)~> +, +2041 4904 2U , +2085 4904 54 45 /0C +$C +,6C.B@-S;2QpI_jU)&Xml5l-m%nkCOs8MnEq[]q.+QR?i+0i`$_<"d3OW^q\5O0R8;d+ZDL#A7H +euU9.6'+M8~> +, +2145 4904 40 45 /3C +$C +0$OLI"@G=+K>]qA+bVs#Hm%:<=1s)i^9h[!q8KB$@u%_oqE9-LfBI8&I<\Ys8LU, +L).UZa*;sIOO-15%b(~> +, +2198 4904 2U , +3.98 w +2250.18 4906.63 31.38 0 S +2280 4904 7J , +2340 4905 39 61 /0G +$C +0H,'5C/^2ns8W-!s8W-!s8SPtQ2fR!q+flRl2U-q@6a~> +, +2384 4905 53 44 /3G +$C +0Fi%5fHiB'[K!/YBrUY-8HcC"s8W-!s8W-!s8W-!s8W-!s8T_2s53_JrAEE\^b2)&O!0fMaALF[ +R^CFV+bU\/~> +, +2444 4904 2U , +2489 4905 53 44 /0K +$C +2@[q9c)/7j9h>F3#QOi(s8W-!s8W-!s8V!Vn,E9^^C=ej\4VO<>]ms?KqQp]Jq*~> +, +2549 4904 3C , +2601 4905 0G , +2654 4904 41 45 /3K +$C +2$jBq&9+0F:5E8!&8m\V60U?):$LtiJ(ErCs8W,R9E3`&[^WB@['mC[9#Cs;X&-[@$n*f+~> +, +2698 4905 0K , +3078 4685 7D , +4 w +255 0 r6 +2470.44 4481.41 637.23 646.34 S +3107.67 5127.75 641.79 -646.34 S +20 w +255 0 r3 +3266.98 4640.72 -314.06 4.55 S +4 w +255 0 r6 +2952.92 4640.72 -477.93 -159.31 S +3266.98 4636.17 482.48 -154.76 S +K +1456.76 5104.99 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +6 w +1456.76 5104.99 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +1456.76 4790.93 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +1456.76 4790.93 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +819.53 4467.76 m +0 8.28 -6.71 15 -15 15 c +-8.29 0 -15 -6.72 -15 -15 c +0 -8.28 6.71 -15 15 -15 c +8.29 0 15 6.72 15 15 c +f* +819.53 4467.76 m +0 8.28 -6.71 15 -15 15 c +-8.29 0 -15 -6.72 -15 -15 c +0 -8.28 6.71 -15 15 -15 c +8.29 0 15 6.72 15 15 c +h +S +1302.01 4631.62 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +1302.01 4631.62 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +1616.07 4627.07 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +1616.07 4627.07 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +2098.55 4467.76 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +2098.55 4467.76 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +2494.54 4481.41 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +2494.54 4481.41 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +3127.22 5123.2 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +3127.22 5123.2 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +3769.01 4481.41 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +3769.01 4481.41 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +3286.53 4636.17 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +3286.53 4636.17 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +3131.77 4645.27 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +3131.77 4645.27 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +2967.91 4649.82 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +2967.91 4649.82 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +1871 4703 43 45 /0Q +$C +.E;Q$M.<32FIT=Z]f0<-hqrp5gOHumhtsmtpV"?1n!CZ@pV6`Wh5C-rn$fL$Fgp]oR^$*OK2;~> +, +1953 4723 51 23 /3Q +$C +1BuQTrMrfqR=f?;Iat@~> +, +2046 4703 41 45 /0U +$C +2$jBq&MFWG"s"i(W,G?jL@j;+n*O<=s53hQrqlHGb'.\eG4#1]GBUlYlGHh?6OY7L<#@"~> +, +2097 4731 41 7 /3U +$C +/fM+]qc9?~> +, +2150 4710 41 49 /0Y +$C +02Qa3nEnkI_m^%9E5Sp=\7+$/h1lHW%`=%g_dUE8WBsPu+JC7l&tkp%#uFHMV$JPIJtT)OC;R3J~> +, +2194 4704 52 43 /3Y +$C +.`Y?6q(_QWl0EiJFoS?)rf_j1-NEp:s7Df\kr8XjDuZWjkCJ58@[_fGdng~> +, +2254 4703 2U , +2299 4704 2Y , +2351 4703 47 56 /1C +$C +.0P5-#Wd(ljA0k/DbjHbn,NEqa8c2>s8W-!kCZg-rm]L`s8W,d5Q~> +, +2411 4703 2U , +2456 4704 52 43 /4C +$C +49QQ''\!*UR[j`8>?dqAXejV& +, +2524 4696 30 77 /1G +$C +.d0V@9!kNH<2_9GWHqOO>ut%XV>W(IV>pSqs7ZKi^\7Zq]C+RcDg/[._maO$[sMP^C&~> +, +2568 4704 0G , +2620 4696 29 77 /4G +$C +2c+aGgc&ZrLUV0W^M_m%IG]8Bs0r%%s8W,Is8$*Np!n1j=1Pq#Uq.SuG=Kk^~> +, +1010.37 3327.85 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.29 6.72 -15 15 -15 c +8.28 0 15 6.71 15 15 c +f* +1010.37 3327.85 m +0 8.28 -6.72 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.29 6.72 -15 15 -15 c +8.28 0 15 6.71 15 15 c +h +S +1401.81 3796.67 m +0 8.28 -6.71 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.29 6.72 -15 15 -15 c +8.29 0 15 6.71 15 15 c +f* +1401.81 3796.67 m +0 8.28 -6.71 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.29 6.72 -15 15 -15 c +8.29 0 15 6.71 15 15 c +h +S +1483.74 3104.82 m +0 8.28 -6.71 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.29 6.72 -15 15 -15 c +8.29 0 15 6.71 15 15 c +f* +1483.74 3104.82 m +0 8.28 -6.71 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.29 6.72 -15 15 -15 c +8.29 0 15 6.71 15 15 c +h +S +1720.43 3587.29 m +0 8.29 -6.72 15 -15 15 c +-8.29 0 -15 -6.71 -15 -15 c +0 -8.28 6.71 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +1720.43 3587.29 m +0 8.29 -6.72 15 -15 15 c +-8.29 0 -15 -6.71 -15 -15 c +0 -8.28 6.71 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +20 w +255 0 r3 +1391.36 3792.12 77.38 -687.3 S +[ 40 ] 0 d +995.37 3318.74 710.06 264 S +[ ] 0 d +12 w +K +2007.23 3664.64 491.13 0 S +2498.36 3664.64 -100 33.33 0 -66.67 f* +2498.36 3664.64 -100 33.33 0 -66.67 H +S +1810 3743 7J , +1870 3743 2U , +1922 3743 7N , +1967 3744 2Y , +2027 3743 2U , +2071 3743 0C , +2132 3743 3C , +2184 3743 2U , +3.98 w +2236.53 3745.96 31.38 0 S +2266 3743 7J , +2326 3744 0G , +2371 3744 3G , +2431 3743 2U , +2475 3744 0K , +2535 3743 3C , +2588 3744 0G , +2640 3743 3K , +2684 3744 0K , +1857 3543 0Q , +1939 3563 3Q , +2032 3543 0U , +2084 3571 3U , +2136 3550 0Y , +2180 3544 3Y , +2241 3543 2U , +2285 3544 2Y , +2337 3543 1C , +2398 3543 2U , +2442 3544 4C , +2510 3536 1G , +2555 3544 0G , +2607 3536 4G , +2790.07 3282.33 m +0 8.29 -6.72 15 -15 15 c +-8.29 0 -15 -6.71 -15 -15 c +0 -8.28 6.71 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +6 w +2790.07 3282.33 m +0 8.29 -6.72 15 -15 15 c +-8.29 0 -15 -6.71 -15 -15 c +0 -8.28 6.71 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +3186.06 3295.99 m +0 8.28 -6.71 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.29 6.72 -15 15 -15 c +8.29 0 15 6.71 15 15 c +f* +3186.06 3295.99 m +0 8.28 -6.71 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.29 6.72 -15 15 -15 c +8.29 0 15 6.71 15 15 c +h +S +3263.44 3059.3 m +0 8.29 -6.72 15 -15 15 c +-8.28 0 -15 -6.71 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +3263.44 3059.3 m +0 8.29 -6.72 15 -15 15 c +-8.28 0 -15 -6.71 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +3500.13 3541.77 m +0 8.29 -6.72 15 -15 15 c +-8.28 0 -15 -6.71 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +f* +3500.13 3541.77 m +0 8.29 -6.72 15 -15 15 c +-8.28 0 -15 -6.71 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.28 0 15 6.72 15 15 c +h +S +1253 3797 7D , +1281 3501 2O , +3117 3329 7D , +4 w +255 0 r6 +1385.23 4287.04 -393.06 -962.31 S +1471.07 3103.35 -76.81 1188.21 S +K +1401.81 4292.8 m +0 8.28 -6.71 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.29 0 15 6.72 15 15 c +f* +6 w +1401.81 4292.8 m +0 8.28 -6.71 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.28 6.72 -15 15 -15 c +8.29 0 15 6.72 15 15 c +h +S +4 w +255 0 r6 +3255.64 3049.13 -87.93 1196.67 S +K +3181.51 4247.28 m +0 8.28 -6.71 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.29 6.72 -15 15 -15 c +8.29 0 15 6.71 15 15 c +f* +6 w +3181.51 4247.28 m +0 8.28 -6.71 15 -15 15 c +-8.28 0 -15 -6.72 -15 -15 c +0 -8.29 6.72 -15 15 -15 c +8.29 0 15 6.71 15 15 c +h +S +cleartomark end end pagesave restore + showpage +%%PageTrailer +%%Trailer +%%Pages: 1 diff --git a/Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.gif b/Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.gif new file mode 100644 index 00000000000..4ba7983bc8e Binary files /dev/null and b/Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.gif differ diff --git a/Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.pdf b/Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.pdf new file mode 100644 index 00000000000..ec0320f7b42 Binary files /dev/null and b/Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.pdf differ diff --git a/Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.png b/Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.png new file mode 100644 index 00000000000..63d84f107e3 Binary files /dev/null and b/Triangulation_3/doc_tex/TriangulationDS_3_ref/tds-dim_down.png differ diff --git a/Triangulation_3/doc_tex/Triangulation_3/PkgDescription.tex b/Triangulation_3/doc_tex/Triangulation_3/PkgDescription.tex index bf5ce84c5bb..9e7b9dccc81 100644 --- a/Triangulation_3/doc_tex/Triangulation_3/PkgDescription.tex +++ b/Triangulation_3/doc_tex/Triangulation_3/PkgDescription.tex @@ -6,7 +6,7 @@ This package allows to build and handle triangulations for point sets in three dimensions. Any \cgal\ triangulation covers the convex hull of its vertices. Triangulations are build incrementally -and can be modified by insertion or removal of vertices. +and can be modified by insertion, displacements or removal of vertices. They offer point location facilities. The package provides plain triangulation (whose faces diff --git a/Triangulation_3/doc_tex/Triangulation_3/Triang3.tex b/Triangulation_3/doc_tex/Triangulation_3/Triang3.tex index 30541903fcc..849aa48e61c 100644 --- a/Triangulation_3/doc_tex/Triangulation_3/Triang3.tex +++ b/Triangulation_3/doc_tex/Triangulation_3/Triang3.tex @@ -146,8 +146,8 @@ These triangulations are uniquely defined except in degenerate cases where five points are co-spherical. Note however that the \cgal\ implementation computes a unique triangulation even in these cases. -This implementation is fully dynamic: it supports both insertions of points -and vertex removal. +This implementation is fully dynamic: it supports insertions of points, vertex removals +and displacements of points. \section{Regular Triangulation\label{Triangulation3-sec-class-Regulartriangulation}} @@ -212,6 +212,8 @@ When all weights are 0, power spheres are nothing more than circumscribing spheres, and the regular triangulation is exactly the Delaunay triangulation. +The implementation of 3D regular triangulation supports insertions of weighted points, and vertex removals. Displacements are not supported in the current implementation. + \section{Software Design\label{Triangulation3-sec-design}} The main classes \ccc{Triangulation_3}, \ccc{Delaunay_triangulation_3} and @@ -358,14 +360,23 @@ or cell base class. \subsection{The Location Policy Parameter\label{Triangulation3-sec-locpol}} The Delaunay triangulation class supports an optional feature which maintains -an additional data structure for fast point location queries. This can be -beneficial when the user needs to do many unrelated queries with no close -starting hint for location in large data sets. +an additional data structure for fast point location queries. +The fast location policy should be used when the user inserts points in a random +order or needs to do many unrelated queries. +If the user is able to give a good hint to help the point location of + its queries (and its newly inserted points), then it should prefer the default + policy. In such a case where good hints are provided, +the default policy save some memory (few percents), and is faster. +Notice that if points are not inserted one by one, but as a range, then a good hint is +automatically computed using spatial sort. + +Reading Section~\ref{Triangulation3-sec-complexity} on complexity and +performance can help making an informed choice for this parameter. The point location strategy can be selected with the third template argument of \ccc{Delaunay_triangulation_3}, \ccc{LocationPolicy}, which enables a fast point location data structure when set to \ccc{Fast_location}. By default, it -uses \ccc{Compact_location}, which has the advantage of using less memory. +uses \ccc{Compact_location}. Note that you can specify the \ccc{LocationPolicy} parameter without specifying the triangulation data structure, in case you are fine with the default there. @@ -374,7 +385,9 @@ geometric traits.\footnote{The mechanism used behind the scenes to allow this syntactical convenience is called \textit{deduced parameters}.} The \ccc{Fast_location} policy is implemented using a hierarchy of -triangulations. As proved in~\cite{cgal:d-dh-02}, this structure has an +triangulations; it changes the behavior of functions \ccc{locate}, +\ccc{insert}, \ccc{move}, and \ccc{remove}. +As proved in~\cite{cgal:d-dh-02}, this structure has an optimal behavior when it is built for Delaunay triangulations. In this setting, if you build a triangulation by iteratively inserting points, @@ -383,9 +396,6 @@ guaranteed only for a randomized order. For example, inserting points in lexicographic order is typically much slower. Note that this shuffling is performed internally by the constructor taking a range of points. -Reading Section~\ref{Triangulation3-sec-complexity} on complexity and -performance can help making an informed choice for this parameter. - Prior to \cgal\ 3.6, this functionality was available through the \ccc{Triangulation_hierarchy_3} class, which is now deprecated. @@ -793,6 +803,8 @@ the package that were integrated in release~3.4. In 2009, Sylvain Pion simplified the design of the Delaunay hierarchy so that it became the simple \ccc{Fast_location} policy in release~3.6. +In 2010, Pedro de Castro and Olivier Devillers added the point displacement. + The authors wish to thank Lutz Kettner for inspiring discussions about the design of CGAL. Jean-Daniel Boissonnat is also acknowledged \cite{bdty-tcgal-00}. diff --git a/Triangulation_3/doc_tex/Triangulation_3_ref/Delaunay_triangulation_3.tex b/Triangulation_3/doc_tex/Triangulation_3_ref/Delaunay_triangulation_3.tex index 6ecc90b6ab0..0b7010a32d0 100644 --- a/Triangulation_3/doc_tex/Triangulation_3_ref/Delaunay_triangulation_3.tex +++ b/Triangulation_3/doc_tex/Triangulation_3_ref/Delaunay_triangulation_3.tex @@ -132,14 +132,19 @@ is used to improve efficiency. \ccPrecond{The \ccc{value_type} of \ccc{first} and \ccc{last} is \ccc{Point}.}} -\ccHeading{Point moving} +\ccHeading{Displacement} -\ccMethod{Vertex_handle move_point(Vertex_handle v, const Point & p);} -{Moves the point stored in \ccc{v} to \ccc{p}, while preserving the Delaunay -property. This performs an action semantically equivalent to \ccc{remove(v)} -followed by \ccc{insert(p)}, but is supposedly faster when the point has -not moved much. Returns the handle to the new vertex. -\ccPrecond{\ccc{v} is a finite vertex of the triangulation.}} +\ccMethod{Vertex_handle move_if_no_collision(Vertex_handle v, const Point & p);} +{ if there is not already another vertex placed on \ccc{p}, +the triangulation is modified such that the new position of vertex \ccc{v} +is \ccc{p}, and \ccc{v} is returned. Otherwise, the triangulation is not +modified and the vertex at point \ccc{p} is returned. +\ccPrecond Vertex \ccc{v} must be finite.} + +\ccMethod{Vertex_handle move(Vertex_handle v, const Point & p);} +{same as above if there is no collision. Otherwise, \ccc{v} +is deleted and the vertex placed on \ccc{p} is returned. + \ccPrecond Vertex \ccc{v} must be finite.} \ccHeading{Removal} diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h index f2b06da0522..e37ffe729b8 100644 --- a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h @@ -227,8 +227,30 @@ public: Vertex_handle insert(const Point & p, Locate_type lt, Cell_handle c, int li, int); + +public: // internal methods + + template + Vertex_handle insert_and_give_new_cells(const Point &p, + OutputItCells fit, + Cell_handle start = Cell_handle() ); + + template + Vertex_handle insert_and_give_new_cells(const Point& p, + OutputItCells fit, + Vertex_handle hint); - Vertex_handle move_point(Vertex_handle v, const Point & p); + template + Vertex_handle insert_and_give_new_cells(const Point& p, + Locate_type lt, + Cell_handle c, int li, int lj, + OutputItCells fit); + +public: + +#ifndef CGAL_NO_DEPRECATED_CODE + CGAL_DEPRECATED Vertex_handle move_point(Vertex_handle v, const Point & p); +#endif template + void remove_and_give_new_cells(Vertex_handle v, + OutputItCells fit); + template < typename InputIterator > int remove(InputIterator first, InputIterator beyond) { @@ -339,6 +367,17 @@ public: return n - number_of_vertices(); } + // MOVE + Vertex_handle move_if_no_collision(Vertex_handle v, const Point &p); + + Vertex_handle move(Vertex_handle v, const Point &p); + + // return new cells (internal) + template + Vertex_handle move_if_no_collision_and_give_new_cells(Vertex_handle v, + const Point &p, + OutputItCells fit); + private: Bounded_side @@ -377,6 +416,9 @@ public: bool is_Gabriel(const Facet& f)const ; bool is_Gabriel(const Edge& e) const; + bool is_delaunay_after_displacement(Vertex_handle v, + const Point &p) const; + // Dual functions Point dual(Cell_handle c) const; @@ -498,6 +540,9 @@ private: template < class DelaunayTriangulation_3 > class Vertex_remover; + template < class DelaunayTriangulation_3 > + class Vertex_inserter; + friend class Perturbation_order; friend class Conflict_tester_3; friend class Conflict_tester_2; @@ -542,6 +587,98 @@ insert(const Point & p, Locate_type lt, Cell_handle c, int li, int lj) } } +template < class Gt, class Tds > +template +typename Delaunay_triangulation_3::Vertex_handle +Delaunay_triangulation_3:: +insert_and_give_new_cells(const Point &p, + OutputItCells fit, + Cell_handle start) +{ + Vertex_handle v = insert(p, start); + int dimension = this->dimension(); + if(dimension == 3) this->incident_cells(v, fit); + else if(dimension == 2) + { + Cell_handle c = v->cell(), end = c; + do { + *fit++ = c; + int i = c->index(v); + c = c->neighbor((i+1)%3); + } while(c != end); + } + else if(dimension == 1) + { + Cell_handle c = v->cell(); + *fit++ = c; + *fit++ = c->neighbor((~(c->index(v)))&1); + } + else *fit++ = v->cell(); // dimension = 0 + return v; +} + +template < class Gt, class Tds > +template +typename Delaunay_triangulation_3::Vertex_handle +Delaunay_triangulation_3:: +insert_and_give_new_cells(const Point& p, + OutputItCells fit, + Vertex_handle hint) +{ + Vertex_handle v = insert(p, hint); + int dimension = this->dimension(); + if(dimension == 3) this->incident_cells(v, fit); + else if(dimension == 2) + { + Cell_handle c = v->cell(), end = c; + do { + *fit++ = c; + int i = c->index(v); + c = c->neighbor((i+1)%3); + } while(c != end); + } + else if(dimension == 1) + { + Cell_handle c = v->cell(); + *fit++ = c; + *fit++ = c->neighbor((~(c->index(v)))&1); + } + else *fit++ = v->cell(); // dimension = 0 + return v; +} + +template < class Gt, class Tds > +template +typename Delaunay_triangulation_3::Vertex_handle +Delaunay_triangulation_3:: +insert_and_give_new_cells(const Point& p, + Locate_type lt, + Cell_handle c, int li, int lj, + OutputItCells fit) +{ + Vertex_handle v = insert(p, lt, c, li, lj); + int dimension = this->dimension(); + if(dimension == 3) this->incident_cells(v, fit); + else if(dimension == 2) + { + Cell_handle c = v->cell(), end = c; + do { + *fit++ = c; + int i = c->index(v); + c = c->neighbor((i+1)%3); + } while(c != end); + } + else if(dimension == 1) + { + Cell_handle c = v->cell(); + *fit++ = c; + *fit++ = c->neighbor((~(c->index(v)))&1); + } + else *fit++ = v->cell(); // dimension = 0 + return v; +} + +#ifndef CGAL_NO_DEPRECATED_CODE template < class Gt, class Tds > typename Delaunay_triangulation_3::Vertex_handle Delaunay_triangulation_3:: @@ -564,6 +701,7 @@ move_point(Vertex_handle v, const Point & p) return insert(p); return insert(p, old_neighbor->cell()); } +#endif template template @@ -586,6 +724,35 @@ public: } }; +template +template +class Delaunay_triangulation_3::Vertex_inserter { + typedef DelaunayTriangulation_3 Delaunay; +public: + typedef Nullptr_t Hidden_points_iterator; + + Vertex_inserter(Delaunay &tmp_) : tmp(tmp_) {} + + Delaunay &tmp; + + void add_hidden_points(Cell_handle) {} + Hidden_points_iterator hidden_points_begin() { return NULL; } + Hidden_points_iterator hidden_points_end() { return NULL; } + + Vertex_handle insert(const Point& p, + Locate_type lt, Cell_handle c, int li, int lj) { + return tmp.insert(p, lt, c, li, lj); + } + + Vertex_handle insert(const Point& p, Cell_handle c) { + return tmp.insert(p, c); + } + + Vertex_handle insert(const Point& p) { + return tmp.insert(p); + } +}; + template < class Gt, class Tds > void Delaunay_triangulation_3:: @@ -598,6 +765,63 @@ remove(Vertex_handle v) CGAL_triangulation_expensive_postcondition(is_valid()); } +template < class Gt, class Tds > +typename Delaunay_triangulation_3::Vertex_handle +Delaunay_triangulation_3:: +move_if_no_collision(Vertex_handle v, const Point &p) +{ + Self tmp; + Vertex_remover remover (tmp); + Vertex_inserter inserter (*this); + Vertex_handle res = Tr_Base::move_if_no_collision(v,p,remover,inserter); + + CGAL_triangulation_expensive_postcondition(is_valid()); + return res; +} + +template +typename Delaunay_triangulation_3::Vertex_handle +Delaunay_triangulation_3:: +move(Vertex_handle v, const Point &p) { + CGAL_triangulation_precondition(!is_infinite(v)); + if(v->point() == p) return v; + Self tmp; + Vertex_remover remover (tmp); + Vertex_inserter inserter (*this); + return Tr_Base::move(v,p,remover,inserter); +} + +template < class Gt, class Tds > +template +void +Delaunay_triangulation_3:: +remove_and_give_new_cells(Vertex_handle v, OutputItCells fit) +{ + Self tmp; + Vertex_remover remover (tmp); + Tr_Base::remove_and_give_new_cells(v,remover,fit); + + CGAL_triangulation_expensive_postcondition(is_valid()); +} + +template < class Gt, class Tds > +template +typename Delaunay_triangulation_3::Vertex_handle +Delaunay_triangulation_3:: +move_if_no_collision_and_give_new_cells(Vertex_handle v, const Point &p, + OutputItCells fit) +{ + Self tmp; + Vertex_remover remover (tmp); + Vertex_inserter inserter (*this); + Vertex_handle res = + Tr_Base::move_if_no_collision_and_give_new_cells(v,p, + remover,inserter,fit); + + CGAL_triangulation_expensive_postcondition(is_valid()); + return res; +} + template < class Gt, class Tds > Oriented_side Delaunay_triangulation_3:: @@ -887,6 +1111,75 @@ nearest_vertex(const Point& p, Cell_handle start) const return nearest; } +// This is not a fast version. +// The optimized version needs an int for book-keeping in +// tds() so as to avoiding the need to clear +// the tds marker in each cell (which is an unsigned char) +// Also the visitor in TDS could be more clever. +// The Delaunay triangulation which filters displacements +// will do these optimizations. +template +bool +Delaunay_triangulation_3:: +is_delaunay_after_displacement(Vertex_handle v, const Point &p) const +{ + CGAL_triangulation_precondition(!this->is_infinite(v)); + CGAL_triangulation_precondition(this->dimension() == 2); + CGAL_triangulation_precondition(!this->test_dim_down(v)); + if(v->point() == p) return true; + Point ant = v->point(); + v->set_point(p); + + int size; + + // are incident cells well-oriented + std::vector cells; + cells.reserve(64); + this->incident_cells(v, std::back_inserter(cells)); + size = cells.size(); + for(int i=0; iis_infinite(c)) continue; + if(this->orientation(c->vertex(0)->point(), c->vertex(1)->point(), + c->vertex(2)->point(), c->vertex(3)->point()) + != POSITIVE) + { + v->set_point(ant); + return false; + } + } + + // are incident bi-cells Delaunay? + std::vector facets; + facets.reserve(128); + this->incident_facets(v, std::back_inserter(facets)); + size = facets.size(); + for(int i=0; ineighbor(j); + int mj = this->mirror_index(c, j); + Vertex_handle h1 = c->vertex(j); + if(this->is_infinite(h1)) { + if(this->side_of_sphere(c, cj->vertex(mj)->point(), true) + != ON_UNBOUNDED_SIDE) { + v->set_point(ant); + return false; + } + } else { + if(this->side_of_sphere(cj, h1->point(), true) != ON_UNBOUNDED_SIDE) { + v->set_point(ant); + return false; + } + } + } + + v->set_point(ant); + return true; +} template < class Gt, class Tds > bool diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index 22db37507ce..d4101b1344b 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -293,8 +293,14 @@ public: return n - number_of_vertices(); } + // DISPLACEMENT Vertex_handle move_point(Vertex_handle v, const Weighted_point & p); + // Displacement works only for Regular triangulation + // without hidden points at any time + Vertex_handle move_if_no_collision(Vertex_handle v, const Weighted_point & p); + Vertex_handle move(Vertex_handle v, const Weighted_point & p); + protected: Oriented_side @@ -680,6 +686,9 @@ private: template < class RegularTriangulation_3 > class Vertex_remover; + template < class RegularTriangulation_3 > + class Vertex_inserter; + Hidden_point_visitor hidden_point_visitor; }; @@ -1241,6 +1250,39 @@ private: std::vector hidden; }; +// The displacement method works only +// on regular triangulation without hidden points at any time +// the vertex inserter is used only +// for the purpose of displacements +template +template +class Regular_triangulation_3::Vertex_inserter { + typedef RegularTriangulation_3 Regular; +public: + typedef Nullptr_t Hidden_points_iterator; + + Vertex_inserter(Regular &tmp_) : tmp(tmp_) {} + + Regular &tmp; + + void add_hidden_points(Cell_handle) {} + Hidden_points_iterator hidden_points_begin() { return NULL; } + Hidden_points_iterator hidden_points_end() { return NULL; } + + Vertex_handle insert(const Weighted_point& p, + Locate_type lt, Cell_handle c, int li, int lj) { + return tmp.insert(p, lt, c, li, lj); + } + + Vertex_handle insert(const Weighted_point& p, Cell_handle c) { + return tmp.insert(p, c); + } + + Vertex_handle insert(const Weighted_point& p) { + return tmp.insert(p); + } +}; + template < class Gt, class Tds > void Regular_triangulation_3:: @@ -1288,6 +1330,34 @@ move_point(Vertex_handle v, const Weighted_point & p) return insert(p, old_neighbor->cell()); } +// Displacement works only for Regular triangulation +// without hidden points at any time +template < class Gt, class Tds > +typename Regular_triangulation_3::Vertex_handle +Regular_triangulation_3:: +move_if_no_collision(Vertex_handle v, const Weighted_point &p) +{ + Self tmp; + Vertex_remover remover (tmp); + Vertex_inserter inserter (*this); + Vertex_handle res = Tr_Base::move_if_no_collision(v,p,remover,inserter); + + CGAL_triangulation_expensive_postcondition(is_valid()); + return res; +} + +template +typename Regular_triangulation_3::Vertex_handle +Regular_triangulation_3:: +move(Vertex_handle v, const Weighted_point &p) { + CGAL_triangulation_precondition(!is_infinite(v)); + if(v->point() == p) return v; + Self tmp; + Vertex_remover remover (tmp); + Vertex_inserter inserter (*this); + return Tr_Base::move(v,p,remover,inserter); +} + template < class Gt, class Tds > bool Regular_triangulation_3:: diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index c46655525bc..5a49f3b7510 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -594,6 +594,25 @@ public: Vertex_handle insert(const Point & p, Cell_handle start = Cell_handle()); Vertex_handle insert(const Point & p, Locate_type lt, Cell_handle c, int li, int lj); + +//protected: // internal methods + + template + Vertex_handle insert_and_give_new_cells(const Point &p, + OutputItCells fit, + Cell_handle start = Cell_handle() ); + + template + Vertex_handle insert_and_give_new_cells(const Point& p, + OutputItCells fit, + Vertex_handle hint); + + template + Vertex_handle insert_and_give_new_cells(const Point& p, + Locate_type lt, + Cell_handle c, int li, int lj, + OutputItCells fit); + template < class Conflict_tester, class Hidden_points_visitor > inline Vertex_handle insert_in_conflict(const Point & p, Locate_type lt, @@ -812,13 +831,119 @@ private: } }; - bool test_dim_down(Vertex_handle v) const; - protected: + // no point being private, we might need to test + // whether a displacement decreases dimension on + // others inherited triangulations + bool test_dim_down(Vertex_handle v) const; + + // REMOVAL template < class VertexRemover > void remove(Vertex_handle v, VertexRemover &remover); + template < class VertexRemover, class OutputItCells > + void remove_and_give_new_cells(Vertex_handle v, VertexRemover &remover, + OutputItCells fit); + + // MOVE + template < class VertexRemover, class VertexInserter > + Vertex_handle move_if_no_collision(Vertex_handle v, const Point &p, + VertexRemover &remover, + VertexInserter &inserter); + + template < class VertexRemover, class VertexInserter > + Vertex_handle move(Vertex_handle v, const Point &p, + VertexRemover &remover, VertexInserter &inserter); + + // move and give new cells + template < class VertexRemover, class VertexInserter, class OutputItCells > + Vertex_handle move_if_no_collision_and_give_new_cells( + Vertex_handle v, const Point &p, VertexRemover &remover, + VertexInserter &inserter, OutputItCells fit); + + // This is a function better suited for tds + // but because it is not required in the model of tds + // at this time, it should be implemented here. + void flip_2D(Cell_handle f, int i) + { + CGAL_triangulation_precondition( dimension()==2); + Cell_handle n = f->neighbor(i); + int ni = this->_tds.mirror_index(f,i); //ni = n->index(f); + + int cwi = (i+2)%3; + int ccwi = (i+1)%3; + int cwni = (ni+2)%3; + int ccwni = (ni+1)%3; + + Vertex_handle v_cw = f->vertex(cwi); + Vertex_handle v_ccw = f->vertex(ccwi); + + // bl == bottom left, tr == top right + Cell_handle tr = f->neighbor(ccwi); + int tri = this->_tds.mirror_index(f,ccwi); + Cell_handle bl = n->neighbor(ccwni); + int bli = this->_tds.mirror_index(n,ccwni); + + f->set_vertex(cwi, n->vertex(ni)); + n->set_vertex(cwni, f->vertex(i)); + + // update the neighborhood relations + this->_tds.set_adjacency(f, i, bl, bli); + this->_tds.set_adjacency(f, ccwi, n, ccwni); + this->_tds.set_adjacency(n, ni, tr, tri); + + if(v_cw->cell() == f) { + v_cw->set_cell(n); + } + + if(v_ccw->cell() == n) { + v_ccw->set_cell(f); + } + } + + template < class VertexRemover, class VertexInserter > + void restore_edges_after_decrease_dimension(Vertex_handle v, + VertexRemover &remover, VertexInserter &inserter) + { + + Cell_handle fkstart = v->cell(); + Cell_handle start = fkstart->neighbor(fkstart->index(v)); + + std::list hole; + make_hole_2D(v, hole, remover); + fill_hole_2D(hole, remover); + // make hole here will work if the link of v is a valid triangulation + // the aim here is Delaunay triangulations + // to make it more general one could have an internal function here + // to remove v without touching its handle + + // This insert must be from Delaunay (or the particular trian.) + // not the basic Triangulation_3. + // Here we correct the recent triangulation (with decreased dimension) formed + // in particular here a 2D (from 3D to 2D displacement) + Vertex_handle inserted = inserter.insert(v->point(), start); + + // fixing pointer + Cell_handle fc = inserted->cell(), done(fc); + std::vector faces_pt; + faces_pt.reserve(16); + do { + faces_pt.push_back(fc); + fc = fc->neighbor((fc->index(inserted) + 1)%3); + } while(fc != done); + int ss = faces_pt.size(); + for(int k=0; kindex(inserted); + f->set_vertex(i, v); + } + v->set_cell(inserted->cell()); + + tds().delete_vertex(inserted); + } + private: typedef Facet Edge_2D; typedef Triple Vertex_triple; @@ -830,7 +955,13 @@ private: VertexRemover& make_hole_2D(Vertex_handle v, std::list & hole, VertexRemover &remover); template < class VertexRemover > + VertexRemover& make_hole_2D(Vertex_handle v, std::list & hole, + VertexRemover &remover, + std::set &cells_set); + + template < class VertexRemover > void fill_hole_2D(std::list & hole, VertexRemover &remover); + void make_hole_3D( Vertex_handle v, std::map& outer_map, std::vector & hole); @@ -843,6 +974,25 @@ private: template < class VertexRemover > VertexRemover& remove_3D(Vertex_handle v, VertexRemover &remover); + template < class VertexRemover, class OutputItCells > + VertexRemover& remove_dim_down(Vertex_handle v, VertexRemover &remover, + OutputItCells fit); + + template < class VertexRemover, class OutputItCells > + VertexRemover& remove_1D(Vertex_handle v, VertexRemover &remover, + OutputItCells fit); + + template < class VertexRemover, class OutputItCells > + VertexRemover& remove_2D(Vertex_handle v, VertexRemover &remover, + OutputItCells fit); + + template < class VertexRemover, class OutputItCells > + VertexRemover& remove_3D(Vertex_handle v, VertexRemover &remover, + OutputItCells fit); + + template < class VertexRemover, class OutputItCells > + void fill_hole_2D(std::list & hole, VertexRemover &remover, + OutputItCells fit); // They access "Self", so need to be friend. friend class Conflict_tester_outside_convex_hull_3; @@ -2786,6 +2936,94 @@ insert_outside_affine_hull(const Point & p) return v; } +template < class GT, class Tds > +template < class OutputItCells > +typename Triangulation_3::Vertex_handle +Triangulation_3::insert_and_give_new_cells(const Point &p, + OutputItCells fit, + Cell_handle start) +{ + Vertex_handle v = insert(p, start); + int dimension = this->dimension(); + if(dimension == 3) this->incident_cells(v, fit); + else if(dimension == 2) + { + Cell_handle c = v->cell(), end = c; + do { + *fit++ = c; + int i = c->index(v); + c = c->neighbor((i+1)%3); + } while(c != end); + } + else if(dimension == 1) + { + Cell_handle c = v->cell(); + *fit++ = c; + *fit++ = c->neighbor((~(c->index(v)))&1); + } + else *fit++ = v->cell(); // dimension = 0 + return v; +} + +template < class GT, class Tds > +template < class OutputItCells > +typename Triangulation_3::Vertex_handle +Triangulation_3::insert_and_give_new_cells(const Point& p, + OutputItCells fit, + Vertex_handle hint) +{ + Vertex_handle v = insert(p, hint); + int dimension = this->dimension(); + if(dimension == 3) this->incident_cells(v, fit); + else if(dimension == 2) + { + Cell_handle c = v->cell(), end = c; + do { + *fit++ = c; + int i = c->index(v); + c = c->neighbor((i+1)%3); + } while(c != end); + } + else if(dimension == 1) + { + Cell_handle c = v->cell(); + *fit++ = c; + *fit++ = c->neighbor((~(c->index(v)))&1); + } + else *fit++ = v->cell(); // dimension = 0 + return v; +} + +template < class GT, class Tds > +template < class OutputItCells > +typename Triangulation_3::Vertex_handle +Triangulation_3::insert_and_give_new_cells(const Point& p, + Locate_type lt, + Cell_handle c, int li, int lj, + OutputItCells fit) +{ + Vertex_handle v = insert(p, lt, c, li, lj); + int dimension = this->dimension(); + if(dimension == 3) this->incident_cells(v, fit); + else if(dimension == 2) + { + Cell_handle c = v->cell(), end = c; + do { + *fit++ = c; + int i = c->index(v); + c = c->neighbor((i+1)%3); + } while(c != end); + } + else if(dimension == 1) + { + Cell_handle c = v->cell(); + *fit++ = c; + *fit++ = c->neighbor((~(c->index(v)))&1); + } + else *fit++ = v->cell(); // dimension = 0 + return v; +} + template < class Gt, class Tds > typename Triangulation_3::Vertex_triple Triangulation_3:: @@ -2890,6 +3128,46 @@ Triangulation_3:: make_hole_2D(Vertex_handle v, std::list &hole, VertexRemover &remover) { std::vector to_delete; + to_delete.reserve(32); + + Face_circulator fc = tds().incident_faces(v); + Face_circulator done(fc); + + // We prepare for deleting all interior cells. + // We ->set_cell() pointers to cells outside the hole. + // We push the Edges_2D of the boundary (seen from outside) in "hole". + do { + Cell_handle f = fc; + int i = f->index(v); + Cell_handle fn = f->neighbor(i); + int in = fn->index(f); + + f->vertex(cw(i))->set_cell(fn); + fn->set_neighbor(in, Cell_handle()); + + hole.push_back(Edge_2D(fn, in)); + remover.add_hidden_points(f); + to_delete.push_back(f); + + ++fc; + } while (fc != done); + + tds().delete_cells(to_delete.begin(), to_delete.end()); + return remover; +} + +// this one also erases a set of cells +// which is useful to the move method +// outputting newly created cells +template +template < class VertexRemover > +VertexRemover& +Triangulation_3:: +make_hole_2D(Vertex_handle v, std::list &hole, VertexRemover &remover, + std::set &cells_set) +{ + std::vector to_delete; + to_delete.reserve(32); Face_circulator fc = tds().incident_faces(v); Face_circulator done(fc); @@ -2913,6 +3191,9 @@ make_hole_2D(Vertex_handle v, std::list &hole, VertexRemover &remover) ++fc; } while (fc != done); + for(typename std::vector::const_iterator ib = to_delete.begin(), + iend = to_delete.end(); ib != iend; ib++) cells_set.erase(*ib); + tds().delete_cells(to_delete.begin(), to_delete.end()); return remover; } @@ -3054,6 +3335,144 @@ fill_hole_2D(std::list & first_hole, VertexRemover &remover) } } +template +template < class VertexRemover, class OutputItCells > +void +Triangulation_3:: +fill_hole_2D(std::list & first_hole, VertexRemover &remover, + OutputItCells fit) +{ + typedef std::list Hole; + + std::vector hole_list; + + Cell_handle f, ff, fn; + int i, ii, in; + + hole_list.push_back(first_hole); + + while( ! hole_list.empty()) + { + Hole hole = hole_list.back(); + hole_list.pop_back(); + + // if the hole has only three edges, create the triangle + if (hole.size() == 3) { + typename Hole::iterator hit = hole.begin(); + f = (*hit).first; i = (*hit).second; + ff = (* ++hit).first; ii = (*hit).second; + fn = (* ++hit).first; in = (*hit).second; + *fit++ = tds().create_face(f, i, ff, ii, fn, in); + continue; + } + + // else find an edge with two finite vertices + // on the hole boundary + // and the new triangle adjacent to that edge + // cut the hole and push it back + + // first, ensure that a neighboring face + // whose vertices on the hole boundary are finite + // is the first of the hole + while (1) { + ff = (hole.front()).first; + ii = (hole.front()).second; + if ( is_infinite(ff->vertex(cw(ii))) || + is_infinite(ff->vertex(ccw(ii)))) { + hole.push_back(hole.front()); + hole.pop_front(); + } + else + break; + } + + // take the first neighboring face and pop it; + ff = (hole.front()).first; + ii = (hole.front()).second; + hole.pop_front(); + + Vertex_handle v0 = ff->vertex(cw(ii)); + Vertex_handle v1 = ff->vertex(ccw(ii)); + Vertex_handle v2 = infinite_vertex(); + const Point &p0 = v0->point(); + const Point &p1 = v1->point(); + const Point *p2 = NULL; // Initialize to NULL to avoid warning. + + typename Hole::iterator hdone = hole.end(); + typename Hole::iterator hit = hole.begin(); + typename Hole::iterator cut_after(hit); + + // if tested vertex is c with respect to the vertex opposite + // to NULL neighbor, + // stop at the before last face; + hdone--; + for (; hit != hdone; ++hit) { + fn = hit->first; + in = hit->second; + Vertex_handle vv = fn->vertex(ccw(in)); + if (is_infinite(vv)) { + if (is_infinite(v2)) + cut_after = hit; + } + else { // vv is a finite vertex + const Point &p = vv->point(); + if (coplanar_orientation(p0, p1, p) == COUNTERCLOCKWISE) { + if (is_infinite(v2) || + remover.side_of_bounded_circle(p0, p1, *p2, p, true) + == ON_BOUNDED_SIDE) { + v2 = vv; + p2 = &p; + cut_after = hit; + } + } + } + } + + // create new triangle and update adjacency relations + Cell_handle newf; + + //update the hole and push back in the Hole_List stack + // if v2 belongs to the neighbor following or preceding *f + // the hole remain a single hole + // otherwise it is split in two holes + + fn = (hole.front()).first; + in = (hole.front()).second; + if (fn->has_vertex(v2, i) && i == ccw(in)) { + newf = tds().create_face(ff, ii, fn, in); + hole.pop_front(); + hole.push_front(Edge_2D(newf, 1)); + hole_list.push_back(hole); + } else { + fn = (hole.back()).first; + in = (hole.back()).second; + if (fn->has_vertex(v2, i) && i == cw(in)) { + newf = tds().create_face(fn, in, ff, ii); + hole.pop_back(); + hole.push_back(Edge_2D(newf, 1)); + hole_list.push_back(hole); + } else { + // split the hole in two holes + newf = tds().create_face(ff, ii, v2); + Hole new_hole; + ++cut_after; + while( hole.begin() != cut_after ) + { + new_hole.push_back(hole.front()); + hole.pop_front(); + } + hole.push_front(Edge_2D(newf, 1)); + new_hole.push_front(Edge_2D(newf, 0)); + hole_list.push_back(hole); + hole_list.push_back(new_hole); + } + } + + *fit++ = newf; + + } +} + template < class Gt, class Tds > void Triangulation_3:: @@ -3304,6 +3723,921 @@ remove(Vertex_handle v, VertexRemover &remover) { } } +// The remove here uses the remover, but +// no function envolving hidden points +// will be used in this internal version +template < class Gt, class Tds > +template < class VertexRemover, class OutputItCells > +VertexRemover& +Triangulation_3:: +remove_dim_down(Vertex_handle v, VertexRemover &remover, OutputItCells fit) { + remove_dim_down(v, remover); + for(All_cells_iterator afi = tds().raw_cells_begin(); + afi != tds().raw_cells_end(); + afi++) *fit++ = afi; +} + +template < class Gt, class Tds > +template < class VertexRemover, class OutputItCells > +VertexRemover& +Triangulation_3:: +remove_1D(Vertex_handle v, VertexRemover &remover, OutputItCells fit) { + Point p = v->point(); + remove_1D(v, remover); + *fit++ = locate(p); +} + +template < class Gt, class Tds > +template < class VertexRemover, class OutputItCells > +VertexRemover& +Triangulation_3:: +remove_2D(Vertex_handle v, VertexRemover &remover, OutputItCells fit) { + CGAL_triangulation_precondition(dimension() == 2); + std::list hole; + make_hole_2D(v, hole, remover); + fill_hole_2D(hole, remover, fit); + tds().delete_vertex(v); + return remover; +} + +template < class Gt, class Tds > +template < class VertexRemover, class OutputItCells > +VertexRemover& +Triangulation_3:: +remove_3D(Vertex_handle v, VertexRemover &remover, OutputItCells fit) { + CGAL_triangulation_precondition(dimension() == 3); + + std::vector hole; + hole.reserve(64); + + // Construct the set of vertex triples on the boundary + // with the facet just behind + typedef std::map Vertex_triple_Facet_map; + Vertex_triple_Facet_map outer_map; + Vertex_triple_Facet_map inner_map; + + make_hole_3D(v, outer_map, hole); + + CGAL_assertion(remover.hidden_points_begin() == + remover.hidden_points_end() ); + + // Output the hidden points. + for (typename std::vector::iterator + hi = hole.begin(), hend = hole.end(); hi != hend; ++hi) + remover.add_hidden_points(*hi); + + bool inf = false; + unsigned int i; + // collect all vertices on the boundary + std::vector vertices; + vertices.reserve(64); + + adjacent_vertices(v, std::back_inserter(vertices)); + + // create a Delaunay triangulation of the points on the boundary + // and make a map from the vertices in remover.tmp towards the vertices + // in *this + + Unique_hash_map vmap; + Cell_handle ch = Cell_handle(); + for(i=0; i < vertices.size(); i++){ + if(! is_infinite(vertices[i])){ + Vertex_handle vh = remover.tmp.insert(vertices[i]->point(), ch); + ch = vh->cell(); + vmap[vh] = vertices[i]; + }else { + inf = true; + } + } + + if(remover.tmp.dimension()==2){ + Vertex_handle fake_inf = remover.tmp.insert(v->point()); + vmap[fake_inf] = infinite_vertex(); + } else { + vmap[remover.tmp.infinite_vertex()] = infinite_vertex(); + } + + CGAL_triangulation_assertion(remover.tmp.dimension() == 3); + + // Construct the set of vertex triples of remover.tmp + // We reorient the vertex triple so that it matches those from outer_map + // Also note that we use the vertices of *this, not of remover.tmp + + if(inf){ + for(All_cells_iterator it = remover.tmp.all_cells_begin(), + end = remover.tmp.all_cells_end(); it != end; ++it) + { + for(i=0; i < 4; i++){ + Facet f = std::pair(it,i); + Vertex_triple vt_aux = make_vertex_triple(f); + Vertex_triple vt(vmap[vt_aux.first],vmap[vt_aux.third],vmap[vt_aux.second]); + make_canonical(vt); + inner_map[vt]= f; + } + } + } else { + for(Finite_cells_iterator it = remover.tmp.finite_cells_begin(), + end = remover.tmp.finite_cells_end(); it != end; ++it) + { + for(i=0; i < 4; i++){ + Facet f = std::pair(it,i); + Vertex_triple vt_aux = make_vertex_triple(f); + Vertex_triple vt(vmap[vt_aux.first],vmap[vt_aux.third],vmap[vt_aux.second]); + make_canonical(vt); + inner_map[vt]= f; + } + } + } + // Grow inside the hole, by extending the surface + while(! outer_map.empty()){ + typename Vertex_triple_Facet_map::iterator oit = outer_map.begin(); + while(is_infinite(oit->first.first) || + is_infinite(oit->first.second) || + is_infinite(oit->first.third)){ + ++oit; + // otherwise the lookup in the inner_map fails + // because the infinite vertices are different + } + typename Vertex_triple_Facet_map::value_type o_vt_f_pair = *oit; + Cell_handle o_ch = o_vt_f_pair.second.first; + unsigned int o_i = o_vt_f_pair.second.second; + + typename Vertex_triple_Facet_map::iterator iit = + inner_map.find(o_vt_f_pair.first); + CGAL_triangulation_assertion(iit != inner_map.end()); + typename Vertex_triple_Facet_map::value_type i_vt_f_pair = *iit; + Cell_handle i_ch = i_vt_f_pair.second.first; + unsigned int i_i = i_vt_f_pair.second.second; + + // create a new cell and glue it to the outer surface + Cell_handle new_ch = tds().create_cell(); + *fit++ = new_ch; + + new_ch->set_vertices(vmap[i_ch->vertex(0)], vmap[i_ch->vertex(1)], + vmap[i_ch->vertex(2)], vmap[i_ch->vertex(3)]); + + o_ch->set_neighbor(o_i,new_ch); + new_ch->set_neighbor(i_i, o_ch); + + // for the other faces check, if they can also be glued + for(i = 0; i < 4; i++){ + if(i != i_i){ + Facet f = std::pair(new_ch,i); + Vertex_triple vt = make_vertex_triple(f); + make_canonical(vt); + std::swap(vt.second,vt.third); + typename Vertex_triple_Facet_map::iterator oit2 = outer_map.find(vt); + if(oit2 == outer_map.end()){ + std::swap(vt.second,vt.third); + outer_map[vt]= f; + } else { + // glue the faces + typename Vertex_triple_Facet_map::value_type o_vt_f_pair2 = *oit2; + Cell_handle o_ch2 = o_vt_f_pair2.second.first; + int o_i2 = o_vt_f_pair2.second.second; + o_ch2->set_neighbor(o_i2,new_ch); + new_ch->set_neighbor(i, o_ch2); + outer_map.erase(oit2); + } + } + } + outer_map.erase(oit); + } + tds().delete_vertex(v); + tds().delete_cells(hole.begin(), hole.end()); + + return remover; +} + + +template < class Gt, class Tds > +template < class VertexRemover, class OutputItCells > +void +Triangulation_3:: +remove_and_give_new_cells(Vertex_handle v, VertexRemover &remover, + OutputItCells fit) { + CGAL_triangulation_precondition( v != Vertex_handle()); + CGAL_triangulation_precondition( !is_infinite(v)); + CGAL_triangulation_expensive_precondition( tds().is_vertex(v) ); + + if (test_dim_down (v)) { + remove_dim_down (v, remover, fit); + } + else { + switch (dimension()) { + case 1: remove_1D (v, remover, fit); break; + case 2: remove_2D (v, remover, fit); break; + case 3: remove_3D (v, remover, fit); break; + default: + CGAL_triangulation_assertion (false); + } + } +} + +// The VertexInserter is needed so as to +// allow us the usage of the insertion method +// from the particular triangulation +template +template < class VertexRemover, class VertexInserter > +typename Triangulation_3::Vertex_handle +Triangulation_3:: +move_if_no_collision(Vertex_handle v, const Point &p, + VertexRemover &remover, VertexInserter &inserter) { + CGAL_assertion(remover.hidden_points_begin() == + remover.hidden_points_end() ); + CGAL_triangulation_precondition(!is_infinite(v)); + if(v->point() == p) return v; + const int dim = dimension(); + + // If displacements are known to be small + // we might want to optimize by checking + // whether there is a topological change + // or not before. + // In this version this will not be put inside this method + // because it is for general purposes, + // and remaining Delaunay after motion is a bit too restrictive. + // In the filtered version optimized for displacements + // it will be used as an a priori. + // However, a non-fully optimized but good version of + // is_delaunay_after_displacement is provided as an internal method of + // Delaunay_triangulation_3 (see the class for more details). + + Locate_type lt; + int li, lj; + Cell_handle loc = locate(p, lt, li, lj, v->cell()); + + if(lt == VERTEX) return loc->vertex(li); + + if(dim == 0) { + v->set_point(p); + return v; + } + + int n_vertices = tds().number_of_vertices(); + + if((lt == OUTSIDE_AFFINE_HULL) && (dim == 1) && (n_vertices == 3)) { + v->set_point(p); + return v; + } + + if((lt == OUTSIDE_AFFINE_HULL) && (dim == 2) && (n_vertices == 4)) { + v->set_point(p); + return v; + } + + if((lt != OUTSIDE_AFFINE_HULL) && (dim == 1)) { + + if(loc->has_vertex(v)) { + v->set_point(p); + } else { + Vertex_handle inserted = insert(p, lt, loc, li, lj); + Cell_handle f = v->cell(); + int i = f->index(v); + if (i==0) {f = f->neighbor(1);} + CGAL_triangulation_assertion(f->index(v) == 1); + Cell_handle g= f->neighbor(0); + f->set_vertex(1, g->vertex(1)); + f->set_neighbor(0,g->neighbor(0)); + g->neighbor(0)->set_neighbor(1,f); + g->vertex(1)->set_cell(f); + tds().delete_cell(g); + Cell_handle f_ins = inserted->cell(); + i = f_ins->index(inserted); + if (i==0) {f_ins = f_ins->neighbor(1);} + CGAL_triangulation_assertion(f_ins->index(inserted) == 1); + Cell_handle g_ins = f_ins->neighbor(0); + f_ins->set_vertex(1, v); + g_ins->set_vertex(0, v); + v->set_point(p); + v->set_cell(inserted->cell()); + tds().delete_vertex(inserted); + } + return v; + } + + bool dim_down = test_dim_down(v); + + if((lt != OUTSIDE_AFFINE_HULL) && dim_down && (dim == 2)) { + // verify if p and two static vertices are collinear in this case + int iinf; + Cell_handle finf = infinite_vertex()->cell(), fdone; + fdone = finf; + do { + iinf = finf->index(infinite_vertex()); + if(!finf->has_vertex(v)) break; + finf = finf->neighbor((iinf+1)%3); + } while(finf != fdone); + iinf = ~iinf; + if(this->collinear(finf->vertex(iinf&1)->point(), + finf->vertex(iinf&2)->point(), + p)) + { + v->set_point(p); + _tds.decrease_dimension(loc, loc->index(v)); + return v; + } + } + + if(((dim == 2) && (lt != OUTSIDE_AFFINE_HULL)) || + ((lt == OUTSIDE_AFFINE_HULL) && (dim == 1))) + { + + // This is insert must be from Delaunay (or the particular trian.) + // not Triangulation_3 ! + Vertex_handle inserted = inserter.insert(p, lt, loc, li, lj); + + std::list hole; + make_hole_2D(v, hole, remover); + fill_hole_2D(hole, remover); + + // fixing pointer + Cell_handle fc = inserted->cell(), done(fc); + std::vector faces_pt; + faces_pt.reserve(16); + do { + faces_pt.push_back(fc); + fc = fc->neighbor((fc->index(inserted) + 1)%3); + } while(fc != done); + int ss = faces_pt.size(); + for(int k=0; kindex(inserted); + f->set_vertex(i, v); + } + v->set_point(p); + v->set_cell(inserted->cell()); + + tds().delete_vertex(inserted); + + return v; + } + + if((lt != OUTSIDE_AFFINE_HULL) && dim_down && (dim == 3)) { + // verify if p and two static vertices are collinear in this case + std::vector ics; + incident_cells(infinite_vertex(), std::back_inserter(ics)); + int size = ics.size(); + Cell_handle finf; + for (int i=0; ihas_vertex(v)) break; + } + int iinf = finf->index(infinite_vertex()); + if(remover.tmp.coplanar(finf->vertex((iinf+1)&3)->point(), + finf->vertex((iinf+2)&3)->point(), + finf->vertex((iinf+3)&3)->point(), + p)) + { + v->set_point(p); + _tds.decrease_dimension(loc, loc->index(v)); + Facet f = *finite_facets_begin(); + if (coplanar_orientation(f.first->vertex(0)->point(), + f.first->vertex(1)->point(), + f.first->vertex(2)->point()) == NEGATIVE) + tds().reorient(); + restore_edges_after_decrease_dimension(v, remover,inserter); + return v; + } + } + + // This is insert must be from Delaunay (or the particular trian.) + // not Triangulation_3 ! + Vertex_handle inserted = inserter.insert(p, lt, loc, li, lj); + + std::vector hole; + hole.reserve(64); + + // Construct the set of vertex triples on the boundary + // with the facet just behind + typedef std::map Vertex_triple_Facet_map; + Vertex_triple_Facet_map outer_map; + Vertex_triple_Facet_map inner_map; + + make_hole_3D(v, outer_map, hole); + + CGAL_assertion(remover.hidden_points_begin() == + remover.hidden_points_end() ); + + // Output the hidden points. + for (typename std::vector::iterator + hi = hole.begin(), hend = hole.end(); hi != hend; ++hi) + remover.add_hidden_points(*hi); + + bool inf = false; + unsigned int i; + // collect all vertices on the boundary + std::vector vertices; + vertices.reserve(64); + + adjacent_vertices(v, std::back_inserter(vertices)); + + // create a Delaunay triangulation of the points on the boundary + // and make a map from the vertices in remover.tmp towards the vertices + // in *this + + Unique_hash_map vmap; + Cell_handle ch = Cell_handle(); + for(i=0; i < vertices.size(); i++){ + if(! is_infinite(vertices[i])){ + Vertex_handle vh = remover.tmp.insert(vertices[i]->point(), ch); + ch = vh->cell(); + vmap[vh] = vertices[i]; + }else { + inf = true; + } + } + + if(remover.tmp.dimension()==2){ + Vertex_handle fake_inf = remover.tmp.insert(v->point()); + vmap[fake_inf] = infinite_vertex(); + } else { + vmap[remover.tmp.infinite_vertex()] = infinite_vertex(); + } + + CGAL_triangulation_assertion(remover.tmp.dimension() == 3); + + // Construct the set of vertex triples of remover.tmp + // We reorient the vertex triple so that it matches those from outer_map + // Also note that we use the vertices of *this, not of remover.tmp + + if(inf){ + for(All_cells_iterator it = remover.tmp.all_cells_begin(), + end = remover.tmp.all_cells_end(); it != end; ++it){ + for(i=0; i < 4; i++){ + Facet f = std::pair(it,i); + Vertex_triple vt_aux = make_vertex_triple(f); + Vertex_triple vt(vmap[vt_aux.first],vmap[vt_aux.third],vmap[vt_aux.second]); + make_canonical(vt); + inner_map[vt]= f; + } + } + } else { + for(Finite_cells_iterator it = remover.tmp.finite_cells_begin(), + end = remover.tmp.finite_cells_end(); it != end; ++it){ + for(i=0; i < 4; i++){ + Facet f = std::pair(it,i); + Vertex_triple vt_aux = make_vertex_triple(f); + Vertex_triple vt(vmap[vt_aux.first],vmap[vt_aux.third],vmap[vt_aux.second]); + make_canonical(vt); + inner_map[vt]= f; + } + } + } + // Grow inside the hole, by extending the surface + while(! outer_map.empty()){ + typename Vertex_triple_Facet_map::iterator oit = outer_map.begin(); + while(is_infinite(oit->first.first) || + is_infinite(oit->first.second) || + is_infinite(oit->first.third)){ + ++oit; + // otherwise the lookup in the inner_map fails + // because the infinite vertices are different + } + typename Vertex_triple_Facet_map::value_type o_vt_f_pair = *oit; + Cell_handle o_ch = o_vt_f_pair.second.first; + unsigned int o_i = o_vt_f_pair.second.second; + + typename Vertex_triple_Facet_map::iterator iit = + inner_map.find(o_vt_f_pair.first); + CGAL_triangulation_assertion(iit != inner_map.end()); + typename Vertex_triple_Facet_map::value_type i_vt_f_pair = *iit; + Cell_handle i_ch = i_vt_f_pair.second.first; + unsigned int i_i = i_vt_f_pair.second.second; + + // create a new cell and glue it to the outer surface + Cell_handle new_ch = tds().create_cell(); + + new_ch->set_vertices(vmap[i_ch->vertex(0)], vmap[i_ch->vertex(1)], + vmap[i_ch->vertex(2)], vmap[i_ch->vertex(3)]); + + o_ch->set_neighbor(o_i,new_ch); + new_ch->set_neighbor(i_i, o_ch); + + // for the other faces check, if they can also be glued + for(i = 0; i < 4; i++){ + if(i != i_i){ + Facet f = std::pair(new_ch,i); + Vertex_triple vt = make_vertex_triple(f); + make_canonical(vt); + std::swap(vt.second,vt.third); + typename Vertex_triple_Facet_map::iterator oit2 = outer_map.find(vt); + if(oit2 == outer_map.end()){ + std::swap(vt.second,vt.third); + outer_map[vt]= f; + } else { + // glue the faces + typename Vertex_triple_Facet_map::value_type o_vt_f_pair2 = *oit2; + Cell_handle o_ch2 = o_vt_f_pair2.second.first; + int o_i2 = o_vt_f_pair2.second.second; + o_ch2->set_neighbor(o_i2,new_ch); + new_ch->set_neighbor(i, o_ch2); + outer_map.erase(oit2); + } + } + } + outer_map.erase(oit); + } + + // fixing pointer + std::vector cells_pt; + cells_pt.reserve(64); + incident_cells(inserted, std::back_inserter(cells_pt)); + int size = cells_pt.size(); + for(int i=0; iset_vertex(c->index(inserted), v); + } + v->set_point(p); + v->set_cell(inserted->cell()); + tds().delete_vertex(inserted); + tds().delete_cells(hole.begin(), hole.end()); + return v; +} + +template +template < class VertexRemover, class VertexInserter > +typename Triangulation_3::Vertex_handle +Triangulation_3:: +move(Vertex_handle v, const Point &p, + VertexRemover &remover, VertexInserter &inserter) { + CGAL_assertion(remover.hidden_points_begin() == + remover.hidden_points_end() ); + CGAL_triangulation_precondition(!is_infinite(v)); + if(v->point() == p) return v; + Vertex_handle w = move_if_no_collision(v,p,remover,inserter); + if(w != v) { + remove(v, remover); + return w; + } + return v; +} + +// The VertexInserter is needed so as to +// allow us the usage of the insertion method +// from the particular triangulation +template +template < class VertexRemover, class VertexInserter, class OutputItCells > +typename Triangulation_3::Vertex_handle +Triangulation_3:: +move_if_no_collision_and_give_new_cells(Vertex_handle v, const Point &p, + VertexRemover &remover, VertexInserter &inserter, OutputItCells fit) { + CGAL_assertion(remover.hidden_points_begin() == + remover.hidden_points_end() ); + CGAL_triangulation_precondition(!is_infinite(v)); + if(v->point() == p) return v; + const int dim = dimension(); + + // If displacements are known to be small + // we might want to optimize by checking + // whether there is a topological change + // or not before. + // In this version this will not be put inside this method + // because it is for general purposes, + // and remaining Delaunay after motion is a bit too restrictive. + // In the filtered version optimized for displacements + // it will be used as an a priori. + // However, a non-fully optimized but good version of + // is_delaunay_after_displacement is provided as an internal method of + // Delaunay_triangulation_3 (see the class for more details). + + Locate_type lt; + int li, lj; + Cell_handle loc = locate(p, lt, li, lj, v->cell()); + + if(lt == VERTEX) return loc->vertex(li); + + if(dim == 0) { + v->set_point(p); + return v; + } + + int n_vertices = tds().number_of_vertices(); + + if((lt == OUTSIDE_AFFINE_HULL) && (dim == 1) && (n_vertices == 3)) { + v->set_point(p); + for(All_cells_iterator afi = tds().raw_cells_begin(); + afi != tds().raw_cells_end(); + afi++) *fit++ = afi; + return v; + } + + if((lt == OUTSIDE_AFFINE_HULL) && (dim == 2) && (n_vertices == 4)) { + v->set_point(p); + for(All_cells_iterator afi = tds().raw_cells_begin(); + afi != tds().raw_cells_end(); + afi++) *fit++ = afi; + return v; + } + + if((lt != OUTSIDE_AFFINE_HULL) && (dim == 1)) { + if(loc->has_vertex(v)) { + v->set_point(p); + } else { + Vertex_handle inserted = insert(p, lt, loc, li, lj); + Cell_handle f = v->cell(); + int i = f->index(v); + if (i==0) {f = f->neighbor(1);} + CGAL_triangulation_assertion(f->index(v) == 1); + Cell_handle g= f->neighbor(0); + f->set_vertex(1, g->vertex(1)); + f->set_neighbor(0,g->neighbor(0)); + g->neighbor(0)->set_neighbor(1,f); + g->vertex(1)->set_cell(f); + tds().delete_cell(g); + *fit++ = f; + Cell_handle f_ins = inserted->cell(); + i = f_ins->index(inserted); + if (i==0) {f_ins = f_ins->neighbor(1);} + CGAL_triangulation_assertion(f_ins->index(inserted) == 1); + Cell_handle g_ins = f_ins->neighbor(0); + f_ins->set_vertex(1, v); + g_ins->set_vertex(0, v); + v->set_point(p); + v->set_cell(inserted->cell()); + tds().delete_vertex(inserted); + } + *fit++ = v->cell(); + if(v->cell()->neighbor(0)->has_vertex(v)) + *fit++ = v->cell()->neighbor(0); + if(v->cell()->neighbor(1)->has_vertex(v)) + *fit++ = v->cell()->neighbor(1); + return v; + } + + bool dim_down = test_dim_down(v); + + if((lt != OUTSIDE_AFFINE_HULL) && dim_down && (dim == 2)) { + // verify if p and two static vertices are collinear in this case + int iinf; + Cell_handle finf = infinite_vertex()->cell(), fdone; + fdone = finf; + do { + iinf = finf->index(infinite_vertex()); + if(!finf->has_vertex(v)) break; + finf = finf->neighbor((iinf+1)%3); + } while(finf != fdone); + iinf = ~iinf; + if(this->collinear(finf->vertex(iinf&1)->point(), + finf->vertex(iinf&2)->point(), + p)) + { + v->set_point(p); + _tds.decrease_dimension(loc, loc->index(v)); + for(All_cells_iterator afi = tds().raw_cells_begin(); + afi != tds().raw_cells_end(); + afi++) *fit++ = afi; + return v; + } + } + + if(((dim == 2) && (lt != OUTSIDE_AFFINE_HULL)) || + ((lt == OUTSIDE_AFFINE_HULL) && (dim == 1))) + { + + std::set cells_set; + // This is insert must be from Delaunay (or the particular trian.) + // not Triangulation_3 ! + Vertex_handle inserted = inserter.insert(p, lt, loc, li, lj); + Cell_handle c = inserted->cell(), end = c; + do { + cells_set.insert(c); + int i = c->index(inserted); + c = c->neighbor((i+1)%3); + } while(c != end); + + std::list hole; + make_hole_2D(v, hole, remover, cells_set); + fill_hole_2D(hole, remover, fit); + + // fixing pointer + Cell_handle fc = inserted->cell(), done(fc); + std::vector faces_pt; + faces_pt.reserve(16); + do { + faces_pt.push_back(fc); + fc = fc->neighbor((fc->index(inserted) + 1)%3); + } while(fc != done); + int ss = faces_pt.size(); + for(int k=0; kindex(inserted); + f->set_vertex(i, v); + } + v->set_point(p); + v->set_cell(inserted->cell()); + + tds().delete_vertex(inserted); + + for(typename std::set::const_iterator ib = cells_set.begin(), + iend = cells_set.end(); ib != iend; ib++) *fit++ = *ib; + + return v; + } + + if((lt != OUTSIDE_AFFINE_HULL) && dim_down && (dim == 3)) { + // verify if p and two static vertices are collinear in this case + std::vector ics; + incident_cells(infinite_vertex(), std::back_inserter(ics)); + int size = ics.size(); + Cell_handle finf; + for (int i=0; ihas_vertex(v)) break; + } + int iinf = finf->index(infinite_vertex()); + if(remover.tmp.coplanar(finf->vertex((iinf+1)&3)->point(), + finf->vertex((iinf+2)&3)->point(), + finf->vertex((iinf+3)&3)->point(), + p)) + { + v->set_point(p); + _tds.decrease_dimension(loc, loc->index(v)); + Facet f = *finite_facets_begin(); + if (coplanar_orientation(f.first->vertex(0)->point(), + f.first->vertex(1)->point(), + f.first->vertex(2)->point()) == NEGATIVE) + tds().reorient(); + restore_edges_after_decrease_dimension(v, remover,inserter); + for(All_cells_iterator afi = tds().raw_cells_begin(); + afi != tds().raw_cells_end(); + afi++) *fit++ = afi; + return v; + } + } + + std::set cells_set; + + // This is insert must be from Delaunay (or the particular trian.) + // not Triangulation_3 ! + Vertex_handle inserted = inserter.insert(p, lt, loc, li, lj); + + std::vector cells_tmp; + cells_tmp.reserve(64); + incident_cells(inserted, std::back_inserter(cells_tmp)); + int size = cells_tmp.size(); + for(int i=0; i hole; + hole.reserve(64); + + // Construct the set of vertex triples on the boundary + // with the facet just behind + typedef std::map Vertex_triple_Facet_map; + Vertex_triple_Facet_map outer_map; + Vertex_triple_Facet_map inner_map; + + make_hole_3D(v, outer_map, hole); + + for(typename std::vector::const_iterator ib = hole.begin(), + iend = hole.end(); ib != iend; ib++) cells_set.erase(*ib); + + CGAL_assertion(remover.hidden_points_begin() == + remover.hidden_points_end() ); + + // Output the hidden points. + for (typename std::vector::iterator + hi = hole.begin(), hend = hole.end(); hi != hend; ++hi) + remover.add_hidden_points(*hi); + + bool inf = false; + unsigned int i; + // collect all vertices on the boundary + std::vector vertices; + vertices.reserve(64); + + adjacent_vertices(v, std::back_inserter(vertices)); + + // create a Delaunay triangulation of the points on the boundary + // and make a map from the vertices in remover.tmp towards the vertices + // in *this + + Unique_hash_map vmap; + Cell_handle ch = Cell_handle(); + for(i=0; i < vertices.size(); i++){ + if(! is_infinite(vertices[i])){ + Vertex_handle vh = remover.tmp.insert(vertices[i]->point(), ch); + ch = vh->cell(); + vmap[vh] = vertices[i]; + }else { + inf = true; + } + } + + if(remover.tmp.dimension()==2){ + Vertex_handle fake_inf = remover.tmp.insert(v->point()); + vmap[fake_inf] = infinite_vertex(); + } else { + vmap[remover.tmp.infinite_vertex()] = infinite_vertex(); + } + + CGAL_triangulation_assertion(remover.tmp.dimension() == 3); + + // Construct the set of vertex triples of remover.tmp + // We reorient the vertex triple so that it matches those from outer_map + // Also note that we use the vertices of *this, not of remover.tmp + + if(inf){ + for(All_cells_iterator it = remover.tmp.all_cells_begin(), + end = remover.tmp.all_cells_end(); it != end; ++it){ + for(i=0; i < 4; i++){ + Facet f = std::pair(it,i); + Vertex_triple vt_aux = make_vertex_triple(f); + Vertex_triple vt(vmap[vt_aux.first],vmap[vt_aux.third],vmap[vt_aux.second]); + make_canonical(vt); + inner_map[vt]= f; + } + } + } else { + for(Finite_cells_iterator it = remover.tmp.finite_cells_begin(), + end = remover.tmp.finite_cells_end(); it != end; ++it){ + for(i=0; i < 4; i++){ + Facet f = std::pair(it,i); + Vertex_triple vt_aux = make_vertex_triple(f); + Vertex_triple vt(vmap[vt_aux.first],vmap[vt_aux.third],vmap[vt_aux.second]); + make_canonical(vt); + inner_map[vt]= f; + } + } + } + // Grow inside the hole, by extending the surface + while(! outer_map.empty()){ + typename Vertex_triple_Facet_map::iterator oit = outer_map.begin(); + while(is_infinite(oit->first.first) || + is_infinite(oit->first.second) || + is_infinite(oit->first.third)){ + ++oit; + // otherwise the lookup in the inner_map fails + // because the infinite vertices are different + } + typename Vertex_triple_Facet_map::value_type o_vt_f_pair = *oit; + Cell_handle o_ch = o_vt_f_pair.second.first; + unsigned int o_i = o_vt_f_pair.second.second; + + typename Vertex_triple_Facet_map::iterator iit = + inner_map.find(o_vt_f_pair.first); + CGAL_triangulation_assertion(iit != inner_map.end()); + typename Vertex_triple_Facet_map::value_type i_vt_f_pair = *iit; + Cell_handle i_ch = i_vt_f_pair.second.first; + unsigned int i_i = i_vt_f_pair.second.second; + + // create a new cell and glue it to the outer surface + Cell_handle new_ch = tds().create_cell(); + *fit++ = new_ch; + + new_ch->set_vertices(vmap[i_ch->vertex(0)], vmap[i_ch->vertex(1)], + vmap[i_ch->vertex(2)], vmap[i_ch->vertex(3)]); + + o_ch->set_neighbor(o_i,new_ch); + new_ch->set_neighbor(i_i, o_ch); + + // for the other faces check, if they can also be glued + for(i = 0; i < 4; i++){ + if(i != i_i){ + Facet f = std::pair(new_ch,i); + Vertex_triple vt = make_vertex_triple(f); + make_canonical(vt); + std::swap(vt.second,vt.third); + typename Vertex_triple_Facet_map::iterator oit2 = outer_map.find(vt); + if(oit2 == outer_map.end()){ + std::swap(vt.second,vt.third); + outer_map[vt]= f; + } else { + // glue the faces + typename Vertex_triple_Facet_map::value_type o_vt_f_pair2 = *oit2; + Cell_handle o_ch2 = o_vt_f_pair2.second.first; + int o_i2 = o_vt_f_pair2.second.second; + o_ch2->set_neighbor(o_i2,new_ch); + new_ch->set_neighbor(i, o_ch2); + outer_map.erase(oit2); + } + } + } + outer_map.erase(oit); + } + + // fixing pointer + std::vector cells_pt; + cells_pt.reserve(64); + incident_cells(inserted, std::back_inserter(cells_pt)); + size = cells_pt.size(); + for(int i=0; iset_vertex(c->index(inserted), v); + } + v->set_point(p); + v->set_cell(inserted->cell()); + tds().delete_vertex(inserted); + tds().delete_cells(hole.begin(), hole.end()); + + for(typename std::set::const_iterator ib = cells_set.begin(), + iend = cells_set.end(); ib != iend; ib++) *fit++ = *ib; + return v; +} + template < class GT, class Tds > bool Triangulation_3:: diff --git a/Triangulation_3/include/CGAL/Triangulation_data_structure_3.h b/Triangulation_3/include/CGAL/Triangulation_data_structure_3.h index 511be5fe965..e940480265d 100644 --- a/Triangulation_3/include/CGAL/Triangulation_data_structure_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_data_structure_3.h @@ -446,6 +446,7 @@ public: remove_decrease_dimension (v, v); } void remove_decrease_dimension(Vertex_handle v, Vertex_handle w); + void decrease_dimension(Cell_handle f, int i); // Change orientation of the whole TDS. void reorient() @@ -2538,6 +2539,145 @@ remove_degree_4(Vertex_handle v) return newc; } +template +void +Triangulation_data_structure_3:: +decrease_dimension(Cell_handle c, int i) +{ + CGAL_triangulation_expensive_precondition( is_valid() );; + CGAL_triangulation_precondition( dimension() >= 2); + CGAL_triangulation_precondition( number_of_vertices() > + (size_type) dimension() + 1 ); + CGAL_triangulation_precondition( degree(c->vertex(i)) == number_of_vertices()-1 ); + + Vertex_handle v = c->vertex(i); + Vertex_handle w = c->vertex(i); + + // the cells incident to w are down graded one dimension + // the other cells are deleted + std::vector to_delete, to_downgrade; + + for (Cell_iterator ib = cells().begin(); + ib != cells().end(); ++ib) { + if ( ib->has_vertex(w) ) + to_downgrade.push_back(ib); + else + to_delete.push_back(ib); + } + + typename std::vector::iterator lfit=to_downgrade.begin(); + for( ; lfit != to_downgrade.end(); ++lfit) { + Cell_handle f = *lfit; + int j = f->index(w); + int k; + if (f->has_vertex(v, k)) f->set_vertex(k, w); + if (j != dimension()) { + f->set_vertex(j, f->vertex(dimension())); + f->set_neighbor(j, f->neighbor(dimension())); + if (dimension() >= 1) + change_orientation(f); + } + f->set_vertex(dimension(), Vertex_handle()); + f->set_neighbor(dimension(), Cell_handle()); + + // Update vertex->cell() pointers. + for (int i = 0; i < dimension(); ++i) + f->vertex(i)->set_cell(f); + } + + delete_cells(to_delete.begin(), to_delete.end()); + + //delete_vertex(v); + set_dimension(dimension()-1); + + if(dimension() == 2) + { + Cell_handle n0 = c->neighbor(0); + Cell_handle n1 = c->neighbor(1); + Cell_handle n2 = c->neighbor(2); + Vertex_handle v0 = c->vertex(0); + Vertex_handle v1 = c->vertex(1); + Vertex_handle v2 = c->vertex(2); + + int i0 = 0, i1 = 0, i2 = 0; + + for(int i=0; i<3; i++) if(n0->neighbor(i) == c) { i0 = i; break; } + for(int i=0; i<3; i++) if(n1->neighbor(i) == c) { i1 = i; break; } + for(int i=0; i<3; i++) if(n2->neighbor(i) == c) { i2 = i; break; } + + Cell_handle c1 = create_cell(v, v0, v1, Vertex_handle()); + Cell_handle c2 = create_cell(v, v1, v2, Vertex_handle()); + + c->set_vertex(0, v); + c->set_vertex(1, v2); + c->set_vertex(2, v0); + c->set_vertex(3, Vertex_handle()); + + //Cell_handle c3 = create_cell(v, v2, v0, Vertex_handle()); + Cell_handle c3 = c; + + c1->set_neighbor(0, n2); n2->set_neighbor(i2, c1); + c1->set_neighbor(1, c2); + c1->set_neighbor(2, c3); + c1->set_neighbor(3, Cell_handle()); + + c2->set_neighbor(0, n0); n0->set_neighbor(i0, c2); + c2->set_neighbor(1, c3); + c2->set_neighbor(2, c1); + c2->set_neighbor(3, Cell_handle()); + + c3->set_neighbor(0, n1); n1->set_neighbor(i1, c3); + c3->set_neighbor(1, c1); + c3->set_neighbor(2, c2); + c3->set_neighbor(3, Cell_handle()); + + v->set_cell(c1); + v0->set_cell(c1); + v1->set_cell(c1); + v2->set_cell(c2); + } + + if(dimension() == 1) + { + Cell_handle n0 = c->neighbor(0); + Cell_handle n1 = c->neighbor(1); + Vertex_handle v0 = c->vertex(0); + Vertex_handle v1 = c->vertex(1); + + int i0 = 0 , i1 = 0; + + for(int i=0; i<2; i++) if(n0->neighbor(i) == c) { i0 = i; break; } + for(int i=0; i<2; i++) if(n1->neighbor(i) == c) { i1 = i; break; } + + Cell_handle c1 = create_cell(v0, v, Vertex_handle(), Vertex_handle()); + + c->set_vertex(0, v); + c->set_vertex(1, v1); + c->set_vertex(2, Vertex_handle()); + c->set_vertex(3, Vertex_handle()); + + //Cell_handle c2 = create_cell(v, v1, Vertex_handle(), Vertex_handle()); + Cell_handle c2 = c; + + c1->set_neighbor(0, c2); + c1->set_neighbor(1, n1); n1->set_neighbor(i1, c1); + c1->set_neighbor(2, Cell_handle()); + c1->set_neighbor(3, Cell_handle()); + + c2->set_neighbor(0, n0); n0->set_neighbor(i0, c2); + c2->set_neighbor(1, c1); + c2->set_neighbor(2, Cell_handle()); + c2->set_neighbor(3, Cell_handle()); + + v->set_cell(c1); + v0->set_cell(c1); + v1->set_cell(c2); + } + + CGAL_triangulation_postcondition(is_valid()); +} + + template typename Triangulation_data_structure_3::size_type Triangulation_data_structure_3:: @@ -2556,19 +2696,27 @@ is_valid(bool verbose, int level ) const switch ( dimension() ) { case 3: { + + if(number_of_vertices() <= 4) { + if (verbose) + std::cerr << "wrong number of vertices" << std::endl; + CGAL_triangulation_assertion(false); + return false; + } + size_type vertex_count; if ( ! count_vertices(vertex_count,verbose,level) ) - return false; + return false; if ( number_of_vertices() != vertex_count ) { if (verbose) - std::cerr << "wrong number of vertices" << std::endl; + std::cerr << "wrong number of vertices" << std::endl; CGAL_triangulation_assertion(false); return false; } size_type cell_count; if ( ! count_cells(cell_count,verbose,level) ) - return false; + return false; size_type edge_count; if ( ! count_edges(edge_count,verbose,level) ) return false; @@ -2588,9 +2736,18 @@ is_valid(bool verbose, int level ) const } case 2: { + + if(number_of_vertices() <= 3) { + if (verbose) + std::cerr << "wrong number of vertices" << std::endl; + CGAL_triangulation_assertion(false); + return false; + } + size_type vertex_count; + if ( ! count_vertices(vertex_count,verbose,level) ) - return false; + return false; if ( number_of_vertices() != vertex_count ) { if (verbose) std::cerr << "false number of vertices" << std::endl; @@ -2625,6 +2782,14 @@ is_valid(bool verbose, int level ) const } case 1: { + + if(number_of_vertices() <= 1) { + if (verbose) + std::cerr << "wrong number of vertices" << std::endl; + CGAL_triangulation_assertion(false); + return false; + } + size_type vertex_count; if ( ! count_vertices(vertex_count,verbose,level) ) return false; diff --git a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h index fee91b6435b..fb830ea56da 100644 --- a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h @@ -167,7 +167,48 @@ public: return n - number_of_vertices(); } - Vertex_handle move_point(Vertex_handle v, const Point & p); +#ifndef CGAL_NO_DEPRECATED_CODE + CGAL_DEPRECATED Vertex_handle move_point(Vertex_handle v, const Point & p); +#endif + + Vertex_handle move_if_no_collision(Vertex_handle v, const Point &p); + Vertex_handle move(Vertex_handle v, const Point &p); + +public: // some internal methods + + // INSERT REMOVE DISPLACEMENT + // GIVING NEW FACES + + template + Vertex_handle insert_and_give_new_cells(const Point &p, + OutputItCells fit, + Cell_handle start = Cell_handle() ); + + template + Vertex_handle insert_and_give_new_cells(const Point& p, + OutputItCells fit, + Vertex_handle hint) + { + return insert_and_give_new_cells(p, hint == Vertex_handle() ? + this->infinite_cell() : hint->cell()); + } + + template + Vertex_handle insert_and_give_new_cells(const Point& p, + Locate_type lt, + Cell_handle c, int li, int lj, + OutputItCells fit); + + template + void remove_and_give_new_cells(Vertex_handle v, + OutputItCells fit); + + template + Vertex_handle move_if_no_collision_and_give_new_cells(Vertex_handle v, + const Point &p, OutputItCells fit); + +public: + //LOCATE Cell_handle locate(const Point& p, Locate_type& lt, int& li, int& lj, @@ -343,6 +384,44 @@ insert(const Point &p, Cell_handle start) return first; } +template +template +typename Triangulation_hierarchy_3::Vertex_handle +Triangulation_hierarchy_3:: +insert_and_give_new_cells(const Point &p, OutputItCells fit, Cell_handle start) +{ + int vertex_level = random_level(); + Locate_type lt; + int i, j; + // locate using hierarchy + locs positions[maxlevel]; + locate(p, lt, i, j, positions, start); + // insert at level 0 + Vertex_handle vertex = hierarchy[0]->insert_and_give_new_cells(p, + positions[0].lt, + positions[0].pos, + positions[0].li, + positions[0].lj,fit); + Vertex_handle previous = vertex; + Vertex_handle first = vertex; + + int level = 1; + while (level <= vertex_level ){ + if (positions[level].pos == Cell_handle()) + vertex = hierarchy[level]->insert(p); + else + vertex = hierarchy[level]->insert(p, + positions[level].lt, + positions[level].pos, + positions[level].li, + positions[level].lj); + set_up_down(vertex, previous); + previous=vertex; + level++; + } + return first; +} + template typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: @@ -379,6 +458,45 @@ insert(const Point &p, Locate_type lt, Cell_handle loc, int li, int lj) return first; } +template +template +typename Triangulation_hierarchy_3::Vertex_handle +Triangulation_hierarchy_3:: +insert_and_give_new_cells(const Point &p, Locate_type lt, Cell_handle loc, + int li, int lj, OutputItCells fit) +{ + int vertex_level = random_level(); + // insert at level 0 + Vertex_handle vertex = + hierarchy[0]->insert_and_give_new_cells(p,lt,loc,li,lj,fit); + Vertex_handle previous = vertex; + Vertex_handle first = vertex; + + if (vertex_level > 0) { + Locate_type lt; + int i, j; + // locate using hierarchy + locs positions[maxlevel]; + locate(p, lt, i, j, positions, vertex->cell()); + + int level = 1; + while (level <= vertex_level ){ + if (positions[level].pos == Cell_handle()) + vertex = hierarchy[level]->insert(p); + else + vertex = hierarchy[level]->insert(p, + positions[level].lt, + positions[level].pos, + positions[level].li, + positions[level].lj); + set_up_down(vertex, previous); + previous=vertex; + level++; + } + } + return first; +} + template void Triangulation_hierarchy_3:: @@ -394,6 +512,25 @@ remove(Vertex_handle v) } } +template +template +void +Triangulation_hierarchy_3:: +remove_and_give_new_cells(Vertex_handle v, OutputItCells fit) +{ + CGAL_triangulation_precondition(v != Vertex_handle()); + CGAL_triangulation_precondition(!is_infinite(v)); + for (int l = 0; l < maxlevel; ++l) { + Vertex_handle u = v->up(); + if(l) hierarchy[l]->remove(v); + else hierarchy[l]->remove_and_give_new_cells(v, fit); + if (u == Vertex_handle()) + break; + v = u; + } +} + +#ifndef CGAL_NO_DEPRECATED_CODE template < class Tr > typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: @@ -419,6 +556,65 @@ move_point(Vertex_handle v, const Point & p) return ret; } +#endif + +template +typename Triangulation_hierarchy_3::Vertex_handle +Triangulation_hierarchy_3:: +move_if_no_collision(Vertex_handle v, const Point & p) +{ + CGAL_triangulation_precondition(!is_infinite(v)); + if(v->point() == p) return v; + Vertex_handle ans; + for (int l = 0; l < maxlevel; ++l) { + Vertex_handle u = v->up(); + if(l) hierarchy[l]->move_if_no_collision(v, p); + else ans = hierarchy[l]->move_if_no_collision(v, p); + if(ans != v) return ans; + if (u == Vertex_handle()) + break; + v = u; + } + return ans; +} + +template +typename Triangulation_hierarchy_3::Vertex_handle +Triangulation_hierarchy_3:: +move(Vertex_handle v, const Point & p) +{ + CGAL_triangulation_precondition(!is_infinite(v)); + if(v->point() == p) return v; + Vertex_handle w = move_if_no_collision(v,p); + if(w != v) { + remove(v); + return w; + } + return v; +} + +template +template +typename Triangulation_hierarchy_3::Vertex_handle +Triangulation_hierarchy_3:: +move_if_no_collision_and_give_new_cells( + Vertex_handle v, const Point & p, OutputItCells fit) +{ + CGAL_triangulation_precondition(!is_infinite(v)); + if(v->point() == p) return v; + Vertex_handle ans; + for (int l = 0; l < maxlevel; ++l) { + Vertex_handle u = v->up(); + if(l) hierarchy[l]->move_if_no_collision(v, p); + else ans = + hierarchy[l]->move_if_no_collision_and_give_new_cells(v, p, fit); + if(ans != v) return ans; + if (u == Vertex_handle()) + break; + v = u; + } + return ans; +} template inline diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h index eabb22b77a0..a21b63099b3 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h @@ -587,6 +587,7 @@ _test_cls_delaunay_3(const Triangulation &) assert(T3_13.number_of_vertices()==22); assert(T3_13.dimension()==3); +#ifndef CGAL_NO_DEPRECATED_CODE { std::cout << " Testing move_point()" << std::endl; Cls T; @@ -611,6 +612,32 @@ _test_cls_delaunay_3(const Triangulation &) assert(T.number_of_vertices()<=22); } } +#endif + + { + std::cout << " Testing move()" << std::endl; + Cls T; + std::list L; + for (i=0; i<22; ++i) + L.push_back(T.insert(q[i])); + assert(T.is_valid()); + assert(T.number_of_vertices()==22); + assert(T.dimension()==3); + + for (i=0; i<100; ++i) { + assert(!L.empty()); + Vertex_handle v = L.front(); + L.pop_front(); + size_type nbv = T.number_of_vertices(); + L.push_back(T.move(v, q[(3*i)%22])); + + if (nbv != T.number_of_vertices()) + L.pop_back(); // it means we move onto an already existing point. + + assert(T.is_valid()); + assert(T.number_of_vertices()<=22); + } + } { std::cout << " Testing nearest_vertex()" << std::endl; @@ -896,6 +923,261 @@ _test_cls_delaunay_3(const Triangulation &) assert(ita->vertex(3)->point() == itb->vertex(3)->point()); } } + + /**********************/ + /******* MOVE *********/ + std::cout << " displacements" << std::endl; + + std::cout << " degenerate cases: " << std::endl; + + Cls TM_0; + Vertex_handle tmv1 = TM_0.insert(Point(0,0,0)); + Vertex_handle tmv2 = TM_0.insert(Point(0,1,0)); + + TM_0.move_if_no_collision(tmv1, Point(0, 2, 1)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 1); + + TM_0.move_if_no_collision(tmv1, Point(0, 0, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 1); + + Vertex_handle tmv3 = TM_0.insert(Point(0,2,1)); + + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv3, Point(0, 2, 2)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv3, Point(0, 2, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 1); + + Vertex_handle tmv4 = TM_0.insert(Point(0,1,1)); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv3, Point(1, 1, 1)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 3); + + TM_0.move_if_no_collision(tmv3, Point(4, 2, 1)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 3); + + TM_0.move_if_no_collision(tmv3, Point(0, 2, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv4, Point(0, 2, 1)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv4, Point(0, 2, -1)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv4, Point(0, 3, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 1); + + TM_0.move_if_no_collision(tmv3, Point(0, 1, 1)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv3, Point(0, -1, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 1); + + TM_0.move_if_no_collision(tmv2, Point(0, -1, 0, 2)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 1); + + TM_0.move_if_no_collision(tmv2, Point(0, -1, 0, 4)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 1); + + TM_0.move_if_no_collision(tmv2, Point(0, -1, 0, 2)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 1); + + TM_0.move_if_no_collision(tmv2, Point(0, -1, 1, 2)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv1, Point(0, 0, 2)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv1, Point(0, 0, 1)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv1, Point(0, 0, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + assert(TM_0.move_if_no_collision(tmv1, Point(0, 3, 0)) != tmv1); + + TM_0.move_if_no_collision(tmv1, Point(0, 0, 1)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv4, Point(0, 1, 2)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 1); + + TM_0.move_if_no_collision(tmv4, Point(0, 3, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv1, Point(0, 2, 3)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv4, Point(0, 1, 2)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 1); + + Vertex_handle tmv5 = TM_0.insert(Point(0,2,0)); + Vertex_handle tmv6 = TM_0.insert(Point(1,0,0)); + assert(TM_0.dimension() == 3); + + TM_0.move_if_no_collision(tmv6, Point(0, 0, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv6, Point(2, 0, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 3); + + TM_0.move_if_no_collision(tmv6, Point(2, 1, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 3); + + TM_0.move_if_no_collision(tmv6, Point(0, 99, 99)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv6, Point(2, 1, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 3); + + TM_0.move_if_no_collision(tmv6, Point(2, 2, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 3); + + TM_0.move_if_no_collision(tmv6, Point(-2, 2, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 3); + + TM_0.move_if_no_collision(tmv6, Point(0, 1, 1)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 2); + + TM_0.move_if_no_collision(tmv6, Point(-2, 2, 0)); + assert(TM_0.tds().is_valid()); + assert(TM_0.is_valid()); + assert(TM_0.dimension() == 3); + + std::cout << " random 1D: " << std::endl; + Cls TM_1; + // non-degenerate cases + std::list points; + for(int count=0; count<50; count++) { + points.push_back(Point(0, 0, rand()%30000)); + } + TM_1.insert(points.begin(), points.end()); + Vertex_handle vTM_1; + for(int i=0; i<2; i++) { + for(typename Cls::Finite_vertices_iterator + fvi = TM_1.finite_vertices_begin(); + fvi != TM_1.finite_vertices_end(); fvi++) { + Point p = Point(0, 0, rand()%30000); + vTM_1 = TM_1.move_if_no_collision(fvi, p); + assert(TM_1.is_valid()); + } + } + assert(TM_1.is_valid()); + + std::cout << " random 2D: " << std::endl; + Cls TM_2; + // non-degenerate cases + points.clear(); TM_2.clear(); + for(int count=0; count<10; count++) { + points.push_back(Point(0, rand()%30000, rand()%30000)); + } + TM_2.insert(points.begin(), points.end()); + Vertex_handle vTM_2; + for(int i=0; i<2; i++) { + for(typename Cls::Finite_vertices_iterator + fvi = TM_2.finite_vertices_begin(); + fvi != TM_2.finite_vertices_end(); fvi++) { + Point p = Point(0, rand()%30000, rand()%30000); + vTM_2 = TM_2.move_if_no_collision(fvi, p); + assert(TM_2.is_valid()); + } + } + assert(TM_2.is_valid()); + + std::cout << " random 3D: " << std::endl; + Cls TM_3; + // non-degenerate cases + points.clear(); TM_3.clear(); + for(int count=0; count<50; count++) { + points.push_back(Point(rand()%30000, rand()%30000, rand()%30000)); + } + TM_3.insert(points.begin(), points.end()); + + assert(TM_3.is_valid()); + + Vertex_handle vTM_3; + for(int i=0; i<2; i++) { + for(typename Cls::Finite_vertices_iterator + fvi = TM_3.finite_vertices_begin(); + fvi != TM_3.finite_vertices_end(); fvi++) { + Point p = Point(rand()%30000, rand()%30000, rand()%30000); + vTM_3 = TM_3.move_if_no_collision(fvi, p); + assert(TM_3.is_valid()); + } + } + + // A simple test to see if move return the good vertex + // when there is a collision + assert(TM_3.move(TM_3.finite_vertices_begin(), vTM_3->point()) == vTM_3); + } #endif // CGAL_TEST_CLS_DELAUNAY_C diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_tds_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_tds_3.h index d0649be43a9..21a2663f2e9 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_tds_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_tds_3.h @@ -266,6 +266,56 @@ _test_cls_tds_3( const Tds &) assert(tds5.is_valid()); assert(tds6.is_valid()); + std::cout << " test decrease dimension" << std::endl; + Tds tds7; + Vertex_handle v7_0 = tds7.insert_increase_dimension(); + Vertex_handle v7_1 = tds7.insert_increase_dimension(v7_0); + Vertex_handle v7_2 = tds7.insert_increase_dimension(v7_1); + Vertex_handle v7_3 = tds7.insert_increase_dimension(v7_2); + Cell_handle fa = v7_3->cell(); + int i7 = fa->index(v7_3); + tds7.decrease_dimension(fa, i7); + assert(tds7.dimension() == 1); + assert(tds7.is_valid()); + Vertex_handle v7_4 = tds7.insert_increase_dimension(v7_3); + Cell_handle fb = v7_4->cell(); + i7 = fb->index(v7_4); + tds7.decrease_dimension(fb, i7); + assert(tds7.dimension() == 1); + assert(tds7.is_valid()); + Vertex_handle v7_5 = tds7.insert_increase_dimension(v7_4); + assert(tds7.dimension() == 2); + assert(tds7.is_valid()); + Vertex_handle v7_6 = tds7.insert_increase_dimension(v7_5); + assert(tds7.dimension() == 3); + assert(tds7.is_valid()); + Cell_handle fc = v7_6->cell(); + i7 = fc->index(v7_6); + tds7.decrease_dimension(fc, i7); + assert(tds7.dimension() == 2); + assert(tds7.is_valid()); + Vertex_handle v7_7 = tds7.insert_increase_dimension(v7_6); + assert(tds7.dimension() == 3); + assert(tds7.is_valid()); + Cell_handle fd = v7_7->cell(); + i7 = fd->index(v7_7); + tds7.decrease_dimension(fd, i7); + assert(tds7.dimension() == 2); + assert(tds7.is_valid()); + Cell_handle fe = v7_7->cell(); + i7 = fe->index(v7_7); + tds7.insert_in_facet(fe, i7); + assert(tds7.dimension() == 2); + assert(tds7.is_valid()); + Vertex_handle v7_8 = tds7.insert_increase_dimension(v7_7); + assert(tds7.dimension() == 3); + assert(tds7.is_valid()); + Cell_handle ff = v7_8->cell(); + i7 = ff->index(v7_8); + tds7.decrease_dimension(ff, i7); + assert(tds7.dimension() == 2); + assert(tds7.is_valid()); + // tds1.clear(); // tds2.clear(); // tds3.clear(); diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h index 9dba28eb2d4..750a131ea3a 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h @@ -604,6 +604,112 @@ _test_cls_triangulation_3(const Triangulation &) assert(T3_3.is_valid()); assert(T3_3.dimension()==3); + // ################## Operations + newly created cells ################ + // Small test for inserting and returning the newly created cells + // (the code is mainly the usual insert + incident_{edges,facets,cells} + // depending on the dimension) + + std::cout << " Test insertion + newly created cells: " << std::endl; + + std::cout << " 1 dimension" << std::endl; + // dimension 1 + Cls TAI1; + for(int i=0; i<50; i++) + { + double x = (double) (2*i); + TAI1.insert(Point(x, x, x)); + } + std::list lis_tai1; + for(int i=0; i<51; i++) + { + lis_tai1.clear(); + double x = (double) (2*i - 1); + Vertex_handle taiv = + TAI1.insert_and_give_new_cells( + Point(x, x, x), + std::back_inserter(lis_tai1)); + assert(TAI1.is_valid()); + assert(TAI1.dimension() == 1); + assert(lis_tai1.size() == 2); + while(!lis_tai1.empty()) + { + Cell_handle c = lis_tai1.front(); + lis_tai1.pop_front(); + assert(TAI1.tds().is_simplex(c)); + } + } + TAI1.clear(); + + std::cout << " 2 dimensions" << std::endl; + CGAL::Random grand; + for(int i=0; i<50; i++) + { + double x = grand.get_double(); + double y = grand.get_double(); + TAI1.insert(Point(x, y, 0)); + } + for(int i=0; i<50; i++) + { + lis_tai1.clear(); + double x = grand.get_double(); + double y = grand.get_double(); + Vertex_handle taiv = + TAI1.insert_and_give_new_cells( + Point(x, y, 0), + std::back_inserter(lis_tai1)); + assert(TAI1.is_valid()); + assert(TAI1.dimension() == 2); + while(!lis_tai1.empty()) + { + Cell_handle c = lis_tai1.front(); + lis_tai1.pop_front(); + assert(TAI1.tds().is_simplex(c)); + } + } + TAI1.clear(); + + std::cout << " 3 dimensions" << std::endl; + for(int i=0; i<50; i++) + { + double x = grand.get_double(); + double y = grand.get_double(); + double z = grand.get_double(); + TAI1.insert(Point(x, y, z)); + } + for(int i=0; i<50; i++) + { + lis_tai1.clear(); + double x = grand.get_double(); + double y = grand.get_double(); + double z = grand.get_double(); + Vertex_handle taiv = + TAI1.insert_and_give_new_cells( + Point(x, y, z), + std::back_inserter(lis_tai1)); + assert(TAI1.is_valid()); + assert(TAI1.dimension() == 3); + while(!lis_tai1.empty()) + { + Cell_handle c = lis_tai1.front(); + lis_tai1.pop_front(); + assert(TAI1.tds().is_simplex(c)); + } + } + TAI1.clear(); + + // the other two insertion methods is exactly the same + // with different version of the basic insert method + // Vertex_handle insert_and_give_new_cells(const Point& p, + // OutputItCells fit, + // Vertex_handle hint) + // Vertex_handle insert_and_give_new_cells(const Point& p, + // Locate_type lt, Cell_handle c, int li, int lj, + // OutputItCells fit + + + // ################################################################## + + // testing some simple basic methods (access functions) std::cout << " Boolean and query functions " <