Update to 2.0.0 tree from current Fremantle build
[opencv] / samples / c / delaunay.c
1 #ifdef _CH_
2 #pragma package <opencv>
3 #endif
4
5 #define CV_NO_BACKWARD_COMPATIBILITY
6
7 #ifndef _EiC
8 #include "cv.h"
9 #include "highgui.h"
10 #include <stdio.h>
11 #endif
12
13 /* the script demostrates iterative construction of
14    delaunay triangulation and voronoi tesselation */
15
16 CvSubdiv2D* init_delaunay( CvMemStorage* storage,
17                            CvRect rect )
18 {
19     CvSubdiv2D* subdiv;
20
21     subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D, sizeof(*subdiv),
22                                sizeof(CvSubdiv2DPoint),
23                                sizeof(CvQuadEdge2D),
24                                storage );
25     cvInitSubdivDelaunay2D( subdiv, rect );
26
27     return subdiv;
28 }
29
30
31 void draw_subdiv_point( IplImage* img, CvPoint2D32f fp, CvScalar color )
32 {
33     cvCircle( img, cvPoint(cvRound(fp.x), cvRound(fp.y)), 3, color, CV_FILLED, 8, 0 );
34 }
35
36
37 void draw_subdiv_edge( IplImage* img, CvSubdiv2DEdge edge, CvScalar color )
38 {
39     CvSubdiv2DPoint* org_pt;
40     CvSubdiv2DPoint* dst_pt;
41     CvPoint2D32f org;
42     CvPoint2D32f dst;
43     CvPoint iorg, idst;
44
45     org_pt = cvSubdiv2DEdgeOrg(edge);
46     dst_pt = cvSubdiv2DEdgeDst(edge);
47
48     if( org_pt && dst_pt )
49     {
50         org = org_pt->pt;
51         dst = dst_pt->pt;
52
53         iorg = cvPoint( cvRound( org.x ), cvRound( org.y ));
54         idst = cvPoint( cvRound( dst.x ), cvRound( dst.y ));
55
56         cvLine( img, iorg, idst, color, 1, CV_AA, 0 );
57     }
58 }
59
60
61 void draw_subdiv( IplImage* img, CvSubdiv2D* subdiv,
62                   CvScalar delaunay_color, CvScalar voronoi_color )
63 {
64     CvSeqReader  reader;
65     int i, total = subdiv->edges->total;
66     int elem_size = subdiv->edges->elem_size;
67
68     cvStartReadSeq( (CvSeq*)(subdiv->edges), &reader, 0 );
69
70     for( i = 0; i < total; i++ )
71     {
72         CvQuadEdge2D* edge = (CvQuadEdge2D*)(reader.ptr);
73
74         if( CV_IS_SET_ELEM( edge ))
75         {
76             draw_subdiv_edge( img, (CvSubdiv2DEdge)edge + 1, voronoi_color );
77             draw_subdiv_edge( img, (CvSubdiv2DEdge)edge, delaunay_color );
78         }
79
80         CV_NEXT_SEQ_ELEM( elem_size, reader );
81     }
82 }
83
84
85 void locate_point( CvSubdiv2D* subdiv, CvPoint2D32f fp, IplImage* img,
86                    CvScalar active_color )
87 {
88     CvSubdiv2DEdge e;
89     CvSubdiv2DEdge e0 = 0;
90     CvSubdiv2DPoint* p = 0;
91
92     cvSubdiv2DLocate( subdiv, fp, &e0, &p );
93
94     if( e0 )
95     {
96         e = e0;
97         do
98         {
99             draw_subdiv_edge( img, e, active_color );
100             e = cvSubdiv2DGetEdge(e,CV_NEXT_AROUND_LEFT);
101         }
102         while( e != e0 );
103     }
104
105     draw_subdiv_point( img, fp, active_color );
106 }
107
108
109 void draw_subdiv_facet( IplImage* img, CvSubdiv2DEdge edge )
110 {
111     CvSubdiv2DEdge t = edge;
112     int i, count = 0;
113     CvPoint* buf = 0;
114
115     // count number of edges in facet
116     do
117     {
118         count++;
119         t = cvSubdiv2DGetEdge( t, CV_NEXT_AROUND_LEFT );
120     } while (t != edge );
121
122     buf = (CvPoint*)malloc( count * sizeof(buf[0]));
123
124     // gather points
125     t = edge;
126     for( i = 0; i < count; i++ )
127     {
128         CvSubdiv2DPoint* pt = cvSubdiv2DEdgeOrg( t );
129         if( !pt ) break;
130         buf[i] = cvPoint( cvRound(pt->pt.x), cvRound(pt->pt.y));
131         t = cvSubdiv2DGetEdge( t, CV_NEXT_AROUND_LEFT );
132     }
133
134     if( i == count )
135     {
136         CvSubdiv2DPoint* pt = cvSubdiv2DEdgeDst( cvSubdiv2DRotateEdge( edge, 1 ));
137         cvFillConvexPoly( img, buf, count, CV_RGB(rand()&255,rand()&255,rand()&255), CV_AA, 0 );
138         cvPolyLine( img, &buf, &count, 1, 1, CV_RGB(0,0,0), 1, CV_AA, 0);
139         draw_subdiv_point( img, pt->pt, CV_RGB(0,0,0));
140     }
141     free( buf );
142 }
143
144 void paint_voronoi( CvSubdiv2D* subdiv, IplImage* img )
145 {
146     CvSeqReader  reader;
147     int i, total = subdiv->edges->total;
148     int elem_size = subdiv->edges->elem_size;
149
150     cvCalcSubdivVoronoi2D( subdiv );
151
152     cvStartReadSeq( (CvSeq*)(subdiv->edges), &reader, 0 );
153
154     for( i = 0; i < total; i++ )
155     {
156         CvQuadEdge2D* edge = (CvQuadEdge2D*)(reader.ptr);
157
158         if( CV_IS_SET_ELEM( edge ))
159         {
160             CvSubdiv2DEdge e = (CvSubdiv2DEdge)edge;
161             // left
162             draw_subdiv_facet( img, cvSubdiv2DRotateEdge( e, 1 ));
163
164             // right
165             draw_subdiv_facet( img, cvSubdiv2DRotateEdge( e, 3 ));
166         }
167
168         CV_NEXT_SEQ_ELEM( elem_size, reader );
169     }
170 }
171
172
173 void run(void)
174 {
175     char win[] = "source";
176     int i;
177     CvRect rect = { 0, 0, 600, 600 };
178     CvMemStorage* storage;
179     CvSubdiv2D* subdiv;
180     IplImage* img;
181     CvScalar active_facet_color, delaunay_color, voronoi_color, bkgnd_color;
182
183     active_facet_color = CV_RGB( 255, 0, 0 );
184     delaunay_color  = CV_RGB( 0,0,0);
185     voronoi_color = CV_RGB(0, 180, 0);
186     bkgnd_color = CV_RGB(255,255,255);
187
188     img = cvCreateImage( cvSize(rect.width,rect.height), 8, 3 );
189     cvSet( img, bkgnd_color, 0 );
190
191     cvNamedWindow( win, 1 );
192
193     storage = cvCreateMemStorage(0);
194     subdiv = init_delaunay( storage, rect );
195
196     printf("Delaunay triangulation will be build now interactively.\n"
197            "To stop the process, press any key\n\n");
198
199     for( i = 0; i < 200; i++ )
200     {
201         CvPoint2D32f fp = cvPoint2D32f( (float)(rand()%(rect.width-10)+5),
202                                         (float)(rand()%(rect.height-10)+5));
203
204         locate_point( subdiv, fp, img, active_facet_color );
205         cvShowImage( win, img );
206
207         if( cvWaitKey( 100 ) >= 0 )
208             break;
209
210         cvSubdivDelaunay2DInsert( subdiv, fp );
211         cvCalcSubdivVoronoi2D( subdiv );
212         cvSet( img, bkgnd_color, 0 );
213         draw_subdiv( img, subdiv, delaunay_color, voronoi_color );
214         cvShowImage( win, img );
215
216         if( cvWaitKey( 100 ) >= 0 )
217             break;
218     }
219
220     cvSet( img, bkgnd_color, 0 );
221     paint_voronoi( subdiv, img );
222     cvShowImage( win, img );
223
224     cvWaitKey(0);
225
226     cvReleaseMemStorage( &storage );
227     cvReleaseImage(&img);
228     cvDestroyWindow( win );
229 }
230
231 int main( int argc, char** argv )
232 {
233 #ifdef _MSC_VER
234     argc, argv;
235 #endif
236     run();
237     return 0;
238 }
239
240 #ifdef _EiC
241 main( 1, "delaunay.c" );
242 #endif