/* * TriangleUtils: mesh manipulation routines: */ #include #include "./triangle.h" #include "../Exceptions/exceptions.h" #include "../MemOps/MemOps.h" #define RIFTPENALTYPAIRSWIDTH 8 int IsGridOnRift(int* riftsegments, int nriftsegs, int node){/*{{{*/ /*Does this node belong to 4 elements, or just 2? If it belongs to 4 elements, it is inside a rift, *if it belongs to 2 elements, it is on the tip of a rift, or it has already been split across the rift (see below).*/ int i; int j; int count; count=0; for (i=0;i(max_number_elements); for (i=0;i(GridElements,current_size,(current_size+max_number_elements)); if (!GridElementsRealloc){ noerr=0; goto cleanup_and_return; } current_size+=max_number_elements; GridElements=GridElementsRealloc; GridElements[NumGridElements]=i; NumGridElements++; break; } } } } cleanup_and_return: if(!noerr){ xDelete(GridElements); } /*Allocate return pointers: */ *pGridElements=GridElements; *pNumGridElements=NumGridElements; return noerr; }/*}}}*/ int IsNeighbor(int el1,int el2,int* index){/*{{{*/ /*From a triangulation held in index, figure out if elements 1 and 2 have two nodes in common: */ int i,j; int count=0; for (i=0;i<3;i++){ for (j=0;j<3;j++){ if (index[3*el1+i]==index[3*el2+j])count++; } } if (count==2){ return 1; } else{ return 0; } }/*}}}*/ int IsOnRift(int el,int nriftsegs,int* riftsegments){/*{{{*/ /*From a list of elements segments, figure out if el belongs to it: */ int i; for (i=0;i(nsegs*5); /*Find the segments that belong to a rift: they are the ones that see two elements. The other ones belong to a boundary *or a hole: */ nriftsegs=0; for (i=0;i(nriftsegs*4); counter=0; for (i=0;i(riftsegments_uncompressed); /*Assign output pointers: */ *priftsegments=riftsegments; *pnriftsegs=nriftsegs; }/*}}}*/ int DetermineGridElementListOnOneSideOfRift(int* pNumGridElementListOnOneSideOfRift, int** pGridElementListOnOneSideOfRift, int segmentnumber, int nriftsegs, int* riftsegments, int node,int* index,int nel){/*{{{*/ int noerr=1; int k,l,counter; int newel; int* GridElements=NULL; int NumGridElements; /*Output: */ int NumGridElementListOnOneSideOfRift; int* GridElementListOnOneSideOfRift=NULL; /*Build a list of all the elements connected to this node: */ GridElementsList(&GridElements,&NumGridElements,node,index,nel); /*Figure out the list of elements that are on the same side of the rift. To do so, we start from one * side of the rift and keep rotating in the same direction:*/ GridElementListOnOneSideOfRift=xNew(NumGridElements); //bootstrap the GridElementListOnOneSideOfRift by filling elements from riftsegments: */ GridElementListOnOneSideOfRift[0]=*(riftsegments+4*segmentnumber+0); /*this one does not belong to the same side, but is just there for a rotation direction, we 'll take it out when we are done rotating*/ GridElementListOnOneSideOfRift[1]=*(riftsegments+4*segmentnumber+1); counter=1; for (;;){ /*Find neighbour of element GridElementListOnOneSideOfRift[counter], not * equal to GridElementListOnOneSideOfRift[counter-1]*/ for (k=0;k(GridElements); /*Assign output pointers: */ *pNumGridElementListOnOneSideOfRift=NumGridElementListOnOneSideOfRift; *pGridElementListOnOneSideOfRift=GridElementListOnOneSideOfRift; return noerr; }/*}}}*/ int UpdateSegments(int** psegments,int** psegmentmarkerlist, int* pnsegs,int* index, double* x,double* y,int* riftsegments,int nriftsegs,int nods,int nel){/*{{{*/ int noerr=1; int i,j,k; int el1,el2; int *segments = NULL; int *segmentmarkerlist = NULL; int nsegs; /*Recover input: */ segments = *psegments; segmentmarkerlist = *psegmentmarkerlist; nsegs = *pnsegs; /*Reallocate segments: */ segments =xReNew(segments, nsegs*3,(nsegs+nriftsegs)*3); segmentmarkerlist=xReNew(segmentmarkerlist,nsegs,(nsegs+nriftsegs)); /*First, update the existing segments to the new nodes :*/ for (i=0;i(new_numsegs*3); new_segmentmarkers=xNew(new_numsegs); /*Copy new segments info : */ counter=0; for (i=0;i(numrifts); riftssegments=xNew(numrifts); for (i=0;i(counter*3); /*Copy new segments info :*/ counter=0; for (j=0;j(segments); /*Assign output pointers: */ *psegments=new_segments; *psegmentmarkerlist=new_segmentmarkers; *pnumsegs=new_numsegs; *pnumrifts=numrifts; *priftssegments=riftssegments; *priftsnumsegs=riftsnumsegs; return noerr; }/*}}}*/ int PairRiftElements(int** priftsnumpairs,int*** priftspairs,int numrifts,int* riftsnumsegments,int** riftssegments,double* x,double* y){/*{{{*/ int noerr=1; int i,j,k; /*output: */ int *riftsnumpairs = NULL; int **riftspairs = NULL; /*intermediary :*/ int numsegs; int* segments=NULL; int* pairs=NULL; int node1,node2,node3,node4; riftsnumpairs=xNew(numrifts); riftspairs=xNew(numrifts); for (i=0;i(2*numsegs); for (j=0;j=2 indicates a certain rift: */ numrifts=0; for (i=0;imaxmark){ numrifts++; maxmark=segmentmarkerlist[i]; } } if(numrifts)riftflag=1; /*Assign output pointers:*/ *priftflag=riftflag; *pnumrifts=numrifts; return noerr; }/*}}}*/ int OrderRifts(int** priftstips,int** riftssegments,int** riftspairs,int numrifts,int* riftsnumsegments,double* x,double* y,int nods,int nels){/*{{{*/ int noerr=1; int i,j,k,counter; /*intermediary: */ int *riftsegments = NULL; int *riftpairs = NULL; int numsegs; /*ordering and copy: */ int *order = NULL; int *riftsegments_copy = NULL; int *riftpairs_copy = NULL; /*node and element manipulation: */ int node1,node2,node3,node4,temp_node,tip1,tip2,node; int el2; int already_ordered=0; /*output: */ int* riftstips=NULL; /*Allocate byproduct of this routine, riftstips: */ riftstips=xNew(numrifts*2); /*Go through all rifts: */ for (i=0;i(numsegs*3); riftpairs_copy=xNew(numsegs*2); order=xNew(numsegs); /*First find the tips, using the pairs. If a pair of elements has one node in common, this node is a rift tip: */ tip1=-1; tip2=-1; for (j=0;j0 && node4>0); if ((x[node1-1]==x[node4-1]) && (y[node1-1]==y[node4-1])){ /*Swap node3 and node4:*/ temp_node=node3; node3=node4; node4=temp_node; } /*Figure out if a tip is on this element: */ if (node3==node1){ /*node1 is a tip*/ if (tip1==-1) { tip1=node1; continue; } if ((tip2==-1) && (node1!=tip1)){ tip2=node1; break; } } if (node4==node2){ /*node2 is a tip*/ if (tip1==-1){ tip1=node2; continue; } if ((tip2==-1) && (node2!=tip1)){ tip2=node2; break; } } } /*Record tips in riftstips: */ *(riftstips+2*i+0)=tip1; *(riftstips+2*i+1)=tip2; /*We have the two tips for this rift. Go from tip1 to tip2, and figure out the order in which segments are sequential. *Because two elements are connected to tip1, we chose one first, which defines the direction we are rotating along the rift. */ node=tip1; for (counter=0;counter(order); xDelete(riftsegments_copy); xDelete(riftpairs_copy); } /*Assign output pointer:*/ *priftstips=riftstips; return noerr; }/*}}}*/ int PenaltyPairs(double*** priftspenaltypairs,int** priftsnumpenaltypairs,int numrifts,int** riftssegments,/*{{{*/ int* riftsnumsegs,int** riftspairs,int* riftstips,double* x,double* y){ int noerr=1; int i,j,k,k0; double el1,el2,node1,node2,node3,node4; double temp_node; /*output: */ double **riftspenaltypairs = NULL; double *riftpenaltypairs = NULL; int *riftsnumpenaltypairs = NULL; /*intermediary: */ int numsegs; int* riftsegments=NULL; int* riftpairs=NULL; int counter; double normal[2]; double length; int k1,k2; /*Allocate: */ riftspenaltypairs=xNew(numrifts); riftsnumpenaltypairs=xNew(numrifts); for(i=0;i((numsegs/2-1)*RIFTPENALTYPAIRSWIDTH); /*Go through only one flank of the rifts, not counting the tips: */ counter=0; for(j=0;j<(numsegs/2);j++){ el1=*(riftpairs+2*j+0); el2=*(riftpairs+2*j+1); node1=*(riftsegments+3*j+0); node2=*(riftsegments+3*j+1); /*Find segment index to recover node3 and node4, facing node1 and node2: */ k0=-1; for(k=0;k(x,nods,nods+1); y=xReNew(y,nods,nods+1); x[nods]=(x[(int)node1-1]+x[(int)node2-1]+x[(int)node3-1])/3; y[nods]=(y[(int)node1-1]+y[(int)node2-1]+y[(int)node3-1])/3; index=xReNew(index,nel*3,(nel+2*3)); /*First, reassign element el: */ *(index+3*el+0)=node1; *(index+3*el+1)=node2; *(index+3*el+2)=nods+1; /*Other two elements: */ *(index+3*nel+0)=node2; *(index+3*nel+1)=node3; *(index+3*nel+2)=nods+1; *(index+3*(nel+1)+0)=node3; *(index+3*(nel+1)+1)=node1; *(index+3*(nel+1)+2)=nods+1; /*we need to change the segment elements corresponding to el: */ for (k=0;k