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}
+
+
+
+\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 " <