1
// $Id: ExtractContour.cpp,v 1.8 2006/01/06 00:34:24 geuzaine Exp $
3
// Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
5
// This program is free software; you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation; either version 2 of the License, or
8
// (at your option) any later version.
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
// GNU General Public License for more details.
15
// You should have received a copy of the GNU General Public License
16
// along with this program; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20
// Please report all bugs and problems to <gmsh@geuz.org>.
29
// Note: we use List_ISearchSeq so that the input lists don't get
30
// sorted: it's less efficient, but it allows us to do multi-level
31
// user-friendly "undo"s...
44
int complink(const void *a, const void *b)
52
// Find all linked edges
54
void recurFindLinkedEdges(int ed, List_T * edges, Tree_T * points, Tree_T * links)
59
Curve *c = FindCurve(ed, THEM);
61
Msg(GERROR, "Unknown curve %d", ed);
68
for(int l = 0; l < 2; l++) {
70
if(!Tree_Search(points, &lk.n))
71
Tree_Add(points, &lk.n);
73
Tree_Suppress(points, &lk.n);
74
Tree_Query(links, &lk);
75
if(List_Nbr(lk.l) == 2) {
76
for(int i = 0; i < 2; i++) {
77
List_Read(lk.l, i, &na);
79
if(List_ISearchSeq(edges, &na.a, fcmp_absint) < 0){
80
List_Add(edges, &na.a);
81
recurFindLinkedEdges(na.a, edges, points, links);
89
int createEdgeLinks(Tree_T *links)
95
List_T *temp = Tree2List(THEM->Curves);
97
for(int i = 0; i < List_Nbr(temp); i++) {
98
List_Read(temp, i, &c);
99
if(!c->beg || !c->end){
101
Msg(GERROR, "Cannot link curves with no begin or end points");
109
for(int k = 0; k < 2; k++){
111
if((pli = (lnk *) Tree_PQuery(links, &li))) {
112
List_Add(pli->l, &na);
115
li.l = List_Create(20, 1, sizeof(nxa));
117
Tree_Add(links, &li);
126
void orientAndSortEdges(List_T *edges, Tree_T *links)
128
// this orients all the edges in a line loop in a consistent manner
129
// (left- or right-oriented, depending on the orientation of the
130
// first edge) *and* sorts them so that they form a path
135
List_T *temp = List_Create(List_Nbr(edges), 1, sizeof(int));
136
List_Copy(edges, temp);
139
List_Read(temp, 0, &num);
140
List_Add(edges, &num);
141
Curve *c0 = FindCurve(abs(num), THEM);
143
Msg(GERROR, "Unknown curve %d", abs(num));
148
while(List_Nbr(edges) < List_Nbr(temp)){
153
Tree_Query(links, &lk);
154
for(int j = 0; j < List_Nbr(lk.l); j++){
155
List_Read(lk.l, j, &na);
156
if(c0->Num != na.a && List_Search(temp, &na.a, fcmp_absint)){
157
Curve *c1 = FindCurve(abs(na.a), THEM);
159
Msg(GERROR, "Unknown curve %d", abs(na.a));
162
if(lk.n == c1->beg->Num){
170
List_Add(edges, &num);
180
int allEdgesLinked(int ed, List_T * edges)
182
Tree_T *links = Tree_Create(sizeof(lnk), complink);
183
Tree_T *points = Tree_Create(sizeof(int), fcmp_int);
185
if(!createEdgeLinks(links))
188
// initialize point tree with all hanging points
189
for(int i = 0; i < List_Nbr(edges); i++){
191
List_Read(edges, i, &num);
192
Curve *c = FindCurve(abs(num), THEM);
194
Msg(GERROR, "Unknown curve %d", abs(num));
200
for(int k = 0; k < 2; k++){
201
if(!Tree_Search(points, &ip[k]))
202
Tree_Add(points, &ip[k]);
204
Tree_Suppress(points, &ip[k]);
208
if(List_ISearchSeq(edges, &ed, fcmp_absint) < 0){
209
List_Add(edges, &ed);
210
recurFindLinkedEdges(ed, edges, points, links);
215
if(!Tree_Nbr(points)){
217
// we can only orient things now since we allow to select
218
// disconnected parts of the loop interactively
219
orientAndSortEdges(edges, links);
228
// Find all linked faces
230
void recurFindLinkedFaces(int fac, List_T * faces, Tree_T * edges, Tree_T * links)
235
Surface *s = FindSurface(abs(fac), THEM);
237
Msg(GERROR, "Unknown surface %d", abs(fac));
241
for(int l = 0; l < List_Nbr(s->Generatrices); l++) {
242
List_Read(s->Generatrices, l, &c);
244
if(!Tree_Search(edges, &lk.n))
245
Tree_Add(edges, &lk.n);
247
Tree_Suppress(edges, &lk.n);
248
Tree_Query(links, &lk);
249
if(List_Nbr(lk.l) == 2) {
250
for(int i = 0; i < 2; i++) {
251
List_Read(lk.l, i, &na);
253
if(List_ISearchSeq(faces, &na.a, fcmp_absint) < 0){
254
List_Add(faces, &na.a);
255
recurFindLinkedFaces(na.a, faces, edges, links);
263
void createFaceLinks(Tree_T * links)
270
List_T *temp = Tree2List(THEM->Surfaces);
272
for(int i = 0; i < List_Nbr(temp); i++) {
273
List_Read(temp, i, &s);
276
for(int k = 0; k < List_Nbr(s->Generatrices); k++) {
277
List_Read(s->Generatrices, k, &c);
279
if((pli = (lnk *) Tree_PQuery(links, &li))) {
280
List_Add(pli->l, &na);
283
li.l = List_Create(20, 1, sizeof(nxa));
285
Tree_Add(links, &li);
293
void recurOrientFace(int face, List_T *faces, List_T *available, Tree_T *links)
295
Surface *s = FindSurface(abs(face), THEM);
297
Msg(GERROR, "Unknown surface %d", abs(face));
300
int ori = sign(face);
302
for(int i = 0; i < List_Nbr(s->Generatrices); i++){
304
List_Read(s->Generatrices, i, &c);
307
Tree_Query(links, &lk);
308
for(int j = 0; j < List_Nbr(lk.l); j++){
310
List_Read(lk.l, j, &na);
312
if(num != abs(s->Num) && List_Search(available, &num, fcmp_absint) &&
313
List_ISearchSeq(faces, &num, fcmp_absint) < 0){
314
Surface *s2 = FindSurface(num, THEM);
316
Msg(GERROR, "Unknown surface %d", num);
319
for(int k = 0; k < List_Nbr(s2->Generatrices); k++){
321
List_Read(s2->Generatrices, k, &c2);
322
if(abs(c->Num) == abs(c2->Num)){
323
if(c->Num * c2->Num > 0)
327
List_Add(faces, &num);
328
recurOrientFace(num, faces, available, links);
337
void orientFaces(List_T *faces, Tree_T *links)
339
// this orients all the faces in a surface loop in a consistent
340
// manner (all normals pointing inside or outside--depending on the
341
// orientation of the first face)
343
List_T *temp = List_Create(List_Nbr(faces), 1, sizeof(int));
344
List_Copy(faces, temp);
348
List_Read(temp, 0, &num);
349
List_Add(faces, &num);
350
recurOrientFace(num, faces, temp, links);
355
int allFacesLinked(int fac, List_T * faces)
357
Tree_T *links = Tree_Create(sizeof(lnk), complink);
358
Tree_T *edges = Tree_Create(sizeof(int), fcmp_int);
360
createFaceLinks(links);
362
// initialize edge tree with all boundary edges
363
for(int i = 0; i < List_Nbr(faces); i++){
365
List_Read(faces, i, &num);
366
Surface *s = FindSurface(abs(num), THEM);
368
Msg(GERROR, "Unknown surface %d", abs(num));
371
for(int k = 0; k < List_Nbr(s->Generatrices); k++) {
373
List_Read(s->Generatrices, k, &c);
374
int ic = abs(c->Num);
375
if(!Tree_Search(edges, &ic))
376
Tree_Add(edges, &ic);
378
Tree_Suppress(edges, &ic);
382
if(List_ISearchSeq(faces, &fac, fcmp_absint) < 0){
383
List_Add(faces, &fac);
384
// Warning: this is correct ONLY if the surfaces are defined
385
// correctly, i.e., if the surface hole boundaries are oriented
386
// consistently with the surface exterior boundaries. There is
387
// currently *nothing* in the code that checks this.
388
recurFindLinkedFaces(fac, faces, edges, links);
393
if(!Tree_Nbr(edges)){
395
// we can only orient things now since we allow to select
396
// disconnected parts of the loop interactively
397
orientFaces(faces, links);