Sun. Oct 6th, 2024

Diagram Voronoi

In the simplest case, shown in the first picture, we are given a finite set of points {p1, …, pn} in the Euclidean plane. 
In this case each site pk is simply a point, and its corresponding Voronoi cell Rk consists of every point in the Euclidean plane whose distance to pk is 
less than or equal to its distance to any other pk. Each such cell is obtained from the intersection of half-spaces, and hence it is a convex polygon. 
The line segments of the Voronoi diagram are all the points in the plane that are equidistant to the two nearest sites. The Voronoi vertices (nodes) are 
the points equidistant to three (or more) sites.

Let X {\displaystyle \scriptstyle X} \scriptstyle X be a metric space with distance function d {\displaystyle \scriptstyle d} \scriptstyle d. Let K {\displaystyle \scriptstyle K} \scriptstyle K be a set of indices and let ( P k ) k ∈ K {\displaystyle \scriptstyle (P_{k})_{k\in K}} \scriptstyle (P_k)_{k \in K} be a tuple (ordered collection) of nonempty subsets (the sites) in the space X {\displaystyle \scriptstyle X} \scriptstyle X. The Voronoi cell, or Voronoi region, R k {\displaystyle \scriptstyle R_{k}} \scriptstyle R_k, associated with the site P k {\displaystyle \scriptstyle P_{k}} \scriptstyle P_k is the set of all points in X {\displaystyle \scriptstyle X} \scriptstyle X whose distance to P k {\displaystyle \scriptstyle P_{k}} \scriptstyle P_k is not greater than their distance to the other sites P j {\displaystyle \scriptstyle P_{j}} \scriptstyle P_j, where j {\displaystyle \scriptstyle j} \scriptstyle j is any index different from k {\displaystyle \scriptstyle k} \scriptstyle k. In other words, if d ( x , A ) = inf { d ( x , a ) ∣ a ∈ A } {\displaystyle \scriptstyle d(x,\,A)\;=\;\inf\{d(x,\,a)\mid a\,\in \,A\}} \scriptstyle d(x,\,A)\;=\;\inf\{d(x,\,a)\mid a\,\in \,A\} denotes the distance between the point x {\displaystyle \scriptstyle x} \scriptstyle x and the subset A {\displaystyle \scriptstyle A} \scriptstyle A, then

R k = { x ∈ X ∣ d ( x , P k ) ≤ d ( x , P j ) for all j ≠ k } {\displaystyle R_{k}=\{x\in X\mid d(x,P_{k})\leq d(x,P_{j})\;{\text{for all}}\;j\neq k\}} R_{k}=\{x\in X\mid d(x,P_{k})\leq d(x,P_{j})\;{\text{for all}}\;j\neq k\}

The Voronoi diagram is simply the tuple of cells ( R k ) k ∈ K {\displaystyle \scriptstyle (R_{k})_{k\in K}} \scriptstyle (R_k)_{k \in K} . In principle some of the sites can intersect and even coincide (an application is described below for sites representing shops), but usually they are assumed to be disjoint. In addition, infinitely many sites are allowed in the definition (this setting has applications in geometry of numbers and crystallography), but again, in many cases only finitely many sites are considered.

In the particular case where the space is a finite-dimensional Euclidean space, each site is a point, there are finitely many points and all of them are different, then the Voronoi cells are convex polytopes and they can be represented in a combinatorial way using their vertices, sides, 2-dimensional faces, etc. Sometimes the induced combinatorial structure is referred to as the Voronoi diagram. However, in general the Voronoi cells may not be convex or even connected.

In the usual Euclidean space, we can rewrite the formal definition in usual terms. Each Voronoi polygon R k {\displaystyle \scriptstyle R_{k}} \scriptstyle R_k is associated with a generator point P k {\displaystyle \scriptstyle P_{k}} \scriptstyle P_k. Let X {\displaystyle \scriptstyle X} \scriptstyle X be the set of all points in the Euclidean space. Let P 1 {\displaystyle \scriptstyle P_{1}} \scriptstyle P_1 be a point that generates its Voronoi region R 1 {\displaystyle \scriptstyle R_{1}} \scriptstyle R_{1}, P 2 {\displaystyle \scriptstyle P_{2}} \scriptstyle P_2 that generates R 2 {\displaystyle \scriptstyle R_{2}} \scriptstyle R_2, and P 3 {\displaystyle \scriptstyle P_{3}} \scriptstyle P_3 that generates R 3 {\displaystyle \scriptstyle R_{3}} \scriptstyle R_3, and so on. Then, as expressed by Tran et al[3] “all locations in the Voronoi polygon are closer to the generator point of that polygon than any other generator point in the Voronoi diagram in Euclidian plane”.

//Diagrame Voronoi		


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <graphics.h>
#include <conio.h>
#define nmax 40

typedef struct{
  float x,y;
 }vector;

typedef struct{
  float x,y;
 }punct;

typedef struct{
  int v[4];
  }triunghi;

punct p[40];
int n,nt=0;
triunghi T[2*nmax];

// functia de citire a punctelor, maxim 40 de puncte 
void citire(){
 int i;
 printf("n=");
 scanf("%d",&n);
 randomize();
 for (i=0;i<n;i++){
     p[i].x=100+random(300);
     p[i].y=100+random(300);
 }
}

//desenarea punctelor 
void desenare(){
   char c[3];
   int i;
   for(i=0;i<n;i++){
       itoa(i,c,10);
       setcolor(YELLOW);
       circle(p[i].x,p[i].y,1);
       setcolor(RED);
       outtextxy(p[i].x+3,p[i].y+3,c);
   }
   getch();
}

//desenarea triunghiului
void desenare_triunghi(punct A,punct B,punct C,int culoare){
     setcolor(culoare);
     moveto(A.x,A.y);
     lineto(B.x,B.y);
     lineto(C.x,C.y);
     lineto(A.x,A.y);
     getch();
}

//calcularea produsului scalar a doi vectori
float produs_scalar(vector u,vector v){
        return (u.x*v.x+u.y*v.y);
}

//diferenta A-B
vector scade(punct A,punct B){
      vector v;
      v.x=A.x-B.x;
      v.y=A.y-B.y;
      return v;
}

//calcularea distantei dintre doua puncte
float dist(punct a,punct b){
      return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
}

//functia pt calcularea tangentei triunhiului ABC
float tangenta(punct A,punct B,punct C){
  vector u=scade(A,B),v=scade(C,B);
  return sqrt(produs_scalar(u,u)*produs_scalar(v,v)-produs_scalar(u,v)*produs_scalar(u,v))/produs_scalar(u,v);
}

//functia ce returneaza centrul cercului circumscris triunghiului(punctul de intersectia a mediatoarelor)
punct centru_cerc(punct A,punct B,punct C){
  vector v1=scade(B,A);
  vector v2=scade(C,B);
  vector v3=scade(A,C);
  punct o;              //centrul cercului
  if(produs_scalar(v1,v3)==0){        //A-drept
      o.x=(B.x+C.x)/2;
      o.y=(B.y+C.y)/2;
      return o;
  }
  if(produs_scalar(v1,v2)==0){        //B-drept  
      o.x=(A.x+C.x)/2;
      o.y=(A.y+C.y)/2;
      return o;
  }
  if(produs_scalar(v2,v3)==0){
      o.x=(B.x+A.x)/2;
      o.y=(B.y+A.y)/2;
      return o;
  }
  float ta=tangenta(B,A,C),tb=tangenta(A,B,C),tc=tangenta(A,C,B);
  float suma=ta+tb+tc;
  o.x=((tb+tc)*A.x+(ta+tc)*B.x+(ta+tb)*C.x)/(2*suma);
  o.y=((tb+tc)*A.y+(ta+tc)*B.y+(ta+tb)*C.y)/(2*suma);
  return o;
}

//functia pt desenarea semidreptei cu originea in M
void semidreapta(punct M,vector v,int culoare){
  float tmax=200,past=0.5;
  float t;
  for(t=0;t<=tmax;t+=past){
    putpixel(M.x+t*v.x,M.y+t*v.y,culoare);
    }
}

//determinarea semnului 
int semn(punct a,punct b,punct c){
  double d1;
  d1=(double)(b.x-a.x)*(c.y-a.y)-(double)(c.x-a.x)*(b.y-a.y);
  if (d1>0)return 1;
           else if(d1<0)return -1;
	           else return 0;
}

//trasarea mediatoarelor
void mediatoare(punct A,punct B,punct C,int culoare){
//deseneaza mediatoarea laturii BC
   vector v;
   if (semn(A,B,C)>0) {
       v.x=C.y-B.y;
       v.y=-(C.x-B.x);
      }
      else{
            v.x=-(C.y-B.y);
            v.y=C.x-B.x;
	  }
   float t=sqrt(produs_scalar(v,v));
   v.x=v.x/t;v.y=v.y/t;
   punct O=centru_cerc(A,B,C);
   semidreapta(O,v,culoare);
}

void mediatoare_triunghi(punct a,punct b,punct c,int culoare){
   mediatoare(a,b,c,culoare);
   mediatoare(b,c,a,culoare);
   mediatoare(c,a,b,culoare);
}

//verifica daca un punct este in interiorul unui triunghi
int punct_in_triunghi(punct M,punct A,punct B,punct C){
  if (semn(A,B,C)>0)
      return (semn(M,A,B)>=0&& semn(M,B,C)>=0 &&semn(M,C,A)>=0);
      else  return (semn(M,A,B)<=0&& semn(M,B,C)<=0 &&semn(M,C,A)<=0);
}

//testeaza daca M se afla in interiorul cercului circumscris, returneaza 1 daca e, 0 altfel
int punct_in_cerc(punct M,punct A,punct B,punct C){
     punct O=centru_cerc(A,B,C);
     float raza=dist(O,A);
     if(dist(O,M)<=raza) return 1;
             else return 0;
}

//triangulare Delaunay
void triangulare_delaunay(){
    int i,j,k,l,ok;
    for(i=0;i<n-2;i++)
       for(j=i+1;j<n-1;j++)
	  for(k=j+1;k<n;k++){
	     ok=1;
	     l=0;
	     while(ok && l<n){
		 if(l!=i&&l!=j&&l!=k&&punct_in_cerc(p[l],p[i],p[j],p[k])) ok=0;
		 l++;
	     }
	     if(ok){
	      desenare_triunghi(p[i],p[j],p[k],3);
	      //mediatoare_triunghi(p[i],p[j],p[k],4);
	      nt++;
	      T[nt].v[1]=i;
	      T[nt].v[2]=j;
	      T[nt].v[3]=k;

	     }
	  }
}


//functia care verifica latura 

void verifica_latura(int i0,int j0,int k0,int i,int culoare){
    //io,jo,ko sunt virfurile triunghiului i
    //functia analizeaza latura iojo
      int ok=0,j,ind,k;
      punct O1=centru_cerc(p[i0],p[j0],p[k0]);
      for(j=1;j<=nt;j++){
	ind=0;
	if(j!=i){
		for(k=1;k<=3;k++){
			if(T[j].v[k]==i0) ind++;
			if(T[j].v[k]==j0) ind++;
			}
		if(ind==2){
			punct O2=centru_cerc(p[T[j].v[1]],p[T[j].v[2]],p[T[j].v[3]]);
			setcolor(culoare);
			line(O1.x,O1.y,O2.x,O2.y);
			ok=1;
			}
		}
      }
if(ok==0) mediatoare(p[k0],p[i0],p[j0],culoare);
}

//functia care realizeaza diagrama Voronoi

void diagrama_voronoi(int culoare){
int i,i0,j0,k0;
for(i=1;i<=nt;i++){
	i0=T[i].v[1];j0=T[i].v[2];k0=T[i].v[3];
	verifica_latura(i0,j0,k0,i,culoare);
		verifica_latura(j0,k0,i0,i,culoare);
	verifica_latura(k0,i0,j0,i,culoare);
	}
}

void main(){
   citire();
   int gm, gd=DETECT;
   initgraph(&gd, &gm, "C:\\borlandc\\bgi");
   desenare();
   triangulare_delaunay();
   diagrama_voronoi(RED) ;
   getch();
}

35,669 total views, 1 views today