/* Authors Martin Schlather, schlather@math.uni-mannheim.de library for simulation of random fields -- init part and error messages Copyright (C) 2012 -- 2016 Felix Ballani 2017 Martin Schlather (slightly modified) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include //#include #include "RF.h" #include "convhull2D.h" /******************************************************************************* * double scProd(const double *x, const double *y) * * returns the scalar product of two two-dimensional vectors x and y ****/ double scProd(const double *x, const double *y) { return x[0]*y[0]+x[1]*y[1]; } /******************************************************************************* * int compareAngles(const void * a, const void * b) * * returns -1 if ab, or 0 if a=b ****/ int compareAngles(const void * a, const void * b) { double diff = ( *(double*)a - *(double*)b ); if(diff<0.0) return -1; if(diff>0.0) return 1; return 0; } /******************************************************************************* * void rTriangle(double *phi) * * returns three random angles from (0,2*PI) according to a joint distribution * which has a density w.r.t. the i.i.d. case proportional to the area of the * triangle spanned by the corresponding points on the unit circle (multiplied * by the indicator that this triangle contains the origin) * * needs a function * double runif(void) * which generates a uniform random number from (0,1) ****/ /* void rTriangle(double *phi) { int onceagain=1, ok=0; double a, amax=1.2990381056766579701455847561294; // amax = maximum area of a triangle with vertices on the unit circle // = 3*SQRT(3.0)/4 while(onceagain) { ok = 0; while(!ok) { ok = 1; phi[0] = 2*PI*UNIFORM_RANDOM; phi[1] = 2*PI*UNIFORM_RANDOM; phi[2] = 2*PI*UNIFORM_RANDOM; q sort(phi, 3, sizeof(double), compareAngles); if(phi[2]-phi[0]phi[0]+PI) ok=0; } a = 0.5*(FABS(SIN(phi[2]-phi[1]))+fabs(SIN(phi[0]-phi[2]))+fabs(SIN(phi[1]-phi[0]))); if(amax*UNIFORM_RANDOMphi[0]+PI); } a = 0.5 * (FABS(SIN(phi[2]-phi[1])) + FABS(SIN(phi[0]-phi[2])) + FABS(SIN(phi[1]-phi[0]))); if(amax * UNIFORM_RANDOM < a) break; } } /******************************************************************************* * int rPoissonPolygon(struct polygon *P, double lambda) * * generates the typical cell of a stationary and isotropic Poisson line * tessellation with intensity lambda>0, see * - Schneider, R. and Weil, W. (2008). Stochastic and Integral Geometry. * Springer-Verlag, Berlin, Heidelberg, pp. 497f. * - Calka, P. (2009). Tessellations. Contributed chapter to New Perspectives in * Stochastic Geometry. Edited by W. Kendall and I. Molchanov. Oxford * University Press * * returns an error code err * * needs * - a function * double runif(void) * which generates a uniform random number from (0,1) * - a function * double rexp(double mu) * which generates a random number from the exponential distribution with * mean 1/mu * - a function * double rpois(double mu) * which generates a random number from the Poisson distribution with mean mu * * ! no errors are catched so far ****/ int rPoissonPolygon(struct polygon *P, double lambda, bool do_centering) { double R,T,RRight,RLeft,RMax,uprim[2],pprim,udual[2],pdual; double sqrlen,ulen,maxlen; int n=0,nold=0,nneu,ok=0,i,j,nV=0; int err=NOERROR; // arrays double phi[3], psi, **vdual, **vdtemp, **vsave; struct vertex *vprim; // generate initial triangle // T = rexp(2.0); T = rexp(0.5); n = 3; rTriangle(phi); vdual = (double **) CALLOC(n, sizeof(double *)); vsave = (double **) CALLOC(n, sizeof(double *)); for(i=0;iRMax) RMax = R; R = T/COS(PI+0.5*(phi[0]-phi[2])); if(R>RMax) RMax = R; // rest of the line process R = 10.0; // seems to be a good initial value RLeft = T-R; RRight = T; while(!ok){ RLeft += R; if(RRight+R>RMax){ ok = 1; R = RMax-RRight; } RRight += R; nneu = rpois(2.0*R); if(nneu>0){ FREE(vprim); n += nneu; vdtemp = (double **) realloc(vdual, (n+1)*sizeof(double *)); if(vdtemp != NULL) vdual = vdtemp; else { err = ERRORMEMORYALLOCATION; goto ErrorHandling; } vdtemp = (double **) realloc(vsave, n*sizeof(double *)); if(vdtemp != NULL) vsave = vdtemp; else { err = ERRORMEMORYALLOCATION; goto ErrorHandling; } for(i=nold;imaxlen) maxlen = sqrlen; } if(maxlenn = nV; P->box0[0] = 0.0; P->box0[1] = 0.0; P->box1[0] = 0.0; P->box1[1] = 0.0; P->v = (struct vertex *) CALLOC(P->n, sizeof(struct vertex)); for(i=0;in;i++){ for(j=0;j<2;j++){ P->v[i].x[j] = vprim[i].x[j]/lambda; // printf("i,j = %d %d %f \n", i, j, P->v[i].x[j]); if(P->v[i].x[j]box0[j]) P->box0[j] = P->v[i].x[j]; if(P->v[i].x[j]>P->box1[j]) P->box1[j] = P->v[i].x[j]; } } /* neu */ if (do_centering) { double centre; int d; for (d=0; d<2; d++) { centre = 0.5 * (P->box0[d] + P->box1[d]); P->box0[d] -= centre; P->box1[d] -= centre; for(i=0;in;i++) P->v[i].x[d] -= centre; } } /* end neu */ P->e = (struct edge *) CALLOC(P->n, sizeof(struct edge)); for(i=0;in;i++) { j = (i+1) % nV; P->e[i].u[0] = P->v[j].x[1]-P->v[i].x[1]; P->e[i].u[1] = P->v[i].x[0]-P->v[j].x[0]; ulen = SQRT(scProd(P->e[i].u,P->e[i].u)); P->e[i].u[0] /= ulen; P->e[i].u[1] /= ulen; P->e[i].p = scProd(P->e[i].u,P->v[i].x); } ErrorHandling: for(i=0;ie); FREE(P->v); } /******************************************************************************* * int isInside(struct polygon *P, double *x) * * returns 1 if the two-dimensional vectors x is inside the polygon P, else 0 ****/ bool isInside(struct polygon *P, double *x) { // changed ! int i; for(i=0;in;i++) if(scProd(x,P->e[i].u) > P->e[i].p) return false; return true; } /******************************************************************************* * double getArea(struct polygon *P) * * returns the area of the polygon P ****/ double getArea(struct polygon *P) { int i, j; double a=0.0, dx, dy; for(i=0;in;i++){ j = (i+1) % P->n; dx = P->v[i].x[0]-P->v[j].x[0]; dy = P->v[i].x[1]-P->v[j].x[1]; a += 0.5*P->e[i].p*SQRT(dx*dx+dy*dy); } return a; }