source: XIOS/dev/branch_yushan_merged/extern/remap/src/intersect.cpp @ 1153

Last change on this file since 1153 was 1153, checked in by yushan, 7 years ago

save modif

File size: 10.7 KB
Line 
1#include <cstdlib>
2#include <cmath>
3#include <cassert>
4#include <cstring>
5#include <iostream>
6#include <fstream>
7#include "node.hpp"
8#include "elt.hpp"
9#include "gridRemap.hpp"
10#include "inside.hpp"
11#include "polyg.hpp"
12#include "intersect.hpp"
13#include "intersection_ym.hpp"
14
15namespace sphereRemap {
16
17using namespace std;
18
19/** returns index of edge of a that is shared with b,
20    or NOT_FOUND if a and b do not share an edge */
21int neighbour_idx(const Elt& a, const Elt& b)
22{
23        for (int i = 0; i < a.n; i++)
24        {
25                for (int j = 0; j < b.n; j++)
26                {
27                        assert(squaredist(a.vertex[ i       ], b.vertex[ j       ]) > EPS*EPS ||
28                               squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+1)%b.n]) > EPS*EPS);
29                        if (   squaredist(a.vertex[ i       ], b.vertex[ j           ]) < 1e-13*1e-13 &&
30                               squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+b.n-1)%b.n]) < 1e-13*1e-13)
31                        {
32                                return i;
33                        }
34                }
35        }
36        return NOT_FOUND;
37}
38
39/** New methods to find an insert a neighbour in a cell of the source mesh.
40 *  return true/false if cell b is a neighbour of a. if "insert" is true, then b will be inserted as a neighbour
41 * in cell a . This is needed for 2 order interpolation that need neighboround for gradient computing.
42 * A cell is a neighbour if :
43 *  - it shares 2 countiguous vertex (ie an edge) with a
44 *  - A vertex of b is located on one of an edge of a.
45 **/
46bool insertNeighbour( Elt& a, const Elt& b, bool insert )
47{
48  // for now suppose pole -> Oz
49  Coord pole(0,0,1) ;
50  Coord O, Oa1, Oa2,Ob1,Ob2,V1,V2 ;
51  double da,db,alpha,alpha1,alpha2,delta ;
52 
53   
54  for (int i = 0; i < a.n; i++)
55  {
56    for (int j = 0; j < b.n; j++)
57    {
58      // share a full edge ? be carefull at the orientation
59     
60      //if(squaredist(a.vertex[i], b.vertex[j]) > 1e-10*1e-10 ||
61      //   squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+1)%b.n]) > 1e-10*1e-10 )
62      //{     
63        //printf("A : squaredist(a.vertex[%d], b.vertex[%d]) = %.10e  %d\n",
64        //        i, j, squaredist(a.vertex[i], b.vertex[j]),
65        //        squaredist(a.vertex[i], b.vertex[j]) > 1e-10*1e-10 ? true : false);
66        //printf("B : squaredist(a.vertex[%d], b.vertex[%d]) = %.10e  %d\n",
67        //        (i+1)%a.n, (j+1)%b.n, squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+1)%b.n]),
68        //        squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+1)%b.n]) > 1e-10*1e-10 ? true : false);
69
70        assert(squaredist(a.vertex[ i       ], b.vertex[ j       ]) > 1e-10*1e-10 ||
71               squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+1)%b.n]) > 1e-10*1e-10);
72       
73      //}
74
75      if (   squaredist(a.vertex[ i       ], b.vertex[ j           ]) < 1e-10*1e-10 &&
76             squaredist(a.vertex[(i+1)%a.n], b.vertex[(j+b.n-1)%b.n]) < 1e-10*1e-10)
77      {
78        if (insert) a.neighbour[i] = b.id.ind ;
79        return true;
80      }
81     
82
83// 1 or 2 vertices of b is located on an edge of a
84       da=a.d[i] ;
85       if (scalarprod(a.edge[i], pole) < 0) da=-da ;
86       db=b.d[(j+b.n-1)%b.n] ;
87       if (scalarprod(b.edge[(j+b.n-1)%b.n], pole) < 0) db=-db ;
88     
89      if ( fabs(da-db)<1e-10 ) 
90      {
91        O=pole*da ;
92        Oa1=a.vertex[i]-O ;
93        Oa2=a.vertex[(i+1)%a.n]-O ; 
94        Ob1=b.vertex[j]-O ;
95        Ob2=b.vertex[(j+b.n-1)%b.n]-O ;
96        V1=crossprod(Oa1,Oa2) ;
97        V2=crossprod(Ob1,Ob2) ;
98        if (norm(crossprod(V1,V2))/(norm(V1)*norm(V2)) < 1e-10)
99        {
100          alpha = vectAngle(Oa1,Oa2,V1) ;
101          alpha1= vectAngle(Oa1,Ob1,V1) ;
102          alpha2= vectAngle(Oa1,Ob2,V1) ;
103          delta= alpha2-alpha1 ;
104          if (delta >= M_PI) delta=2*M_PI-delta ;
105          else if (delta <= -M_PI) delta=2*M_PI+delta ;
106         
107          if (alpha >= 0)
108          {
109            if (alpha1 > 1e-10 && alpha1 < alpha-1e-10)
110            {
111              if (alpha2 > 1e-10 && alpha2 < alpha-1e-10)
112              {
113                assert(delta > 0) ;
114                if (insert)
115                {
116                // insert both
117                  a.insert_vertex(i,b.vertex[(j+b.n-1)%b.n]);
118                  a.insert_vertex(i,b.vertex[j]);
119                  a.neighbour[i+1] = b.id.ind ;
120                }
121                return true ;
122              }
123              else
124              {
125                assert( delta > 0 ) ;
126                if (insert)
127                {
128                //insert alpha1
129                  a.insert_vertex(i,b.vertex[j]);
130                  a.neighbour[i+1] = b.id.ind ;
131                }
132                return true ;
133              }
134            }
135            else if (alpha2 > 1e-10 && alpha2 < alpha-1e-10)
136            {
137              assert( delta > 0 ) ;
138              if (insert)
139              {
140              // insert alpha2
141                a.insert_vertex(i,b.vertex[(j+b.n-1)%b.n]);
142                a.neighbour[i] = b.id.ind ;
143              }
144              return true ;
145            }
146            else
147            {
148              // nothing to do
149            } 
150
151          }
152          else  // alpha < 0
153          {
154            if (alpha1 < -1e-10 && alpha1 > alpha+1e-10)
155            {
156              if (alpha2 < -1e-10 && alpha2 > alpha+1e-10)
157              {
158                assert(delta < 0) ;
159                if (insert)
160                {
161                // insert both
162                  a.insert_vertex(i,b.vertex[(j+b.n-1)%b.n]);
163                  a.insert_vertex(i,b.vertex[j]);
164                  a.neighbour[i+1] = b.id.ind ;
165                }
166                return true ;
167              }
168              else
169              {
170                assert(delta < 0) ;
171                if (insert)
172                {
173                //insert alpha1
174                  a.insert_vertex(i,b.vertex[j]);
175                  a.neighbour[i+1] = b.id.ind ;
176                }
177                return true ;
178              }
179            }
180            else if (alpha2 < -1e-10 && alpha2 > alpha+1e-10)
181            {
182              assert(delta < 0) ;
183              if (insert)
184              {
185              // insert alpha2
186                a.insert_vertex(i,b.vertex[(j+b.n-1)%b.n]);
187                a.neighbour[i] = b.id.ind ;
188              }
189              return true ;
190            }
191            else
192            {
193               // nothing to do
194            }
195          }
196        }
197      }
198    }
199  }
200  return false;
201}
202
203/**
204If `a` and `b` are neighbours (in the sense that they share an edge)
205then this information will be stored in `a` (but not in `b`)
206*/
207void set_neighbour(Elt& a, const Elt& b)
208{
209  if (b.id.ind == a.id.ind) return;
210/*
211  int idx = neighbour_idx(a, b);
212  if (idx != NOT_FOUND)
213  a.neighbour[idx] = b.id.ind;
214*/
215  insertNeighbour(a,b,true) ; 
216}
217
218/** return true if `a` and `b` share an edge */
219bool isNeighbour(Elt& a, const Elt& b)
220{
221        // return neighbour_idx(a, b) != NOT_FOUND;
222  return insertNeighbour(a,b,false) ;
223}
224
225/* computes intersection between elements a and b */
226
227void intersect(Elt *a, Elt *b)
228{
229        int na = a->n; /* vertices of a */
230        int nb = b->n; /* vertices of b */
231        Coord *c   = new Coord[na+nb];
232        Coord *c2  = new Coord[na+nb];
233        Coord *xc  = new Coord[na+nb];
234        Coord *xc2 = new Coord[na+nb];
235        Coord gc, gc2;
236        double *d = new double[na+nb];
237        double *d2 = new double[na+nb];
238        double are, are2;
239        Ipt ipt[NMAX*NMAX];
240        Ipt ipt2[NMAX*NMAX];
241        ptsec(a, b, ipt);
242        /* make ipt2 transpose of ipt */
243        for (int ii = 0; ii < na; ii++)
244                for (int jj = 0; jj < nb; jj++)
245                        ipt2[jj*na+ii] = ipt[ii*nb+jj];
246        list<Sgm> iscot;
247        recense(a, b, ipt, iscot, 0);
248        recense(b, a, ipt2, iscot, 1);
249
250        int nseg = iscot.size();
251        int nc = 0;
252        int nc2 = 0;
253        while (iscot.size() && nc < 2)
254                nc = assemble(iscot, c, d, xc);
255        while (iscot.size() && nc2 < 2)
256                nc2 = assemble(iscot, c2, d2, xc2);
257//      assert(nseg == nc + nc2 || nseg == 1); // unused segment
258
259        if (!(nseg == nc + nc2 || nseg == 1))
260        {
261
262
263//          cout<<a->x.x<<"  "<<a->x.y<<"  "<<a->x.z<<endl ;
264//          cout<<b->x.x<<"  "<<b->x.y<<"  "<<b->x.z<<endl ;
265//          cout<<" List of vertex from a and b"<<endl ;
266//          for(int i=0;i<na;i++) cout <<"polygonPoints.InsertPoint("<<i<<", "<<a->vertex[i].x<<", "<<a->vertex[i].y<<", "<<a->vertex[i].z<<")"<<endl ;
267//          for(int i=0;i<nb;i++) cout <<"polygonPoints.InsertPoint("<<i+6<<", "<<b->vertex[i].x<<", "<<b->vertex[i].y<<", "<<b->vertex[i].z<<")"<<endl ;
268//          cout<<"na : "<<na<<"   nb : "<<nb<<endl;
269//          cout<<"nc :"<<nc<<"  nc2 :"<<nc2<<"   nseg : "<<nseg<<endl ;
270//          abort() ;
271//         cout<<"**********************************************"<<endl ;
272//         intersect_ym(a,b) ;
273        }
274
275//    intersect_ym(a,b) ;
276        if (nc == 1) nc = 0;
277        if (nc2 == 1) nc2 = 0;
278        gc = barycentre(xc, nc);
279        gc2 = barycentre(xc2, nc2);
280        orient(nc, xc, c, d, gc);
281
282        Coord pole = srcGrid.pole;
283        if (pole == ORIGIN) pole = tgtGrid.pole;
284        const double MINBASE = 1e-11;
285        if (nc == 2) /* nc is the number of vertices of super mesh element */
286        {
287                double base = arcdist(xc[0], xc[1]);
288cerr << "DID ARRIVE " << base << xc[0] << xc[1] << endl;
289                gc = midpoint(gc, midpointSC(xc[0], xc[1]));
290                /* intersection area `are` must be zero here unless we have one great and one small circle */
291                are = alun(base, fabs(scalarprod(xc[0], pole)));
292        }
293        else
294        {
295                are = airbar(nc, xc, c, d, pole, gc);
296        }
297        if (nc2 == 2)
298        {
299                double base = arcdist(xc2[0], xc2[1]);
300cerr << "DID ARRIVE " << base << xc2[0] << xc2[1] << endl;
301                assert(base > MINBASE);
302                gc2 = midpoint(gc2, midpointSC(xc2[0], xc2[1]));
303                are2 = alun(base, fabs(scalarprod(xc2[0], pole))); // 0
304        }
305        else
306        {
307                are2 = airbar(nc2, xc2, c2, d2, pole, gc2);
308        }
309
310//  double ym_area=intersect_ym(a,b) ;
311
312  if (nc > 1)
313        {
314                /* create one super mesh polygon that src and dest point to */
315                Polyg *is = new Polyg;
316                is->x = gc;
317                is->area = are;
318                is->id = b->id;
319                is->src_id = b->src_id;
320                is->n = nc;
321                (a->is).push_back(is);
322                (b->is).push_back(is);
323/*
324          if (  2*fabs(are-ym_area)/(are+ym_area) > 1.1 && ym_area>1e-8)
325    {
326      cout<<"Big area difference : "<<are<<"  "<<ym_area<<endl ;
327      intersect_ym(a,b) ;
328    }
329*/
330//              cout<<"intersection : "<<are<<" "<< ym_area<<"  diff : "<<fabs(are-ym_area)<<"  ratio : "<<fabs(are-ym_area)/(0.5*(are+ym_area))<<endl ;
331        }
332        if (nc2 > 1)
333        {
334                Polyg *is = new Polyg;
335                is->x = gc2;
336                is->area = are2;
337                is->id = b->id; /* intersection holds id of corresponding source element (see Elt class definition for details about id) */
338                is->src_id = b->src_id;
339                is->n = nc2;
340                (a->is).push_back(is);
341                (b->is).push_back(is);
342/*
343    if (        2*fabs(are-ym_area)/(are+ym_area) > 1.1 && ym_area>1e-8 )
344    {
345      cout<<"Big area difference : "<<are<<"  "<<ym_area<<endl ;
346      intersect_ym(a,b) ;
347    }
348*/
349//              cout<<"intersection : "<<are2<<" "<< ym_area<<"  diff : "<<fabs(are-ym_area)<<"  ratio : "<<fabs(are-ym_area)/(0.5*(are+ym_area))<<endl ;
350        }
351/*
352  if (nc<=1 && nc2<=1)
353  {
354    if (ym_area>1e-12)
355    {
356      cout<<"Big area difference : "<<0<<"  "<<ym_area<<endl ;
357    }
358  }
359*/
360        delete [] c;
361        delete [] c2;
362        delete [] xc;
363        delete [] xc2;
364        delete [] d;
365        delete [] d2;
366}
367
368}
Note: See TracBrowser for help on using the repository browser.