1.in 644 316 311 771 5456537470 4620 E 0.3 0.3 0.3 0.6 E 0.3 0.6 0.6 0.6 E 0.6 0.6 0.6 0.3 E 0.6 0.3 0.3 0.3 E 0.25 0.4 0.25 0.7 E 0.25 0.7 0.55 0.7 E 0.55 0.7 0.55 0.4 E 0.55 0.4 0.25 0.4 E 0.35 0.35 0.35 0.65 E 0.35 0.65 0.65 0.65 E 0.65 0.65 0.65 0.35 E 0.65 0.35 0.35 0.35 #interconnections E 0.3 0.3 0.35 0.35 E 0.3 0.3 0.25 0.4 E 0.25 0.4 0.35 0.35 E 0.3 0.6 0.35 0.65 E 0.3 0.6 0.25 0.7 E 0.25 0.7 0.35 0.65 E 0.6 0.6 0.65 0.65 E 0.6 0.6 0.55 0.7 E 0.55 0.7 0.65 0.65 E 0.6 0.3 0.65 0.35 E 0.6 0.3 0.55 0.4 E 0.55 0.4 0.65 0.35 10.in 644 316 311 1737 5456757740 4727 V 0.0 0.3 V 0.0 0.4 V 0.0 0.5 V 0.0 0.6 V 0.1 0.5 V 0.3 0.4 V 0.3 0.766 V 0.45 0.15 V 0.45 0.25 V 0.55 0.2 V 0.55 0.25 V 0.6 0.3 V 0.6 0.966 V 0.75 0.15 V 0.75 0.25 V 0.75 0.4 V 0.85 0.2 V 0.85 0.465 V 0.9 0.5 #"random points" V 0.87 0.87 V 0.15 0.9 V 0.17 0.7 V 0.25 0.15 V 0.13 0.1 V 0.3 0.05 V 0.38 0.3 #E 0.6 0.3 0.3 0.766 E 0.6 0.3 0.55 0.375 E 0.55 0.375 0.45 0.525 E 0.45 0.525 0.3 0.766 #E 0.9 0.5 0.6 0.3 E 0.9 0.5 0.85 0.465 E 0.85 0.465 0.75 0.4 E 0.75 0.4 0.6 0.3 E 0.6 0.966 0.3 0.766 E 0.6 0.966 0.9 0.5 E 0.0 0.6 0.3 0.4 E 0.3 0.4 0.0 0.3 E 0.0 0.3 0.1 0.5 E 0.3 0.4 0.1 0.5 E 0.3 0.4 0.0 0.4 E 0.1 0.5 0.0 0.5 E 0.1 0.5 0.0 0.566 E 0.45 0.15 0.75 0.15 E 0.85 0.2 0.55 0.2 E 0.45 0.25 0.75 0.25 E 0.45 0.15 0.55 0.2 E 0.45 0.25 0.55 0.2 E 0.45 0.25 0.45 0.15 E 0.85 0.2 0.75 0.15 E 0.85 0.2 0.75 0.25 E 0.75 0.25 0.75 0.2 E 0.75 0.15 0.75 0.2 E 0.55 0.25 0.55 0.2 E 0.45 0.25 0.45 0.525 E 0.55 0.25 0.55 0.375 E 0.75 0.4 0.75 0.25 E 0.85 0.465 0.85 0.2 2.in 644 316 311 222 5456537470 4610 E 0.3 0.3 0.3 0.6 E 0.3 0.6 0.6 0.6 E 0.6 0.6 0.6 0.3 E 0.6 0.3 0.3 0.3 E 0.4 0.3 0.3 0.6 E 0.3 0.6 0.6 0.6 E 0.6 0.6 0.7 0.3 E 0.7 0.3 0.4 0.3 75 0.15 V 0.75 0.25 V 0.75 0.4 V 0.85 0.2 V 0.85 0.465 V 0.9 0.5 #"random points" V 0.87 0.87 V 0.15 0.9 V 0.17 0.7 V 0.25 0.15 V 0.13 0.1 V 0.3 0.05 V 0.38 0.3 #E 0.6 0.3 0.3 0.766 E 0.6 0.3 0.55 0.375 E 0.55 0.375 0.45 0.525 E 0.45 0.525 0.3 0.766 #E 0.9 0.5 0.6 0.3 E 0.9 0.5 0.85 0.465 E 0.85 0.465 0.75 0.4 E 0.75 0.4 0.6 0.3 E 0.6 0.966 0.3 0.766 E 0.6 0.3.in 644 316 311 704 5456537470 4616 E 0.3 0.3 0.3 0.6 E 0.3 0.6 0.6 0.6 E 0.6 0.6 0.6 0.3 E 0.6 0.3 0.3 0.3 E 0.4 0.3 0.3 0.6 E 0.3 0.6 0.6 0.6 E 0.6 0.6 0.7 0.3 E 0.7 0.3 0.4 0.3 E 0.238524 0.352135 0.302145 0.645311 E 0.302145 0.645311 0.595322 0.581689 E 0.595322 0.581689 0.531700 0.288513 E 0.531700 0.288513 0.238524 0.352135 E 0.336249 0.330927 0.302145 0.645311 E 0.302145 0.645311 0.595322 0.581689 E 0.595322 0.581689 0.629425 0.267306 E 0.629425 0.267306 0.336249 0.330927 0.75 0.4 E 0.75 0.4 0.6 0.3 E 0.6 0.966 0.3 0.766 E 0.6 0.4.in 644 316 311 101 5456537470 4606 E 0.2 0.2 0.7 0.7 E 0.5 0 0.5 1 E 0 0.5 1 0.5 E 0.2 0.8 0.8 0.2 .3 0.3 E 0.4 0.3 0.3 0.6 E 0.3 0.6 0.6 0.6 E 0.6 0.6 0.7 0.3 E 0.7 0.3 0.4 0.3 E 0.238524 0.352135 0.302145 0.645311 E 0.302145 0.645311 0.595322 0.581689 E 0.595322 0.581689 0.531700 0.288513 E 0.531700 0.288513 0.238524 0.352135 E 0.336249 0.330927 0.302145 0.645311 E 0.302145 0.645311 0.595322 0.581689 E 0.595322 0.581689 0.629425 0.267306 E 0.629425 0.267306 0.336249 0.330927 0.75 0.4 E 0.75 0.4 0.6 0.3 E 0.6 0.966 0.3 0.766 E 0.6 0.5.in 644 316 311 1037 5456537470 4640 E 0.6 0.3 0.4 0.6 E 0.4 0.6 0.7 0.8 E 0.7 0.8 0.9 0.5 E 0.9 0.5 0.6 0.3 E 0.0 0.6 0.3 0.4 E 0.3 0.4 0.0 0.3 E 0.0 0.3 0.1 0.5 E 0.1 0.5 0.3 0.4 E 0.3 0.4 0.0 0.4 E 0.1 0.5 0.0 0.5 E 0.1 0.5 0.0 0.6 E 0.45 0.2 0.75 0.2 E 0.85 0.225 0.55 0.225 E 0.45 0.25 0.75 0.25 E 0.55 0.225 0.45 0.2 E 0.45 0.25 0.55 0.225 E 0.45 0.25 0.45 0.2 E 0.85 0.225 0.75 0.2 E 0.85 0.225 0.75 0.25 E 0.75 0.25 0.75 0.225 E 0.75 0.2 0.75 0.225 E 0.45 0.25 0.45 0.525 E 0.55 0.225 0.55 0.25 E 0.55 0.25 0.55 0.45 E 0.75 0.4 0.75 0.25 E 0.85 0.475 0.85 0.25 E 0.3 0.4 0.0 0.3 E 0.0 0.3 0.1 0.5 E 0.3 0.4 0.1 0.5 E 0.3 0.4 0.0 0.4 E 0.1 0.5 0.0 0.5 E 0.1 0.5 0.0 0.566 E 0.45 0.15 0.75 0.15 E 0.85 0.2 0.55 0.2 E 0.45 0.25 0.75 0.25 E 0.45 0.15 0.55 0.2 E 0.45 0.25 0.55 0.2 E 0.45 0.25 0.45 0.15 E 0.85 0.2 0.75 0.15 E 0.85 0.2 0.75 0.25 E 0.75 0.25 0.75 0.2 E 0.75 0.15 0.75 0.2 E 0.55 0.25 0.55 0.2 E 0.45 0.25 0.45 0.525 E 0.55 0.25 0.55 0.375 E 0.75 0.4 0.75 0.25 E 0.85 0.465 0.85 0.2 6.in 644 316 311 1036 5456537471 4641 E 0.6 0.3 0.4 0.6 E 0.4 0.6 0.7 0.8 E 0.7 0.8 0.9 0.5 E 0.9 0.5 0.6 0.3 E 0.0 0.6 0.3 0.4 E 0.3 0.4 0.0 0.3 E 0.0 0.3 0.1 0.5 E 0.1 0.5 0.3 0.4 E 0.3 0.4 0.0 0.4 E 0.1 0.5 0.0 0.5 E 0.1 0.5 0.0 0.6 E 0.45 0.2 0.75 0.2 E 0.85 0.225 0.55 0.225 E 0.45 0.25 0.75 0.25 E 0.55 0.225 0.45 0.2 E 0.45 0.25 0.55 0.225 E 0.45 0.25 0.45 0.2 E 0.85 0.225 0.75 0.2 E 0.85 0.225 0.75 0.25 E 0.75 0.25 0.75 0.225 E 0.75 0.2 0.75 0.225 E 0.45 0.25 0.45 0.525 E 0.55 0.225 0.55 0.25 E 0.55 0.25 0.55 0.45 E 0.75 0.25 0.75 0.4 E 0.85 0.25 0.85 0.475 7 0.8 E 0.7 0.8 0.9 0.5 E 0.9 0.5 0.6 0.3 E 0.0 0.6 0.3 0.4 E 0.3 0.4 0.0 0.3 E 0.0 0.3 0.1 0.5 E 0.1 0.5 0.3 0.4 E 0.3 0.4 0.0 0.4 E 0.1 0.5 0.0 0.5 E 0.1 0.5 0.0 0.6 E 0.45 0.2 0.75 0.2 E 0.85 0.225 0.55 0.225 E 0.45 0.25 0.75 0.25 E 0.55 0.225 0.45 0.2 E 0.45 0.25 0.55 0.225 E 0.45 0.25 0.45 0.2 E 0.85 0.225 0.75 0.2 E 0.85 0.225 0.75 0.25 E 0.75 0.25 0.75 0.225 E 0.75 0.2 0.75 0.225 E 0.45 0.25 0.45 0.525 E 0.55 0.225 0.55 0.25 E 0.55 0.25 0.55 0.45 E 0.75 0.25 0.77.in 644 316 311 644 5456537471 4626 E 0.6 0.3 0.4 0.6 E 0.4 0.6 0.7 0.8 E 0.7 0.8 0.9 0.5 E 0.9 0.5 0.6 0.3 E 0.0 0.6 0.3 0.4 E 0.3 0.4 0.0 0.3 E 0.0 0.3 0.1 0.5 E 0.1 0.5 0.3 0.4 E 0.3 0.4 0.0 0.4 E 0.1 0.5 0.0 0.5 E 0.1 0.5 0.0 0.6 E 0.45 0.05 0.75 0.2 E 0.85 0.15 0.55 0.15 E 0.45 0.25 0.75 0.25 E 0.55 0.15 0.45 0.05 E 0.45 0.25 0.55 0.15 E 0.45 0.25 0.45 0.2 E 0.85 0.15 0.75 0.2 E 0.85 0.15 0.75 0.25 E 0.75 0.25 0.75 0.15 E 0.75 0.05 0.75 0.15 0.225 E 0.45 0.25 0.45 0.525 E 0.55 0.225 0.55 0.25 E 0.55 0.25 0.55 0.45 E 0.75 0.25 0.78.in 644 316 311 2075 5456537471 4647 E 0.6 0.3 0.4 0.6 E 0.4 0.6 0.7 0.8 E 0.7 0.8 0.9 0.5 E 0.9 0.5 0.6 0.3 E 0.0 0.6 0.3 0.4 E 0.3 0.4 0.0 0.3 E 0.0 0.3 0.1 0.5 E 0.1 0.5 0.3 0.4 E 0.3 0.4 0.0 0.4 E 0.1 0.5 0.0 0.5 E 0.1 0.5 0.0 0.6 E 0.45 0.2 0.75 0.2 E 0.85 0.225 0.55 0.225 E 0.45 0.25 0.75 0.25 E 0.55 0.225 0.45 0.2 E 0.45 0.25 0.55 0.225 E 0.45 0.25 0.45 0.2 E 0.85 0.225 0.75 0.2 E 0.85 0.225 0.75 0.25 E 0.75 0.25 0.75 0.225 E 0.75 0.2 0.75 0.225 E 0.45 0.25 0.45 0.525 E 0.55 0.225 0.55 0.25 E 0.55 0.25 0.55 0.45 E 0.75 0.4 0.75 0.25 E 0.85 0.475 0.85 0.25 E 0.6 0.3 0.4 0.6 E 0.4 0.6 0.7 0.8 E 0.7 0.8 0.9 0.5 E 0.9 0.5 0.6 0.3 E 0.0 0.6 0.3 0.4 E 0.3 0.4 0.0 0.3 E 0.0 0.3 0.1 0.5 E 0.1 0.5 0.3 0.4 E 0.3 0.4 0.0 0.4 E 0.1 0.5 0.0 0.5 E 0.1 0.5 0.0 0.6 E 0.45 0.2 0.75 0.2 E 0.85 0.225 0.55 0.225 E 0.45 0.25 0.75 0.25 E 0.55 0.225 0.45 0.2 E 0.45 0.25 0.55 0.225 E 0.45 0.25 0.45 0.2 E 0.85 0.225 0.75 0.2 E 0.85 0.225 0.75 0.25 E 0.75 0.25 0.75 0.225 E 0.75 0.2 0.75 0.225 E 0.45 0.25 0.45 0.525 E 0.55 0.225 0.55 0.25 E 0.55 0.25 0.55 0.45 E 0.75 0.25 0.75 0.4 E 0.85 0.25 0.85 0.475 9.in 644 316 311 731 5456757710 4625 V 0.618292 0.280765 V 0.796142 0.67984 V 0.08896 0.110964 V 0.979481 0.899576 V 0.626606 0.90818 V 0.825787 0.188881 V 0.348996 0.510312 V 0.071448 0.969064 V 0.66649 0.602292 V 0.514141 0.355362 V 0.736412 0.438599 V 0.801016 0.305985 V 0.813527 0.720386 V 0.264764 0.880869 V 0.664803 0.825501 V 0.705477 0.564639 V 0.709036 0.261268 V 0.537745 0.243866 V 0.021377 0.532223 V 0.199031 0.825687 E 0.3 0.8 0.2 0.3 E 0.6 0.95 0.75 0.1 E 0.1 0.4 0.8 0.5 E 0.6 0.95 0.1 0.82 E 0.55 0.25 0.55 0.45 E 0.75 0.4 0.7Makefile 644 316 311 227 5456537517 5566 CFLAGS = -g -I/usr/openwin/include -DXWIN -DRANDOM OFILES = vd3.o vd1.o vdx.o CC = gcc vdx: $(OFILES) $(CC) $(CFLAGS) -o vdx $(OFILES) -lX11 -lm 69064 V 0.66649 0.602292 V 0.514141 0.355362 V 0.736412 0.438599 V 0.801016 0.305985 V 0.813527 0.720386 V 0.264764 0.880869 V 0.664803 0.825501 V 0.705477 0.564639 V 0.709036 0.261268 V 0.537745 0.243866 V 0.021377 0.532223 V 0.199031 0.825687 E 0.3 0.8 0.2 0.3 E 0.6 0.95 0.75 0.1 E 0.1 0.4 0.8 0.5 E 0.6 0.95 0.1 0.82 E 0.55 0.25 0.55 0.45 E 0.75 0.4 0.7vd.doc 644 316 311 16024 5456761075 5266 Voronoi-diagramm/Delaunay-triangulation (c) 1993 by Wolfgang Stuerzlinger This code may be used only for non-commercial purposes! This code may not be redistributed without the authors permission. **************************************************************************** The Voronoi-diagramm part is not included. All routines are written for stability/readability/ease of debugging and not for speed. There are a lot of possibilities to speed this thing up i.e. make it 5 to 10 times faster, especially the insertion routines. Also we could do a lot in terms of memory efficiency. The info part of the sites (see insert_site()) can be used to store additional information with each site (e.g. color information, radiosity, ...). To pass this info (mostly you will use a struct) cast the pointer to it to a (char *). One known bug remains (as always): sometimes it hangs :-(, I haven't traced that bug down yet, due to the lack of test data, which hangs 'reliable'. It appears most of the time with more than 200 discontinuity edges. **************************** Datatypes ************************************* * type enum { DBDRY, D0, D1, D2, DINF } DISCONTINUITY; Describes the DISCONTINUITY of an edge. DINF = discontinuity of infinite degree = continous; DBDRY = Boundary of surface! * type SURFACE; Used to describe all parameters for one surface, so that we can reference to it. Do not read/modify any of the structure members. * type SITE_PTR; Used to describe one site (i.e. one point), so that we can reference to it. Do not read/modify any of the structure members - use functions below. * typedef struct { struct NEIGHBOURS *next; SITE_PTR site; DISCONTINUITY d; } NEIGHBOURS; Used to find all neigbours to a given site (function get_neigbours()). 'next' makes the list (terminated with NULL), 'site' is the neighbouring site, 'd' describes the discontinuity of the edge. **************************** Functions ************************************* * void init_surface(SURFACE *surf,double x0,double y0,double x1,double y1); Initialize the surface. 'x0'/'y0'-'x1'/'y1' describe the range of the surface, mostly we will use 0/0-1/1. 'surf' is afterwards a valid surface desrciptor. * void delete_surface(SURFACE *surf); Frees all the memory associated with 'surf', which is invalid afterwards. * BOOLEAN insert_site(SURFACE *surf,double x,double y, SITE_PTR *site,char *info); Inserts a site at 'x'/'y' on the surface 'surf' with the additional information 'info'. Returned is site descriptor 'site'. If there exists a site already at the same position it returns FALSE and 'info' contains the information of the old site. * void insert_edge(SURFACE *surf, SITE_PTR a,SITE_PTR b, DISCONTINUITY discontinuity,SITE_PTR *new_sites,int *n_new); Inserts an fixed edge into the triangulation of the surface 'surf'. 'a' and 'b' are the endpoints, 'discontinuity' describes the degree of the edge. In the array 'new_sites' all newly created sites are returned, this happens when two (or more) fixed edges cross, there we need to create a new site. 'n_new' returns the number of newly created sites. If we have e.g. 100 fixed edges a new fixed edge may generate up to 100 new sites! * void get_coords(SURFACE *surf,SITE_PTR site,double *x,double *y); Get the 'x'/'y' coordinates of a given 'site' on a surface 'surf'. * char *get_info(SURFACE *surf,SITE_PTR site); Get the additional information associated with a given 'site' on a surface 'surf'. The returnvalue should be casted to the correct type. * void set_info(SURFACE *surf,SITE_PTR site,char *info); Set the additional information for a given 'site' on a surface 'surf'. The 'info'-parameter will need a cast to (char *) from the original type. * void locate_point(SURFACE *surf,double x,double y,SITE_PTR sites[3]); Locate the 3 'sites' around a given point ('x'/'y') on the surface 'surf'. * void get_neighbours(SURFACE *surf,SITE_PTR site,NEIGHBOURS **neigh); Returns the neigbours to a given 'site' on a surface 'surf'. See also the description of NEIGBOURS. The memory for 'neigh' is pre-allocated by get_neighbours and should not be freed! * void for_all_sites(SURFACE *surf,void (*siteproc)(SURFACE *surf,SITE_PTR s)); To iterate through all sites on the surface 'surf'. The parameter to 'siteproc' is the site. Do NOT modifiy the surface inside 'siteproc', i.e. no insert_site/_edge! * void for_all_edges(SURFACE *surf, void (*edgeproc)(SURFACE *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d)); To iterate through all edges on the surface 'surf'. The parameters 's1' and 's2' to 'edgeproc' are the begin- and endpoint of the edge, no ordering is specified, 'd' describes the discontinuity. Do NOT modifiy the surface inside 'edgeproc', i.e. no insert_site/_edge! If you want e.g. to generate new sites on the edges, save the coordinates in a list, and insert them later on. * void for_all_triangles(SURFACE *surf, void (*triproc)(SURFACE *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3)); To iterate through all triangles on the surface 'surf'. The parameters 's1', 's2' and 's3' to 'triproc' are the 3 vertices of the triangle. Do NOT modifiy the surface inside 'triproc', i.e. no insert_site/_edge! If you want e.g. to generate new sites inside the triangles, save the coordinates in a list, and insert them later on. * void flip_flipable_edges(SURFACE *surf,int (*testproc)(char *s1,char *s2, char *s3,char *s4)); Used to flip all edges which are indeterminate e.g. the two diagonals of a square. Here we could use e.g. color information to determine which diagonal we want. The 4 parameters to the procedure 'testproc' are the pointers to the information for the 4 sites ('s1'/'s2' are the first diagonal, 's3'/'s4' form the second diagonal). Do NOT modifiy the surface inside 'testproc', i.e. no insert_site/_edge! ********************** Description of vdtest ******************************** All commands are entered via the keyboard at the promt. All commands can also be passed on the command line. E.g. vdtest r 200 o q or vdtest f 4.in Commands: * r Generates new random points, if is negative generate new random edges. * f Read in the coordinates from the file and insert the points/edges into the triangulation. Fileformat: ASCII-lines with either 'V ' for a point or 'E ' for an edge. All other lines are ignored. * i Insert a point at . * e Insert a fixed edge from to . * t Initiate some tests. * w Flip (randomly) the flipable edges (only those in e.g. squares). * o Output the triangulation. Filename: vd.out Format: ASCII file with 3 kinds of lines: I to declare the region (mostly 0/0-1/1). V for a Vertex. E for an Edge with a color (discontinuity). * d Output the triangulation (see 'o') and call a program 'dis' for display. * q Quit, what else. vd.h 644 316 311 17541 5456760526 4755 /**********************************************************************/ /* Voronoi/Delaunay-Module */ /* header file */ /* */ /* (c) 1993 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* This code may not be redistributed without the authors permission. */ /**********************************************************************/ #include #include #include #include #define EPSILON (1.0e-6) #ifndef TRUE #define TRUE 1==1 #define FALSE 0==1 #endif /******************************************************************************/ /* Reference for Quad-edge data structure: Leonidas Guibas and Jorge Stolfi, "Primitives for the manipulation of general subdivisions and the computations of Voronoi diagrams", ACM Transactions on Graphics 4, 74-123 (1985). */ /******************************************************************************/ /**************************** Common data structures **************************/ typedef int BOOLEAN; typedef int SITE_PTR; typedef int EDGE_PTR; typedef int INFO_PTR; typedef enum DISCONTINUITY { DBDRY, D0, D1, D2, DINF } DISCONTINUITY; typedef struct VEC2 { double x,y; } VEC2; struct SITE { VEC2 vc; EDGE_PTR edge; int invisible; char *info; }; struct EDGE_INFO { DISCONTINUITY disco; }; typedef struct SURFACE { int n_sites; int n_edges; int alloced_sites; struct SITE *sa ; EDGE_PTR *next ; SITE_PTR *org ; struct EDGE_INFO *ei ; EDGE_PTR One_bndry_edge; VEC2 min,max; /* bounding box */ EDGE_PTR Last_locate_edge; EDGE_PTR next_edge; EDGE_PTR avail_edge; } SURFACE; typedef struct NEIGHBOURS { struct NEIGHBOURS *next; SITE_PTR site; DISCONTINUITY d; } NEIGHBOURS; typedef struct VORONOIS { struct VORONOIS *next; /* as we need a ring ! */ struct VORONOIS *prev; /* but it is split up later on ! */ VEC2 from; VEC2 to; DISCONTINUITY d; int done; } VORONOIS; /******************************************************************************/ /********************** Macros for manipulation of quad-edges *****************/ /* SITE_PTR s */ #define X(s) _surf->sa[s].vc.x #define Y(s) _surf->sa[s].vc.y #define Edge(s) _surf->sa[s].edge #define Invis(s) _surf->sa[s].invisible #define Site(s) _surf->sa[s].vc #define Info(s) _surf->sa[s].info /* EDGE_PTR a */ #define sym(a) ((a) ^ 2) #define rot(a) ( (((a) + 1) & 3) | ((a) & ~3) ) #define rotinv(a) ( (((a) + 3) & 3) | ((a) & ~3) ) #define onext(a) _surf->next[a] #define oprev(a) rot(onext(rot(a))) #define lnext(a) rot(onext(rotinv(a))) #define lprev(a) sym(onext(a)) #define rnext(a) rotinv(onext(rot(a))) #define rprev(a) onext(sym(a)) #define dnext(a) sym(onext(sym(a))) #define dprev(a) rotinv(onext(rotinv(a))) #define orig(a) _surf->org[a] #define dest(a) orig(sym(a)) #define left(a) orig(rotinv(a)) #define right(a) orig(rot(a)) #define origv(a) _surf->sa[orig(a)].vc #define destv(a) _surf->sa[dest(a)].vc #define leftv(a) _surf->fa[left(a)].vc #define rightv(a) _surf->fa[right(a)].vc #define info(a) _surf->ei[(a)>>2] #define disco(a) (info(a).disco) /******************************************************************************/ /******************************* General macros *******************************/ #ifdef DEBUG #define alive(x) printf(x) #else #define alive(x) #endif #define my_alloc(str_name, str_type, str_cnt) \ if (NULL == ((str_name) = (str_type *) \ malloc ((unsigned) ((str_cnt) * sizeof(str_type))))) \ exit(fprintf(stderr," cannot malloc %s \n",#str_name)) #define V2_dotq(u,v) ((u).x*(v).x + (u).y*(v).y) #define V2_cprodq(u,v) ((u).x*(v).y - (u).y*(v).x) #define V2_magnq(u) sqrt((u).x * (u).x + (u).y * (u).y) /********************************* MISC ***************************************/ #define flipable(e) (disco(e) > D2) #define disco_edge(e) (disco(e) <= D2) #define rightofline(X,a,b) (ccw(X,a,b)< 0.0) #define rightoronline(X,a,b) (ccw(X,a,b)<=0.0) #define leftofline(X,a,b) (ccw(X,a,b)> 0.0) #define leftoronline(X,a,b) (ccw(X,a,b)>=0.0) #define online(X,a,b) (ccw(X,a,b)==0.0) #define rightof(X,e) (ccw(X,orig(e),dest(e))< 0.0) #define rightoron(X,e) (ccw(X,orig(e),dest(e))<=0.0) #define leftof(X,e) (ccw(X,orig(e),dest(e))> 0.0) #define leftoron(X,e) (ccw(X,orig(e),dest(e))>=0.0) #define onedge(X,e) (ccw(X,orig(e),dest(e))==0.0) #define v_rightofline(X,a,b) (v_ccw(X,a,b)< 0.0) #define v_rightoronline(X,a,b) (v_ccw(X,a,b)<=0.0) #define v_leftofline(X,a,b) (v_ccw(X,a,b)> 0.0) #define v_leftoronline(X,a,b) (v_ccw(X,a,b)>=0.0) #define v_online(X,a,b) (v_ccw(X,a,b)==0.0) #define v_rightof(X,e) (v_ccw(X,origv(e),destv(e))< 0.0) #define v_rightoron(X,e) (v_ccw(X,origv(e),destv(e))<=0.0) #define v_leftof(X,e) (v_ccw(X,origv(e),destv(e))> 0.0) #define v_leftoron(X,e) (v_ccw(X,origv(e),destv(e))>=0.0) #define v_onedge(X,e) (v_ccw(X,origv(e),destv(e))==0.0) /* calc center of triangle to the left! of e */ #define cntr(e,corner) circle_center(origv(e),destv(e),destv(onext(e)),corner) /****************************** PROTOTYPES ***********************************/ /* vd1.c */ void init_surface(SURFACE *surf,double x0,double y0,double x1,double y1); void delete_surface(SURFACE *surf); BOOLEAN insert_site(SURFACE *surf,double x,double y,SITE_PTR *site,char *info); void locate_point(SURFACE *surf,double x,double y,SITE_PTR sites[3]); void get_coords(SURFACE *surf,SITE_PTR site,double *x,double *y); char *get_info(SURFACE *surf,SITE_PTR site); void set_info(SURFACE *surf,SITE_PTR site,char *info); void get_neighbours(SURFACE *surf,SITE_PTR site,NEIGHBOURS **neigh); void for_all_sites(SURFACE *surf,void (*siteproc)(SURFACE *surf,SITE_PTR s)); void for_all_edges(SURFACE *surf, void (*edgeproc)(SURFACE *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d)); void for_all_triangles(SURFACE *surf, void (*triproc)(SURFACE *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3)); void flip_flipable_edges(SURFACE *surf,int (*testproc)(char *s1,char *s2, char *s3,char *s4)); void insert_edge(SURFACE *surf, SITE_PTR a,SITE_PTR b, DISCONTINUITY discontinuity,SITE_PTR *new_sites,int *n_new); /* vd2.c */ void get_voronoi(SURFACE *surf,SITE_PTR site,VORONOIS **voronoi); /* vd3.c: INTERNAL ROUTINES !*/ void free_neighbours(void); NEIGHBOURS *alloc_neighbour_node(SITE_PTR site,DISCONTINUITY d); void free_voronois(void); void insert_node(VORONOIS **ring,VEC2 from,VEC2 to,DISCONTINUITY d,int done); void delete_node(VORONOIS **ring); EDGE_PTR makeedge(SITE_PTR origin,SITE_PTR destination,DISCONTINUITY d); void splice(EDGE_PTR a,EDGE_PTR b); void swapedge(EDGE_PTR e); EDGE_PTR connect_left(EDGE_PTR a, EDGE_PTR b,DISCONTINUITY d); EDGE_PTR connect_right(EDGE_PTR a, EDGE_PTR b,DISCONTINUITY d); void deleteedge(EDGE_PTR e); void splitedge(EDGE_PTR e,SITE_PTR site); void push_edge(EDGE_PTR edge); EDGE_PTR pop_edge(void); void zero_seen(void); void zero_seen_int(void); void push_sym_ring(EDGE_PTR edge); void sef_alloc(int n); void sef_enlarge(int additional); void sef_free(void); void delete_all_edges(void); EDGE_PTR alloc_edge(void); void free_edge(EDGE_PTR e); void delete_all_faces(void); BOOLEAN incircle(SITE_PTR a,SITE_PTR b,SITE_PTR c,SITE_PTR d); double distcircle(SITE_PTR a,SITE_PTR b,SITE_PTR c,SITE_PTR d); double ccw(SITE_PTR a,SITE_PTR b,SITE_PTR c); double v_ccw(VEC2 a,VEC2 b,VEC2 c); BOOLEAN intersect_test(VEC2 from,VEC2 to,EDGE_PTR e); BOOLEAN vintersect(VEC2 a,VEC2 b,VEC2 a1,VEC2 b1,VEC2 *inter); void circle_center(VEC2 a,VEC2 b,VEC2 c,VEC2 *corner); double V2_cprod(VEC2 u,VEC2 v); double V2_dot(VEC2 u,VEC2 v); VEC2 V2_times(double c,VEC2 v); VEC2 V2_sum(VEC2 u,VEC2 v); VEC2 V2_sub(VEC2 u,VEC2 v); double V2_magn(VEC2 u); VEC2 V2_cross(VEC2 v); VEC2 V2_crossl(VEC2 v); VEC2 V2_normalize(VEC2 v); VEC2 V2_midpoint(VEC2 v,VEC2 v1); vd1.c 644 316 311 26763 5456760503 5032 /**********************************************************************/ /* Voronoi/Delaunay-Module */ /* main interface module */ /* */ /* (c) 1993 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* This code may not be redistributed without the authors permission. */ /**********************************************************************/ #include "vd.h" #include #include #define SITEALLOC 1000 SURFACE *_surf; static BOOLEAN v_locate ( VEC2 site, EDGE_PTR *edge,SITE_PTR *oldsite ); static void incremental_delaunay( SITE_PTR site, EDGE_PTR edge); static void fix_edge_right(EDGE_PTR *e); static void triangulate_left(EDGE_PTR first); /****************************************************************/ /* Top-level Delaunay Triangulation Procedure */ /****************************************************************/ void init_surface(SURFACE *surf,double x0,double y0,double x1,double y1) { double lenx,leny; EDGE_PTR a,b,c; _surf = surf; surf->alloced_sites = SITEALLOC; sef_alloc(surf->alloced_sites); delete_all_edges(); surf->min.x = x0; surf->min.y = y0; surf->max.x = x1; surf->max.y = y1; surf->n_edges = 0; /******************** Generate Basic Mesh **************************/ surf->n_sites = 4; /* we generate a 10% bigger square */ lenx = (x1 - x0) / 10.0; leny = (y1 - y0) / 10.0; X(0) = x0 - lenx; Y(0) = y0 - leny; Invis(0) = 1; Info(0) = NULL; X(1) = x1 + lenx; Y(1) = y0 - leny; Invis(1) = 1; Info(1) = NULL; X(2) = x1 + lenx; Y(2) = y1 + leny; Invis(2) = 1; Info(2) = NULL; X(3) = x0 - lenx; Y(3) = y1 + leny; Invis(3) = 1; Info(3) = NULL; a = makeedge(0,3,DBDRY); b = makeedge(1,2,DBDRY); c = connect_left(sym(b),a,DBDRY); surf->One_bndry_edge = sym(c); c = sym(connect_right(rprev(c),c,DINF)); c = connect_left(b,sym(c),DBDRY); surf->Last_locate_edge = surf->One_bndry_edge; /* init locate */ } void delete_surface(SURFACE *surf) { _surf = surf; sef_free(); } BOOLEAN insert_site(SURFACE *surf,double x,double y,SITE_PTR *site,char *info) { EDGE_PTR e; VEC2 xy; int n; _surf = surf; if (x < _surf->min.x || x > _surf->max.x || y < _surf->min.y || y > _surf->max.y) { fprintf(stderr,"SITE outside! %g,%g\n",x,y); *site = 0; return(FALSE); } xy.x = x; xy.y = y; if (v_locate(xy,&e,site)) { /* already there ! */ Info(*site) = info; return(FALSE); } if (surf->n_sites == surf->alloced_sites) /* we're full ! */ sef_enlarge(SITEALLOC); n = surf->n_sites++; Site(n) = xy; Invis(n) = 0; /* it's visible */ Info(n) = info; incremental_delaunay(n,e); *site = n; return(TRUE); } void locate_point(SURFACE *surf,double x,double y,SITE_PTR sites[3]) { EDGE_PTR e; SITE_PTR site; VEC2 xy; _surf = surf; if (x < _surf->min.x || x > _surf->max.x || y < _surf->min.y || y > _surf->max.y) { fprintf(stderr,"POINT outside! %g,%g\n",x,y); return; } xy.x = x; xy.y = y; if (v_locate(xy,&e,&site)) /* already there */ ; /* don't care */ sites[0] = orig(e); sites[1] = dest(e); sites[2] = dest(lnext(e)); } void get_coords(SURFACE *surf,SITE_PTR site,double *x,double *y) { _surf = surf; *x = X(site); *y = Y(site); } char *get_info(SURFACE *surf,SITE_PTR site) { _surf = surf; return(Info(site)); } void set_info(SURFACE *surf,SITE_PTR site,char *info) { _surf = surf; Info(site) = info; } void get_neighbours(SURFACE *surf,SITE_PTR site,NEIGHBOURS **neigh) { EDGE_PTR e,t; NEIGHBOURS *n; _surf = surf; free_neighbours(); /* make room */ *neigh = NULL; e = Edge(site); t = e; do { if (! Invis(dest(e))) { n = alloc_neighbour_node(dest(e),disco(e)); n->next = *neigh; *neigh = n; } e = oprev(e); } while (t != e); } void for_all_sites(SURFACE *surf,void (*siteproc)(SURFACE *surf,SITE_PTR s)) { SITE_PTR site; _surf = surf; for (site = 0; site < surf->n_sites; site++) { if (Invis(site)) continue; (*siteproc)(surf,site); } } void for_all_edges(SURFACE *surf, void (*edgeproc)(SURFACE *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d)) { int i; EDGE_PTR e; _surf = surf; if (_surf->avail_edge != -1) { fprintf(stderr,"Aw, Shit not all edges are valid !\n"); return; } e = 0; for (i = 0; i < _surf->n_edges; i++, e += 4) { if (Invis(orig(e)) || Invis(dest(e))) continue; (*edgeproc)(surf,orig(e),dest(e),disco(e)); } } void for_all_triangles(SURFACE *surf, void (*triproc)(SURFACE *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3)) { EDGE_PTR e,t; SITE_PTR site; _surf = surf; for (site = 0; site < surf->n_sites; site++) { if (Invis(site)) continue; e = Edge(site); t = e; do { if (! Invis(dest(e)) && ! Invis(dest(onext(e))) && Y(site) < Y(dest(onext(e)))) { if (Y(site) < Y(dest(e)) || (Y(site) == Y(dest(e)) && X(site) < X(dest(e)))) (*triproc)(surf,site,dest(e),dest(onext(e))); } e = oprev(e); } while (t != e); } } void flip_flipable_edges(SURFACE *surf,int (*testproc)(char *s1,char *s2, char *s3,char *s4)) { int i; double dist1,dist2; EDGE_PTR e; SITE_PTR s1,s2,s3,s4; _surf = surf; if (_surf->avail_edge != -1) { fprintf(stderr,"Aw, Shit not all edges are valid !\n"); return; } e = 0; for (i = 0; i < _surf->n_edges; i++, e += 4) { s1 = orig(e); s2 = dest(e); if (disco_edge(e) || Invis(s1) || Invis(s2)) continue; s3 = dest(oprev(e)); /* point on right */ s4 = dest(onext(e)); /* point on left */ dist1 = distcircle(s1,s3,s2,s4); dist2 = distcircle(s3,s2,s4,s1); if (dist1 >= 0.0 && dist2 >= 0.0) { /* both are inside */ if ((*testproc)(Info(s1),Info(s2),Info(s3),Info(s4))) swapedge(e); } } } /****************************************************************/ /* Incremental Delaunay Triangulation Procedure */ /****************************************************************/ /* find an edge where site lies left or on ! */ static BOOLEAN v_locate ( VEC2 site, EDGE_PTR *edge,SITE_PTR *oldsite ) { register EDGE_PTR e; int i; i = 0; e = _surf->Last_locate_edge; while (1) { i++; if (site.x == X(orig(e)) && site.y == Y(orig(e))) { *edge = e; *oldsite = orig(e); return(TRUE); } else if (site.x == X(dest(e)) && site.y == Y(dest(e))) { *edge = e; *oldsite = dest(e); return(TRUE); } else if (v_rightof(site,e)) e = sym(e); else if (v_leftoron(site,onext(e))) e = onext(e); else if (v_leftoron(site,dprev(e))) e = dprev(e); else break; } /* As Gordon said: Check it! */ assert(v_leftoron(site,e)); assert(v_leftof(site,lnext(e))); assert(v_leftof(site,lprev(e))); assert(v_rightoron(site,sym(e))); assert(v_rightof(site,dprev(e))); assert(v_rightof(site,onext(e))); assert(dest(lnext(e)) == orig(lprev(e))); assert(dest(onext(e)) == orig(dprev(e))); assert(dest(lnext(e)) == orig(dprev(e))); *edge = e; *oldsite = 0; return(FALSE); } /****************************************************************/ /* Incremental Edge Insertion */ /* with a lot of ideas by Dani Lischinski */ /****************************************************************/ /* this one does not flip unflippable edges ! */ static void incremental_delaunay(SITE_PTR site,EDGE_PTR edge) { SITE_PTR first; EDGE_PTR e,t,base; EDGE_PTR a,b,c,d; e = edge; /* site lies left or on edge ! */ if (onedge(site,e)) { /* we are on an existing edge */ a = oprev(e); b = dnext(e); c = lnext(e); d = lprev(e); splitedge(e,site); connect_left(e,lprev(e),DINF); connect_left(oprev(e),sym(e),DINF); fix_edge_right(&a); fix_edge_right(&b); fix_edge_right(&c); fix_edge_right(&d); return; } first = orig(e); base = makeedge(first,site,DINF); splice(base,e); do { base = connect_left(e,sym(base),DINF); e = oprev(base); } while (dest(e) != first); while (1) { t = oprev(e); if (flipable(e) && rightof(dest(t),e) && incircle(orig(e),dest(t),dest(e),site)) { swapedge(e); e = oprev(e); continue; } else if (orig(e) == first) break; e = lprev(onext(e)); } } /* recursive edge flipping to the right of an edge */ static void fix_edge_right(EDGE_PTR *e) { EDGE_PTR f,g; if (disco_edge(*e)) return; f = oprev(*e); g = dnext(*e); if (incircle(dest(*e),dest(onext(*e)),orig(*e),dest(f))) { swapedge(*e); fix_edge_right(&f); fix_edge_right(&g); } } /* triangulate anew the loop to the left of first */ /* ??? maybe this only works if all vertices lie to the left of last */ /* i.e. the edge preceeding first ??? */ static void triangulate_left(EDGE_PTR first) { EDGE_PTR last,a,b,ea,t1,t2; fflush(stdout); last = lprev(first); while (lnext(lnext(first)) != last) { /* still > triangle */ ea = lnext(first); t1 = first; while (ea != last) { alive("T"); t2 = lnext(ea); if (t2 == last && t1 == first) break; if (leftof(dest(ea),t1)) { if (t1 == first) { first = sym(connect_left(ea,t1,DINF)); t1 = first; } else t1 = sym(connect_left(ea,t1,DINF)); a = oprev(t1); b = dnext(t1); fix_edge_right(&a); fix_edge_right(&b); ea = t2; } else { t1 = ea; ea = t2; } } } a = lnext(last); b = lprev(last); fix_edge_right(&a); fix_edge_right(&b); fix_edge_right(&last); } void insert_edge(SURFACE *surf, SITE_PTR a,SITE_PTR b, DISCONTINUITY discontinuity,SITE_PTR *new_sites,int *n_new) { EDGE_PTR ea,eb,t,ne; SITE_PTR last,cross; VEC2 inter; if (n_new != NULL) *n_new = 0; /* at the beginning no new stuff */ _surf = surf; ea = Edge(a); /* get edge with a as orig */ eb = Edge(b); /* get edge with b as orig */ alive("."); last = orig(eb); while (orig(ea) != last) { alive("e"); while (rightof(b,ea) || leftoron(b,onext(ea))) ea = onext(ea); assert(dest(onext(ea)) != last); assert(! online(dest(onext(ea)),a,b)); if (online(dest(ea),a,b)) { disco(ea) = discontinuity; ea = sym(ea); continue; } t = ea; while (1) { alive("E"); if (online(dest(lnext(t)),a,b)) { if (lnext(lnext(lnext(t))) == ea) { disco(lnext(lnext(t))) = discontinuity; ea = sym(lnext(t)); break; } else { ne = connect_left(lnext(t),ea,discontinuity); ea = sym(lnext(t)); triangulate_left(lnext(ne)); triangulate_left(oprev(ne)); break; } } if (leftofline(dest(lnext(t)),a,b)) { /* left not on! */ if (flipable(lnext(t))) deleteedge(lnext(t)); else { /* 2 x-ing disco edges */ assert(vintersect(origv(lnext(t)),destv(lnext(t)), Site(a),Site(b),&inter)); assert(inter.x != X(orig(lnext(t))) || inter.y != Y(orig(lnext(t)))); /* orig not on edge but cross == dest */ assert(inter.x != X(dest(lnext(t))) || inter.y != Y(dest(lnext(t)))); /* dest not on edge but cross = dest */ if (new_sites == NULL) { fprintf(stderr,"can't create site for x-ing edges"); abort(); } if (surf->n_sites == surf->alloced_sites) /* full */ sef_enlarge(SITEALLOC); cross = surf->n_sites++; Site(cross) = inter; Invis(cross) = 0; Info(cross) = NULL; /* has to be set by caller later on */ new_sites[(*n_new)++] = cross; splitedge(lnext(t),cross); ne = connect_left(lnext(t),ea,discontinuity); ea = sym(lnext(t)); triangulate_left(lnext(ne)); triangulate_left(oprev(ne)); break; } } else t = lnext(t); } } } te,char *infovd3.c 644 316 311 31672 5456760515 5032 /**********************************************************************/ /* Voronoi/Delaunay-Module */ /* internal routines */ /* */ /* (c) 1993 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* This code may not be redistributed without the authors permission. */ /**********************************************************************/ #include "vd.h" #include extern SURFACE *_surf; #define VORONOISIZE 100 #define NEIGHBOURSIZE 100 static int v_index = 0; static VORONOIS v_list[VORONOISIZE]; static int n_index; static NEIGHBOURS n_list[NEIGHBOURSIZE]; void free_neighbours(void) { n_index = 0; } NEIGHBOURS *alloc_neighbour_node(SITE_PTR site,DISCONTINUITY d) { NEIGHBOURS *n; if (n_index >= NEIGHBOURSIZE) { fprintf(stderr,"No more neighbours\n"); exit(1); } n = &n_list[n_index]; n_index++; n->site = site; n->d = d; n->next = NULL; return(n); } void free_voronois(void) { v_index = 0; } /* Double linked list manipulation */ /* insert a node after ring, ring points to new node afterwards ! */ void insert_node(VORONOIS **ring,VEC2 from,VEC2 to,DISCONTINUITY d,int done) { VORONOIS *node,*temp; if (v_index >= VORONOISIZE) { fprintf(stderr,"No more voronois\n"); exit(1); } node = &v_list[v_index]; v_index++; if (*ring == NULL) { *ring = node; node->next = node; node->prev = node; } else { temp = (*ring)->next; (*ring)->next = node; node->next = temp; temp->prev = node; node->prev = *ring; *ring = node; } node->from = from; node->to = to; node->d = d; node->done = done; } /* delete the node at ring, ring points to next node afterwards */ void delete_node(VORONOIS **ring) { VORONOIS *temp; if ((*ring)->next == *ring || (*ring)->next == NULL) { /* optional: release *ring */ *ring = NULL; return; } temp = *ring; temp->next->prev = temp->prev; temp->prev->next = temp->next; *ring = temp->next; /* optional release temp */ } /****************************************************************/ /* Quad-edge manipulation primitives */ /****************************************************************/ EDGE_PTR makeedge(SITE_PTR origin,SITE_PTR destination,DISCONTINUITY d) { register EDGE_PTR temp, ans; assert(origin != destination); assert(X(origin) != X(destination) || Y(origin) != Y(destination)); temp = alloc_edge(); ans = temp; disco(ans) = d; onext(temp) = ans; orig(temp) = origin; onext(++temp) = ans + 3; onext(++temp) = ans + 2; orig(temp) = destination; onext(++temp) = ans + 1; Edge(origin) = ans; Edge(destination) = sym(ans); return(ans); } void splice(EDGE_PTR a,EDGE_PTR b) { EDGE_PTR alpha, beta, temp; alpha = rot(onext(a)); beta = rot(onext(b)); temp = onext(alpha); onext(alpha) = onext(beta); onext(beta) = temp; temp = onext(a); onext(a) = onext(b); onext(b) = temp; Edge(orig(a)) = a; Edge(orig(b)) = b; } void swapedge(EDGE_PTR e) { EDGE_PTR a,b,syme; a = oprev(e); syme = sym(e); b = oprev(syme); splice(e, a); splice(syme, b); splice(e, lnext(a)); splice(syme, lnext(b)); orig(e) = dest(a); Edge(orig(a)) = a; /* correct point references */ dest(e) = dest(b); Edge(orig(b)) = b; } EDGE_PTR connect_left(EDGE_PTR a, EDGE_PTR b,DISCONTINUITY d) { register EDGE_PTR ans; ans = makeedge(dest(a), orig(b),d); splice(ans, lnext(a)); splice(sym(ans), b); return(ans); } EDGE_PTR connect_right(EDGE_PTR a, EDGE_PTR b,DISCONTINUITY d) { register EDGE_PTR ans; ans = makeedge(dest(a), orig(b),d); splice(ans, sym(a)); splice(sym(ans), oprev(b)); return(ans); } void deleteedge(EDGE_PTR e) /* disconnects e from the rest of the structure and destroys it. */ { if (e == _surf->Last_locate_edge || e == sym(_surf->Last_locate_edge)) _surf->Last_locate_edge = onext(e); Edge(orig(e)) = oprev(e); /* reset point references */ Edge(dest(e)) = lnext(e); splice(e, oprev(e)); splice(sym(e), oprev(sym(e))); free_edge(e); } /* copied from code by Dani Lischinski */ void splitedge(EDGE_PTR e,SITE_PTR site) { EDGE_PTR t,newe; t = lnext(e); splice(sym(e),t); Edge(orig(t)) = t; /* to make sure it's ok ! */ dest(e) = site; newe = connect_left(e,t,disco(e)); Edge(site) = newe; } /****************************************************************/ /* Quad-edge storage allocation */ /****************************************************************/ /******************** Overall storage allocation ****************/ void sef_alloc(int n) { my_alloc(_surf->sa, struct SITE, n ); my_alloc(_surf->org, SITE_PTR, 12*n ); my_alloc(_surf->next, EDGE_PTR, 12*n ); my_alloc(_surf->ei, struct EDGE_INFO, 3*n ); } void sef_enlarge(int additional) { int n; SURFACE old_surf,*temp; old_surf = *_surf; n = _surf->alloced_sites; _surf->alloced_sites += additional; sef_alloc(_surf->alloced_sites); memcpy(_surf->sa,old_surf.sa,sizeof(struct SITE) * n); memcpy(_surf->org,old_surf.org,sizeof(SITE_PTR) * 12 * n); memcpy(_surf->next,old_surf.next,sizeof(EDGE_PTR) * 12 * n); memcpy(_surf->ei,old_surf.ei,sizeof(struct EDGE_INFO) * 3 * n); temp = _surf; _surf = &old_surf; sef_free(); _surf = temp; } void sef_free(void) { free((char *)_surf->sa); free((char *)_surf->org); free((char *)_surf->next); free((char *)_surf->ei); } /*************************** Edge storage management *************************/ #define NYL -1 void delete_all_edges(void) { _surf->next_edge = 0; _surf->avail_edge = NYL; _surf->n_edges = 0; } EDGE_PTR alloc_edge(void) { EDGE_PTR ans; _surf->n_edges++; if (_surf->avail_edge == NYL) ans = _surf->next_edge, _surf->next_edge += 4; else ans = _surf->avail_edge, _surf->avail_edge = onext(_surf->avail_edge); return(ans); } void free_edge(EDGE_PTR e) { e ^= e & 3; onext(e) = _surf->avail_edge; _surf->avail_edge = e; _surf->n_edges--; } /****************************************************************/ /* Geometric primitives */ /****************************************************************/ BOOLEAN incircle(SITE_PTR a,SITE_PTR b,SITE_PTR c,SITE_PTR d) { double az,bz,cz,dz,result; az = X(a) * X(a) + Y(a) * Y(a); bz = X(b) * X(b) + Y(b) * Y(b); cz = X(c) * X(c) + Y(c) * Y(c); dz = X(d) * X(d) + Y(d) * Y(d); result = ( Y(a) * (bz * X(c) + cz * X(d) + X(b) * dz) + az * (X(b) * Y(c) + Y(b) * X(d) + X(c) * Y(d)) + X(a) * (Y(b) * cz + bz * Y(d) + Y(c) * dz) + bz * Y(c) * X(d) + X(b) * cz * Y(d) + Y(b) * X(c) * dz ) - ( az * (Y(b) * X(c) + Y(c) * X(d) + X(b) * Y(d)) + X(a) * (bz * Y(c) + cz * Y(d) + Y(b) * dz) + Y(a) * (X(b) * cz + X(c) * dz + bz * X(d)) + Y(b) * cz * X(d) + bz * X(c) * Y(d) + X(b) * Y(c) * dz ); return (result > 0.0 ? TRUE : FALSE); /* as in the Guibas-Stolfi paper. register double adx, ady, bdx, bdy, cdx, cdy, dx, dy, nad, nbd, ncd; dx = X(d); dy = Y(d); adx = X(a) - dx; ady = Y(a) - dy; bdx = X(b) - dx; bdy = Y(b) - dy; cdx = X(c) - dx; cdy = Y(c) - dy; nad = adx*adx+ady*ady; nbd = bdx*bdx+bdy*bdy; ncd = cdx*cdx+cdy*cdy; return( (0.0 < (nad * (bdx * cdy - bdy * cdx) + nbd * (cdx * ady - cdy * adx) + ncd * (adx * bdy - ady * bdx))) ? TRUE : FALSE );*/ } double distcircle(SITE_PTR a,SITE_PTR b,SITE_PTR c,SITE_PTR d) { double az,bz,cz,dz,result; az = X(a) * X(a) + Y(a) * Y(a); bz = X(b) * X(b) + Y(b) * Y(b); cz = X(c) * X(c) + Y(c) * Y(c); dz = X(d) * X(d) + Y(d) * Y(d); result = ( Y(a) * (bz * X(c) + cz * X(d) + X(b) * dz) + az * (X(b) * Y(c) + Y(b) * X(d) + X(c) * Y(d)) + X(a) * (Y(b) * cz + bz * Y(d) + Y(c) * dz) + bz * Y(c) * X(d) + X(b) * cz * Y(d) + Y(b) * X(c) * dz ) - ( az * (Y(b) * X(c) + Y(c) * X(d) + X(b) * Y(d)) + X(a) * (bz * Y(c) + cz * Y(d) + Y(b) * dz) + Y(a) * (X(b) * cz + X(c) * dz + bz * X(d)) + Y(b) * cz * X(d) + bz * X(c) * Y(d) + X(b) * Y(c) * dz ); return(result); } /*#define calc_ccw(a,b,c) ((X(a) * Y(b) + Y(a) * X(c) + X(b) * Y(c)) - \ (Y(a) * X(b) + Y(b) * X(c) + X(a) * Y(c))) */ #define calc_ccw(a,b,c) \ ((X(a) - X(c)) * (Y(b) - Y(c)) - (X(b) - X(c)) * (Y(a) - Y(c))) double ccw(SITE_PTR a,SITE_PTR b,SITE_PTR c) /* > 0.0 iff A, B, C form a counterclockwise oriented triangle */ { double result; if (a == b || a == c || c == b) return(0.0); result = calc_ccw(a,b,c); if (fabs(result) < 1E-10) { result += calc_ccw(a,c,b); result += calc_ccw(b,a,c); result += calc_ccw(b,c,a); result += calc_ccw(c,a,b); result += calc_ccw(c,b,a); result /= 6.0; } return (result); } #define v_calc_ccw(a,b,c) \ ((a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y)) double v_ccw(VEC2 a,VEC2 b,VEC2 c) { double result; if ((a.x == b.x && a.y == b.y) || (a.x == c.x && a.y == c.y) || (b.x == c.x && b.y == c.y)) return(0.0); result = v_calc_ccw(a,b,c); if (fabs(result) < 1E-10) { result += v_calc_ccw(a,c,b); result += v_calc_ccw(b,a,c); result += v_calc_ccw(b,c,a); result += v_calc_ccw(c,a,b); result += v_calc_ccw(c,b,a); result /= 6.0; } return(result); } BOOLEAN intersect_test(VEC2 from,VEC2 to,EDGE_PTR e) { if (v_leftoron(from,e) && /* from lies left or on */ v_rightof(to,e) && /* to lies right */ v_rightoronline(origv(e),from,to) && /* orig lies right or on */ v_leftoronline(destv(e),from,to)) /* dest lies left or on */ return(TRUE); return(FALSE); } /* use intersect_test before that proc to test if the lines really intersect */ /* the test is disabled because intersect_test is much more reliable as test */ BOOLEAN vintersect(VEC2 p1,VEC2 p2,VEC2 p3,VEC2 p4,VEC2 *inter) { double a1,a2,b1,b2,c1,c2; double denom,num; a1 = p2.y - p1.y; /* calc: a1 x + b1 y + c1 = 0 */ b1 = p1.x - p2.x; c1 = p2.x * p1.y - p1.x * p2.y; a2 = p4.y - p3.y; /* calc: a2 x + b2 y + c2 = 0 */ b2 = p3.x - p4.x; c2 = p4.x * p3.y - p3.x * p4.y; denom = a1 * b2 - a2 * b1; if (denom == 0.0) /* collinear :-( */ return(FALSE); num = b1 * c2 - b2 * c1; inter->x = num / denom; num = a2 * c1 - a1 * c2; inter->y = num / denom; return(TRUE); } #ifdef WITH_INTERSECT_TEST BOOLEAN vintersect(VEC2 p1,VEC2 p2,VEC2 p3,VEC2 p4,VEC2 *inter) { double a1,a2,b1,b2,c1,c2; double denom,num; double r1,r2,r3,r4; a1 = p2.y - p1.y; b1 = p1.x - p2.x; c1 = p2.x * p1.y - p1.x * p2.y; r3 = a1 * p3.x + b1 * p3.y + c1; r4 = a1 * p4.x + b1 * p4.y + c1; if (r3 != 0.0 && r4 != 0.0 && ((r3 > 0.0 && r4 > 0.0) || (r3 < 0.0 && r4 < 0.0))) return(FALSE); a2 = p4.y - p3.y; b2 = p3.x - p4.x; c2 = p4.x * p3.y - p3.x * p4.y; r1 = a2 * p1.x + b2 * p1.y + c2; r2 = a2 * p2.x + b2 * p2.y + c2; if (r1 != 0.0 && r2 != 0.0 && ((r1 > 0.0 && r2 > 0.0) || (r1 < 0.0 && r2 < 0.0))) return(FALSE); denom = a1 * b2 - a2 * b1; if (denom == 0.0) return(FALSE); num = b1 * c2 - b2 * c1; inter->x = num / denom; num = a2 * c1 - a1 * c2; inter->y = num / denom; return(TRUE); } #endif void circle_center(VEC2 a,VEC2 b,VEC2 c,VEC2 *corner) /* computes the center of the circle passing through A, B & C. */ { VEC2 ac,bc; register double ac2,bc2,area; ac = V2_sub(a,c); ac2=V2_dotq(ac,ac); bc = V2_sub(b,c); bc2=V2_dotq(bc,bc); area = V2_cprodq(ac,bc); ac = V2_times(bc2,ac); bc = V2_times(ac2,bc); *corner = V2_sum(c,V2_times(-0.5 / area,V2_cross(V2_sub(ac,bc)))); } /****************************************************************/ /* Vector Routines. */ /* From CMU vision library. */ /* They are used only for the VD, not the DT. */ /* They are slow because of large call-by-value parameters. */ /****************************************************************/ /* V2_cprod: forms triple scalar product of [u,v,k] */ /* (returns the magnitude of u cross v in space) or *(u x v) in the plane */ double V2_cprod(VEC2 u,VEC2 v) { return(u.x * v.y - u.y * v.x); } /* V2_dot: vector dot product */ double V2_dot(VEC2 u,VEC2 v) { return(u.x * v.x + u.y * v.y); } /* V2_times: multiply a vector by a scalar */ VEC2 V2_times(double c,VEC2 v) { VEC2 ans; ans.x = c * v.x; ans.y = c * v.y; return(ans); } /* V2_sum, V2_sub: Vector addition and subtraction */ VEC2 V2_sum(VEC2 u,VEC2 v) { VEC2 ans; ans.x = u.x + v.x; ans.y = u.y + v.y; return(ans); } VEC2 V2_sub(VEC2 u,VEC2 v) { VEC2 ans; ans.x = u.x - v.x; ans.y = u.y - v.y; return(ans); } /* V2_magn: magnitude of vector */ double V2_magn(VEC2 u) { return( sqrt(u.x * u.x + u.y * u.y) ); } /* returns *v = k x v (cross product). this is a vector perpendicular to v */ /* but beware: it points to the right ! */ VEC2 V2_cross(VEC2 v) { VEC2 ans; ans.x = v.y; ans.y = -v.x; return(ans); } /* this one points to the left, as god intended it to be :-) */ VEC2 V2_crossl(VEC2 v) { VEC2 ans; ans.x = -v.y; ans.y = v.x; return(ans); } VEC2 V2_normalize(VEC2 v) { VEC2 ans; double len; len = V2_magn(v); ans = V2_times(1.0 / len,v); return(ans); } VEC2 V2_midpoint(VEC2 v,VEC2 v1) { VEC2 ans; ans = V2_sum(v,v1); ans = V2_times(0.5,ans); return(ans); } st(ea),t1)) { if (t1 == first) { first = sym(connect_left(ea,vdx.c 644 316 311 16667 5456762117 5146 /**********************************************************************/ /* Voronoi/Delaunay-Module */ /* testprogram */ /* */ /* (c) 1993 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* This code may not be redistributed without the authors permission. */ /**********************************************************************/ #include "vd.h" #define COMMAND_STRING \ "r ,f ,i ,e ,o,t,w,d,q" #include #ifdef RANDOM #define INITRAND srandom( (long) time( (long *) 0 ) ) #define RAND ((double) random() / 2147483647.0) #else #define INITRAND srand( (int) time( (long *) 0 ) ) #define RAND ((double) (((long) rand() >> 2) ^ ((long) rand() << 16) ^ \ ((long) rand() << 7)) / (double) 0x7FFFFFFF) #endif static char input_string[80]; typedef struct { int n; } Info; Info *dummy; #define alloc_info (dummy = (Info *) malloc(sizeof(Info)), \ dummy->n = RAND * 10, (char *) dummy) char *nextarg(int *argc,char *argv[]) { char *x; static int argsread = 1; static char *input = NULL; if (argsread < *argc) { x = argv[argsread]; argsread++; return(x); } if (input == NULL) { printf(COMMAND_STRING); printf("> "); gets(input_string); input = input_string; } x = input; while (*input != '\0' && *input != ' ') input++; while (*input == ' ') input++; if (*input == '\0') { /* end of string */ input = NULL; return(x); } if (input == x) { /* something is very wrong :-( */ printf("???????\n"); input_string[0] = '\0'; x = input_string; input = NULL; return(x); } input--; *input = '\0'; input++; return(x); } void Out(SURFACE *surf,SITE_PTR *sites,int n_sites) { FILE *f; int i,col; double x,y,x1,y1; NEIGHBOURS *neigh; f = fopen("vd.out","w"); fprintf(f,"I 0.0 0.0 1.0 1.0\n"); fflush(f); /* if we should bomb :-) */ for (i = 0; i < n_sites; i++) { get_coords(surf,sites[i],&x,&y); /* output DT */ get_neighbours(surf,sites[i],&neigh); while (neigh != NULL) { get_coords(surf,neigh->site,&x1,&y1); switch (neigh->d) { case DBDRY: col = 1; break; case D0: col = 2; break; case D1: col = 3; break; case D2: col = 4; break; case DINF: col = 5; break; default: col = 6; break; } if (x < x1 || (x == x1 && y < y1)) /* each just once */ fprintf(f,"E %g %g %g %g %d\n",x,y,x1,y1,col); neigh = neigh->next; } } for (i = 0; i < n_sites; i++) { /* output vertices */ get_coords(surf,sites[i],&x,&y); fprintf(f,"V %g %g\n",x,y); } fclose(f); } void Random(SURFACE *surf,SITE_PTR *sites,int *n_sites,int num) { int i,j,new_sites; double x,y,x1,y1; SITE_PTR a,b; if (num < 0) { num = -num; for (i = 0; i < num; i++) { x = RAND; y = RAND; x1 = RAND; y1 = RAND; if (insert_site(surf,x,y,&a,alloc_info)) sites[(*n_sites)++] = a; if (insert_site(surf,x1,y1,&b,alloc_info)) sites[(*n_sites)++] = b; insert_edge(surf,a,b,D0,&sites[*n_sites],&new_sites); if (new_sites > 0) { for (j = 0; j < new_sites; j++) set_info(surf,sites[*n_sites + j],alloc_info); *n_sites += new_sites; } } } else { for (i = 0; i < num; i++) { x = RAND; y = RAND; if (insert_site(surf,x,y,&a,alloc_info)) sites[(*n_sites)++] = a; } } } void File(SURFACE *surf,SITE_PTR *sites,int *n_sites,char *name) { FILE *f; char string[127]; int i,line,new_sites; double x,y,x1,y1; SITE_PTR a,b; f = fopen(name,"r"); if (f == NULL) { printf("Can't open file %s\n",name); return; } line = 0; while (fgets(string,120,f)) { printf(string); line++; if (string[0] == 'E') { if (sscanf(string,"E %lf %lf %lf %lf",&x,&y,&x1,&y1) < 4) { printf("Error in line %d\n",line); break; } if (insert_site(surf,x,y,&a,alloc_info)) sites[(*n_sites)++] = a; if (insert_site(surf,x1,y1,&b,alloc_info)) sites[(*n_sites)++] = b; insert_edge(surf,a,b,D0,&sites[*n_sites],&new_sites); if (new_sites > 0) { for (i = 0; i < new_sites; i++) set_info(surf,sites[*n_sites + i],alloc_info); *n_sites += new_sites; } } else if (string[0] == 'V') { if (sscanf(string,"V %lf %lf",&x,&y) < 2) { printf("Error in line %d\n",line); break; } if (insert_site(surf,x,y,&a,alloc_info)) sites[(*n_sites)++] = a; } } fclose(f); } int sits; long sit_sum; void siteproc(SURFACE *surf,SITE_PTR s) { sit_sum += ((Info *)get_info(surf,s))->n; sits++; } int edgs; void edgeproc(SURFACE *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d) {edgs++;} int tris; void triproc(SURFACE *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3) {tris++;} int testproc(char *s1,char *s2,char *s3,char *s4) { if (((Info *)s1)->n > 5) return(1); return(0); } #define SITES 10000 int main(int argc,char *argv[]) { int i,ai; double ax,ay,ax1,ay1; struct SURFACE surf; char *cmd ,*ac; SITE_PTR *sites,site,site1; int n_sites,new_sites; INITRAND; init_surface(&surf,0.0,0.0,1.0,1.0); /********************** Construct user plane **********************/ n_sites = 0; sites = malloc(SITES * sizeof(SITE_PTR)); if (insert_site(&surf,0.0,0.0,&site,alloc_info)) /* corners */ sites[n_sites++] = site; if (insert_site(&surf,1.0,0.0,&site,alloc_info)) sites[n_sites++] = site; if (insert_site(&surf,1.0,1.0,&site,alloc_info)) sites[n_sites++] = site; if (insert_site(&surf,0.0,1.0,&site,alloc_info)) sites[n_sites++] = site; assert(n_sites == 4); /* just in case some joker ... */ insert_edge(&surf,sites[0],sites[1],DBDRY,sites,&i); /* Boundary */ assert(i == 0); insert_edge(&surf,sites[1],sites[2],DBDRY,sites,&i); assert(i == 0); insert_edge(&surf,sites[2],sites[3],DBDRY,sites,&i); assert(i == 0); insert_edge(&surf,sites[3],sites[0],DBDRY,sites,&i); assert(i == 0); while (1) { cmd = nextarg(&argc,argv); if (*cmd == 'q') break; switch (*cmd) { case 'o': Out(&surf,sites,n_sites); break; case 'r': ai = atoi(nextarg(&argc,argv)); Random(&surf,sites,&n_sites,ai); break; case 'f': ac = nextarg(&argc,argv); File(&surf,sites,&n_sites,ac); break; case 'i': ax = atof(nextarg(&argc,argv)); ay = atof(nextarg(&argc,argv)); if (insert_site(&surf,ax,ay,&site,alloc_info)) sites[n_sites++] = site; break; case 't': sits = 0; sit_sum = 0; for_all_sites(&surf,siteproc); edgs = 0; for_all_edges(&surf,edgeproc); tris = 0; for_all_triangles(&surf,triproc); printf("%d sites, %d edges, %d triangles\n",sits,edgs,tris); printf("%ld random sum\n",sit_sum); break; case 'w': flip_flipable_edges(&surf,testproc); break; case 'e': ax = atof(nextarg(&argc,argv)); ay = atof(nextarg(&argc,argv)); ax1 = atof(nextarg(&argc,argv)); ay1 = atof(nextarg(&argc,argv)); if (insert_site(&surf,ax,ay,&site,alloc_info)) sites[n_sites++] = site; if (insert_site(&surf,ax1,ay1,&site1,alloc_info)) sites[n_sites++] = site1; insert_edge(&surf,site,site1,D0,&sites[n_sites],&new_sites); if (new_sites > 0) { for (i = 0; i < new_sites; i++) set_info(&surf,sites[n_sites + i],alloc_info); n_sites += new_sites; } break; case 'd': Out(&surf,sites,n_sites); system("dis"); break; } } delete_surface(&surf); return(0); } } st(ea),t1)) { if (t1 == first) { first = sym(connect_left(ea,**********************************************************************/ #include "vd.h" #define COMMAND_STRING \ "r ,f ,i ,e ,o,t,w,d,q" #include #ifdef RANDOM #define INITRAND srandom( (long) time( (long *) 0 ) ) #define RAND ((double) random() / 2147483647.0) #else #define INITRAND srand( (int) time( (long *) 0 ) ) #define RAND ((double) (((long) rand() >> 2) ^ ((long) rand() << 16) ^ \ ((long) rand() << 7)) / (double) 0x7FFFFFFF) #endif static char input_string[80]; typedef struct { int n; } Info; Info *dummy; #define alloc_info (dummy = (Info *) malloc(sizeof(Info)), \ dummy->n = RAND * 10, (char *) dummy) char *nextarg(int *argc,char *argv[]) { char *x; static int argsread = 1; static char *input = NULL; if (argsread < *argc) { x = argv[argsread]; argsread++; return(x); } if (input == NULL) { printf(COMMAND_STRING); printf("> "); gets(input_string); input = input_string; } x = input; while (*input != '\0' && *input != ' ') input++; while (*input == ' ') input++; if (*input == '\0') { /* end of string */ input = NULL; return(x); } if (input == x) { /* something is very wrong :-( */ printf("???????\n"); input_string[0] = '\0'; x = input_string; input = NULL; return(x); } input--; *input = '\0'; input++; return(x); } void Out(SURFACE *surf,SITE_PTR *sites,int n_sites) { FILE *f; int i,col; double x,y,x1,y1; NEIGHBOURS *neigh; f = fopen("vd.out","w"); fprintf(f,"I 0.0 0.0 1.0 1.0\n"); fflush(f); /* if we should bomb :-) */ for (i = 0; i < n_sites; i++) { get_coords(surf,sites[i],&x,&y); /* output DT */ get_neighbours(surf,sites[i],&neigh); while (neigh != NULL) { get_coords(surf,neigh->site,&x1,&y1); switch (neigh->d) { case DBDRY: col = 1; break; case D0: col = 2; break; case D1: col = 3; break; case D2: col = 4; break; case DINF: col = 5; break; default: col = 6; break; } if (x < x1 || (x == x1 && y < y1)) /* each just once */ fprintf(f,"E %g %g %g %g %d\n",x,y,x1,y1,col); neigh = neigh->next; } } for (i = 0; i < n_sites; i++) { /* output vertices */ get_coords(surf,sites[i],&x,&y); fprintf(f,"V %g %g\n",x,y); } fclose(f); } void Random(SURFACE *surf,SITE_PTR *sites,int *n_sites,int num) { int i,j,new_sites; double x,y,x1,y1; SITE_PTR a,b; if (num < 0) { num = -num; for (i = 0; i < num; i++) { x = RAND; y = RAND; x1 = RAND; y1 = RAND; if (insert_site(surf,x,y,&a,alloc_info)) sites[(*n_sites)++] = a; if (insert_site(surf,x1,y1,&b,alloc_info)) sites[(*n_sites)++] = b; insert_edge(surf,a,b,D0,&sites[*n_sites],&new_sites); if (new_sites > 0) { for (j = 0; j < new_sites; j++) set_info(surf,sites[*n_sites + j],alloc_info); *n_sites += new_sites; } } } else { for (i = 0; i < num; i++) { x = RAND; y = RAND; if (insert_site(surf,x,y,&a,alloc_info)) sites[(*n_sites)++] = a; } } } void File(SURFACE *surf,SITE_PTR *sites,int *n_sites,char *name) { FILE *f; char string[127]; int i,line,new_sites; double x,y,x1,y1; SITE_PTR a,b; f = fopen(name,"r"); if (f == NULL) { printf("Can't open file %s\n",name); return; } line = 0; while (fgets(string,120,f)) { printf(string); line++; if (string[0] == 'E') { if (sscanf(string,"E %lf %lf %lf %lf",&x,&y,&x1,&y1) < 4) { printf("Error in line %d\n",line); break; } if (insert_site(surf,x,y,&a,alloc_info)) sites[(*n_sites)++] = a; if (insert_site(surf,x1,y1,&b,alloc_info)) sites[(*n_sites)++] = b; insert_edge(surf,a,b,D0,&sites[*n_sites],&new_sites); if (new_sites > 0) { for (i = 0; i < new_sites; i++) set_info(surf,sites[*n_sites + i],alloc_info); *n_sites += new_sites; } } else if (string[0] == 'V') { if (sscanf(string,"V %lf %lf",&x,&y) < 2) { printf("Error in line %d\n",line); break; } if (insert_site(surf,x,y,&a,alloc_info)) sites[(*n_sites)++] = a; } } fclose(f); } int sits; long sit_sum; void siteproc(SURFACE *surf,SITE_PTR s) { sit_sum += ((Info *)get_info(surf,s))->n; sits++; } int edgs; void edgeproc(SURFACE *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d) {edgs++;} int tris; void triproc(SURFACE *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3) {tris++;} int testproc(char *s1,char *s2,char *s3,char *s4) { if (((Info *)s1)->n > 5) return(1); return(0); } #define SITES 10000 int main(int argc,char *argv[]) { int i,ai; double ax,ay,ax1,ay1; struct SURFACE surf; char *cmd ,*ac; SITE_PTR *sites,site,site1; int n_sites,new_sites; INITRAND; init_surface(&surf,0.0,0.0,1.0,1.0); /********************** Construct user plane **********************/ n_sites = 0; sites = malloc(SITES * sizeof(SITE_PTR)); if (insert_site(&surf,0.0,0.0,&site,alloc_info)) /* corners */ sites[n_sites++] = site; if (insert_site(&surf,1.0,0.0,&site,alloc_info)) sites[n_sites++] = site; if (insert_site(&surf,1.0,1.0,&site,alloc_info)) sites[n_sites++] = site; if (insert_site(&surf,0.0,1.0,&site,alloc_info)) sites[n_sites++] = site; assert(n_sites == 4); /* just in case some joker ... */ insert_edge(&surf,sites[0],sites[1],DBDRY,sites,&i); /* Boundary */ assert(i == 0); insert_edge(&surf,sites[1],sites[2],DBDRY,sites,&i); assert(i == 0); insert_edge(&surf,sites[2],sites[3],DBDRY,sites,&i); assert(i == 0); insert_edge(&surf,sites[3],sites[0],DBDRY,sites,&i); assert(i == 0); while (1) { cmd = nextarg(&argc,argv); if (*cmd == 'q') break; switch (*cmd) { case 'o': Out(&surf,sites,n_sites); break; case 'r': ai = atoi(nextarg(&argc,argv)); Random(&surf,sites,&n_sites,ai); break; case 'f': ac = nextarg(&argc,argv); File(&surf,sites,&n_sites,ac); break; case 'i': ax = atof(nextarg(&argc,argv)); ay = atof(nextarg(&argc,argv)); if (insert_site(&surf,ax,ay,&site,alloc_info)) sites[n_sites++] = site; break; case 't': sits = 0; sit_sum = 0; for_all_sites(&surf,siteproc); edgs = 0; for_all_edges(&surf,edgeproc); tris = 0; for_all_triangles(&surf,triproc); printf("%d sites, %d edges, %d triangles\n",sits,edgs,tris); printf("%ld random sum\n",sit_sum); break; case 'w': flip_flipable_edges(&surf,testproc); break; case 'e': ax = atof(nextarg(&argc,argv)); ay = atof(nextarg(&argc,argv)); ax1 = atof(nextarg(&argc,argv)); ay1 = atof(nextarg(&argc,argv)); if (insert_site(&surf,ax,ay,&site,alloc_info)) sites[n_sites++] = site; if (insert_site(&surf,ax1,ay1,&site1,alloc_info)) sites[n_sites++] = site1; insert_edge(&surf,site,site1,D0,&sites[n_sites],&new_sites); if (new_sites > 0) { for (i = 0; i < new_sites; i++) set_info(&surf,sites[n_sites + i],alloc_info); n_sites += new_sites; } break; case 'd': Out(&surf,sites,n_sites); system("dis"); break; } } delete_surface(&surf); return(0); } } st(ea),t1)) { if (t1 == first) { first = sym(connect_left(ea,