Welcome to mirror list, hosted at ThFree Co, Russian Federation.

BOP_Triangulator.cpp « intern « boolop « intern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: eb9b4fb0fb9d29691afa715db9839257ab31e5ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
/**
 * ***** BEGIN GPL LICENSE BLOCK *****
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
 * All rights reserved.
 *
 * The Original Code is: all of this file.
 *
 * Contributor(s): none yet.
 *
 * ***** END GPL LICENSE BLOCK *****
 */
 
#include "BOP_Triangulator.h"
#include <iostream>
using namespace std;

void BOP_addFace(BOP_Mesh* mesh, BOP_Faces *faces, BOP_Face* face, BOP_TAG tag);
void BOP_splitQuad(BOP_Mesh* mesh, MT_Plane3 plane, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, 
				   BOP_Face* triangles[], BOP_Index original);
BOP_Index BOP_getTriangleVertex(BOP_Mesh* mesh, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4);
BOP_Index BOP_getNearestVertex(BOP_Mesh* mesh, BOP_Index u, BOP_Index v1, BOP_Index v2);
bool BOP_isInsideCircle(BOP_Mesh* mesh, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, BOP_Index v5);
bool BOP_isInsideCircle(BOP_Mesh* mesh, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index w);
void BOP_triangulateC_split(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, 
							BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, BOP_Index v5);
void BOP_triangulateD_split(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, 
							BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, BOP_Index v5);

/**
 * Triangulates the face in two new faces by splitting one edge.
 *
 *         *
 *        /|\
 *       / | \
 *      /  |  \
 *     /   |   \
 *    /    |    \
 *   *-----x-----*
 *
 * @param mesh mesh that contains the faces, edges and vertices
 * @param faces set of faces that contains face and will contains new faces
 * @param face input face to be triangulate
 * @param v vertex index that intersects the edge
 * @param e relative edge index used to triangulate the face
 */


void BOP_triangulateA(BOP_Mesh *mesh, BOP_Faces *faces, BOP_Face * face, BOP_Index v, unsigned int e)
{
	BOP_Face *face1, *face2;
	if (e == 1) {
		face1 = new BOP_Face3(face->getVertex(0), v, face->getVertex(2), face->getPlane(),
							  face->getOriginalFace());
		face2 = new BOP_Face3(v, face->getVertex(1), face->getVertex(2), face->getPlane(),
							  face->getOriginalFace());
	}
	else if (e == 2) {
		face1 = new BOP_Face3(face->getVertex(0), face->getVertex(1), v, face->getPlane(),
							  face->getOriginalFace());
		face2 = new BOP_Face3(face->getVertex(0), v, face->getVertex(2), face->getPlane(),
							  face->getOriginalFace());
	}
	else if (e == 3) {
		face1 = new BOP_Face3(face->getVertex(0), face->getVertex(1), v, face->getPlane(),
							  face->getOriginalFace());
		face2 = new BOP_Face3(face->getVertex(1), face->getVertex(2), v, face->getPlane(),
							  face->getOriginalFace());
	}
	else {
		return;
	}
	
	BOP_addFace(mesh, faces, face1, face->getTAG());
	BOP_addFace(mesh, faces, face2, face->getTAG());
	face1->setSplit(face->getSplit());
	face2->setSplit(face->getSplit());
	
	face->setTAG(BROKEN);
	face->freeBBox();
}

/**
 * Triangulates the face in three new faces by one inner point.
 *
 *         *
 *        / \
 *       /   \
 *      /     \
 *     /   x   \
 *    /         \
 *   *-----------*
 *
 * @param mesh mesh that contains the faces, edges and vertices
 * @param faces set of faces that contains face and will contains new faces
 * @param face input face to be triangulate
 * @param v vertex index that lays inside face
 */
void BOP_triangulateB(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, BOP_Index v)
{
	BOP_Face *face1 = new BOP_Face3(face->getVertex(0), face->getVertex(1), v, face->getPlane(),
									face->getOriginalFace());
	BOP_Face *face2 = new BOP_Face3(face->getVertex(1), face->getVertex(2), v, face->getPlane(),
									face->getOriginalFace());
	BOP_Face *face3 = new BOP_Face3(face->getVertex(2), face->getVertex(0), v, face->getPlane(),
									face->getOriginalFace());
  
	BOP_addFace(mesh,faces,face1,face->getTAG());
	BOP_addFace(mesh,faces,face2,face->getTAG());
	BOP_addFace(mesh,faces,face3,face->getTAG());
	face1->setSplit(face->getSplit());
	face2->setSplit(face->getSplit());
	face3->setSplit(face->getSplit());
	face->setTAG(BROKEN);
	face->freeBBox();
}


/**
 * Triangulates the face in five new faces by two inner points.
 *
 *         *
 *        / \
 *       /   \
 *      /     \
 *     /  x x  \
 *    /         \
 *   *-----------*
 *
 * @param mesh mesh that contains the faces, edges and vertices
 * @param faces set of faces that contains face and will contains new faces
 * @param face input face to be triangulate
 * @param v1 first vertex index that lays inside face
 * @param v2 second vertex index that lays inside face
 */
void BOP_triangulateC(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, BOP_Index v1, BOP_Index v2)
{
	if (!BOP_isInsideCircle(mesh, face->getVertex(0), v1, v2, face->getVertex(1), face->getVertex(2))) {
		BOP_triangulateC_split(mesh, faces, face, face->getVertex(0), face->getVertex(1), 
							   face->getVertex(2), v1, v2);
	}
	else if (!BOP_isInsideCircle(mesh, face->getVertex(1), v1, v2, face->getVertex(0), face->getVertex(2))) {
		BOP_triangulateC_split(mesh, faces, face, face->getVertex(1), face->getVertex(2), 
							   face->getVertex(0), v1, v2);
	}
	else if (!BOP_isInsideCircle(mesh, face->getVertex(2), v1, v2, face->getVertex(0), face->getVertex(1))) {
		BOP_triangulateC_split(mesh, faces, face, face->getVertex(2), face->getVertex(0), 
							   face->getVertex(1), v1, v2);
	}
	else {
		BOP_triangulateC_split(mesh, faces, face, face->getVertex(2), face->getVertex(0),
							   face->getVertex(1), v1, v2);
	}  
}

/**
 * Triangulates the face (v1,v2,v3) in five new faces by two inner points (v4,v5), where
 * v1 v4 v5 defines the nice triangle and v4 v5 v2 v3 defines the quad to be tesselated.
 * @param mesh mesh that contains the faces, edges and vertices
 * @param faces set of faces that contains face and will contains new faces
 * @param face input face to be triangulate
 * @param v1 first vertex index that defines the original triangle
 * @param v2 second vertex index that defines the original triangle
 * @param v3 third vertex index that defines the original triangle
 * @param v4 first vertex index that lays inside face
 * @param v5 second vertex index that lays inside face
 */
void BOP_triangulateC_split(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, 
							BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, BOP_Index v5)
{
	BOP_Index v = BOP_getTriangleVertex(mesh, v1, v2, v4, v5);
	BOP_Index w = (v == v4 ? v5 : v4);
	BOP_Face *face1 = new BOP_Face3(v1, v, w, face->getPlane(), face->getOriginalFace());
	BOP_Face *face2 = new BOP_Face3(v1, v2, v, face->getPlane(), face->getOriginalFace());
	BOP_Face *face3 = new BOP_Face3(v1, w, v3, face->getPlane(), face->getOriginalFace());
	
	// v1 v w defines the nice triangle in the correct order
	// v1 v2 v defines one lateral triangle in the correct order
	// v1 w v3 defines the other lateral triangle in the correct order
	// w v v2 v3 defines the quad in the correct order
	
	BOP_addFace(mesh, faces, face1, face->getTAG());
	BOP_addFace(mesh, faces, face2, face->getTAG());
	BOP_addFace(mesh, faces, face3, face->getTAG());

	face1->setSplit(face->getSplit());
	face2->setSplit(face->getSplit());
	face3->setSplit(face->getSplit());
	
	BOP_Face *faces45[2];
	
	BOP_splitQuad(mesh, face->getPlane(), v2, v3, w, v, faces45, face->getOriginalFace());
	BOP_addFace(mesh, faces, faces45[0], face->getTAG());
	BOP_addFace(mesh, faces, faces45[1], face->getTAG());
	faces45[0]->setSplit(face->getSplit());
	faces45[1]->setSplit(face->getSplit());
	
	face->setTAG(BROKEN); 
	face->freeBBox();
}


/**
 * Triangulates the face in three new faces by splitting twice an edge.
 *
 *         *
 *        / \
 *       /   \
 *      /     \
 *     /       \
 *    /         \
 *   *---x---x---*
 *
 * @param mesh mesh that contains the faces, edges and vertices
 * @param faces set of faces that contains face and will contains new faces
 * @param face input face to be triangulate
 * @param v1 first vertex index that intersects the edge
 * @param v2 second vertex index that intersects the edge
 * @param e relative edge index used to triangulate the face
 */
void BOP_triangulateD(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, BOP_Index v1, 
					  BOP_Index v2, unsigned int e)
{
	if (e == 1) {
		BOP_triangulateD_split(mesh, faces, face, face->getVertex(0), face->getVertex(1),
							   face->getVertex(2), v1, v2);
	}
	else if (e == 2) {
		BOP_triangulateD_split(mesh, faces, face, face->getVertex(1), face->getVertex(2),
							   face->getVertex(0), v1, v2);
	}
	else if (e == 3) {
		BOP_triangulateD_split(mesh, faces, face, face->getVertex(2), face->getVertex(0),
							   face->getVertex(1), v1, v2);
	}
}

/**
 * Triangulates the face (v1,v2,v3) in three new faces by splitting twice an edge.
 * @param mesh mesh that contains the faces, edges and vertices
 * @param faces set of faces that contains face and will contains new faces
 * @param face input face to be triangulate
 * @param v1 first vertex index that defines the original triangle
 * @param v2 second vertex index that defines the original triangle
 * @param v3 third vertex index that defines the original triangle
 * @param v4 first vertex index that lays on the edge
 * @param v5 second vertex index that lays on the edge
 */
void BOP_triangulateD_split(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, 
							BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, BOP_Index v5)
{
	BOP_Index v = BOP_getNearestVertex(mesh, v1, v4, v5);
	BOP_Index w = (v == v4 ? v5 : v4);
	BOP_Face *face1 = new BOP_Face3(v1, v, v3, face->getPlane(), face->getOriginalFace());
	BOP_Face *face2 = new BOP_Face3(v, w, v3, face->getPlane(), face->getOriginalFace());
	BOP_Face *face3 = new BOP_Face3(w, v2, v3, face->getPlane(), face->getOriginalFace());
	
	BOP_addFace(mesh, faces, face1, face->getTAG());
	BOP_addFace(mesh, faces, face2, face->getTAG());
	BOP_addFace(mesh, faces, face3, face->getTAG());
	face1->setSplit(face->getSplit());
	face2->setSplit(face->getSplit());
	face3->setSplit(face->getSplit());

	face->setTAG(BROKEN);
	face->freeBBox();
}


/**
 * Triangulates the face in three new faces by splitting two edges.
 *
 *         *
 *        / \
 *       /   \
 *      x     x
 *     /       \
 *    /         \
 *   *-----------*
 *
 * @param mesh mesh that contains the faces, edges and vertices
 * @param faces set of faces that contains face and will contains new faces
 * @param face input face to be triangulate
 * @param v1 vertex index that intersects the first edge
 * @param v1 vertex index that intersects the second edge
 * @param e1 first relative edge index used to triangulate the face
 * @param e2 second relative edge index used to triangulate the face
 */
void BOP_triangulateE(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, 
					  BOP_Index v1, BOP_Index v2, unsigned int e1, unsigned int e2)
{
	// Sort the edges to reduce the cases
	if (e1 > e2) {
		unsigned int aux = e1;
		e1 = e2;
		e2 = aux;
		aux = v1;
		v1 = v2;
		v2 = aux;
	}
	// e1 < e2!
	BOP_Face *face1;
	BOP_Face *faces23[2];
	if (e1 == 1 && e2 == 2) {
		// the vertex is 2
		face1 = new BOP_Face3(face->getVertex(1), v2, v1, face->getPlane(), 
							  face->getOriginalFace());
		BOP_splitQuad(mesh, face->getPlane(), face->getVertex(2), face->getVertex(0), v1, v2,
					  faces23, face->getOriginalFace());
	}
	else if (e1 == 1 && e2 == 3) {
		// the vertex is 1
		face1 = new BOP_Face3(face->getVertex(0), v1, v2, face->getPlane(), 
							  face->getOriginalFace());
		BOP_splitQuad(mesh, face->getPlane(), face->getVertex(1), face->getVertex(2), v2, v1, 
					  faces23, face->getOriginalFace());
	}
	else if (e1 == 2 && e2 == 3) {
		// the vertex is 3
		face1 = new BOP_Face3(face->getVertex(2), v2, v1, face->getPlane(), 
							  face->getOriginalFace());
		BOP_splitQuad(mesh, face->getPlane(), face->getVertex(0), face->getVertex(1), v1, v2, 
					  faces23, face->getOriginalFace());
	}
	else {
		return;
	}
	
	BOP_addFace(mesh, faces, face1, face->getTAG());
	BOP_addFace(mesh, faces, faces23[0], face->getTAG());
	BOP_addFace(mesh, faces, faces23[1], face->getTAG());
	face1->setSplit(face->getSplit());
	faces23[0]->setSplit(face->getSplit());
	faces23[1]->setSplit(face->getSplit());
	face->setTAG(BROKEN);
	face->freeBBox();
}

/**
 * Triangulates the face in four new faces by one edge and one inner point.
 *
 *         *
 *        / \
 *       /   \
 *      x  x  \
 *     /       \
 *    /         \
 *   *-----------*
 *
 * @param mesh mesh that contains the faces, edges and vertices
 * @param faces set of faces that contains face and will contains new faces
 * @param face input face to be triangulate
 * @param v1 vertex index that lays inside face
 * @param v2 vertex index that intersects the edge
 * @param e relative edge index used to triangulate the face
 */
void BOP_triangulateF(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, 
					  BOP_Index v1, BOP_Index v2, unsigned int e)
{
	BOP_Face *faces12[2];
	BOP_Face *faces34[2];
	if (e == 1) {      
		BOP_splitQuad(mesh, face->getPlane(), face->getVertex(2), face->getVertex(0), v2, v1,
					  faces12, face->getOriginalFace());
		BOP_splitQuad(mesh, face->getPlane(), face->getVertex(1), face->getVertex(2), v1, v2,
					  faces34, face->getOriginalFace());
	}
	else if (e == 2) {
		BOP_splitQuad(mesh, face->getPlane(), face->getVertex(0), face->getVertex(1), v2, v1,
					  faces12, face->getOriginalFace());
		BOP_splitQuad(mesh, face->getPlane(), face->getVertex(2), face->getVertex(0), v1, v2,
					  faces34, face->getOriginalFace());
	}
	else if (e==3) {
		BOP_splitQuad(mesh, face->getPlane(), face->getVertex(1), face->getVertex(2), v2, v1,
					  faces12, face->getOriginalFace());
		BOP_splitQuad(mesh, face->getPlane(), face->getVertex(0), face->getVertex(1), v1, v2,
					  faces34, face->getOriginalFace());
	}
	else {
		return;
	}
	
	BOP_addFace(mesh, faces, faces12[0], face->getTAG());
	BOP_addFace(mesh, faces, faces12[1], face->getTAG());
	BOP_addFace(mesh, faces, faces34[0], face->getTAG());
	BOP_addFace(mesh, faces, faces34[1], face->getTAG());
	faces12[0]->setSplit(face->getSplit());
	faces12[1]->setSplit(face->getSplit());
	faces34[0]->setSplit(face->getSplit());
	faces34[1]->setSplit(face->getSplit());
	
	face->setTAG(BROKEN);
	face->freeBBox();
}

/**
 * Adds the new face into the faces set and the mesh and sets it a new tag.
 * @param mesh mesh that contains the faces, edges and vertices
 * @param faces set of faces that contains oldFace
 * @param face input face to be added
 * @param tag tag of the new face
 */
void BOP_addFace(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, BOP_TAG tag)
{
	BOP_Index av1 = face->getVertex(0);
	BOP_Index av2 = face->getVertex(1);
	BOP_Index av3 = face->getVertex(2);

	/*
	 * Before adding a new face to the face list, be sure it's not
	 * already there.  Duplicate faces have been found to cause at
	 * least two instances of infinite loops.  Also, some faces are
	 * created which have the same vertex twice.  Don't add these either.
	 *
	 * When someone has more time to look into this issue, it's possible
	 * this code may be removed again.
	 */
	if( av1==av2 || av2==av3  || av3==av1 ) return;

	for(unsigned int idxFace=0;idxFace<faces->size();idxFace++) {
		BOP_Face *faceA = (*faces)[idxFace];
		BOP_Index bv1 = faceA->getVertex(0);
		BOP_Index bv2 = faceA->getVertex(1);
		BOP_Index bv3 = faceA->getVertex(2);

		if( ( av1==bv1 && av2==bv2 && av3==bv3 ) ||
	        ( av1==bv1 && av2==bv3 && av3==bv2 ) ||
	        ( av1==bv2 && av2==bv1 && av3==bv3 ) ||
	        ( av1==bv2 && av2==bv3 && av3==bv1 ) ||
	        ( av1==bv3 && av2==bv2 && av3==bv1 ) ||
	        ( av1==bv3 && av2==bv1 && av3==bv3 ) )
			return;
	}

	face->setTAG(tag);    
	faces->push_back(face);
	mesh->addFace(face);
}

/**
 * Computes the best quad triangulation.
 * @param mesh mesh that contains the faces, edges and vertices
 * @param plane plane used to create the news faces
 * @param v1 first vertex index
 * @param v2 second vertex index
 * @param v3 third vertex index
 * @param v4 fourth vertex index
 * @param triangles array of faces where the new two faces will be saved
 * @param original face index to the new faces
 */
void BOP_splitQuad(BOP_Mesh* mesh, MT_Plane3 plane, BOP_Index v1, BOP_Index v2, 
				   BOP_Index v3, BOP_Index v4, BOP_Face* triangles[], BOP_Index original)
{
	MT_Point3 p1 = mesh->getVertex(v1)->getPoint();
	MT_Point3 p2 = mesh->getVertex(v2)->getPoint();
	MT_Point3 p3 = mesh->getVertex(v3)->getPoint();
	MT_Point3 p4 = mesh->getVertex(v4)->getPoint();
	
	int res = BOP_concave(p1,p2,p3,p4);
	
	if (res==0) {
		MT_Plane3 plane1(p1, p2, p3);
		MT_Plane3 plane2(p1, p3, p4);
		
		if (BOP_isInsideCircle(mesh, v1, v2, v4, v3) && 
			BOP_orientation(plane1, plane) &&
			BOP_orientation(plane2, plane)) {
			triangles[0] = new BOP_Face3(v1, v2, v3, plane, original);
			triangles[1] = new BOP_Face3(v1, v3, v4, plane, original);
		}
		else {
			triangles[0] = new BOP_Face3(v1, v2, v4, plane, original);
			triangles[1] = new BOP_Face3(v2, v3, v4, plane, original);
		}
	}
	else if (res==-1) {
		triangles[0] = new BOP_Face3(v1, v2, v4, plane, original);
		triangles[1] = new BOP_Face3(v2, v3, v4, plane, original);
	}
	else {
		triangles[0] = new BOP_Face3(v1, v2, v3, plane, original);
		triangles[1] = new BOP_Face3(v1, v3, v4, plane, original);
	}
}

/**
 * Returns the vertex (v3 or v4) that splits the quad (v1,v2,v3,v4) in the best pair of triangles.
 * @param mesh mesh that contains the faces, edges and vertices
 * @param v1 first vertex index
 * @param v2 second vertex index
 * @param v3 third vertex index
 * @param v4 fourth vertex index
 * @return v3 if the best split triangles are (v1,v2,v3) and (v1,v3,v4), v4 otherwise
 */
BOP_Index BOP_getTriangleVertex(BOP_Mesh* mesh, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4)
{
	if (BOP_isInsideCircle(mesh, v1, v2, v4, v3)) {
		return v3;
	}
	return v4; 
}

/**
 * Returns which of vertex v1 or v2 is nearest to u.
 * @param mesh mesh that contains the faces, edges and vertices
 * @param u reference vertex index
 * @param v1 first vertex index
 * @param v2 second vertex index
 * @return the nearest vertex index
 */
BOP_Index BOP_getNearestVertex(BOP_Mesh* mesh, BOP_Index u, BOP_Index v1, BOP_Index v2)
{
	MT_Point3 q = mesh->getVertex(u)->getPoint();
	MT_Point3 p1 = mesh->getVertex(v1)->getPoint();
	MT_Point3 p2 = mesh->getVertex(v2)->getPoint();
	if (BOP_comp(q.distance(p1), q.distance(p2)) > 0) return v2;
	else return v1;
}

/**
 * Computes if vertexs v4 and v5 are not inside the circle defined by v1,v2,v3 (seems to be a nice triangle)
 * @param mesh mesh that contains the faces, edges and vertices
 * @param v1 first vertex index
 * @param v2 second vertex index
 * @param v3 third vertex index
 * @param v4 fourth vertex index
 * @param v5 five vertex index
 * @return if v1,v2,v3 defines a nice triangle against v4,v5
 */
bool BOP_isInsideCircle(BOP_Mesh* mesh, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index v4, BOP_Index v5)
{
	return BOP_isInsideCircle(mesh->getVertex(v1)->getPoint(),
							  mesh->getVertex(v2)->getPoint(),
							  mesh->getVertex(v3)->getPoint(),
							  mesh->getVertex(v4)->getPoint(),
							  mesh->getVertex(v5)->getPoint());
}

/**
 * Computes if vertex w is not inside the circle defined by v1,v2,v3 (seems to be a nice triangle)
 * @param mesh mesh that contains the faces, edges and vertices
 * @param v1 first vertex index
 * @param v2 second vertex index
 * @param v3 third vertex index
 * @param w fourth vertex index
 * @return if v1,v2,v3 defines a nice triangle against w
 */
bool BOP_isInsideCircle(BOP_Mesh* mesh, BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index w) 
{
	return BOP_isInsideCircle(mesh->getVertex(v1)->getPoint(),
							  mesh->getVertex(v2)->getPoint(),
							  mesh->getVertex(v3)->getPoint(),
							  mesh->getVertex(w)->getPoint());
}