Blender V2.61 - r43446

reeb.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Martin Poirier
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00028 #include <math.h>
00029 #include <string.h> // for memcpy
00030 #include <stdio.h>
00031 #include <stdlib.h> // for qsort
00032 #include <float.h>
00033 
00034 #include "DNA_scene_types.h"
00035 #include "DNA_object_types.h"
00036 
00037 #include "MEM_guardedalloc.h"
00038 
00039 #include "BKE_context.h"
00040 
00041 #include "BLI_blenlib.h"
00042 #include "BLI_math.h"
00043 #include "BLI_utildefines.h"
00044 #include "BLI_editVert.h"
00045 #include "BLI_edgehash.h"
00046 #include "BLI_ghash.h"
00047 #include "BLI_heap.h"
00048 
00049 //#include "BDR_editobject.h"
00050 
00051 //#include "BIF_interface.h"
00052 //#include "BIF_toolbox.h"
00053 //#include "BIF_graphics.h"
00054 
00055 
00056 //#include "blendef.h"
00057 
00058 #include "ONL_opennl.h"
00059 
00060 #include "reeb.h"
00061 
00062 #if 0 /* UNUSED 2.5 */
00063 static ReebGraph *GLOBAL_RG = NULL;
00064 static ReebGraph *FILTERED_RG = NULL;
00065 #endif
00066 
00067 /*
00068  * Skeleton generation algorithm based on: 
00069  * "Harmonic Skeleton for Realistic Character Animation"
00070  * Gregoire Aujay, Franck Hetroy, Francis Lazarus and Christine Depraz
00071  * SIGGRAPH 2007
00072  * 
00073  * Reeb graph generation algorithm based on: 
00074  * "Robust On-line Computation of Reeb Graphs: Simplicity and Speed"
00075  * Valerio Pascucci, Giorgio Scorzelli, Peer-Timo Bremer and Ajith Mascarenhas
00076  * SIGGRAPH 2007
00077  * 
00078  * */
00079  
00080 #define DEBUG_REEB
00081 #define DEBUG_REEB_NODE
00082 
00083 typedef struct VertexData
00084 {
00085     float w; /* weight */
00086     int i; /* index */
00087     ReebNode *n;
00088 } VertexData;
00089 
00090 typedef struct EdgeIndex
00091 {
00092     EditEdge **edges;
00093     int      *offset;
00094 } EdgeIndex;
00095 
00096 typedef enum {
00097     MERGE_LOWER,
00098     MERGE_HIGHER,
00099     MERGE_APPEND
00100 } MergeDirection;
00101 
00102 int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1);
00103 void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection direction);
00104 int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1);
00105 EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, int index);
00106 void mergeArcFaces(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc);
00107 void addFacetoArc(ReebArc *arc, EditFace *efa);
00108 
00109 void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count);
00110 void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BArc* barc1, BArc* barc2);
00111 
00112 void flipArcBuckets(ReebArc *arc);
00113 
00114 
00115 /***************************************** UTILS **********************************************/
00116 
00117 static VertexData *allocVertexData(EditMesh *em)
00118 {
00119     VertexData *data;
00120     EditVert *eve;
00121     int totvert, index;
00122     
00123     totvert = BLI_countlist(&em->verts);
00124     
00125     data = MEM_callocN(sizeof(VertexData) * totvert, "VertexData");
00126 
00127     for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next)
00128     {
00129         data[index].i = index;
00130         data[index].w = 0;
00131         eve->tmp.p = data + index;
00132     }
00133         
00134     return data;
00135 }
00136 
00137 static int indexData(EditVert *eve)
00138 {
00139     return ((VertexData*)eve->tmp.p)->i;
00140 }
00141 
00142 static float weightData(EditVert *eve)
00143 {
00144     return ((VertexData*)eve->tmp.p)->w;
00145 }
00146 
00147 static void weightSetData(EditVert *eve, float w)
00148 {
00149     ((VertexData*)eve->tmp.p)->w = w;
00150 }
00151 
00152 static ReebNode* nodeData(EditVert *eve)
00153 {
00154     return ((VertexData*)eve->tmp.p)->n;
00155 }
00156 
00157 static void nodeSetData(EditVert *eve, ReebNode *n)
00158 {
00159     ((VertexData*)eve->tmp.p)->n = n;
00160 }
00161 
00162 void REEB_freeArc(BArc *barc)
00163 {
00164     ReebArc *arc = (ReebArc*)barc;
00165     BLI_freelistN(&arc->edges);
00166     
00167     if (arc->buckets)
00168         MEM_freeN(arc->buckets);
00169         
00170     if (arc->faces)
00171         BLI_ghash_free(arc->faces, NULL, NULL);
00172     
00173     MEM_freeN(arc);
00174 }
00175 
00176 void REEB_freeGraph(ReebGraph *rg)
00177 {
00178     ReebArc *arc;
00179     ReebNode *node;
00180     
00181     // free nodes
00182     for( node = rg->nodes.first; node; node = node->next )
00183     {
00184         BLI_freeNode((BGraph*)rg, (BNode*)node);
00185     }
00186     BLI_freelistN(&rg->nodes);
00187     
00188     // free arcs
00189     arc = rg->arcs.first;
00190     while( arc )
00191     {
00192         ReebArc *next = arc->next;
00193         REEB_freeArc((BArc*)arc);
00194         arc = next;
00195     }
00196     
00197     // free edge map
00198     BLI_edgehash_free(rg->emap, NULL);
00199     
00200     /* free linked graph */
00201     if (rg->link_up)
00202     {
00203         REEB_freeGraph(rg->link_up);
00204     }
00205     
00206     MEM_freeN(rg);
00207 }
00208 
00209 ReebGraph * newReebGraph(void)
00210 {
00211     ReebGraph *rg;
00212     rg = MEM_callocN(sizeof(ReebGraph), "reeb graph");
00213     
00214     rg->totnodes = 0;
00215     rg->emap = BLI_edgehash_new();
00216     
00217     
00218     rg->free_arc = REEB_freeArc;
00219     rg->free_node = NULL;
00220     rg->radial_symmetry = REEB_RadialSymmetry;
00221     rg->axial_symmetry = REEB_AxialSymmetry;
00222     
00223     return rg;
00224 }
00225 
00226 void BIF_flagMultiArcs(ReebGraph *rg, int flag)
00227 {
00228     for ( ; rg; rg = rg->link_up)
00229     {
00230         BLI_flagArcs((BGraph*)rg, flag);
00231     }
00232 }
00233 
00234 static ReebNode * addNode(ReebGraph *rg, EditVert *eve)
00235 {
00236     float weight;
00237     ReebNode *node = NULL;
00238     
00239     weight = weightData(eve);
00240     
00241     node = MEM_callocN(sizeof(ReebNode), "reeb node");
00242     
00243     node->flag = 0; // clear flag on init
00244     node->symmetry_level = 0;
00245     node->arcs = NULL;
00246     node->degree = 0;
00247     node->weight = weight;
00248     node->index = rg->totnodes;
00249     VECCOPY(node->p, eve->co);  
00250     
00251     BLI_addtail(&rg->nodes, node);
00252     rg->totnodes++;
00253     
00254     nodeSetData(eve, node);
00255     
00256     return node;
00257 }
00258 
00259 static ReebNode * copyNode(ReebGraph *rg, ReebNode *node)
00260 {
00261     ReebNode *cp_node = NULL;
00262     
00263     cp_node = MEM_callocN(sizeof(ReebNode), "reeb node copy");
00264     
00265     memcpy(cp_node, node, sizeof(ReebNode));
00266     
00267     cp_node->prev = NULL;
00268     cp_node->next = NULL;
00269     cp_node->arcs = NULL;
00270     
00271     cp_node->link_up = NULL;
00272     cp_node->link_down = NULL;
00273     
00274     BLI_addtail(&rg->nodes, cp_node);
00275     rg->totnodes++;
00276     
00277     return cp_node; 
00278 }
00279 
00280 static void relinkNodes(ReebGraph *low_rg, ReebGraph *high_rg)
00281 {
00282     ReebNode *low_node, *high_node;
00283     
00284     if (low_rg == NULL || high_rg == NULL)
00285     {
00286         return;
00287     }
00288     
00289     for (low_node = low_rg->nodes.first; low_node; low_node = low_node->next)
00290     {
00291         for (high_node = high_rg->nodes.first; high_node; high_node = high_node->next)
00292         {
00293             if (low_node->index == high_node->index)
00294             {
00295                 high_node->link_down = low_node;
00296                 low_node->link_up = high_node;
00297                 break;
00298             }
00299         }
00300     }
00301 }
00302 
00303 ReebNode *BIF_otherNodeFromIndex(ReebArc *arc, ReebNode *node)
00304 {
00305     return (arc->head->index == node->index) ? arc->tail : arc->head;
00306 }
00307 
00308 ReebNode *BIF_NodeFromIndex(ReebArc *arc, ReebNode *node)
00309 {
00310     return (arc->head->index == node->index) ? arc->head : arc->tail;
00311 }
00312 
00313 ReebNode *BIF_lowestLevelNode(ReebNode *node)
00314 {
00315     while (node->link_down)
00316     {
00317         node = node->link_down;
00318     }
00319     
00320     return node;
00321 }
00322 
00323 static ReebArc * copyArc(ReebGraph *rg, ReebArc *arc)
00324 {
00325     ReebArc *cp_arc;
00326     ReebNode *node;
00327     
00328     cp_arc = MEM_callocN(sizeof(ReebArc), "reeb arc copy");
00329 
00330     memcpy(cp_arc, arc, sizeof(ReebArc));
00331     
00332     cp_arc->link_up = arc;
00333     
00334     cp_arc->head = NULL;
00335     cp_arc->tail = NULL;
00336 
00337     cp_arc->prev = NULL;
00338     cp_arc->next = NULL;
00339 
00340     cp_arc->edges.first = NULL;
00341     cp_arc->edges.last = NULL;
00342 
00343     /* copy buckets */  
00344     cp_arc->buckets = MEM_callocN(sizeof(EmbedBucket) * cp_arc->bcount, "embed bucket");
00345     memcpy(cp_arc->buckets, arc->buckets, sizeof(EmbedBucket) * cp_arc->bcount);
00346     
00347     /* copy faces map */
00348     cp_arc->faces = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "copyArc gh");
00349     mergeArcFaces(rg, cp_arc, arc);
00350     
00351     /* find corresponding head and tail */
00352     for (node = rg->nodes.first; node && (cp_arc->head == NULL || cp_arc->tail == NULL); node = node->next)
00353     {
00354         if (node->index == arc->head->index)
00355         {
00356             cp_arc->head = node;
00357         }
00358         else if (node->index == arc->tail->index)
00359         {
00360             cp_arc->tail = node;
00361         }
00362     }
00363     
00364     BLI_addtail(&rg->arcs, cp_arc);
00365     
00366     return cp_arc;
00367 }
00368 
00369 static ReebGraph * copyReebGraph(ReebGraph *rg, int level)
00370 {
00371     ReebNode *node;
00372     ReebArc *arc;
00373     ReebGraph *cp_rg = newReebGraph();
00374     
00375     cp_rg->resolution = rg->resolution;
00376     cp_rg->length = rg->length;
00377     cp_rg->link_up = rg;
00378     cp_rg->multi_level = level;
00379 
00380     /* Copy nodes */    
00381     for (node = rg->nodes.first; node; node = node->next)
00382     {
00383         ReebNode *cp_node = copyNode(cp_rg, node);
00384         cp_node->multi_level = level;
00385     }
00386     
00387     /* Copy arcs */
00388     for (arc = rg->arcs.first; arc; arc = arc->next)
00389     {
00390         copyArc(cp_rg, arc);
00391     }
00392     
00393     BLI_buildAdjacencyList((BGraph*)cp_rg);
00394     
00395     return cp_rg;
00396 }
00397 
00398 ReebGraph *BIF_graphForMultiNode(ReebGraph *rg, ReebNode *node)
00399 {
00400     ReebGraph *multi_rg = rg;
00401     
00402     while(multi_rg && multi_rg->multi_level != node->multi_level)
00403     {
00404         multi_rg = multi_rg->link_up;
00405     }
00406     
00407     return multi_rg;
00408 }
00409 
00410 static ReebEdge * copyEdge(ReebEdge *edge)
00411 {
00412     ReebEdge *newEdge = NULL;
00413     
00414     newEdge = MEM_callocN(sizeof(ReebEdge), "reeb edge");
00415     memcpy(newEdge, edge, sizeof(ReebEdge));
00416     
00417     newEdge->next = NULL;
00418     newEdge->prev = NULL;
00419     
00420     return newEdge;
00421 }
00422 
00423 static void printArc(ReebArc *arc)
00424 {
00425     ReebEdge *edge;
00426     ReebNode *head = (ReebNode*)arc->head;
00427     ReebNode *tail = (ReebNode*)arc->tail;
00428     printf("arc: (%i) %f -> (%i) %f\n", head->index, head->weight, tail->index, tail->weight);
00429     
00430     for(edge = arc->edges.first; edge ; edge = edge->next)
00431     {
00432         printf("\tedge (%i, %i)\n", edge->v1->index, edge->v2->index);
00433     }
00434 }
00435 
00436 static void flipArc(ReebArc *arc)
00437 {
00438     ReebNode *tmp;
00439     tmp = arc->head;
00440     arc->head = arc->tail;
00441     arc->tail = tmp;
00442     
00443     flipArcBuckets(arc);
00444 }
00445 
00446 #ifdef DEBUG_REEB_NODE
00447 static void NodeDegreeDecrement(ReebGraph *UNUSED(rg), ReebNode *node)
00448 {
00449     node->degree--;
00450 
00451 //  if (node->degree == 0)
00452 //  {
00453 //      printf("would remove node %i\n", node->index);
00454 //  }
00455 }
00456 
00457 static void NodeDegreeIncrement(ReebGraph *UNUSED(rg), ReebNode *node)
00458 {
00459 //  if (node->degree == 0)
00460 //  {
00461 //      printf("first connect node %i\n", node->index);
00462 //  }
00463 
00464     node->degree++;
00465 }
00466 
00467 #else
00468 #define NodeDegreeDecrement(rg, node) {node->degree--;}
00469 #define NodeDegreeIncrement(rg, node) {node->degree++;}
00470 #endif
00471 
00472 void repositionNodes(ReebGraph *rg)
00473 {
00474     BArc *arc = NULL;
00475     BNode *node = NULL;
00476     
00477     // Reset node positions
00478     for(node = rg->nodes.first; node; node = node->next)
00479     {
00480         node->p[0] = node->p[1] = node->p[2] = 0;
00481     }
00482     
00483     for(arc = rg->arcs.first; arc; arc = arc->next)
00484     {
00485         if (((ReebArc*)arc)->bcount > 0)
00486         {
00487             float p[3];
00488             
00489             VECCOPY(p, ((ReebArc*)arc)->buckets[0].p);
00490             mul_v3_fl(p, 1.0f / arc->head->degree);
00491             add_v3_v3(arc->head->p, p);
00492             
00493             VECCOPY(p, ((ReebArc*)arc)->buckets[((ReebArc*)arc)->bcount - 1].p);
00494             mul_v3_fl(p, 1.0f / arc->tail->degree);
00495             add_v3_v3(arc->tail->p, p);
00496         }
00497     }
00498 }
00499 
00500 void verifyNodeDegree(ReebGraph *rg)
00501 {
00502 #ifdef DEBUG_REEB
00503     ReebNode *node = NULL;
00504     ReebArc *arc = NULL;
00505 
00506     for(node = rg->nodes.first; node; node = node->next)
00507     {
00508         int count = 0;
00509         for(arc = rg->arcs.first; arc; arc = arc->next)
00510         {
00511             if (arc->head == node || arc->tail == node)
00512             {
00513                 count++;
00514             }
00515         }
00516         if (count != node->degree)
00517         {
00518             printf("degree error in node %i: expected %i got %i\n", node->index, count, node->degree);
00519         }
00520         if (node->degree == 0)
00521         {
00522             printf("zero degree node %i with weight %f\n", node->index, node->weight);
00523         }
00524     }
00525 #endif
00526 }
00527 
00528 static void verifyBucketsArc(ReebGraph *UNUSED(rg), ReebArc *arc)
00529 {
00530     ReebNode *head = (ReebNode*)arc->head;
00531     ReebNode *tail = (ReebNode*)arc->tail;
00532 
00533     if (arc->bcount > 0)
00534     {
00535         int i;
00536         for(i = 0; i < arc->bcount; i++)
00537         {
00538             if (arc->buckets[i].nv == 0)
00539             {
00540                 printArc(arc);
00541                 printf("count error in bucket %i/%i\n", i+1, arc->bcount);
00542             }
00543         }
00544         
00545         if (ceilf(head->weight) != arc->buckets[0].val)
00546         {
00547             printArc(arc);
00548             printf("alloc error in first bucket: %f should be %f \n", arc->buckets[0].val, ceil(head->weight));
00549         }
00550         if (floorf(tail->weight) != arc->buckets[arc->bcount - 1].val)
00551         {
00552             printArc(arc);
00553             printf("alloc error in last bucket: %f should be %f \n", arc->buckets[arc->bcount - 1].val, floor(tail->weight));
00554         }
00555     }
00556 }
00557 
00558 void verifyBuckets(ReebGraph *rg)
00559 {
00560 #ifdef DEBUG_REEB
00561     ReebArc *arc = NULL;
00562     for(arc = rg->arcs.first; arc; arc = arc->next)
00563     {
00564         verifyBucketsArc(rg, arc);
00565     }
00566 #endif
00567 }
00568 
00569 void verifyFaces(ReebGraph *rg)
00570 {
00571 #ifdef DEBUG_REEB
00572     int total = 0;
00573     ReebArc *arc = NULL;
00574     for(arc = rg->arcs.first; arc; arc = arc->next)
00575     {
00576         total += BLI_ghash_size(arc->faces);
00577     }
00578     
00579 #endif
00580 }
00581 
00582 void verifyArcs(ReebGraph *rg)
00583 {
00584     ReebArc *arc;
00585     
00586     for (arc = rg->arcs.first; arc; arc = arc->next)
00587     {
00588         if (arc->head->weight > arc->tail->weight)
00589         {
00590             printf("FLIPPED ARC!\n");
00591         }
00592     }
00593 }
00594 
00595 static void verifyMultiResolutionLinks(ReebGraph *rg, int level)
00596 {
00597 #ifdef DEBUG_REEB
00598     ReebGraph *lower_rg = rg->link_up;
00599     
00600     if (lower_rg)
00601     {
00602         ReebArc *arc;
00603         
00604         for (arc = rg->arcs.first; arc; arc = arc->next)
00605         {
00606             if (BLI_findindex(&lower_rg->arcs, arc->link_up) == -1)
00607             {
00608                 printf("missing arc %p for level %i\n", (void *)arc->link_up, level);
00609                 printf("Source arc was ---\n");
00610                 printArc(arc);
00611 
00612                 arc->link_up = NULL;
00613             }
00614         }
00615         
00616         
00617         verifyMultiResolutionLinks(lower_rg, level + 1);
00618     }
00619 #endif
00620 }
00621 /***************************************** BUCKET UTILS **********************************************/
00622 
00623 static void addVertToBucket(EmbedBucket *b, float co[3])
00624 {
00625     b->nv++;
00626     interp_v3_v3v3(b->p, b->p, co, 1.0f / b->nv);
00627 }
00628 
00629 #if 0 /* UNUSED 2.5 */
00630 static void removeVertFromBucket(EmbedBucket *b, float co[3])
00631 {
00632     mul_v3_fl(b->p, (float)b->nv);
00633     sub_v3_v3(b->p, co);
00634     b->nv--;
00635     mul_v3_fl(b->p, 1.0f / (float)b->nv);
00636 }
00637 #endif
00638 
00639 static void mergeBuckets(EmbedBucket *bDst, EmbedBucket *bSrc)
00640 {
00641     if (bDst->nv > 0 && bSrc->nv > 0)
00642     {
00643         bDst->nv += bSrc->nv;
00644         interp_v3_v3v3(bDst->p, bDst->p, bSrc->p, (float)bSrc->nv / (float)(bDst->nv));
00645     }
00646     else if (bSrc->nv > 0)
00647     {
00648         bDst->nv = bSrc->nv;
00649         VECCOPY(bDst->p, bSrc->p);
00650     }
00651 }
00652 
00653 static void mergeArcBuckets(ReebArc *aDst, ReebArc *aSrc, float start, float end)
00654 {
00655     if (aDst->bcount > 0 && aSrc->bcount > 0)
00656     {
00657         int indexDst = 0, indexSrc = 0;
00658         
00659         start = MAX3(start, aDst->buckets[0].val, aSrc->buckets[0].val);
00660         
00661         while(indexDst < aDst->bcount && aDst->buckets[indexDst].val < start)
00662         {
00663             indexDst++;
00664         }
00665 
00666         while(indexSrc < aSrc->bcount && aSrc->buckets[indexSrc].val < start)
00667         {
00668             indexSrc++;
00669         }
00670         
00671         for( ;  indexDst < aDst->bcount &&
00672                 indexSrc < aSrc->bcount &&
00673                 aDst->buckets[indexDst].val <= end &&
00674                 aSrc->buckets[indexSrc].val <= end
00675                 
00676              ;  indexDst++, indexSrc++)
00677         {
00678             mergeBuckets(aDst->buckets + indexDst, aSrc->buckets + indexSrc);
00679         }
00680     }
00681 }
00682 
00683 void flipArcBuckets(ReebArc *arc)
00684 {
00685     int i, j;
00686     
00687     for (i = 0, j = arc->bcount - 1; i < j; i++, j--)
00688     {
00689         EmbedBucket tmp;
00690         
00691         tmp = arc->buckets[i];
00692         arc->buckets[i] = arc->buckets[j];
00693         arc->buckets[j] = tmp;
00694     }
00695 }
00696 
00697 static int countArcBuckets(ReebArc *arc)
00698 {
00699     return (int)(floor(arc->tail->weight) - ceil(arc->head->weight)) + 1;
00700 }
00701 
00702 static void allocArcBuckets(ReebArc *arc)
00703 {
00704     int i;
00705     float start = ceil(arc->head->weight);
00706     arc->bcount = countArcBuckets(arc);
00707     
00708     if (arc->bcount > 0)
00709     {
00710         arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "embed bucket");
00711         
00712         for(i = 0; i < arc->bcount; i++)
00713         {
00714             arc->buckets[i].val = start + i;
00715         }
00716     }
00717     else
00718     {
00719         arc->buckets = NULL;
00720     }
00721     
00722 }
00723 
00724 static void resizeArcBuckets(ReebArc *arc)
00725 {
00726     EmbedBucket *oldBuckets = arc->buckets;
00727     int oldBCount = arc->bcount;
00728     
00729     if (countArcBuckets(arc) == oldBCount)
00730     {
00731         return;
00732     }
00733     
00734     allocArcBuckets(arc);
00735     
00736     if (oldBCount != 0 && arc->bcount != 0)
00737     {
00738         int oldStart = (int)oldBuckets[0].val;
00739         int oldEnd = (int)oldBuckets[oldBCount - 1].val;
00740         int newStart = (int)arc->buckets[0].val;
00741         int newEnd = (int)arc->buckets[arc->bcount - 1].val;
00742         int oldOffset = 0;
00743         int newOffset = 0;
00744         int len;
00745         
00746         if (oldStart < newStart)
00747         {
00748             oldOffset = newStart - oldStart;
00749         }
00750         else
00751         {
00752             newOffset = oldStart - newStart;
00753         }
00754         
00755         len = MIN2(oldEnd - (oldStart + oldOffset) + 1, newEnd - (newStart - newOffset) + 1);
00756         
00757         memcpy(arc->buckets + newOffset, oldBuckets + oldOffset, len * sizeof(EmbedBucket)); 
00758     }
00759 
00760     if (oldBuckets != NULL)
00761     {
00762         MEM_freeN(oldBuckets);
00763     }
00764 }
00765 
00766 static void reweightBuckets(ReebArc *arc)
00767 {
00768     int i;
00769     float start = ceil((arc->head)->weight);
00770     
00771     if (arc->bcount > 0)
00772     {
00773         for(i = 0; i < arc->bcount; i++)
00774         {
00775             arc->buckets[i].val = start + i;
00776         }
00777     }
00778 }
00779 
00780 static void interpolateBuckets(ReebArc *arc, float *start_p, float *end_p, int start_index, int end_index)
00781 {
00782     int total;
00783     int j;
00784     
00785     total = end_index - start_index + 2;
00786     
00787     for (j = start_index; j <= end_index; j++)
00788     {
00789         EmbedBucket *empty = arc->buckets + j;
00790         empty->nv = 1;
00791         interp_v3_v3v3(empty->p, start_p, end_p, (float)(j - start_index + 1) / total);
00792     }
00793 }
00794 
00795 static void fillArcEmptyBuckets(ReebArc *arc)
00796 {
00797     float *start_p, *end_p;
00798     int start_index = 0, end_index = 0;
00799     int missing = 0;
00800     int i;
00801     
00802     start_p = arc->head->p;
00803     
00804     for(i = 0; i < arc->bcount; i++)
00805     {
00806         EmbedBucket *bucket = arc->buckets + i;
00807         
00808         if (missing)
00809         {
00810             if (bucket->nv > 0)
00811             {
00812                 missing = 0;
00813                 
00814                 end_p = bucket->p;
00815                 end_index = i - 1;
00816                 
00817                 interpolateBuckets(arc, start_p, end_p, start_index, end_index);
00818             }
00819         }
00820         else
00821         {
00822             if (bucket->nv == 0)
00823             {
00824                 missing = 1;
00825                 
00826                 if (i > 0)
00827                 {
00828                     start_p = arc->buckets[i - 1].p;
00829                 }
00830                 start_index = i;
00831             }
00832         }
00833     }
00834     
00835     if (missing)
00836     {
00837         end_p = arc->tail->p;
00838         end_index = arc->bcount - 1;
00839         
00840         interpolateBuckets(arc, start_p, end_p, start_index, end_index);
00841     }
00842 }
00843 
00844 static void ExtendArcBuckets(ReebArc *arc)
00845 {
00846     ReebArcIterator arc_iter;
00847     BArcIterator *iter = (BArcIterator*)&arc_iter;
00848     EmbedBucket *last_bucket, *first_bucket;
00849     float *previous = NULL;
00850     float average_length = 0, length;
00851     int padding_head = 0, padding_tail = 0;
00852     
00853     if (arc->bcount == 0)
00854     {
00855         return; /* failsafe, shouldn't happen */
00856     }
00857     
00858     initArcIterator(iter, arc, arc->head);
00859     IT_next(iter);
00860     previous = iter->p;
00861     
00862     for (   IT_next(iter);
00863             IT_stopped(iter) == 0;
00864             previous = iter->p, IT_next(iter)
00865         )
00866     {
00867         average_length += len_v3v3(previous, iter->p);
00868     }
00869     average_length /= (arc->bcount - 1);
00870     
00871     first_bucket = arc->buckets;
00872     last_bucket = arc->buckets + (arc->bcount - 1);
00873     
00874     length = len_v3v3(first_bucket->p, arc->head->p);
00875     if (length > 2 * average_length)
00876     {
00877         padding_head = (int)floor(length / average_length);
00878     }
00879 
00880     length = len_v3v3(last_bucket->p, arc->tail->p);
00881     if (length > 2 * average_length)
00882     {
00883         padding_tail = (int)floor(length / average_length);
00884     }
00885     
00886     if (padding_head + padding_tail > 0)
00887     {
00888         EmbedBucket *old_buckets = arc->buckets;
00889         
00890         arc->buckets = MEM_callocN(sizeof(EmbedBucket) * (padding_head + arc->bcount + padding_tail), "embed bucket");
00891         memcpy(arc->buckets + padding_head, old_buckets, arc->bcount * sizeof(EmbedBucket));
00892         
00893         arc->bcount = padding_head + arc->bcount + padding_tail;
00894         
00895         MEM_freeN(old_buckets);
00896     }
00897     
00898     if (padding_head > 0)
00899     {
00900         interpolateBuckets(arc, arc->head->p, first_bucket->p, 0, padding_head);
00901     }
00902     
00903     if (padding_tail > 0)
00904     {
00905         interpolateBuckets(arc, last_bucket->p, arc->tail->p, arc->bcount - padding_tail, arc->bcount - 1);
00906     }
00907 }
00908 
00909 /* CALL THIS ONLY AFTER FILTERING, SINCE IT MESSES UP WEIGHT DISTRIBUTION */
00910 static void extendGraphBuckets(ReebGraph *rg)
00911 {
00912     ReebArc *arc;
00913     
00914     for (arc = rg->arcs.first; arc; arc = arc->next)
00915     {
00916         ExtendArcBuckets(arc);
00917     }
00918 }
00919 
00920 /**************************************** LENGTH CALCULATIONS ****************************************/
00921 
00922 static void calculateArcLength(ReebArc *arc)
00923 {
00924     ReebArcIterator arc_iter;
00925     BArcIterator *iter = (BArcIterator*)&arc_iter;
00926     float *vec0, *vec1;
00927 
00928     arc->length = 0;
00929     
00930     initArcIterator(iter, arc, arc->head);
00931 
00932     vec0 = arc->head->p;
00933     vec1 = arc->head->p; /* in case there's no embedding */
00934 
00935     while (IT_next(iter))   
00936     {
00937         vec1 = iter->p;
00938         
00939         arc->length += len_v3v3(vec0, vec1);
00940         
00941         vec0 = vec1;
00942     }
00943     
00944     arc->length += len_v3v3(arc->tail->p, vec1);    
00945 }
00946 
00947 static void calculateGraphLength(ReebGraph *rg)
00948 {
00949     ReebArc *arc;
00950     
00951     for (arc = rg->arcs.first; arc; arc = arc->next)
00952     {
00953         calculateArcLength(arc);
00954     }
00955 }
00956 
00957 /**************************************** SYMMETRY HANDLING ******************************************/
00958 
00959 void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count)
00960 {
00961     ReebNode *node = (ReebNode*)root_node;
00962     float axis[3];
00963     int i;
00964     
00965     VECCOPY(axis, root_node->symmetry_axis);
00966     
00967     /* first pass, merge incrementally */
00968     for (i = 0; i < count - 1; i++)
00969     {
00970         ReebNode *node1, *node2;
00971         ReebArc *arc1, *arc2;
00972         float tangent[3];
00973         float normal[3];
00974         int j = i + 1;
00975 
00976         add_v3_v3v3(tangent, ring[i].n, ring[j].n);
00977         cross_v3_v3v3(normal, tangent, axis);
00978         
00979         node1 = (ReebNode*)BLI_otherNode(ring[i].arc, root_node);
00980         node2 = (ReebNode*)BLI_otherNode(ring[j].arc, root_node);
00981         
00982         arc1 = (ReebArc*)ring[i].arc;
00983         arc2 = (ReebArc*)ring[j].arc;
00984 
00985         /* mirror first node and mix with the second */
00986         BLI_mirrorAlongAxis(node1->p, root_node->p, normal);
00987         interp_v3_v3v3(node2->p, node2->p, node1->p, 1.0f / (j + 1));
00988         
00989         /* Merge buckets
00990          * there shouldn't be any null arcs here, but just to be safe 
00991          * */
00992         if (arc1->bcount > 0 && arc2->bcount > 0)
00993         {
00994             ReebArcIterator arc_iter1, arc_iter2;
00995             BArcIterator *iter1 = (BArcIterator*)&arc_iter1;
00996             BArcIterator *iter2 = (BArcIterator*)&arc_iter2;
00997             EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
00998             
00999             initArcIterator(iter1, arc1, (ReebNode*)root_node);
01000             initArcIterator(iter2, arc2, (ReebNode*)root_node);
01001             
01002             bucket1 = IT_next(iter1);
01003             bucket2 = IT_next(iter2);
01004         
01005             /* Make sure they both start at the same value */   
01006             while(bucket1 && bucket2 && bucket1->val < bucket2->val)
01007             {
01008                 bucket1 = IT_next(iter1);
01009             }
01010             
01011             while(bucket1 && bucket2 && bucket2->val < bucket1->val)
01012             {
01013                 bucket2 = IT_next(iter2);
01014             }
01015     
01016     
01017             for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2))
01018             {
01019                 bucket2->nv += bucket1->nv; /* add counts */
01020                 
01021                 /* mirror on axis */
01022                 BLI_mirrorAlongAxis(bucket1->p, root_node->p, normal);
01023                 /* add bucket2 in bucket1 */
01024                 interp_v3_v3v3(bucket2->p, bucket2->p, bucket1->p, (float)bucket1->nv / (float)(bucket2->nv));
01025             }
01026         }
01027     }
01028     
01029     /* second pass, mirror back on previous arcs */
01030     for (i = count - 1; i > 0; i--)
01031     {
01032         ReebNode *node1, *node2;
01033         ReebArc *arc1, *arc2;
01034         float tangent[3];
01035         float normal[3];
01036         int j = i - 1;
01037 
01038         add_v3_v3v3(tangent, ring[i].n, ring[j].n);
01039         cross_v3_v3v3(normal, tangent, axis);
01040         
01041         node1 = (ReebNode*)BLI_otherNode(ring[i].arc, root_node);
01042         node2 = (ReebNode*)BLI_otherNode(ring[j].arc, root_node);
01043         
01044         arc1 = (ReebArc*)ring[i].arc;
01045         arc2 = (ReebArc*)ring[j].arc;
01046 
01047         /* copy first node than mirror */
01048         VECCOPY(node2->p, node1->p);
01049         BLI_mirrorAlongAxis(node2->p, root_node->p, normal);
01050         
01051         /* Copy buckets
01052          * there shouldn't be any null arcs here, but just to be safe 
01053          * */
01054         if (arc1->bcount > 0 && arc2->bcount > 0)
01055         {
01056             ReebArcIterator arc_iter1, arc_iter2;
01057             BArcIterator *iter1 = (BArcIterator*)&arc_iter1;
01058             BArcIterator *iter2 = (BArcIterator*)&arc_iter2;
01059             EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
01060             
01061             initArcIterator(iter1, arc1, node);
01062             initArcIterator(iter2, arc2, node);
01063             
01064             bucket1 = IT_next(iter1);
01065             bucket2 = IT_next(iter2);
01066         
01067             /* Make sure they both start at the same value */   
01068             while(bucket1 && bucket1->val < bucket2->val)
01069             {
01070                 bucket1 = IT_next(iter1);
01071             }
01072             
01073             while(bucket2 && bucket2->val < bucket1->val)
01074             {
01075                 bucket2 = IT_next(iter2);
01076             }
01077     
01078     
01079             for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2))
01080             {
01081                 /* copy and mirror back to bucket2 */           
01082                 bucket2->nv = bucket1->nv;
01083                 VECCOPY(bucket2->p, bucket1->p);
01084                 BLI_mirrorAlongAxis(bucket2->p, node->p, normal);
01085             }
01086         }
01087     }
01088 }
01089 
01090 void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BArc* barc1, BArc* barc2)
01091 {
01092     ReebArc *arc1, *arc2;
01093     float nor[3], p[3];
01094 
01095     arc1 = (ReebArc*)barc1;
01096     arc2 = (ReebArc*)barc2;
01097 
01098     VECCOPY(nor, root_node->symmetry_axis);
01099     
01100     /* mirror node2 along axis */
01101     VECCOPY(p, node2->p);
01102     BLI_mirrorAlongAxis(p, root_node->p, nor);
01103 
01104     /* average with node1 */
01105     add_v3_v3(node1->p, p);
01106     mul_v3_fl(node1->p, 0.5f);
01107     
01108     /* mirror back on node2 */
01109     VECCOPY(node2->p, node1->p);
01110     BLI_mirrorAlongAxis(node2->p, root_node->p, nor);
01111     
01112     /* Merge buckets
01113      * there shouldn't be any null arcs here, but just to be safe 
01114      * */
01115     if (arc1->bcount > 0 && arc2->bcount > 0)
01116     {
01117         ReebArcIterator arc_iter1, arc_iter2;
01118         BArcIterator *iter1 = (BArcIterator*)&arc_iter1;
01119         BArcIterator *iter2 = (BArcIterator*)&arc_iter2;
01120         EmbedBucket *bucket1 = NULL, *bucket2 = NULL;
01121         
01122         initArcIterator(iter1, arc1, (ReebNode*)root_node);
01123         initArcIterator(iter2, arc2, (ReebNode*)root_node);
01124         
01125         bucket1 = IT_next(iter1);
01126         bucket2 = IT_next(iter2);
01127     
01128         /* Make sure they both start at the same value */   
01129         while(bucket1 && bucket1->val < bucket2->val)
01130         {
01131             bucket1 = IT_next(iter1);
01132         }
01133         
01134         while(bucket2 && bucket2->val < bucket1->val)
01135         {
01136             bucket2 = IT_next(iter2);
01137         }
01138 
01139 
01140         for ( ;bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2))
01141         {
01142             bucket1->nv += bucket2->nv; /* add counts */
01143             
01144             /* mirror on axis */
01145             BLI_mirrorAlongAxis(bucket2->p, root_node->p, nor);
01146             /* add bucket2 in bucket1 */
01147             interp_v3_v3v3(bucket1->p, bucket1->p, bucket2->p, (float)bucket2->nv / (float)(bucket1->nv));
01148 
01149             /* copy and mirror back to bucket2 */           
01150             bucket2->nv = bucket1->nv;
01151             VECCOPY(bucket2->p, bucket1->p);
01152             BLI_mirrorAlongAxis(bucket2->p, root_node->p, nor);
01153         }
01154     }
01155 }
01156 
01157 /************************************** ADJACENCY LIST *************************************************/
01158 
01159 
01160 /****************************************** SMOOTHING **************************************************/
01161 
01162 void postprocessGraph(ReebGraph *rg, char mode)
01163 {
01164     ReebArc *arc;
01165     float fac1 = 0, fac2 = 1, fac3 = 0;
01166 
01167     switch(mode)
01168     {
01169     case SKGEN_AVERAGE:
01170         fac1 = fac2 = fac3 = 1.0f / 3.0f;
01171         break;
01172     case SKGEN_SMOOTH:
01173         fac1 = fac3 = 0.25f;
01174         fac2 = 0.5f;
01175         break;
01176     case SKGEN_SHARPEN:
01177         fac1 = fac2 = -0.25f;
01178         fac2 = 1.5f;
01179         break;
01180     default:
01181 //      XXX
01182 //      error("Unknown post processing mode");
01183         return;
01184     }
01185     
01186     for(arc = rg->arcs.first; arc; arc = arc->next)
01187     {
01188         EmbedBucket *buckets = arc->buckets;
01189         int bcount = arc->bcount;
01190         int index;
01191 
01192         for(index = 1; index < bcount - 1; index++)
01193         {
01194             interp_v3_v3v3(buckets[index].p, buckets[index].p, buckets[index - 1].p, fac1 / (fac1 + fac2));
01195             interp_v3_v3v3(buckets[index].p, buckets[index].p, buckets[index + 1].p, fac3 / (fac1 + fac2 + fac3));
01196         }
01197     }
01198 }
01199 
01200 /********************************************SORTING****************************************************/
01201 
01202 static int compareNodesWeight(void *vnode1, void *vnode2)
01203 {
01204     ReebNode *node1 = (ReebNode*)vnode1;
01205     ReebNode *node2 = (ReebNode*)vnode2;
01206     
01207     if (node1->weight < node2->weight)
01208     {
01209         return -1;
01210     }
01211     if (node1->weight > node2->weight)
01212     {
01213         return 1;
01214     }
01215     else
01216     {
01217         return 0;
01218     }
01219 }
01220 
01221 void sortNodes(ReebGraph *rg)
01222 {
01223     BLI_sortlist(&rg->nodes, compareNodesWeight);
01224 }
01225 
01226 static int compareArcsWeight(void *varc1, void *varc2)
01227 {
01228     ReebArc *arc1 = (ReebArc*)varc1;
01229     ReebArc *arc2 = (ReebArc*)varc2;
01230     ReebNode *node1 = (ReebNode*)arc1->head; 
01231     ReebNode *node2 = (ReebNode*)arc2->head; 
01232     
01233     if (node1->weight < node2->weight)
01234     {
01235         return -1;
01236     }
01237     if (node1->weight > node2->weight)
01238     {
01239         return 1;
01240     }
01241     else
01242     {
01243         return 0;
01244     }
01245 }
01246 
01247 void sortArcs(ReebGraph *rg)
01248 {
01249     BLI_sortlist(&rg->arcs, compareArcsWeight);
01250 }
01251 /******************************************* JOINING ***************************************************/
01252 
01253 static void reweightArc(ReebGraph *rg, ReebArc *arc, ReebNode *start_node, float start_weight)
01254 {
01255     ReebNode *node;
01256     float old_weight;
01257     float end_weight = start_weight + ABS(arc->tail->weight - arc->head->weight);
01258     int i;
01259     
01260     node = (ReebNode*)BLI_otherNode((BArc*)arc, (BNode*)start_node);
01261     
01262     /* prevent backtracking */
01263     if (node->flag == 1)
01264     {
01265         return;
01266     }
01267 
01268     if (arc->tail == start_node)
01269     {
01270         flipArc(arc);
01271     }
01272     
01273     start_node->flag = 1;
01274     
01275     for (i = 0; i < node->degree; i++)
01276     {
01277         ReebArc *next_arc = node->arcs[i];
01278         
01279         reweightArc(rg, next_arc, node, end_weight);
01280     }
01281 
01282     /* update only if needed */ 
01283     if (arc->head->weight != start_weight || arc->tail->weight != end_weight)
01284     {
01285         old_weight = arc->head->weight; /* backup head weight, other arcs need it intact, it will be fixed by the source arc */
01286         
01287         arc->head->weight = start_weight;
01288         arc->tail->weight = end_weight;
01289         
01290         reweightBuckets(arc);
01291         resizeArcBuckets(arc);
01292         fillArcEmptyBuckets(arc);
01293         
01294         arc->head->weight = old_weight;
01295     }
01296 } 
01297 
01298 static void reweightSubgraph(ReebGraph *rg, ReebNode *start_node, float start_weight)
01299 {
01300     int i;
01301         
01302     BLI_flagNodes((BGraph*)rg, 0);
01303 
01304     for (i = 0; i < start_node->degree; i++)
01305     {
01306         ReebArc *next_arc = start_node->arcs[i];
01307         
01308         reweightArc(rg, next_arc, start_node, start_weight);
01309     }
01310     start_node->weight = start_weight;
01311 }
01312 
01313 static int joinSubgraphsEnds(ReebGraph *rg, float threshold, int nb_subgraphs)
01314 {
01315     int joined = 0;
01316     int subgraph;
01317     
01318     for (subgraph = 1; subgraph <= nb_subgraphs; subgraph++)
01319     {
01320         ReebNode *start_node, *end_node;
01321         ReebNode *min_node_start = NULL, *min_node_end = NULL;
01322         float min_distance = FLT_MAX;
01323         
01324         for (start_node = rg->nodes.first; start_node; start_node = start_node->next)
01325         {
01326             if (start_node->subgraph_index == subgraph && start_node->degree == 1)
01327             {
01328                 
01329                 for (end_node = rg->nodes.first; end_node; end_node = end_node->next)
01330                 {
01331                     if (end_node->subgraph_index != subgraph)
01332                     {
01333                         float distance = len_v3v3(start_node->p, end_node->p);
01334                         
01335                         if (distance < threshold && distance < min_distance)
01336                         {
01337                             min_distance = distance;
01338                             min_node_end = end_node;
01339                             min_node_start = start_node;
01340                         }
01341                     }
01342                 }
01343             }
01344         }
01345         
01346         end_node = min_node_end;
01347         start_node = min_node_start;
01348         
01349         if (end_node && start_node)
01350         {
01351             ReebArc *start_arc /* , *end_arc */ /* UNUSED */;
01352             int merging = 0;
01353             
01354             start_arc = start_node->arcs[0];
01355             /* end_arc = end_node->arcs[0]; */ /* UNUSED */
01356             
01357             if (start_arc->tail == start_node)
01358             {
01359                 reweightSubgraph(rg, end_node, start_node->weight);
01360                 
01361                 start_arc->tail = end_node;
01362                 
01363                 merging = 1;
01364             }
01365             else if (start_arc->head == start_node)
01366             {
01367                 reweightSubgraph(rg, start_node, end_node->weight);
01368 
01369                 start_arc->head = end_node;
01370 
01371                 merging = 2;
01372             }
01373             
01374             if (merging)
01375             {
01376                 BLI_ReflagSubgraph((BGraph*)rg, end_node->flag, subgraph);
01377                                     
01378                 resizeArcBuckets(start_arc);
01379                 fillArcEmptyBuckets(start_arc);
01380                 
01381                 NodeDegreeIncrement(rg, end_node);
01382                 BLI_rebuildAdjacencyListForNode((BGraph*)rg, (BNode*)end_node);
01383                 
01384                 BLI_removeNode((BGraph*)rg, (BNode*)start_node);
01385             }
01386             
01387             joined = 1;
01388         }       
01389     }
01390     
01391     return joined;
01392 }
01393 
01394 /* Reweight graph from smallest node, fix fliped arcs */
01395 static void fixSubgraphsOrientation(ReebGraph *rg, int nb_subgraphs)
01396 {
01397     int subgraph;
01398     
01399     for (subgraph = 1; subgraph <= nb_subgraphs; subgraph++)
01400     {
01401         ReebNode *node;
01402         ReebNode *start_node = NULL;
01403         
01404         for (node = rg->nodes.first; node; node = node->next)
01405         {
01406             if (node->subgraph_index == subgraph)
01407             {
01408                 if (start_node == NULL || node->weight < start_node->weight)
01409                 {
01410                     start_node = node;
01411                 }
01412             }
01413         }
01414         
01415         if (start_node)
01416         {
01417             reweightSubgraph(rg, start_node, start_node->weight);
01418         }
01419     }
01420 }
01421 
01422 static int joinSubgraphs(ReebGraph *rg, float threshold)
01423 {
01424     int nb_subgraphs;
01425     int joined = 0;
01426     
01427     BLI_buildAdjacencyList((BGraph*)rg);
01428     
01429     if (BLI_isGraphCyclic((BGraph*)rg))
01430     {
01431         /* don't deal with cyclic graphs YET */
01432         return 0;
01433     }
01434     
01435     /* sort nodes before flagging subgraphs to make sure root node is subgraph 0 */
01436     sortNodes(rg);
01437     
01438     nb_subgraphs = BLI_FlagSubgraphs((BGraph*)rg);
01439     
01440     /* Harmonic function can create flipped arcs, take the occasion to fix them */
01441 //  XXX
01442 //  if (G.scene->toolsettings->skgen_options & SKGEN_HARMONIC)
01443 //  {
01444         fixSubgraphsOrientation(rg, nb_subgraphs);
01445 //  }
01446 
01447     if (nb_subgraphs > 1)
01448     {
01449         joined |= joinSubgraphsEnds(rg, threshold, nb_subgraphs);
01450         
01451         if (joined)
01452         {
01453             removeNormalNodes(rg);
01454             BLI_buildAdjacencyList((BGraph*)rg);
01455         }
01456     }
01457     
01458     return joined;
01459 }
01460 
01461 /****************************************** FILTERING **************************************************/
01462 
01463 static float lengthArc(ReebArc *arc)
01464 {
01465 #if 0
01466     ReebNode *head = (ReebNode*)arc->head;
01467     ReebNode *tail = (ReebNode*)arc->tail;
01468     
01469     return tail->weight - head->weight;
01470 #else
01471     return arc->length;
01472 #endif
01473 }
01474 
01475 static int compareArcs(void *varc1, void *varc2)
01476 {
01477     ReebArc *arc1 = (ReebArc*)varc1;
01478     ReebArc *arc2 = (ReebArc*)varc2;
01479     float len1 = lengthArc(arc1);
01480     float len2 = lengthArc(arc2);
01481     
01482     if (len1 < len2)
01483     {
01484         return -1;
01485     }
01486     if (len1 > len2)
01487     {
01488         return 1;
01489     }
01490     else
01491     {
01492         return 0;
01493     }
01494 }
01495 
01496 static void filterArc(ReebGraph *rg, ReebNode *newNode, ReebNode *removedNode, ReebArc * srcArc, int merging)
01497 {
01498     ReebArc *arc = NULL, *nextArc = NULL;
01499 
01500     if (merging)
01501     {
01502         /* first pass, merge buckets for arcs that spawned the two nodes into the source arc*/
01503         for(arc = rg->arcs.first; arc; arc = arc->next)
01504         {
01505             if (arc->head == srcArc->head && arc->tail == srcArc->tail && arc != srcArc)
01506             {
01507                 ReebNode *head = srcArc->head;
01508                 ReebNode *tail = srcArc->tail;
01509                 mergeArcBuckets(srcArc, arc, head->weight, tail->weight);
01510             }
01511         }
01512     }
01513 
01514     /* second pass, replace removedNode by newNode, remove arcs that are collapsed in a loop */
01515     arc = rg->arcs.first;
01516     while(arc)
01517     {
01518         nextArc = arc->next;
01519         
01520         if (arc->head == removedNode || arc->tail == removedNode)
01521         {
01522             if (arc->head == removedNode)
01523             {
01524                 arc->head = newNode;
01525             }
01526             else
01527             {
01528                 arc->tail = newNode;
01529             }
01530 
01531             // Remove looped arcs           
01532             if (arc->head == arc->tail)
01533             {
01534                 // v1 or v2 was already newNode, since we're removing an arc, decrement degree
01535                 NodeDegreeDecrement(rg, newNode);
01536                 
01537                 // If it's srcArc, it'll be removed later, so keep it for now
01538                 if (arc != srcArc)
01539                 {
01540                     BLI_remlink(&rg->arcs, arc);
01541                     REEB_freeArc((BArc*)arc);
01542                 }
01543             }
01544             else
01545             {
01546                 /* flip arcs that flipped, can happen on diamond shapes, mostly on null arcs */
01547                 if (arc->head->weight > arc->tail->weight)
01548                 {
01549                     flipArc(arc);
01550                 }
01551                 //newNode->degree++; // incrementing degree since we're adding an arc
01552                 NodeDegreeIncrement(rg, newNode);
01553                 mergeArcFaces(rg, arc, srcArc);
01554 
01555                 if (merging)
01556                 {
01557                     ReebNode *head = arc->head;
01558                     ReebNode *tail = arc->tail;
01559 
01560                     // resize bucket list
01561                     resizeArcBuckets(arc);
01562                     mergeArcBuckets(arc, srcArc, head->weight, tail->weight);
01563                     
01564                     /* update length */
01565                     arc->length += srcArc->length;
01566                 }
01567             }
01568         }
01569         
01570         arc = nextArc;
01571     }
01572 }
01573 
01574 void filterNullReebGraph(ReebGraph *rg)
01575 {
01576     ReebArc *arc = NULL, *nextArc = NULL;
01577     
01578     arc = rg->arcs.first;
01579     while(arc)
01580     {
01581         nextArc = arc->next;
01582         // Only collapse arcs too short to have any embed bucket
01583         if (arc->bcount == 0)
01584         {
01585             ReebNode *newNode = (ReebNode*)arc->head;
01586             ReebNode *removedNode = (ReebNode*)arc->tail;
01587             float blend;
01588             
01589             blend = (float)newNode->degree / (float)(newNode->degree + removedNode->degree); // blending factors
01590             
01591             interp_v3_v3v3(newNode->p, removedNode->p, newNode->p, blend);
01592             
01593             filterArc(rg, newNode, removedNode, arc, 0);
01594 
01595             // Reset nextArc, it might have changed
01596             nextArc = arc->next;
01597             
01598             BLI_remlink(&rg->arcs, arc);
01599             REEB_freeArc((BArc*)arc);
01600             
01601             BLI_removeNode((BGraph*)rg, (BNode*)removedNode);
01602         }
01603         
01604         arc = nextArc;
01605     }
01606 }
01607 
01608 static int filterInternalExternalReebGraph(ReebGraph *rg, float threshold_internal, float threshold_external)
01609 {
01610     ReebArc *arc = NULL, *nextArc = NULL;
01611     int value = 0;
01612     
01613     BLI_sortlist(&rg->arcs, compareArcs);
01614     
01615     for (arc = rg->arcs.first; arc; arc = nextArc)
01616     {
01617         nextArc = arc->next;
01618 
01619         // Only collapse non-terminal arcs that are shorter than threshold
01620         if (threshold_internal > 0 && arc->head->degree > 1 && arc->tail->degree > 1 && (lengthArc(arc) < threshold_internal))
01621         {
01622             ReebNode *newNode = NULL;
01623             ReebNode *removedNode = NULL;
01624             
01625             /* Always remove lower node, so arcs don't flip */
01626             newNode = arc->head;
01627             removedNode = arc->tail;
01628 
01629             filterArc(rg, newNode, removedNode, arc, 1);
01630 
01631             // Reset nextArc, it might have changed
01632             nextArc = arc->next;
01633             
01634             BLI_remlink(&rg->arcs, arc);
01635             REEB_freeArc((BArc*)arc);
01636             
01637             BLI_removeNode((BGraph*)rg, (BNode*)removedNode);
01638             value = 1;
01639         }
01640         
01641         // Only collapse terminal arcs that are shorter than threshold
01642         else if (threshold_external > 0 && (arc->head->degree == 1 || arc->tail->degree == 1) && (lengthArc(arc) < threshold_external))
01643         {
01644             ReebNode *terminalNode = NULL;
01645             ReebNode *middleNode = NULL;
01646             ReebNode *removedNode = NULL;
01647             
01648             // Assign terminal and middle nodes
01649             if (arc->head->degree == 1)
01650             {
01651                 terminalNode = arc->head;
01652                 middleNode = arc->tail;
01653             }
01654             else
01655             {
01656                 terminalNode = arc->tail;
01657                 middleNode = arc->head;
01658             }
01659             
01660             if (middleNode->degree == 2 && middleNode != rg->nodes.first)
01661             {
01662 #if 1
01663                 // If middle node is a normal node, it will be removed later
01664                 // Only if middle node is not the root node
01665                 /* USE THIS IF YOU WANT TO PROLONG ARCS TO THEIR TERMINAL NODES
01666                  * FOR HANDS, THIS IS NOT THE BEST RESULT 
01667                  * */
01668                 continue;
01669 #else
01670                 removedNode = terminalNode;
01671 
01672                 // removing arc, so we need to decrease the degree of the remaining node
01673                 NodeDegreeDecrement(rg, middleNode);
01674 #endif
01675             }
01676             // Otherwise, just plain remove of the arc
01677             else
01678             {
01679                 removedNode = terminalNode;
01680 
01681                 // removing arc, so we need to decrease the degree of the remaining node
01682                 NodeDegreeDecrement(rg, middleNode);
01683             }
01684 
01685             // Reset nextArc, it might have changed
01686             nextArc = arc->next;
01687             
01688             BLI_remlink(&rg->arcs, arc);
01689             REEB_freeArc((BArc*)arc);
01690             
01691             BLI_removeNode((BGraph*)rg, (BNode*)removedNode);
01692             value = 1;
01693         }
01694     }
01695     
01696     return value;
01697 }
01698 
01699 static int filterCyclesReebGraph(ReebGraph *rg, float UNUSED(distance_threshold))
01700 {
01701     ReebArc *arc1, *arc2;
01702     ReebArc *next2;
01703     int filtered = 0;
01704     
01705     for (arc1 = rg->arcs.first; arc1; arc1 = arc1->next)
01706     {
01707         for (arc2 = arc1->next; arc2; arc2 = next2)
01708         {
01709             next2 = arc2->next;
01710             if (arc1 != arc2 && arc1->head == arc2->head && arc1->tail == arc2->tail)
01711             {
01712                 mergeArcEdges(rg, arc1, arc2, MERGE_APPEND);
01713                 mergeArcFaces(rg, arc1, arc2);
01714                 mergeArcBuckets(arc1, arc2, arc1->head->weight, arc1->tail->weight);
01715 
01716                 NodeDegreeDecrement(rg, arc1->head);
01717                 NodeDegreeDecrement(rg, arc1->tail);
01718 
01719                 BLI_remlink(&rg->arcs, arc2);
01720                 REEB_freeArc((BArc*)arc2);
01721                 
01722                 filtered = 1;
01723             }
01724         }
01725     }
01726     
01727     return filtered;
01728 }
01729 
01730 int filterSmartReebGraph(ReebGraph *UNUSED(rg), float UNUSED(threshold))
01731 {
01732     int value = 0;
01733 #if 0 //XXX
01734     ReebArc *arc = NULL, *nextArc = NULL;
01735     
01736     BLI_sortlist(&rg->arcs, compareArcs);
01737 
01738 #ifdef DEBUG_REEB
01739     {   
01740         EditFace *efa;
01741         for(efa=G.editMesh->faces.first; efa; efa=efa->next) {
01742             efa->tmp.fp = -1;
01743         }
01744     }
01745 #endif
01746 
01747     arc = rg->arcs.first;
01748     while(arc)
01749     {
01750         nextArc = arc->next;
01751         
01752         /* need correct normals and center */
01753         recalc_editnormals();
01754 
01755         // Only test terminal arcs
01756         if (arc->head->degree == 1 || arc->tail->degree == 1)
01757         {
01758             GHashIterator ghi;
01759             int merging = 0;
01760             int total = BLI_ghash_size(arc->faces);
01761             float avg_angle = 0;
01762             float avg_vec[3] = {0,0,0};
01763             
01764             for(BLI_ghashIterator_init(&ghi, arc->faces);
01765                 !BLI_ghashIterator_isDone(&ghi);
01766                 BLI_ghashIterator_step(&ghi))
01767             {
01768                 EditFace *efa = BLI_ghashIterator_getValue(&ghi);
01769 
01770 #if 0
01771                 ReebArcIterator arc_iter;
01772                 BArcIterator *iter = (BArcIterator*)&arc_iter;
01773                 EmbedBucket *bucket = NULL;
01774                 EmbedBucket *previous = NULL;
01775                 float min_distance = -1;
01776                 float angle = 0;
01777         
01778                 initArcIterator(iter, arc, arc->head);
01779         
01780                 bucket = nextBucket(iter);
01781                 
01782                 while (bucket != NULL)
01783                 {
01784                     float *vec0 = NULL;
01785                     float *vec1 = bucket->p;
01786                     float midpoint[3], tangent[3];
01787                     float distance;
01788         
01789                     /* first bucket. Previous is head */
01790                     if (previous == NULL)
01791                     {
01792                         vec0 = arc->head->p;
01793                     }
01794                     /* Previous is a valid bucket */
01795                     else
01796                     {
01797                         vec0 = previous->p;
01798                     }
01799                     
01800                     VECCOPY(midpoint, vec1);
01801                     
01802                     distance = len_v3v3(midpoint, efa->cent);
01803                     
01804                     if (min_distance == -1 || distance < min_distance)
01805                     {
01806                         min_distance = distance;
01807                     
01808                         sub_v3_v3v3(tangent, vec1, vec0);
01809                         normalize_v3(tangent);
01810                         
01811                         angle = dot_v3v3(tangent, efa->n);
01812                     }
01813                     
01814                     previous = bucket;
01815                     bucket = nextBucket(iter);
01816                 }
01817                 
01818                 avg_angle += saacos(fabs(angle));
01819 #ifdef DEBUG_REEB
01820                 efa->tmp.fp = saacos(fabs(angle));
01821 #endif
01822 #else
01823                 add_v3_v3(avg_vec, efa->n);     
01824 #endif
01825             }
01826 
01827 
01828 #if 0           
01829             avg_angle /= total;
01830 #else
01831             mul_v3_fl(avg_vec, 1.0 / total);
01832             avg_angle = dot_v3v3(avg_vec, avg_vec);
01833 #endif
01834             
01835             arc->angle = avg_angle;
01836             
01837             if (avg_angle > threshold)
01838                 merging = 1;
01839             
01840             if (merging)
01841             {
01842                 ReebNode *terminalNode = NULL;
01843                 ReebNode *middleNode = NULL;
01844                 ReebNode *newNode = NULL;
01845                 ReebNode *removedNode = NULL;
01846                 int merging = 0;
01847                 
01848                 // Assign terminal and middle nodes
01849                 if (arc->head->degree == 1)
01850                 {
01851                     terminalNode = arc->head;
01852                     middleNode = arc->tail;
01853                 }
01854                 else
01855                 {
01856                     terminalNode = arc->tail;
01857                     middleNode = arc->head;
01858                 }
01859                 
01860                 // If middle node is a normal node, merge to terminal node
01861                 if (middleNode->degree == 2)
01862                 {
01863                     merging = 1;
01864                     newNode = terminalNode;
01865                     removedNode = middleNode;
01866                 }
01867                 // Otherwise, just plain remove of the arc
01868                 else
01869                 {
01870                     merging = 0;
01871                     newNode = middleNode;
01872                     removedNode = terminalNode;
01873                 }
01874                 
01875                 // Merging arc
01876                 if (merging)
01877                 {
01878                     filterArc(rg, newNode, removedNode, arc, 1);
01879                 }
01880                 else
01881                 {
01882                     // removing arc, so we need to decrease the degree of the remaining node
01883                     //newNode->degree--;
01884                     NodeDegreeDecrement(rg, newNode);
01885                 }
01886     
01887                 // Reset nextArc, it might have changed
01888                 nextArc = arc->next;
01889                 
01890                 BLI_remlink(&rg->arcs, arc);
01891                 REEB_freeArc((BArc*)arc);
01892                 
01893                 BLI_freelinkN(&rg->nodes, removedNode);
01894                 value = 1;
01895             }
01896         }
01897         
01898         arc = nextArc;
01899     }
01900     
01901     #endif
01902     
01903     return value;
01904 }
01905 
01906 static void filterGraph(ReebGraph *rg, short options, float threshold_internal, float threshold_external)
01907 {
01908     int done = 1;
01909     
01910     calculateGraphLength(rg);
01911 
01912     if ((options & SKGEN_FILTER_EXTERNAL) == 0)
01913     {
01914         threshold_external = 0;
01915     }
01916 
01917     if ((options & SKGEN_FILTER_INTERNAL) == 0)
01918     {
01919         threshold_internal = 0;
01920     }
01921 
01922     if (threshold_internal > 0 || threshold_external > 0)
01923     { 
01924         /* filter until there's nothing more to do */
01925         while (done == 1)
01926         {
01927             done = 0; /* no work done yet */
01928             
01929             done = filterInternalExternalReebGraph(rg, threshold_internal, threshold_external);
01930         }
01931     }
01932 
01933     if (options & SKGEN_FILTER_SMART)
01934     {
01935         filterSmartReebGraph(rg, 0.5);
01936         filterCyclesReebGraph(rg, 0.5);
01937     }
01938 
01939     repositionNodes(rg);
01940 
01941     /* Filtering might have created degree 2 nodes, so remove them */
01942     removeNormalNodes(rg);
01943 }
01944 
01945 static void finalizeGraph(ReebGraph *rg, char passes, char method)
01946 {
01947     int i;
01948     
01949     BLI_buildAdjacencyList((BGraph*)rg);
01950 
01951     sortNodes(rg);
01952     
01953     sortArcs(rg);
01954     
01955     for(i = 0; i <  passes; i++)
01956     {
01957         postprocessGraph(rg, method);
01958     }
01959     
01960     extendGraphBuckets(rg);
01961 }
01962 
01963 /************************************** WEIGHT SPREADING ***********************************************/
01964 
01965 static int compareVerts( const void* a, const void* b )
01966 {
01967     EditVert *va = *(EditVert**)a;
01968     EditVert *vb = *(EditVert**)b;
01969     int value = 0;
01970     
01971     if (weightData(va) < weightData(vb))
01972     {
01973         value = -1;
01974     }
01975     else if (weightData(va) > weightData(vb))
01976     {
01977         value = 1;
01978     }
01979 
01980     return value;       
01981 }
01982 
01983 static void spreadWeight(EditMesh *em)
01984 {
01985     EditVert **verts, *eve;
01986     float lastWeight = 0.0f;
01987     int totvert = BLI_countlist(&em->verts);
01988     int i;
01989     int work_needed = 1;
01990     
01991     verts = MEM_callocN(sizeof(EditVert*) * totvert, "verts array");
01992     
01993     for(eve = em->verts.first, i = 0; eve; eve = eve->next, i++)
01994     {
01995         verts[i] = eve;
01996     }
01997     
01998     while(work_needed == 1)
01999     {
02000         work_needed = 0;
02001         qsort(verts, totvert, sizeof(EditVert*), compareVerts);
02002         
02003         for(i = 0; i < totvert; i++)
02004         {
02005             eve = verts[i];
02006             
02007             if (i == 0 || (weightData(eve) - lastWeight) > FLT_EPSILON)
02008             {
02009                 lastWeight = weightData(eve);
02010             }
02011             else
02012             {
02013                 work_needed = 1;
02014                 weightSetData(eve, lastWeight + FLT_EPSILON * 2);
02015                 lastWeight = weightData(eve);
02016             }
02017         }
02018     }
02019     
02020     MEM_freeN(verts);
02021 }
02022 
02023 /******************************************** EXPORT ***************************************************/
02024 
02025 static void exportNode(FILE *f, const char *text, ReebNode *node)
02026 {
02027     fprintf(f, "%s i:%i w:%f d:%i %f %f %f\n", text, node->index, node->weight, node->degree, node->p[0], node->p[1], node->p[2]);
02028 }
02029 
02030 void REEB_exportGraph(ReebGraph *rg, int count)
02031 {
02032     ReebArc *arc;
02033     char filename[128];
02034     FILE *f;
02035     
02036     if (count == -1)
02037     {
02038         strcpy(filename, "test.txt");
02039     }
02040     else {
02041         sprintf(filename, "test%05i.txt", count);
02042     }
02043     f = fopen(filename, "w");
02044 
02045     for(arc = rg->arcs.first; arc; arc = arc->next)
02046     {
02047         int i;
02048         float p[3];
02049         
02050         exportNode(f, "v1", arc->head);
02051         
02052         for(i = 0; i < arc->bcount; i++)
02053         {
02054             fprintf(f, "b nv:%i %f %f %f\n", arc->buckets[i].nv, arc->buckets[i].p[0], arc->buckets[i].p[1], arc->buckets[i].p[2]);
02055         }
02056         
02057         add_v3_v3v3(p, arc->tail->p, arc->head->p);
02058         mul_v3_fl(p, 0.5f);
02059         
02060         fprintf(f, "angle %0.3f %0.3f %0.3f %0.3f %i\n", p[0], p[1], p[2], arc->angle, BLI_ghash_size(arc->faces));
02061         exportNode(f, "v2", arc->tail);
02062     }   
02063     
02064     fclose(f);
02065 }
02066 
02067 /***************************************** MAIN ALGORITHM **********************************************/
02068 
02069 /* edges alone will create zero degree nodes, use this function to remove them */
02070 static void removeZeroNodes(ReebGraph *rg)
02071 {
02072     ReebNode *node, *next_node;
02073     
02074     for (node = rg->nodes.first; node; node = next_node)
02075     {
02076         next_node = node->next;
02077         
02078         if (node->degree == 0)
02079         {
02080             BLI_removeNode((BGraph*)rg, (BNode*)node);
02081         }
02082     }
02083 }
02084 
02085 void removeNormalNodes(ReebGraph *rg)
02086 {
02087     ReebArc *arc, *nextArc;
02088     
02089     // Merge degree 2 nodes
02090     for(arc = rg->arcs.first; arc; arc = nextArc)
02091     {
02092         nextArc = arc->next;
02093         
02094         while (arc->head->degree == 2 || arc->tail->degree == 2)
02095         {
02096             // merge at v1
02097             if (arc->head->degree == 2)
02098             {
02099                 ReebArc *connectedArc = (ReebArc*)BLI_findConnectedArc((BGraph*)rg, (BArc*)arc, (BNode*)arc->head);
02100 
02101                 /* If arcs are one after the other */
02102                 if (arc->head == connectedArc->tail)
02103                 {       
02104                     /* remove furthest arc */       
02105                     if (arc->tail->weight < connectedArc->head->weight)
02106                     {
02107                         mergeConnectedArcs(rg, arc, connectedArc);
02108                         nextArc = arc->next;
02109                     }
02110                     else
02111                     {
02112                         mergeConnectedArcs(rg, connectedArc, arc);
02113                         break; /* arc was removed, move to next */
02114                     }
02115                 }
02116                 /* Otherwise, arcs are side by side */
02117                 else
02118                 {
02119                     /* Don't do anything, we need to keep the lowest node, even if degree 2 */
02120                     break;
02121                 }
02122             }
02123             
02124             // merge at v2
02125             if (arc->tail->degree == 2)
02126             {
02127                 ReebArc *connectedArc = (ReebArc*)BLI_findConnectedArc((BGraph*)rg, (BArc*)arc, (BNode*)arc->tail);
02128                 
02129                 /* If arcs are one after the other */
02130                 if (arc->tail == connectedArc->head)
02131                 {               
02132                     /* remove furthest arc */       
02133                     if (arc->head->weight < connectedArc->tail->weight)
02134                     {
02135                         mergeConnectedArcs(rg, arc, connectedArc);
02136                         nextArc = arc->next;
02137                     }
02138                     else
02139                     {
02140                         mergeConnectedArcs(rg, connectedArc, arc);
02141                         break; /* arc was removed, move to next */
02142                     }
02143                 }
02144                 /* Otherwise, arcs are side by side */
02145                 else
02146                 {
02147                     /* Don't do anything, we need to keep the lowest node, even if degree 2 */
02148                     break;
02149                 }
02150             }
02151         }
02152     }
02153     
02154 }
02155 
02156 static int edgeEquals(ReebEdge *e1, ReebEdge *e2)
02157 {
02158     return (e1->v1 == e2->v1 && e1->v2 == e2->v2);
02159 }
02160 
02161 static ReebArc *nextArcMappedToEdge(ReebArc *arc, ReebEdge *e)
02162 {
02163     ReebEdge *nextEdge = NULL;
02164     ReebEdge *edge = NULL;
02165     ReebArc *result = NULL;
02166 
02167     /* Find the ReebEdge in the edge list */
02168     for(edge = arc->edges.first; edge && !edgeEquals(edge, e); edge = edge->next)
02169     {   }
02170     
02171     nextEdge = edge->nextEdge;
02172     
02173     if (nextEdge != NULL)
02174     {
02175         result = nextEdge->arc;
02176     }
02177 
02178     return result;
02179 }
02180 
02181 void addFacetoArc(ReebArc *arc, EditFace *efa)
02182 {
02183     BLI_ghash_insert(arc->faces, efa, efa);
02184 }
02185 
02186 void mergeArcFaces(ReebGraph *UNUSED(rg), ReebArc *aDst, ReebArc *aSrc)
02187 {
02188     GHashIterator ghi;
02189     
02190     for(BLI_ghashIterator_init(&ghi, aSrc->faces);
02191         !BLI_ghashIterator_isDone(&ghi);
02192         BLI_ghashIterator_step(&ghi))
02193     {
02194         EditFace *efa = BLI_ghashIterator_getValue(&ghi);
02195         BLI_ghash_insert(aDst->faces, efa, efa);
02196     }
02197 } 
02198 
02199 void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection direction)
02200 {
02201     ReebEdge *e = NULL;
02202     
02203     if (direction == MERGE_APPEND)
02204     {
02205         for(e = aSrc->edges.first; e; e = e->next)
02206         {
02207             e->arc = aDst; // Edge is stolen by new arc
02208         }
02209         
02210         BLI_movelisttolist(&aDst->edges , &aSrc->edges);
02211     }
02212     else
02213     {
02214         for(e = aSrc->edges.first; e; e = e->next)
02215         {
02216             ReebEdge *newEdge = copyEdge(e);
02217 
02218             newEdge->arc = aDst;
02219             
02220             BLI_addtail(&aDst->edges, newEdge);
02221             
02222             if (direction == MERGE_LOWER)
02223             {
02224                 void **p = BLI_edgehash_lookup_p(rg->emap, e->v1->index, e->v2->index);
02225                 
02226                 newEdge->nextEdge = e;
02227 
02228                 // if edge was the first in the list, point the edit edge to the new reeb edge instead.                         
02229                 if (*p == e)
02230                 {
02231                     *p = (void*)newEdge;
02232                 }
02233                 // otherwise, advance in the list until the predecessor is found then insert it there
02234                 else
02235                 {
02236                     ReebEdge *previous = (ReebEdge*)*p;
02237                     
02238                     while(previous->nextEdge != e)
02239                     {
02240                         previous = previous->nextEdge;
02241                     }
02242                     
02243                     previous->nextEdge = newEdge;
02244                 }
02245             }
02246             else
02247             {
02248                 newEdge->nextEdge = e->nextEdge;
02249                 e->nextEdge = newEdge;
02250             }
02251         }
02252     }
02253 } 
02254 
02255 // return 1 on full merge
02256 int mergeConnectedArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1)
02257 {
02258     int result = 0;
02259     ReebNode *removedNode = NULL;
02260     
02261     a0->length += a1->length;
02262     
02263     mergeArcEdges(rg, a0, a1, MERGE_APPEND);
02264     mergeArcFaces(rg, a0, a1);
02265     
02266     // Bring a0 to the combine length of both arcs
02267     if (a0->tail == a1->head)
02268     {
02269         removedNode = a0->tail;
02270         a0->tail = a1->tail;
02271     }
02272     else if (a0->head == a1->tail)
02273     {
02274         removedNode = a0->head;
02275         a0->head = a1->head;
02276     }
02277     
02278     resizeArcBuckets(a0);
02279     // Merge a1 in a0
02280     mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight);
02281     
02282     // remove a1 from graph
02283     BLI_remlink(&rg->arcs, a1);
02284     REEB_freeArc((BArc*)a1);
02285     
02286     BLI_removeNode((BGraph*)rg, (BNode*)removedNode);
02287     result = 1;
02288     
02289     return result;
02290 }
02291 // return 1 on full merge
02292 int mergeArcs(ReebGraph *rg, ReebArc *a0, ReebArc *a1)
02293 {
02294     int result = 0;
02295     // TRIANGLE POINTS DOWN
02296     if (a0->head->weight == a1->head->weight) // heads are the same
02297     {
02298         if (a0->tail->weight == a1->tail->weight) // tails also the same, arcs can be totally merge together
02299         {
02300             mergeArcEdges(rg, a0, a1, MERGE_APPEND);
02301             mergeArcFaces(rg, a0, a1);
02302             
02303             mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight);
02304             
02305             // Adjust node degree
02306             //a1->head->degree--;
02307             NodeDegreeDecrement(rg, a1->head);
02308             //a1->tail->degree--;
02309             NodeDegreeDecrement(rg, a1->tail);
02310             
02311             // remove a1 from graph
02312             BLI_remlink(&rg->arcs, a1);
02313             
02314             REEB_freeArc((BArc*)a1);
02315             result = 1;
02316         }
02317         else if (a0->tail->weight > a1->tail->weight) // a1->tail->weight is in the middle
02318         {
02319             mergeArcEdges(rg, a1, a0, MERGE_LOWER);
02320             mergeArcFaces(rg, a1, a0);
02321 
02322             // Adjust node degree
02323             //a0->head->degree--;
02324             NodeDegreeDecrement(rg, a0->head);
02325             //a1->tail->degree++;
02326             NodeDegreeIncrement(rg, a1->tail);
02327             
02328             mergeArcBuckets(a1, a0, a1->head->weight, a1->tail->weight);
02329             a0->head = a1->tail;
02330             resizeArcBuckets(a0);
02331         }
02332         else // a0>n2 is in the middle
02333         {
02334             mergeArcEdges(rg, a0, a1, MERGE_LOWER);
02335             mergeArcFaces(rg, a0, a1);
02336             
02337             // Adjust node degree
02338             //a1->head->degree--;
02339             NodeDegreeDecrement(rg, a1->head);
02340             //a0->tail->degree++;
02341             NodeDegreeIncrement(rg, a0->tail);
02342             
02343             mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight);
02344             a1->head = a0->tail;
02345             resizeArcBuckets(a1);
02346         }
02347     }
02348     // TRIANGLE POINTS UP
02349     else if (a0->tail->weight == a1->tail->weight) // tails are the same
02350     {
02351         if (a0->head->weight > a1->head->weight) // a0->head->weight is in the middle
02352         {
02353             mergeArcEdges(rg, a0, a1, MERGE_HIGHER);
02354             mergeArcFaces(rg, a0, a1);
02355             
02356             // Adjust node degree
02357             //a1->tail->degree--;
02358             NodeDegreeDecrement(rg, a1->tail);
02359             //a0->head->degree++;
02360             NodeDegreeIncrement(rg, a0->head);
02361             
02362             mergeArcBuckets(a0, a1, a0->head->weight, a0->tail->weight);
02363             a1->tail = a0->head;
02364             resizeArcBuckets(a1);
02365         }
02366         else // a1->head->weight is in the middle
02367         {
02368             mergeArcEdges(rg, a1, a0, MERGE_HIGHER);
02369             mergeArcFaces(rg, a1, a0);
02370 
02371             // Adjust node degree
02372             //a0->tail->degree--;
02373             NodeDegreeDecrement(rg, a0->tail);
02374             //a1->head->degree++;
02375             NodeDegreeIncrement(rg, a1->head);
02376 
02377             mergeArcBuckets(a1, a0, a1->head->weight, a1->tail->weight);
02378             a0->tail = a1->head;
02379             resizeArcBuckets(a0);
02380         }
02381     }
02382     else
02383     {
02384         // Need something here (OR NOT)
02385     }
02386     
02387     return result;
02388 }
02389 
02390 static void glueByMergeSort(ReebGraph *rg, ReebArc *a0, ReebArc *a1, ReebEdge *e0, ReebEdge *e1)
02391 {
02392     int total = 0;
02393     while (total == 0 && a0 != a1 && a0 != NULL && a1 != NULL)
02394     {
02395         total = mergeArcs(rg, a0, a1);
02396         
02397         if (total == 0) // if it wasn't a total merge, go forward
02398         {
02399             if (a0->tail->weight < a1->tail->weight)
02400             {
02401                 a0 = nextArcMappedToEdge(a0, e0);
02402             }
02403             else
02404             {
02405                 a1 = nextArcMappedToEdge(a1, e1);
02406             }
02407         }
02408     }
02409 }
02410 
02411 static void mergePaths(ReebGraph *rg, ReebEdge *e0, ReebEdge *e1, ReebEdge *e2)
02412 {
02413     ReebArc *a0, *a1, *a2;
02414     a0 = e0->arc;
02415     a1 = e1->arc;
02416     a2 = e2->arc;
02417     
02418     glueByMergeSort(rg, a0, a1, e0, e1);
02419     glueByMergeSort(rg, a0, a2, e0, e2);
02420 } 
02421 
02422 static ReebEdge * createArc(ReebGraph *rg, ReebNode *node1, ReebNode *node2)
02423 {
02424     ReebEdge *edge;
02425     
02426     edge = BLI_edgehash_lookup(rg->emap, node1->index, node2->index);
02427     
02428     // Only add existing edges that haven't been added yet
02429     if (edge == NULL)
02430     {
02431         ReebArc *arc;
02432         ReebNode *v1, *v2;
02433         float len, offset;
02434         int i;
02435         
02436         arc = MEM_callocN(sizeof(ReebArc), "reeb arc");
02437         edge = MEM_callocN(sizeof(ReebEdge), "reeb edge");
02438         
02439         arc->flag = 0; // clear flag on init
02440         arc->symmetry_level = 0;
02441         arc->faces = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createArc gh");
02442         
02443         if (node1->weight <= node2->weight)
02444         {
02445             v1 = node1; 
02446             v2 = node2; 
02447         }
02448         else
02449         {
02450             v1 = node2; 
02451             v2 = node1; 
02452         }
02453         
02454         arc->head = v1;
02455         arc->tail = v2;
02456         
02457         // increase node degree
02458         //v1->degree++;
02459         NodeDegreeIncrement(rg, v1);
02460         //v2->degree++;
02461         NodeDegreeIncrement(rg, v2);
02462 
02463         BLI_edgehash_insert(rg->emap, node1->index, node2->index, edge);
02464         
02465         edge->arc = arc;
02466         edge->nextEdge = NULL;
02467         edge->v1 = v1;
02468         edge->v2 = v2;
02469         
02470         BLI_addtail(&rg->arcs, arc);
02471         BLI_addtail(&arc->edges, edge);
02472         
02473         /* adding buckets for embedding */
02474         allocArcBuckets(arc);
02475         
02476         offset = arc->head->weight;
02477         len = arc->tail->weight - arc->head->weight;
02478 
02479 #if 0
02480         /* This is the actual embedding filling described in the paper
02481          * the problem is that it only works with really dense meshes
02482          */
02483         if (arc->bcount > 0)
02484         {
02485             addVertToBucket(&(arc->buckets[0]), arc->head->co);
02486             addVertToBucket(&(arc->buckets[arc->bcount - 1]), arc->tail->co);
02487         }
02488 #else
02489         for(i = 0; i < arc->bcount; i++)
02490         {
02491             float co[3];
02492             float f = (arc->buckets[i].val - offset) / len;
02493             
02494             interp_v3_v3v3(co, v1->p, v2->p, f);
02495             addVertToBucket(&(arc->buckets[i]), co);
02496         }
02497 #endif
02498 
02499     }
02500     
02501     return edge;
02502 }
02503 
02504 static void addTriangleToGraph(ReebGraph *rg, ReebNode * n1, ReebNode * n2, ReebNode * n3, EditFace *efa)
02505 {
02506     ReebEdge *re1, *re2, *re3;
02507     ReebEdge *e1, *e2, *e3;
02508     float len1, len2, len3;
02509     
02510     re1 = createArc(rg, n1, n2);
02511     re2 = createArc(rg, n2, n3);
02512     re3 = createArc(rg, n3, n1);
02513     
02514     addFacetoArc(re1->arc, efa);
02515     addFacetoArc(re2->arc, efa);
02516     addFacetoArc(re3->arc, efa);
02517     
02518     len1 = (float)fabs(n1->weight - n2->weight);
02519     len2 = (float)fabs(n2->weight - n3->weight);
02520     len3 = (float)fabs(n3->weight - n1->weight);
02521     
02522     /* The rest of the algorithm assumes that e1 is the longest edge */
02523     
02524     if (len1 >= len2 && len1 >= len3)
02525     {
02526         e1 = re1;
02527         e2 = re2;
02528         e3 = re3;
02529     }
02530     else if (len2 >= len1 && len2 >= len3)
02531     {
02532         e1 = re2;
02533         e2 = re1;
02534         e3 = re3;
02535     }
02536     else
02537     {
02538         e1 = re3;
02539         e2 = re2;
02540         e3 = re1;
02541     }
02542     
02543     /* And e2 is the lowest edge
02544      * If e3 is lower than e2, swap them
02545      */
02546     if (e3->v1->weight < e2->v1->weight)
02547     {
02548         ReebEdge *etmp = e2;
02549         e2 = e3;
02550         e3 = etmp;
02551     }
02552     
02553     
02554     mergePaths(rg, e1, e2, e3);
02555 }
02556 
02557 ReebGraph * generateReebGraph(EditMesh *em, int subdivisions)
02558 {
02559     ReebGraph *rg;
02560     EditVert *eve;
02561     EditFace *efa;
02562     int index;
02563     /*int totvert;*/
02564     
02565 #ifdef DEBUG_REEB
02566     int totfaces;
02567     int countfaces = 0;
02568 #endif
02569 
02570     rg = newReebGraph();
02571     
02572     rg->resolution = subdivisions;
02573     
02574     /*totvert = BLI_countlist(&em->verts);*/ /*UNUSED*/
02575 #ifdef DEBUG_REEB
02576     totfaces = BLI_countlist(&em->faces);
02577 #endif
02578     
02579     renormalizeWeight(em, 1.0f);
02580     
02581     /* Spread weight to minimize errors */
02582     spreadWeight(em);
02583 
02584     renormalizeWeight(em, (float)rg->resolution);
02585 
02586     /* Adding vertice */
02587     for(index = 0, eve = em->verts.first; eve; eve = eve->next)
02588     {
02589         if (eve->h == 0)
02590         {
02591             addNode(rg, eve);
02592             eve->f2 = 0;
02593             index++;
02594         }
02595     }
02596     
02597     /* Adding face, edge per edge */
02598     for(efa = em->faces.first; efa; efa = efa->next)
02599     {
02600         if (efa->h == 0)
02601         {
02602             ReebNode *n1, *n2, *n3;
02603             
02604             n1 = nodeData(efa->v1);
02605             n2 = nodeData(efa->v2);
02606             n3 = nodeData(efa->v3);
02607             
02608             addTriangleToGraph(rg, n1, n2, n3, efa);
02609             
02610             if (efa->v4)
02611             {
02612                 ReebNode *n4 = nodeData(efa->v4);
02613                 addTriangleToGraph(rg, n1, n3, n4, efa);
02614             }
02615 #ifdef DEBUG_REEB
02616             countfaces++;
02617             if (countfaces % 100 == 0)
02618             {
02619                 printf("\rface %i of %i", countfaces, totfaces);
02620             }
02621 #endif
02622         }
02623     }
02624     
02625     printf("\n");
02626     
02627     removeZeroNodes(rg);
02628     
02629     removeNormalNodes(rg);
02630     
02631     return rg;
02632 }
02633 
02634 /***************************************** WEIGHT UTILS **********************************************/
02635 
02636 void renormalizeWeight(EditMesh *em, float newmax)
02637 {
02638     EditVert *eve;
02639     float minimum, maximum, range;
02640     
02641     if (em == NULL || BLI_countlist(&em->verts) == 0)
02642         return;
02643 
02644     /* First pass, determine maximum and minimum */
02645     eve = em->verts.first;
02646     minimum = weightData(eve);
02647     maximum = minimum;
02648     for(; eve; eve = eve->next)
02649     {
02650         maximum = MAX2(maximum, weightData(eve));
02651         minimum = MIN2(minimum, weightData(eve));
02652     }
02653     
02654     range = maximum - minimum;
02655 
02656     /* Normalize weights */
02657     for(eve = em->verts.first; eve; eve = eve->next)
02658     {
02659         float weight = (weightData(eve) - minimum) / range * newmax;
02660         weightSetData(eve, weight);
02661     }
02662 }
02663 
02664 
02665 int weightFromLoc(EditMesh *em, int axis)
02666 {
02667     EditVert *eve;
02668     
02669     if (em == NULL || BLI_countlist(&em->verts) == 0 || axis < 0 || axis > 2)
02670         return 0;
02671 
02672     /* Copy coordinate in weight */
02673     for(eve = em->verts.first; eve; eve = eve->next)
02674     {
02675         weightSetData(eve, eve->co[axis]);
02676     }
02677 
02678     return 1;
02679 }
02680 
02681 static float cotan_weight(float *v1, float *v2, float *v3)
02682 {
02683     float a[3], b[3], c[3], clen;
02684 
02685     sub_v3_v3v3(a, v2, v1);
02686     sub_v3_v3v3(b, v3, v1);
02687     cross_v3_v3v3(c, a, b);
02688 
02689     clen = len_v3(c);
02690 
02691     if (clen == 0.0f)
02692         return 0.0f;
02693     
02694     return dot_v3v3(a, b)/clen;
02695 }
02696 
02697 static void addTriangle(EditVert *v1, EditVert *v2, EditVert *v3, int e1, int e2, int e3)
02698 {
02699     /* Angle opposite e1 */
02700     float t1= cotan_weight(v1->co, v2->co, v3->co) / e2;
02701     
02702     /* Angle opposite e2 */
02703     float t2 = cotan_weight(v2->co, v3->co, v1->co) / e3;
02704 
02705     /* Angle opposite e3 */
02706     float t3 = cotan_weight(v3->co, v1->co, v2->co) / e1;
02707     
02708     int i1 = indexData(v1);
02709     int i2 = indexData(v2);
02710     int i3 = indexData(v3);
02711     
02712     nlMatrixAdd(i1, i1, t2+t3);
02713     nlMatrixAdd(i2, i2, t1+t3);
02714     nlMatrixAdd(i3, i3, t1+t2);
02715 
02716     nlMatrixAdd(i1, i2, -t3);
02717     nlMatrixAdd(i2, i1, -t3);
02718 
02719     nlMatrixAdd(i2, i3, -t1);
02720     nlMatrixAdd(i3, i2, -t1);
02721 
02722     nlMatrixAdd(i3, i1, -t2);
02723     nlMatrixAdd(i1, i3, -t2);
02724 }
02725 
02726 int weightToHarmonic(EditMesh *em, EdgeIndex *indexed_edges)
02727 {
02728     NLboolean success;
02729     EditVert *eve;
02730     EditEdge *eed;
02731     EditFace *efa;
02732     int totvert = 0;
02733     int index;
02734     int rval;
02735     
02736     /* Find local extrema */
02737     for(eve = em->verts.first; eve; eve = eve->next)
02738     {
02739         totvert++;
02740     }
02741 
02742     /* Solve with openNL */
02743     
02744     nlNewContext();
02745 
02746     nlSolverParameteri(NL_NB_VARIABLES, totvert);
02747 
02748     nlBegin(NL_SYSTEM);
02749     
02750     /* Find local extrema */
02751     for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next)
02752     {
02753         if (eve->h == 0)
02754         {
02755             EditEdge *eed;
02756             int maximum = 1;
02757             int minimum = 1;
02758             
02759             NextEdgeForVert(indexed_edges, -1); /* Reset next edge */
02760             for(eed = NextEdgeForVert(indexed_edges, index); eed && (maximum || minimum); eed = NextEdgeForVert(indexed_edges, index))
02761             {
02762                 EditVert *eve2;
02763                 
02764                 if (eed->v1 == eve)
02765                 {
02766                     eve2 = eed->v2;
02767                 }
02768                 else
02769                 {
02770                     eve2 = eed->v1;
02771                 }
02772                 
02773                 if (eve2->h == 0)
02774                 {
02775                     /* Adjacent vertex is bigger, not a local maximum */
02776                     if (weightData(eve2) > weightData(eve))
02777                     {
02778                         maximum = 0;
02779                     }
02780                     /* Adjacent vertex is smaller, not a local minimum */
02781                     else if (weightData(eve2) < weightData(eve))
02782                     {
02783                         minimum = 0;
02784                     }
02785                 }
02786             }
02787             
02788             if (maximum || minimum)
02789             {
02790                 float w = weightData(eve);
02791                 eve->f1 = 0;
02792                 nlSetVariable(0, index, w);
02793                 nlLockVariable(index);
02794             }
02795             else
02796             {
02797                 eve->f1 = 1;
02798             }
02799         }
02800     }
02801     
02802     nlBegin(NL_MATRIX);
02803 
02804     /* Zero edge weight */
02805     for(eed = em->edges.first; eed; eed = eed->next)
02806     {
02807         eed->tmp.l = 0;
02808     }
02809     
02810     /* Add faces count to the edge weight */
02811     for(efa = em->faces.first; efa; efa = efa->next)
02812     {
02813         if (efa->h == 0)
02814         {
02815             efa->e1->tmp.l++;
02816             efa->e2->tmp.l++;
02817             efa->e3->tmp.l++;
02818             
02819             if (efa->e4)
02820             {
02821                 efa->e4->tmp.l++;
02822             }
02823         }
02824     }
02825 
02826     /* Add faces angle to the edge weight */
02827     for(efa = em->faces.first; efa; efa = efa->next)
02828     {
02829         if (efa->h == 0)
02830         {
02831             if (efa->v4 == NULL)
02832             {
02833                 addTriangle(efa->v1, efa->v2, efa->v3, efa->e1->tmp.l, efa->e2->tmp.l, efa->e3->tmp.l);
02834             }
02835             else
02836             {
02837                 addTriangle(efa->v1, efa->v2, efa->v3, efa->e1->tmp.l, efa->e2->tmp.l, 2);
02838                 addTriangle(efa->v3, efa->v4, efa->v1, efa->e3->tmp.l, efa->e4->tmp.l, 2);
02839             }
02840         }
02841     }
02842     
02843     nlEnd(NL_MATRIX);
02844 
02845     nlEnd(NL_SYSTEM);
02846 
02847     success = nlSolveAdvanced(NULL, NL_TRUE);
02848 
02849     if (success)
02850     {
02851         rval = 1;
02852         for(index = 0, eve = em->verts.first; eve; index++, eve = eve->next)
02853         {
02854             weightSetData(eve, nlGetVariable(0, index));
02855         }
02856     }
02857     else
02858     {
02859         rval = 0;
02860     }
02861 
02862     nlDeleteContext(nlGetCurrent());
02863 
02864     return rval;
02865 }
02866 
02867 
02868 EditEdge * NextEdgeForVert(EdgeIndex *indexed_edges, int index)
02869 {
02870     static int offset = -1;
02871     
02872     /* Reset method, call with NULL mesh pointer */
02873     if (index == -1)
02874     {
02875         offset = -1;
02876         return NULL;
02877     }
02878     
02879     /* first pass, start at the head of the list */
02880     if (offset == -1)
02881     {
02882         offset = indexed_edges->offset[index];
02883     }
02884     /* subsequent passes, start on the next edge */
02885     else
02886     {
02887         offset++;
02888     }
02889     
02890     return indexed_edges->edges[offset];
02891 }
02892 
02893 static void shortestPathsFromVert(EditMesh *em, EditVert *starting_vert, EdgeIndex *indexed_edges)
02894 {
02895     Heap     *edge_heap;
02896     EditVert *current_eve = NULL;
02897     EditEdge *eed = NULL;
02898     EditEdge *select_eed = NULL;
02899     
02900     edge_heap = BLI_heap_new();
02901     
02902     current_eve = starting_vert;
02903     
02904     /* insert guard in heap, when that is returned, no more edges */
02905     BLI_heap_insert(edge_heap, FLT_MAX, NULL);
02906 
02907     /* Initialize edge flag */
02908     for(eed= em->edges.first; eed; eed= eed->next)
02909     {
02910         eed->f1 = 0;
02911     }
02912     
02913     while (BLI_heap_size(edge_heap) > 0)
02914     {
02915         float current_weight;
02916         
02917         current_eve->f1 = 1; /* mark vertex as selected */
02918         
02919         /* Add all new edges connected to current_eve to the list */
02920         NextEdgeForVert(indexed_edges, -1); // Reset next edge
02921         for(eed = NextEdgeForVert(indexed_edges, indexData(current_eve)); eed; eed = NextEdgeForVert(indexed_edges, indexData(current_eve)))
02922         { 
02923             if (eed->f1 == 0)
02924             {
02925                 BLI_heap_insert(edge_heap, weightData(current_eve) + eed->tmp.fp, eed);
02926                 eed->f1 = 1;
02927             }
02928         }
02929         
02930         /* Find next shortest edge with unselected verts */
02931         do
02932         {
02933             current_weight = BLI_heap_node_value(BLI_heap_top(edge_heap));
02934             select_eed = BLI_heap_popmin(edge_heap);
02935         } while (select_eed != NULL && select_eed->v1->f1 != 0 && select_eed->v2->f1);
02936         
02937         if (select_eed != NULL)
02938         {
02939             select_eed->f1 = 2;
02940             
02941             if (select_eed->v1->f1 == 0) /* v1 is the new vertex */
02942             {
02943                 current_eve = select_eed->v1;
02944             }
02945             else /* otherwise, it's v2 */
02946             {
02947                 current_eve = select_eed->v2;
02948             }
02949             
02950             weightSetData(current_eve, current_weight);
02951         }
02952     }
02953     
02954     BLI_heap_free(edge_heap, NULL);
02955 }
02956 
02957 static void freeEdgeIndex(EdgeIndex *indexed_edges)
02958 {
02959     MEM_freeN(indexed_edges->offset);
02960     MEM_freeN(indexed_edges->edges);
02961 }
02962 
02963 static void buildIndexedEdges(EditMesh *em, EdgeIndex *indexed_edges)
02964 {
02965     EditVert *eve;
02966     EditEdge *eed;
02967     int totvert = 0;
02968     int tot_indexed = 0;
02969     int offset = 0;
02970 
02971     totvert = BLI_countlist(&em->verts);
02972 
02973     indexed_edges->offset = MEM_callocN(totvert * sizeof(int), "EdgeIndex offset");
02974 
02975     for(eed = em->edges.first; eed; eed = eed->next)
02976     {
02977         if (eed->v1->h == 0 && eed->v2->h == 0)
02978         {
02979             tot_indexed += 2;
02980             indexed_edges->offset[indexData(eed->v1)]++;
02981             indexed_edges->offset[indexData(eed->v2)]++;
02982         }
02983     }
02984     
02985     tot_indexed += totvert;
02986 
02987     indexed_edges->edges = MEM_callocN(tot_indexed * sizeof(EditEdge*), "EdgeIndex edges");
02988 
02989     /* setting vert offsets */
02990     for(eve = em->verts.first; eve; eve = eve->next)
02991     {
02992         if (eve->h == 0)
02993         {
02994             int d = indexed_edges->offset[indexData(eve)];
02995             indexed_edges->offset[indexData(eve)] = offset;
02996             offset += d + 1;
02997         }
02998     }
02999 
03000     /* adding edges in array */
03001     for(eed = em->edges.first; eed; eed= eed->next)
03002     {
03003         if (eed->v1->h == 0 && eed->v2->h == 0)
03004         {
03005             int i;
03006             for (i = indexed_edges->offset[indexData(eed->v1)]; i < tot_indexed; i++)
03007             {
03008                 if (indexed_edges->edges[i] == NULL)
03009                 {
03010                     indexed_edges->edges[i] = eed;
03011                     break;
03012                 }
03013             }
03014             
03015             for (i = indexed_edges->offset[indexData(eed->v2)]; i < tot_indexed; i++)
03016             {
03017                 if (indexed_edges->edges[i] == NULL)
03018                 {
03019                     indexed_edges->edges[i] = eed;
03020                     break;
03021                 }
03022             }
03023         }
03024     }
03025 }
03026 
03027 int weightFromDistance(EditMesh *em, EdgeIndex *indexed_edges)
03028 {
03029     EditVert *eve;
03030     int totedge = 0;
03031     int totvert = 0;
03032     int vCount = 0;
03033     
03034     totvert = BLI_countlist(&em->verts);
03035     
03036     if (em == NULL || totvert == 0)
03037     {
03038         return 0;
03039     }
03040     
03041     totedge = BLI_countlist(&em->edges);
03042     
03043     if (totedge == 0)
03044     {
03045         return 0;
03046     }
03047     
03048     /* Initialize vertice flag and find at least one selected vertex */
03049     for(eve = em->verts.first; eve; eve = eve->next)
03050     {
03051         eve->f1 = 0;
03052         if (eve->f & SELECT)
03053         {
03054             vCount = 1;
03055         }
03056     }
03057     
03058     if (vCount == 0)
03059     {
03060         return 0; /* no selected vert, failure */
03061     }
03062     else
03063     {
03064         EditEdge *eed;
03065         int allDone = 0;
03066 
03067         /* Calculate edge weight */
03068         for(eed = em->edges.first; eed; eed= eed->next)
03069         {
03070             if (eed->v1->h == 0 && eed->v2->h == 0)
03071             {
03072                 eed->tmp.fp = len_v3v3(eed->v1->co, eed->v2->co);
03073             }
03074         }
03075 
03076         /* Apply dijkstra spf for each selected vert */
03077         for(eve = em->verts.first; eve; eve = eve->next)
03078         {
03079             if (eve->f & SELECT)
03080             {
03081                 shortestPathsFromVert(em, eve, indexed_edges);              
03082             }
03083         }
03084         
03085         /* connect unselected islands */
03086         while (allDone == 0)
03087         {
03088             EditVert *selected_eve = NULL;
03089             float selected_weight = 0;
03090             float min_distance = FLT_MAX;
03091             
03092             allDone = 1;
03093             
03094             for (eve = em->verts.first; eve; eve = eve->next)
03095             {
03096                 /* for every vertex visible that hasn't been processed yet */
03097                 if (eve->h == 0 && eve->f1 != 1)
03098                 {
03099                     EditVert *closest_eve;
03100                     
03101                     /* find the closest processed vertex */
03102                     for (closest_eve = em->verts.first; closest_eve; closest_eve = closest_eve->next)
03103                     {
03104                         /* vertex is already processed and distance is smaller than current minimum */
03105                         if (closest_eve->f1 == 1)
03106                         {
03107                             float distance = len_v3v3(closest_eve->co, eve->co);
03108                             if (distance < min_distance)
03109                             {
03110                                 min_distance = distance;
03111                                 selected_eve = eve;
03112                                 selected_weight = weightData(closest_eve);
03113                             }
03114                         }
03115                     }
03116                 }
03117             }
03118             
03119             if (selected_eve)
03120             {
03121                 allDone = 0;
03122 
03123                 weightSetData(selected_eve, selected_weight + min_distance);
03124                 shortestPathsFromVert(em, selected_eve, indexed_edges);
03125             }
03126         }
03127     }
03128 
03129     for(eve = em->verts.first; eve && vCount == 0; eve = eve->next)
03130     {
03131         if (eve->f1 == 0)
03132         {
03133             printf("vertex not reached\n");
03134             break;
03135         }
03136     }
03137     
03138     return 1;
03139 }
03140 
03141 /****************************************** BUCKET ITERATOR **************************************************/
03142 
03143 static void* headNode(void *arg);
03144 static void* tailNode(void *arg);
03145 static void* nextBucket(void *arg);
03146 static void* nextNBucket(void *arg, int n);
03147 static void* peekBucket(void *arg, int n);
03148 static void* previousBucket(void *arg);
03149 static int   iteratorStopped(void *arg);
03150 
03151 static void initIteratorFct(ReebArcIterator *iter)
03152 {
03153     iter->head = headNode;
03154     iter->tail = tailNode;
03155     iter->peek = peekBucket;
03156     iter->next = nextBucket;
03157     iter->nextN = nextNBucket;
03158     iter->previous = previousBucket;
03159     iter->stopped = iteratorStopped;    
03160 }
03161 
03162 static void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket)
03163 {
03164     if (bucket)
03165     {
03166         iter->p = bucket->p;
03167         iter->no = bucket->no;
03168     }
03169     else
03170     {
03171         iter->p = NULL;
03172         iter->no = NULL;
03173     }
03174     iter->size = 0;
03175 }
03176 
03177 void initArcIterator(BArcIterator *arg, ReebArc *arc, ReebNode *head)
03178 {
03179     ReebArcIterator *iter = (ReebArcIterator*)arg;
03180 
03181     initIteratorFct(iter);
03182     iter->arc = arc;
03183     
03184     if (head == arc->head)
03185     {
03186         iter->start = 0;
03187         iter->end = arc->bcount - 1;
03188         iter->stride = 1;
03189     }
03190     else
03191     {
03192         iter->start = arc->bcount - 1;
03193         iter->end = 0;
03194         iter->stride = -1;
03195     }
03196     
03197     iter->length = arc->bcount;
03198     
03199     iter->index = -1;
03200 }
03201 
03202 void initArcIteratorStart(BArcIterator *arg, struct ReebArc *arc, struct ReebNode *head, int start)
03203 {
03204     ReebArcIterator *iter = (ReebArcIterator*)arg;
03205 
03206     initIteratorFct(iter);
03207     iter->arc = arc;
03208     
03209     if (head == arc->head)
03210     {
03211         iter->start = start;
03212         iter->end = arc->bcount - 1;
03213         iter->stride = 1;
03214     }
03215     else
03216     {
03217         iter->start = arc->bcount - 1 - start;
03218         iter->end = 0;
03219         iter->stride = -1;
03220     }
03221     
03222     iter->index = -1;
03223     
03224     iter->length = arc->bcount - start;
03225 
03226     if (start >= arc->bcount)
03227     {
03228         iter->start = iter->end; /* stop iterator since it's past its end */
03229     }
03230 }
03231 
03232 void initArcIterator2(BArcIterator *arg, ReebArc *arc, int start, int end)
03233 {
03234     ReebArcIterator *iter = (ReebArcIterator*)arg;
03235 
03236     initIteratorFct(iter);
03237     iter->arc = arc;
03238     
03239     iter->start = start;
03240     iter->end = end;
03241     
03242     if (end > start)
03243     {
03244         iter->stride = 1;
03245     }
03246     else
03247     {
03248         iter->stride = -1;
03249     }
03250 
03251     iter->index = -1;
03252 
03253     iter->length = abs(iter->end - iter->start) + 1;
03254 }
03255 
03256 static void* headNode(void *arg)
03257 {
03258     ReebArcIterator *iter = (ReebArcIterator*)arg;
03259     ReebNode *node;
03260     
03261     if (iter->start < iter->end)
03262     {
03263         node = iter->arc->head;
03264     }
03265     else
03266     {
03267         node = iter->arc->tail;
03268     }
03269     
03270     iter->p = node->p;
03271     iter->no = node->no;
03272     iter->size = 0;
03273     
03274     return node;
03275 }
03276 
03277 static void* tailNode(void *arg)
03278 {
03279     ReebArcIterator *iter = (ReebArcIterator*)arg;
03280     ReebNode *node;
03281     
03282     if (iter->start < iter->end)
03283     {
03284         node = iter->arc->tail;
03285     }
03286     else
03287     {
03288         node = iter->arc->head;
03289     }
03290     
03291     iter->p = node->p;
03292     iter->no = node->no;
03293     iter->size = 0;
03294     
03295     return node;
03296 }
03297 
03298 static void* nextBucket(void *arg)
03299 {
03300     ReebArcIterator *iter = (ReebArcIterator*)arg;
03301     EmbedBucket *result = NULL;
03302     
03303     iter->index++;
03304     
03305     if (iter->index < iter->length)
03306     {
03307         result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]);
03308     }
03309     
03310     setIteratorValues(iter, result);
03311     return result;
03312 }
03313 
03314 static void* nextNBucket(void *arg, int n)
03315 {
03316     ReebArcIterator *iter = (ReebArcIterator*)arg;
03317     EmbedBucket *result = NULL;
03318         
03319     iter->index += n;
03320 
03321     /* check if passed end */
03322     if (iter->index < iter->length)
03323     {
03324         result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]);
03325     }
03326     
03327     setIteratorValues(iter, result);
03328     return result;
03329 }
03330 
03331 static void* peekBucket(void *arg, int n)
03332 {
03333     ReebArcIterator *iter = (ReebArcIterator*)arg;
03334     EmbedBucket *result = NULL;
03335     int index = iter->index + n;
03336 
03337     /* check if passed end */
03338     if (index < iter->length)
03339     {
03340         result = &(iter->arc->buckets[iter->start + (iter->stride * index)]);
03341     }
03342 
03343     setIteratorValues(iter, result);
03344     return result;
03345 }
03346 
03347 static void* previousBucket(void *arg)
03348 {
03349     ReebArcIterator *iter = (ReebArcIterator*)arg;
03350     EmbedBucket *result = NULL;
03351     
03352     if (iter->index > 0)
03353     {
03354         iter->index--;
03355         result = &(iter->arc->buckets[iter->start + (iter->stride * iter->index)]);
03356     }
03357 
03358     setIteratorValues(iter, result);
03359     return result;
03360 }
03361 
03362 static int iteratorStopped(void *arg)
03363 {
03364     ReebArcIterator *iter = (ReebArcIterator*)arg;
03365 
03366     if (iter->index >= iter->length)
03367     {
03368         return 1;
03369     }
03370     else
03371     {
03372         return 0;
03373     }
03374 }
03375 
03376 /************************ PUBLIC FUNCTIONS *********************************************/
03377 
03378 ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C)
03379 {
03380     Scene *scene = CTX_data_scene(C);
03381     Object *obedit = CTX_data_edit_object(C);
03382     EditMesh *em =( (Mesh*)obedit->data)->edit_mesh;
03383     EdgeIndex indexed_edges;
03384     VertexData *data;
03385     ReebGraph *rg = NULL;
03386     ReebGraph *rgi, *previous;
03387     int i, nb_levels = REEB_MAX_MULTI_LEVEL;
03388 
03389     if (em == NULL)
03390         return NULL;
03391     
03392     data = allocVertexData(em);
03393 
03394     buildIndexedEdges(em, &indexed_edges);
03395 
03396     if (weightFromDistance(em, &indexed_edges) == 0)
03397     {
03398         // XXX error("No selected vertex\n");
03399         freeEdgeIndex(&indexed_edges);
03400         return NULL;
03401     }
03402     
03403     renormalizeWeight(em, 1.0f);
03404 
03405     if (scene->toolsettings->skgen_options & SKGEN_HARMONIC)
03406     {
03407         weightToHarmonic(em, &indexed_edges);
03408     }
03409     
03410     freeEdgeIndex(&indexed_edges);
03411     
03412     rg = generateReebGraph(em, scene->toolsettings->skgen_resolution);
03413 
03414     /* Remove arcs without embedding */
03415     filterNullReebGraph(rg);
03416 
03417     /* smart filter and loop filter on basic level */
03418     filterGraph(rg, SKGEN_FILTER_SMART, 0, 0);
03419 
03420     repositionNodes(rg);
03421 
03422     /* Filtering might have created degree 2 nodes, so remove them */
03423     removeNormalNodes(rg);
03424     
03425     joinSubgraphs(rg, 1.0);
03426 
03427     BLI_buildAdjacencyList((BGraph*)rg);
03428     
03429     /* calc length before copy, so we have same length on all levels */
03430     BLI_calcGraphLength((BGraph*)rg);
03431 
03432     previous = NULL;
03433     for (i = 0; i <= nb_levels; i++)
03434     {
03435         rgi = rg;
03436         
03437         /* don't filter last level */
03438         if (i > 0)
03439         {
03440             float internal_threshold;
03441             float external_threshold;
03442 
03443             /* filter internal progressively in second half only*/
03444             if (i > nb_levels / 2)
03445             {
03446                 internal_threshold = rg->length * scene->toolsettings->skgen_threshold_internal;
03447             }
03448             else
03449             {
03450                 internal_threshold = rg->length * scene->toolsettings->skgen_threshold_internal * (2 * i / (float)nb_levels);
03451             }
03452             
03453             external_threshold = rg->length * scene->toolsettings->skgen_threshold_external * (i / (float)nb_levels);
03454 
03455             filterGraph(rgi, scene->toolsettings->skgen_options, internal_threshold, external_threshold);
03456         }
03457 
03458         if (i < nb_levels)
03459         {
03460             rg = copyReebGraph(rgi, i + 1);
03461         }
03462 
03463         finalizeGraph(rgi, scene->toolsettings->skgen_postpro_passes, scene->toolsettings->skgen_postpro);
03464 
03465         BLI_markdownSymmetry((BGraph*)rgi, rgi->nodes.first, scene->toolsettings->skgen_symmetry_limit);
03466         
03467         if (previous != NULL)
03468         {
03469             relinkNodes(rgi, previous);
03470         }
03471         previous = rgi;
03472     }
03473     
03474     verifyMultiResolutionLinks(rg, 0);
03475     
03476     MEM_freeN(data);
03477 
03478     return rg;
03479 }
03480 
03481 #if 0
03482 
03483 ReebGraph *BIF_ReebGraphFromEditMesh(void)
03484 {
03485     EditMesh *em = G.editMesh;
03486     EdgeIndex indexed_edges;
03487     VertexData *data;
03488     ReebGraph *rg = NULL;
03489     
03490     if (em == NULL)
03491         return NULL;
03492 
03493     data = allocVertexData(em);
03494 
03495     buildIndexedEdges(em, &indexed_edges);
03496     
03497     if (weightFromDistance(em, &indexed_edges) == 0)
03498     {
03499         error("No selected vertex\n");
03500         freeEdgeIndex(&indexed_edges);
03501         freeEdgeIndex(&indexed_edges);
03502         return NULL;
03503     }
03504     
03505     renormalizeWeight(em, 1.0f);
03506 
03507     if (G.scene->toolsettings->skgen_options & SKGEN_HARMONIC)
03508     {
03509         weightToHarmonic(em, &indexed_edges);
03510     }
03511     
03512     freeEdgeIndex(&indexed_edges);
03513     
03514 #ifdef DEBUG_REEB
03515     weightToVCol(em, 1);
03516 #endif
03517     
03518     rg = generateReebGraph(em, G.scene->toolsettings->skgen_resolution);
03519 
03520 
03521     /* Remove arcs without embedding */
03522     filterNullReebGraph(rg);
03523 
03524     /* smart filter and loop filter on basic level */
03525     filterGraph(rg, SKGEN_FILTER_SMART, 0, 0);
03526 
03527     repositionNodes(rg);
03528 
03529     /* Filtering might have created degree 2 nodes, so remove them */
03530     removeNormalNodes(rg);
03531     
03532     joinSubgraphs(rg, 1.0);
03533 
03534     BLI_buildAdjacencyList((BGraph*)rg);
03535     
03536     /* calc length before copy, so we have same length on all levels */
03537     BLI_calcGraphLength((BGraph*)rg);
03538     
03539     filterGraph(rg, G.scene->toolsettings->skgen_options, G.scene->toolsettings->skgen_threshold_internal, G.scene->toolsettings->skgen_threshold_external);
03540 
03541     finalizeGraph(rg, G.scene->toolsettings->skgen_postpro_passes, G.scene->toolsettings->skgen_postpro);
03542 
03543 #ifdef DEBUG_REEB
03544     REEB_exportGraph(rg, -1);
03545     
03546     arcToVCol(rg, em, 0);
03547     //angleToVCol(em, 1);
03548 #endif
03549 
03550     printf("DONE\n");
03551     printf("%i subgraphs\n", BLI_FlagSubgraphs((BGraph*)rg));
03552     
03553     MEM_freeN(data);
03554 
03555     return rg;
03556 }
03557 
03558 void BIF_GlobalReebFree()
03559 {
03560     if (GLOBAL_RG != NULL)
03561     {
03562         REEB_freeGraph(GLOBAL_RG);
03563         GLOBAL_RG = NULL;
03564     }
03565 }
03566 
03567 void BIF_GlobalReebGraphFromEditMesh(void)
03568 {
03569     ReebGraph *rg;
03570     
03571     BIF_GlobalReebFree();
03572     
03573     rg = BIF_ReebGraphMultiFromEditMesh();
03574 
03575     GLOBAL_RG = rg;
03576 }
03577 
03578 void REEB_draw()
03579 {
03580     ReebGraph *rg;
03581     ReebArc *arc;
03582     int i = 0;
03583     
03584     if (GLOBAL_RG == NULL)
03585     {
03586         return;
03587     }
03588     
03589     if (GLOBAL_RG->link_up && G.scene->toolsettings->skgen_options & SKGEN_DISP_ORIG)
03590     {
03591         for (rg = GLOBAL_RG; rg->link_up; rg = rg->link_up) ;
03592     }
03593     else
03594     {
03595         i = G.scene->toolsettings->skgen_multi_level;
03596         
03597         for (rg = GLOBAL_RG; rg->multi_level != i && rg->link_up; rg = rg->link_up) ;
03598     }
03599     
03600     glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
03601     
03602     glDisable(GL_DEPTH_TEST);
03603     for (arc = rg->arcs.first; arc; arc = arc->next, i++)
03604     {
03605         ReebArcIterator arc_iter;
03606         BArcIterator *iter = (BArcIterator*)&arc_iter;
03607         float vec[3];
03608         char text[128];
03609         char *s = text;
03610         
03611         glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE) + 2);
03612         glColor3f(0, 0, 0);
03613         glBegin(GL_LINE_STRIP);
03614             glVertex3fv(arc->head->p);
03615             
03616             if (arc->bcount)
03617             {
03618                 initArcIterator(iter, arc, arc->head);
03619                 for (IT_next(iter); IT_stopped(iter) == 0; IT_next(iter))
03620                 {
03621                     glVertex3fv(iter->p);
03622                 }
03623             }
03624             
03625             glVertex3fv(arc->tail->p);
03626         glEnd();
03627 
03628         glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE));
03629 
03630         if (arc->symmetry_level == 1)
03631         {
03632             glColor3f(1, 0, 0);
03633         }
03634         else if (arc->symmetry_flag == SYM_SIDE_POSITIVE || arc->symmetry_flag == SYM_SIDE_NEGATIVE)
03635         {
03636             glColor3f(1, 0.5f, 0);
03637         }
03638         else if (arc->symmetry_flag >= SYM_SIDE_RADIAL)
03639         {
03640             glColor3f(0.5f, 1, 0);
03641         }
03642         else
03643         {
03644             glColor3f(1, 1, 0);
03645         }
03646         glBegin(GL_LINE_STRIP);
03647             glVertex3fv(arc->head->p);
03648             
03649             if (arc->bcount)
03650             {
03651                 initArcIterator(iter, arc, arc->head);
03652                 for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter))
03653                 {
03654                     glVertex3fv(iter->p);
03655                 }
03656             }
03657             
03658             glVertex3fv(arc->tail->p);
03659         glEnd();
03660 
03661         
03662         if (G.scene->toolsettings->skgen_options & SKGEN_DISP_EMBED)
03663         {
03664             glColor3f(1, 1, 1);             
03665             glBegin(GL_POINTS);
03666                 glVertex3fv(arc->head->p);
03667                 glVertex3fv(arc->tail->p);
03668                 
03669                 glColor3f(0.5f, 0.5f, 1);               
03670                 if (arc->bcount)
03671                 {
03672                     initArcIterator(iter, arc, arc->head);
03673                     for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter))
03674                     {
03675                         glVertex3fv(iter->p);
03676                     }
03677                 }
03678             glEnd();
03679         }
03680         
03681         if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX)
03682         {
03683             mid_v3_v3v3(vec, arc->head->p, arc->tail->p);
03684             s += sprintf(s, "%i (%i-%i-%i) ", i, arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group);
03685         
03686             if (G.scene->toolsettings->skgen_options & SKGEN_DISP_WEIGHT)
03687             {
03688                 s += sprintf(s, "w:%0.3f ", arc->tail->weight - arc->head->weight);
03689             }
03690             
03691             if (G.scene->toolsettings->skgen_options & SKGEN_DISP_LENGTH)
03692             {
03693                 s += sprintf(s, "l:%0.3f", arc->length);
03694             }
03695             
03696             glColor3f(0, 1, 0);
03697             glRasterPos3fv(vec);
03698             BMF_DrawString( G.fonts, text);
03699         }
03700 
03701         if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX)
03702         {
03703             sprintf(text, "  %i", arc->head->index);
03704             glRasterPos3fv(arc->head->p);
03705             BMF_DrawString( G.fonts, text);
03706     
03707             sprintf(text, "  %i", arc->tail->index);
03708             glRasterPos3fv(arc->tail->p);
03709             BMF_DrawString( G.fonts, text);
03710         }
03711     }
03712     glEnable(GL_DEPTH_TEST);
03713     
03714     glLineWidth(1.0);
03715     glPointSize(1.0);
03716 }
03717 
03718 #endif