Style Cleanup:
[blender-staging.git] / source / blender / bmesh / intern / bmesh_queries.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Joseph Eagar, Geoffrey Bantle, Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/bmesh/intern/bmesh_queries.c
24  *  \ingroup bmesh
25  *
26  * This file contains functions for answering common
27  * Topological and geometric queries about a mesh, such
28  * as, "What is the angle between these two faces?" or,
29  * "How many faces are incident upon this vertex?" Tool
30  * authors should use the functions in this file instead
31  * of inspecting the mesh structure directly.
32  */
33
34 #include <string.h>
35
36 #include "bmesh.h"
37 #include "bmesh_private.h"
38
39 #include "BKE_utildefines.h"
40
41 #include "BLI_math.h"
42 #include "BLI_utildefines.h"
43
44 #define BM_OVERLAP (1 << 13)
45
46 /*
47  * BMESH COUNT ELEMENT
48  *
49  * Return the amount of element of
50  * type 'type' in a given bmesh.
51  */
52
53 int BM_Count_Element(BMesh *bm, const char htype)
54 {
55         if (htype == BM_VERT) return bm->totvert;
56         else if (htype == BM_EDGE) return bm->totedge;
57         else if (htype == BM_FACE) return bm->totface;
58
59         return 0;
60 }
61
62
63 /*
64  * BMESH VERT IN EDGE
65  *
66  * Returns whether or not a given vertex is
67  * is part of a given edge.
68  *
69  */
70
71 int BM_Vert_In_Edge(BMEdge *e, BMVert *v)
72 {
73         return bmesh_vert_in_edge(e, v);
74 }
75
76 /*
77  * BMESH OTHER EDGE IN FACE SHARING A VERTEX
78  *
79  * Returns an opposing loop that shares the same face.
80  *
81  */
82
83 BMLoop *BM_OtherFaceLoop(BMEdge *e, BMFace *f, BMVert *v)
84 {
85         BMLoop *l_iter;
86         BMLoop *l_first;
87
88         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
89         
90         do {
91                 if (l_iter->e == e) {
92                         break;
93                 }
94         } while ((l_iter = l_iter->next) != l_first);
95         
96         return l_iter->v == v ? l_iter->prev : l_iter->next;
97 }
98
99 /*
100  * BMESH VERT IN FACE
101  *
102  * Returns whether or not a given vertex is
103  * is part of a given face.
104  *
105  */
106
107 int BM_Vert_In_Face(BMFace *f, BMVert *v)
108 {
109         BMLoopList *lst;
110         BMLoop *l_iter;
111
112         for (lst = f->loops.first; lst; lst = lst->next) {
113                 l_iter = lst->first;
114                 do {
115                         if (l_iter->v == v) {
116                                 return TRUE;
117                         }
118                 } while ((l_iter = l_iter->next) != lst->first);
119         }
120
121         return FALSE;
122 }
123
124 /*
125  * BMESH VERTS IN FACE
126  *
127  * Compares the number of vertices in an array
128  * that appear in a given face
129  *
130  */
131 int BM_Verts_In_Face(BMesh *bm, BMFace *f, BMVert **varr, int len)
132 {
133         BMLoopList *lst;
134         BMLoop *curloop = NULL;
135         int i, count = 0;
136         
137         for (i = 0; i < len; i++) BMO_SetFlag(bm, varr[i], BM_OVERLAP);
138         
139         for (lst = f->loops.first; lst; lst = lst->next) {
140                 curloop = lst->first;
141
142                 do {
143                         if (BMO_TestFlag(bm, curloop->v, BM_OVERLAP))
144                                 count++;
145
146                         curloop = curloop->next;
147                 } while (curloop != lst->first);
148         }
149
150         for (i = 0; i < len; i++) BMO_ClearFlag(bm, varr[i], BM_OVERLAP);
151
152         return count;
153 }
154
155 /*
156  * BMESH EDGE IN FACE
157  *
158  * Returns whether or not a given edge is
159  * is part of a given face.
160  *
161  */
162
163 int BM_Edge_In_Face(BMFace *f, BMEdge *e)
164 {
165         BMLoop *l_iter;
166         BMLoop *l_first;
167
168         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
169
170         do {
171                 if (l_iter->e == e) {
172                         return TRUE;
173                 }
174         } while ((l_iter = l_iter->next) != l_first);
175
176         return FALSE;
177 }
178
179 /*
180  * BMESH VERTS IN EDGE
181  *
182  * Returns whether or not two vertices are in
183  * a given edge
184  *
185  */
186
187 int BM_Verts_In_Edge(BMVert *v1, BMVert *v2, BMEdge *e)
188 {
189         return bmesh_verts_in_edge(v1, v2, e);
190 }
191
192 /*
193  * BMESH GET OTHER EDGEVERT
194  *
195  * Given a edge and one of its vertices, returns
196  * the other vertex.
197  *
198  */
199
200 BMVert *BM_OtherEdgeVert(BMEdge *e, BMVert *v)
201 {
202         return bmesh_edge_getothervert(e, v);
203 }
204
205 /*
206  *  BMESH VERT EDGECOUNT
207  *
208  *      Returns the number of edges around this vertex.
209  */
210
211 int BM_Vert_EdgeCount(BMVert *v)
212 {
213         return bmesh_disk_count(v);
214 }
215
216 /*
217  *  BMESH EDGE FACECOUNT
218  *
219  *      Returns the number of faces around this edge
220  */
221
222 int BM_Edge_FaceCount(BMEdge *e)
223 {
224         int count = 0;
225         BMLoop *curloop = NULL;
226
227         if (e->l) {
228                 curloop = e->l;
229                 do {
230                         count++;
231                         curloop = bmesh_radial_nextloop(curloop);
232                 } while (curloop != e->l);
233         }
234
235         return count;
236 }
237
238 /*
239  *  BMESH VERT FACECOUNT
240  *
241  *      Returns the number of faces around this vert
242  */
243
244 int BM_Vert_FaceCount(BMVert *v)
245 {
246         int count = 0;
247         BMLoop *l;
248         BMIter iter;
249
250         BM_ITER(l, &iter, NULL, BM_LOOPS_OF_VERT, v) {
251                 count++;
252         }
253
254         return count;
255 #if 0 //this code isn't working
256         BMEdge *curedge = NULL;
257
258         if (v->e) {
259                 curedge = v->e;
260                 do {
261                         if (curedge->l) count += BM_Edge_FaceCount(curedge);
262                         curedge = bmesh_disk_nextedge(curedge, v);
263                 } while (curedge != v->e);
264         }
265         return count;
266 #endif
267 }
268
269 /*
270  *                      BMESH WIRE VERT
271  *
272  *      Tests whether or not the vertex is part of a wire edge.
273  *  (ie: has no faces attached to it)
274  *
275  *  Returns -
276  *      1 for true, 0 for false.
277  */
278
279 int BM_Wire_Vert(BMesh *UNUSED(bm), BMVert *v)
280 {
281         BMEdge *curedge;
282
283         if (v->e == NULL) {
284                 return FALSE;
285         }
286         
287         curedge = v->e;
288         do {
289                 if (curedge->l) {
290                         return FALSE;
291                 }
292
293                 curedge = bmesh_disk_nextedge(curedge, v);
294         } while (curedge != v->e);
295
296         return TRUE;
297 }
298
299 /*
300  *                      BMESH WIRE EDGE
301  *
302  *      Tests whether or not the edge is part of a wire.
303  *  (ie: has no faces attached to it)
304  *
305  *  Returns -
306  *      1 for true, 0 for false.
307  */
308
309 int BM_Wire_Edge(BMesh *UNUSED(bm), BMEdge *e)
310 {
311         return (e->l) ? FALSE : TRUE;
312 }
313
314 /*
315  *                      BMESH NONMANIFOLD VERT
316  *
317  *  A vertex is non-manifold if it meets the following conditions:
318  *    1: Loose - (has no edges/faces incident upon it)
319  *    2: Joins two distinct regions - (two pyramids joined at the tip)
320  *    3: Is part of a non-manifold edge (edge with more than 2 faces)
321  *    4: Is part of a wire edge
322  *
323  *  Returns -
324  *      1 for true, 0 for false.
325  */
326
327 int BM_Nonmanifold_Vert(BMesh *UNUSED(bm), BMVert *v)
328 {
329         BMEdge *e, *oe;
330         BMLoop *l;
331         int len, count, flag;
332
333         if (v->e == NULL) {
334                 /* loose vert */
335                 return TRUE;
336         }
337
338         /* count edges while looking for non-manifold edges */
339         oe = v->e;
340         for (len = 0, e = v->e; e != oe || (e == oe && len == 0); len++, e = bmesh_disk_nextedge(e, v)) {
341                 if (e->l == NULL) {
342                         /* loose edge */
343                         return TRUE;
344                 }
345
346                 if (bmesh_radial_length(e->l) > 2) {
347                         /* edge shared by more than two faces */
348                         return TRUE;
349                 }
350         }
351
352         count = 1;
353         flag = 1;
354         e = NULL;
355         oe = v->e;
356         l = oe->l;
357         while (e != oe) {
358                 l = (l->v == v) ? l->prev : l->next;
359                 e = l->e;
360                 count++; /* count the edges */
361
362                 if (flag && l->radial_next == l) {
363                         /* we've hit the edge of an open mesh, reset once */
364                         flag = 0;
365                         count = 1;
366                         oe = e;
367                         e = NULL;
368                         l = oe->l;
369                 }
370                 else if (l->radial_next == l) {
371                         /* break the loop */
372                         e = oe;
373                 }
374                 else {
375                         l = l->radial_next;
376                 }
377         }
378
379         if (count < len) {
380                 /* vert shared by multiple regions */
381                 return TRUE;
382         }
383
384         return FALSE;
385 }
386
387 /*
388  *                      BMESH NONMANIFOLD EDGE
389  *
390  *      Tests whether or not this edge is manifold.
391  *  A manifold edge either has 1 or 2 faces attached
392  *      to it.
393  *
394  *  Returns -
395  *      1 for true, 0 for false.
396  */
397
398 int BM_Nonmanifold_Edge(BMesh *UNUSED(bm), BMEdge *e)
399 {
400         int count = BM_Edge_FaceCount(e);
401         if (count != 2 && count != 1) {
402                 return TRUE;
403         }
404         return FALSE;
405 }
406
407 /*
408  *                      BMESH BOUNDARY EDGE
409  *
410  *      Tests whether or not an edge is on the boundary
411  *  of a shell (has one face associated with it)
412  *
413  *  Returns -
414  *      1 for true, 0 for false.
415  */
416
417 int BM_Boundary_Edge(BMEdge *e)
418 {
419         int count = BM_Edge_FaceCount(e);
420         if (count == 1) {
421                 return TRUE;
422         }
423         return FALSE;
424 }
425
426 /*
427  *                      BMESH FACE SHAREDEDGES
428  *
429  *  Counts the number of edges two faces share (if any)
430  *
431  *  BMESH_TODO:
432  *    Move this to structure, and wrap.
433  *
434  *  Returns -
435  *      Integer
436  */
437
438 int BM_Face_Share_Edges(BMFace *f1, BMFace *f2)
439 {
440         BMLoop *l_iter;
441         BMLoop *l_first;
442         int count = 0;
443         
444         l_iter = l_first = BM_FACE_FIRST_LOOP(f1);
445         do {
446                 if (bmesh_radial_find_face(l_iter->e, f2)) {
447                         count++;
448                 }
449         } while ((l_iter = l_iter->next) != l_first);
450
451         return count;
452 }
453
454 /*
455  *
456  *           BMESH EDGE SHARE FACES
457  *
458  *      Tests to see if e1 shares any faces with e2
459  *
460  */
461
462 int BM_Edge_Share_Faces(BMEdge *e1, BMEdge *e2)
463 {
464         BMLoop *l;
465         BMFace *f;
466
467         if (e1->l && e2->l) {
468                 l = e1->l;
469                 do {
470                         f = l->f;
471                         if (bmesh_radial_find_face(e2, f)) {
472                                 return TRUE;
473                         }
474                         l = l->radial_next;
475                 } while (l != e1->l);
476         }
477         return FALSE;
478 }
479
480 /**
481  *
482  *           BMESH EDGE SHARE A VERTEX
483  *
484  *      Tests to see if e1 shares a vertex with e2
485  *
486  */
487
488 int BM_Edge_Share_Vert(struct BMEdge *e1, struct BMEdge *e2)
489 {
490         return (e1->v1 == e2->v1 ||
491                 e1->v1 == e2->v2 ||
492                 e1->v2 == e2->v1 ||
493                 e1->v2 == e2->v2);
494 }
495
496 /**
497  *
498  *           BMESH EDGE ORDERED VERTS
499  *
500  *      Returns the verts of an edge as used in a face
501  *  if used in a face at all, otherwise just assign as used in the edge.
502  *
503  *  Useful to get a determanistic winding order when calling
504  *  BM_Make_Ngon() on an arbitrary array of verts,
505  *  though be sure to pick an edge which has a face.
506  *
507  */
508
509 void BM_Edge_OrderedVerts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
510 {
511         if ( (edge->l == NULL) ||
512              ( ((edge->l->prev->v == edge->v1) && (edge->l->v == edge->v2)) ||
513                ((edge->l->v == edge->v1) && (edge->l->next->v == edge->v2)) )
514              )
515         {
516                 *r_v1 = edge->v1;
517                 *r_v2 = edge->v2;
518         }
519         else {
520                 *r_v1 = edge->v2;
521                 *r_v2 = edge->v1;
522         }
523 }
524
525 /**
526  *                      BMESH FACE ANGLE
527  *
528  *  Calculates the angle between two faces. Assumes
529  *  That face normals are correct.
530  *
531  *  Returns -
532  *      Float.
533  */
534
535 float BM_Face_Angle(BMesh *UNUSED(bm), BMEdge *e)
536 {
537         if (BM_Edge_FaceCount(e) == 2) {
538                 BMLoop *l1 = e->l;
539                 BMLoop *l2 = e->l->radial_next;
540                 return acosf(dot_v3v3(l1->f->no, l2->f->no));
541         }
542         else {
543                 return (float)M_PI / 2.0f; /* acos(0.0) */
544         }
545 }
546
547 /*
548  * BMESH EXIST FACE OVERLAPS
549  *
550  * Given a set of vertices (varr), find out if
551  * all those vertices overlap an existing face.
552  *
553  * Returns:
554  * 0 for no overlap
555  * 1 for overlap
556  *
557  *
558  */
559
560 int BM_Exist_Face_Overlaps(BMesh *bm, BMVert **varr, int len, BMFace **overlapface)
561 {
562         BMIter vertfaces;
563         BMFace *f;
564         int i, amount;
565
566         if (overlapface) *overlapface = NULL;
567
568         for (i = 0; i < len; i++) {
569                 f = BMIter_New(&vertfaces, bm, BM_FACES_OF_VERT, varr[i]);
570                 while (f) {
571                         amount = BM_Verts_In_Face(bm, f, varr, len);
572                         if (amount >= len) {
573                                 if (overlapface) *overlapface = f;
574                                 return TRUE;
575                         }
576                         f = BMIter_Step(&vertfaces);
577                 }
578         }
579         return FALSE;
580 }
581
582 /*
583  * BMESH FACE EXISTS
584  *
585  * Given a set of vertices (varr), find out if
586  * there is a face with exactly those vertices
587  * (and only those vertices).
588  *
589  * Returns:
590  * 0 for no face found
591  * 1 for face found
592  */
593
594 int BM_Face_Exists(BMesh *bm, BMVert **varr, int len, BMFace **existface)
595 {
596         BMIter vertfaces;
597         BMFace *f;
598         int i, amount;
599
600         if (existface) *existface = NULL;
601
602         for (i = 0; i < len; i++) {
603                 f = BMIter_New(&vertfaces, bm, BM_FACES_OF_VERT, varr[i]);
604                 while (f) {
605                         amount = BM_Verts_In_Face(bm, f, varr, len);
606                         if (amount == len && amount == f->len) {
607                                 if (existface) *existface = f;
608                                 return TRUE;
609                         }
610                         f = BMIter_Step(&vertfaces);
611                 }
612         }
613         return FALSE;
614 }