OOFEM 3.0
Loading...
Searching...
No Matches
delaunay.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
35#include "delaunay.h"
36#include "floatarray.h"
37#include "intarray.h"
38#include "geometry.h"
39#include "node.h"
40#include "mathfem.h"
41
42#include <cstdlib>
43#include <map>
44#include <algorithm>
45
46namespace oofem {
47bool Delaunay :: colinear(const FloatArray &iP1, const FloatArray &iP2, const FloatArray &iP3) const
48{
49 double dist = iP1.at(1) * ( iP2.at(2) - iP3.at(2) ) + iP2.at(1) * ( iP3.at(2) - iP1.at(2) ) +
50 iP3.at(1) * ( iP1.at(2) - iP2.at(2) );
51
52 if ( dist < mTol && dist > -mTol ) {
53 return true;
54 } else {
55 return false;
56 }
57}
58
59void Delaunay :: printTriangles(std :: vector< Triangle > &triangles)
60{
61 for ( auto &tri: triangles ) {
62 tri.printYourself();
63 }
64}
65
66bool Delaunay :: isInsideCC(const FloatArray &iP, const FloatArray &iP1, const FloatArray &iP2, const FloatArray &iP3) const
67{
68 Triangle tr(iP1, iP2, iP3);
69 double r = tr.getRadiusOfCircumCircle();
70 FloatArray circumCenter;
71 tr.computeCenterOfCircumCircle(circumCenter);
72 double dist = distance(circumCenter, iP);
73 if ( dist < r ) {
74 return true;
75 } else {
76 return false;
77 }
78}
79
80void Delaunay :: triangulate(const std :: vector< FloatArray > &iVertices, std :: vector< Triangle > &oTriangles) const
81{
82 // 4th order algorithm - four loops, only for testing purposes
83
84 if ( iVertices.size() == 4 ) {
85 // Check if the points approximately form a rectangle
86 // and treat that case separately .
87 // The purpose is to avoid annyoing round-off effects for
88 // this quite common case. /ES
89
90 const double relTol2 = 1.0e-6;
91
92 std :: vector< double >dist_square = {
93 distance(iVertices [ 0 ], iVertices [ 1 ]),
94 distance(iVertices [ 0 ], iVertices [ 2 ]),
95 distance(iVertices [ 0 ], iVertices [ 3 ])
96 };
97
98 std :: sort( dist_square.begin(), dist_square.end() );
99
100 // This expression is zero for a rectangle according to the Pythagorean theorem
101 if ( fabs(dist_square [ 2 ] - dist_square [ 1 ] - dist_square [ 0 ]) < relTol2 * dist_square [ 2 ] ) {
102 // We found a rectangle
103
104 double maxDist_square = distance_square(iVertices [ 0 ], iVertices [ 1 ]);
105 int maxDistInd = 1;
106
107 double d2 = distance_square(iVertices [ 0 ], iVertices [ 2 ]);
108 if ( d2 > maxDist_square ) {
109 maxDist_square = d2;
110 maxDistInd = 2;
111 }
112
113 double d2b = distance_square(iVertices [ 0 ], iVertices [ 3 ]);
114 if ( d2b > maxDist_square ) {
115 maxDist_square = d2b;
116 maxDistInd = 3;
117 }
118
119
120 int remainingInd1 = -1, remainingInd2 = -1;
121
122 switch ( maxDistInd ) {
123 case 1:
124 remainingInd1 = 2;
125 remainingInd2 = 3;
126 break;
127
128 case 2:
129 remainingInd1 = 1;
130 remainingInd2 = 3;
131 break;
132
133 case 3:
134 remainingInd1 = 1;
135 remainingInd2 = 2;
136 break;
137 default:
138 OOFEM_ERROR("Case not handled in switch.")
139 break;
140 }
141
142
143 Triangle tri1(iVertices [ 0 ], iVertices [ remainingInd1 ], iVertices [ maxDistInd ]);
144 if ( !tri1.isOrientedAnticlockwise() ) {
146 }
147
148 oTriangles.push_back(tri1);
149
150
151 Triangle tri2(iVertices [ 0 ], iVertices [ remainingInd2 ], iVertices [ maxDistInd ]);
152 if ( !tri2.isOrientedAnticlockwise() ) {
154 }
155
156 oTriangles.push_back(tri2);
157
158 return;
159 }
160 }
161
162
163 int n = iVertices.size();
164
165 // copy of vertices, since they will be shifted
166 std :: vector< FloatArray >vertices(iVertices);
167
168 // small shift of vertices
169 const double shift = 1.0e-12;
170 for ( int i = 1; i <= n; i++ ) {
171 vertices [ i - 1 ].at(1) += vertices [ i - 1 ].at(1) * shift * double ( rand() ) / RAND_MAX;
172 vertices [ i - 1 ].at(2) += vertices [ i - 1 ].at(2) * shift * double ( rand() ) / RAND_MAX;
173 }
174
175 for ( int i = 1; i <= n; i++ ) {
176 for ( int j = i + 1; j <= n; j++ ) {
177 for ( int k = j + 1; k <= n; k++ ) {
178 bool isTriangle = true;
179 if ( colinear(vertices [ i - 1 ], vertices [ j - 1 ], vertices [ k - 1 ]) ) {
180 isTriangle = false;
181 } else {
182 for ( int a = 1; a <= n; a++ ) {
183 if ( a != i && a != j && a != k ) {
184 // checks whether a point a is inside a circumcircle of a triangle ijk
185 if ( isInsideCC(vertices [ a - 1 ], vertices [ i - 1 ], vertices [ j - 1 ],
186 vertices [ k - 1 ]) ) {
187 isTriangle = false;
188 break;
189 }
190 }
191 }
192 }
193
194 if ( isTriangle ) {
195 // here we switch to old vertices
196 Triangle tri(iVertices [ i - 1 ], iVertices [ j - 1 ], iVertices [ k - 1 ]);
197 if ( !tri.isOrientedAnticlockwise() ) {
199 }
200
201 oTriangles.push_back(tri);
202 }
203 }
204 }
205 }
206}
207} // end namespace oofem
bool colinear(const FloatArray &iP1, const FloatArray &iP2, const FloatArray &iP3) const
Definition delaunay.C:47
const double mTol
Definition delaunay.h:64
bool isInsideCC(const FloatArray &iP, const FloatArray &iP1, const FloatArray &iP2, const FloatArray &iP3) const
Definition delaunay.C:66
double & at(Index i)
Definition floatarray.h:202
void changeToAnticlockwise()
Definition geometry.C:480
void computeCenterOfCircumCircle(FloatArray &answer) const
Definition geometry.C:441
bool isOrientedAnticlockwise()
Definition geometry.C:463
double getRadiusOfCircumCircle()
Definition geometry.C:417
#define OOFEM_ERROR(...)
Definition error.h:79
double distance(const FloatArray &x, const FloatArray &y)
double distance_square(const FloatArray &x, const FloatArray &y)

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011