1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
42 /* Reconstruction of contour skeleton */
43 #include "precomp.hpp"
46 #define NEXT_SEQ(seq,seq_first) ((seq) == (seq_first) ? seq->v_next : seq->h_next)
47 #define SIGN(x) ( x<0 ? -1:( x>0 ? 1:0 ) )
49 const float LEE_CONST_ZERO = 1e-6f;
50 const float LEE_CONST_DIFF_POINTS = 1e-2f;
51 const float LEE_CONST_ACCEPTABLE_ERROR = 1e-4f;
53 /****************************************************************************************\
54 * Auxiliary struct definitions *
55 \****************************************************************************************/
63 typedef CvLeePoint<float> CvPointFloat;
64 typedef CvLeePoint<float> CvDirection;
66 struct CvVoronoiSiteInt;
67 struct CvVoronoiEdgeInt;
68 struct CvVoronoiNodeInt;
69 struct CvVoronoiParabolaInt;
70 struct CvVoronoiChainInt;
71 struct CvVoronoiHoleInt;
73 struct CvVoronoiDiagramInt
82 CvVoronoiSiteInt* reflex_site;
83 CvVoronoiHoleInt* top_hole;
86 struct CvVoronoiStorageInt
88 CvMemStorage* SiteStorage;
89 CvMemStorage* EdgeStorage;
90 CvMemStorage* NodeStorage;
91 CvMemStorage* ChainStorage;
92 CvMemStorage* ParabolaStorage;
93 CvMemStorage* DirectionStorage;
94 CvMemStorage* HoleStorage;
97 struct CvVoronoiNodeInt
103 struct CvVoronoiSiteInt
105 CvVoronoiNodeInt* node1;
106 CvVoronoiNodeInt* node2;
107 CvVoronoiEdgeInt* edge1;
108 CvVoronoiEdgeInt* edge2;
109 CvVoronoiSiteInt* next_site;
110 CvVoronoiSiteInt* prev_site;
111 CvDirection* direction;
114 struct CvVoronoiEdgeInt
116 CvVoronoiNodeInt* node1;
117 CvVoronoiNodeInt* node2;
118 CvVoronoiSiteInt* site;
119 CvVoronoiEdgeInt* next_edge;
120 CvVoronoiEdgeInt* prev_edge;
121 CvVoronoiEdgeInt* twin_edge;
122 CvVoronoiParabolaInt* parabola;
123 CvDirection* direction;
126 struct CvVoronoiParabolaInt
130 CvVoronoiNodeInt* focus;
131 CvVoronoiSiteInt* directrice;
134 struct CvVoronoiChainInt
136 CvVoronoiSiteInt * first_site;
137 CvVoronoiSiteInt * last_site;
138 CvVoronoiChainInt* next_chain;
141 struct CvVoronoiHoleInt
145 CvVoronoiSiteInt* site_top;
146 CvVoronoiSiteInt* site_nearest;
147 CvVoronoiSiteInt* site_opposite;
148 CvVoronoiNodeInt* node;
149 CvVoronoiHoleInt* next_hole;
154 typedef CvVoronoiSiteInt* pCvVoronoiSite;
155 typedef CvVoronoiEdgeInt* pCvVoronoiEdge;
156 typedef CvVoronoiNodeInt* pCvVoronoiNode;
157 typedef CvVoronoiParabolaInt* pCvVoronoiParabola;
158 typedef CvVoronoiChainInt* pCvVoronoiChain;
159 typedef CvVoronoiHoleInt* pCvVoronoiHole;
160 typedef CvPointFloat* pCvPointFloat;
161 typedef CvDirection* pCvDirection;
163 /****************************************************************************************\
164 * Function definitions *
165 \****************************************************************************************/
167 /*F///////////////////////////////////////////////////////////////////////////////////////
168 // Author: Andrey Sobolev
170 // Purpose: Compute Voronoi Diagram for one given polygon with holes
173 // ContourSeq : in, vertices of polygon.
174 // VoronoiDiagramInt : in&out, pointer to struct, which contains the
175 // description of Voronoi Diagram.
176 // VoronoiStorage: in, storage for Voronoi Diagram.
177 // contour_type: in, type of vertices.
178 // The possible values are CV_LEE_INT,CV_LEE_FLOAT,CV_LEE_DOUBLE.
179 // contour_orientation: in, orientation of polygons.
180 // = 1, if contour is left - oriented in left coordinat system
181 // =-1, if contour is left - oriented in right coordinat system
182 // attempt_number: in, number of unsuccessful attemts made by program to compute
183 // the Voronoi Diagram befor return the error
185 // Returns: 1, if Voronoi Diagram was succesfully computed
186 // 0, if some error occures
188 static int _cvLee(CvSeq* ContourSeq,
189 CvVoronoiDiagramInt* pVoronoiDiagramInt,
190 CvMemStorage* VoronoiStorage,
191 CvLeeParameters contour_type,
192 int contour_orientation,
195 /*F///////////////////////////////////////////////////////////////////////////////////////
196 // Author: Andrey Sobolev
197 // Name: _cvConstuctSites
198 // Purpose : Compute sites for given polygon with holes
199 // (site is an edge of polygon or a reflex vertex).
202 // ContourSeq : in, vertices of polygon
203 // pVoronoiDiagram : in, pointer to struct, which contains the
204 // description of Voronoi Diagram
205 // contour_type: in, type of vertices. The possible values are
206 // CV_LEE_INT,CV_LEE_FLOAT,CV_LEE_DOUBLE.
207 // contour_orientation: in, orientation of polygons.
208 // = 1, if contour is left - oriented in left coordinat system
209 // =-1, if contour is left - oriented in right coordinat system
210 // Return: 1, if sites were succesfully constructed
211 // 0, if some error occures
213 static int _cvConstuctSites(CvSeq* ContourSeq,
214 CvVoronoiDiagramInt* pVoronoiDiagram,
215 CvLeeParameters contour_type,
216 int contour_orientation);
218 /*F///////////////////////////////////////////////////////////////////////////////////////
219 // Author: Andrey Sobolev
220 // Name: _cvConstructChains
221 // Purpose : Compute chains for given polygon with holes.
224 // pVoronoiDiagram : in, pointer to struct, which contains the
225 // description of Voronoi Diagram
226 // Return: 1, if chains were succesfully constructed
227 // 0, if some error occures
229 static int _cvConstructChains(CvVoronoiDiagramInt* pVoronoiDiagram);
231 /*F///////////////////////////////////////////////////////////////////////////////////////
232 // Author: Andrey Sobolev
233 // Name: _cvConstructSkeleton
234 // Purpose: Compute skeleton for given collection of sites, using Lee algorithm
237 // VoronoiDiagram : in, pointer to struct, which contains the
238 // description of Voronoi Diagram.
239 // Returns: 1, if skeleton was succesfully computed
240 // 0, if some error occures
242 static int _cvConstructSkeleton(CvVoronoiDiagramInt* pVoronoiDiagram);
244 /*F///////////////////////////////////////////////////////////////////////////////////////
245 // Author: Andrey Sobolev
246 // Name: _cvConstructSiteTree
247 // Purpose: Construct tree of sites (by analogy with contour tree).
250 // VoronoiDiagram : in, pointer to struct, which contains the
251 // description of Voronoi Diagram.
254 static void _cvConstructSiteTree(CvVoronoiDiagramInt* pVoronoiDiagram);
256 /*F///////////////////////////////////////////////////////////////////////////////////////
257 // Author: Andrey Sobolev
258 // Name: _cvReleaseVoronoiStorage
259 // Purpose : Function realease storages.
260 // The storages are divided into two groups:
261 // SiteStorage, EdgeStorage, NodeStorage form the first group;
262 // ChainStorage,ParabolaStorage,DirectionStorage,HoleStorage form the second group.
265 // pVoronoiStorage: in,
266 // group1,group2: in, if group1<>0 then storages from first group released
267 // if group2<>0 then storages from second group released
270 static void _cvReleaseVoronoiStorage(CvVoronoiStorageInt* pVoronoiStorage, int group1, int group2);
272 /*F///////////////////////////////////////////////////////////////////////////////////////
273 // Author: Andrey Sobolev
275 // Purpose : Function convert internal representation of VD (via
276 // structs CvVoronoiSiteInt, CvVoronoiEdgeInt,CvVoronoiNodeInt) into
277 // external representation of VD (via structs CvVoronoiSite2D, CvVoronoiEdge2D,
281 // VoronoiDiagram: in
282 // VoronoiStorage: in
283 // change_orientation: in, if = -1 then the convertion is accompanied with change
286 // Return: 1, if convertion was succesfully completed
287 // 0, if some error occures
290 static int _cvConvert(CvVoronoiDiagram2D* VoronoiDiagram,
291 CvMemStorage* VoronoiStorage,
292 int change_orientation);
294 static int _cvConvert(CvVoronoiDiagram2D* VoronoiDiagram,
295 CvVoronoiDiagramInt VoronoiDiagramInt,
296 CvSet* &NewSiteSeqPrev,
297 CvSeqWriter &NodeWriter,
298 CvSeqWriter &EdgeWriter,
299 CvMemStorage* VoronoiStorage,
300 int change_orientation);
302 /*F///////////////////////////////////////////////////////////////////////////////////////
303 // Author: Andrey Sobolev
304 // Name: _cvConvertSameOrientation
305 // Purpose : Function convert internal representation of VD (via
306 // structs CvVoronoiSiteInt, CvVoronoiEdgeInt,CvVoronoiNodeInt) into
307 // external representation of VD (via structs CvVoronoiSite2D, CvVoronoiEdge2D,
308 // CvVoronoiNode2D) without change of orientation
311 // VoronoiDiagram: in
312 // VoronoiStorage: in
314 // Return: 1, if convertion was succesfully completed
315 // 0, if some error occures
318 static int _cvConvertSameOrientation(CvVoronoiDiagram2D* VoronoiDiagram,
319 CvMemStorage* VoronoiStorage);
321 static int _cvConvertSameOrientation(CvVoronoiDiagram2D* VoronoiDiagram,
322 CvVoronoiDiagramInt VoronoiDiagramInt,
323 CvSet* &NewSiteSeqPrev,
324 CvSeqWriter &NodeWriter,
325 CvSeqWriter &EdgeWriter,
326 CvMemStorage* VoronoiStorage);
328 /*F///////////////////////////////////////////////////////////////////////////////////////
329 // Author: Andrey Sobolev
330 // Name: _cvConvertChangeOrientation
331 // Purpose : Function convert internal representation of VD (via
332 // structs CvVoronoiSiteInt, CvVoronoiEdgeInt,CvVoronoiNodeInt) into
333 // external representation of VD (via structs CvVoronoiSite2D, CvVoronoiEdge2D,
334 // CvVoronoiNode2D) with change of orientation
337 // VoronoiDiagram: in
338 // VoronoiStorage: in
340 // Return: 1, if convertion was succesfully completed
341 // 0, if some error occures
344 static int _cvConvertChangeOrientation(CvVoronoiDiagram2D* VoronoiDiagram,
345 CvMemStorage* VoronoiStorage);
347 static int _cvConvertChangeOrientation(CvVoronoiDiagram2D* VoronoiDiagram,
348 CvVoronoiDiagramInt VoronoiDiagramInt,
349 CvSet* &NewSiteSeqPrev,
350 CvSeqWriter &NodeWriter,
351 CvSeqWriter &EdgeWriter,
352 CvMemStorage* VoronoiStorage);
354 /*--------------------------------------------------------------------------
355 Author : Andrey Sobolev
356 Description : Compute sites for external polygon.
358 pVoronoiDiagram : in, pointer to struct, which contains the
359 description of Voronoi Diagram
360 ContourSeq : in, vertices of polygon
361 pReflexSite: out, pointer to reflex site,if any exist,else NULL
362 orientation: in, orientation of contour ( = 1 or = -1)
363 type: in, type of vertices. The possible values are (int)1,
365 Return: 1, if sites were succesfully constructed
366 0, if some error occures :
367 --------------------------------------------------------------------------*/
369 int _cvConstructExtSites(CvVoronoiDiagramInt* pVoronoiDiagram,
374 /*--------------------------------------------------------------------------
375 Author : Andrey Sobolev
376 Description : Compute sites for internal polygon (for hole).
378 pVoronoiDiagram : in, pointer to struct, which contains the
379 description of Voronoi Diagram
380 CurrSiteSeq: in, the sequence for sites to be constructed
381 CurrContourSeq : in, vertices of polygon
382 pTopSite: out, pointer to the most left site of polygon (it is the most left
384 orientation: in, orientation of contour ( = 1 or = -1)
385 type: in, type of vertices. The possible values are (int)1,
387 Return: 1, if sites were succesfully constructed
388 0, if some error occures :
389 --------------------------------------------------------------------------*/
391 int _cvConstructIntSites(CvVoronoiDiagramInt* pVoronoiDiagram,
393 CvSeq* CurrContourSeq,
394 pCvVoronoiSite &pTopSite,
398 /*--------------------------------------------------------------------------
399 Author : Andrey Sobolev
400 Description : Compute the simple chains of sites for external polygon.
402 pVoronoiDiagram : in&out, pointer to struct, which contains the
403 description of Voronoi Diagram
405 Return: 1, if chains were succesfully constructed
406 0, if some error occures
407 --------------------------------------------------------------------------*/
408 static int _cvConstructExtChains(CvVoronoiDiagramInt* pVoronoiDiagram);
410 /*--------------------------------------------------------------------------
411 Author : Andrey Sobolev
412 Description : Compute the simple chains of sites for internal polygon (= hole)
414 pVoronoiDiagram : in, pointer to struct, which contains the
415 description of Voronoi Diagram
416 CurrSiteSeq : in, the sequence of sites
417 CurrChainSeq : in,the sequence for chains to be constructed
418 pTopSite : in, the most left site of hole
421 --------------------------------------------------------------------------*/
422 static void _cvConstructIntChains(CvVoronoiDiagramInt* pVoronoiDiagram,
425 pCvVoronoiSite pTopSite);
427 /*--------------------------------------------------------------------------
428 Author : Andrey Sobolev
429 Description : Compute the initial Voronoi Diagram for single site
431 pVoronoiDiagram : in, pointer to struct, which contains the
432 description of Voronoi Diagram
433 pSite: in, pointer to site
436 --------------------------------------------------------------------------*/
437 static void _cvConstructEdges(pCvVoronoiSite pSite,CvVoronoiDiagramInt* pVoronoiDiagram);
439 /*--------------------------------------------------------------------------
440 Author : Andrey Sobolev
441 Description : Function moves each node on small random value. The nodes are taken
442 from pVoronoiDiagram->NodeSeq.
444 pVoronoiDiagram : in, pointer to struct, which contains the
445 description of Voronoi Diagram
446 begin,end: in, the first and the last nodes in pVoronoiDiagram->NodeSeq,
448 shift: in, the value of maximal shift.
450 --------------------------------------------------------------------------*/
451 static void _cvRandomModification(CvVoronoiDiagramInt* pVoronoiDiagram, int begin, int end, float shift);
453 /*--------------------------------------------------------------------------
454 Author : Andrey Sobolev
455 Description : Compute the internal Voronoi Diagram for external polygon.
457 pVoronoiDiagram : in, pointer to struct, which contains the
458 description of Voronoi Diagram
459 Return : 1, if VD was constructed succesfully
460 0, if some error occure
461 --------------------------------------------------------------------------*/
462 static int _cvConstructExtVD(CvVoronoiDiagramInt* pVoronoiDiagram);
464 /*--------------------------------------------------------------------------
465 Author : Andrey Sobolev
466 Description : Compute the external Voronoi Diagram for each internal polygon (hole).
468 pVoronoiDiagram : in, pointer to struct, which contains the
469 description of Voronoi Diagram
471 --------------------------------------------------------------------------*/
472 static void _cvConstructIntVD(CvVoronoiDiagramInt* pVoronoiDiagram);
474 /*--------------------------------------------------------------------------
475 Author : Andrey Sobolev
476 Description : Function joins the Voronoi Diagrams of different
477 chains into one Voronoi Diagram
479 pVoronoiDiagram : in, pointer to struct, which contains the
480 description of Voronoi Diagram
481 pChain1,pChain1: in, given chains
482 Return : 1, if joining was succesful
483 0, if some error occure
484 --------------------------------------------------------------------------*/
485 static int _cvJoinChains(pCvVoronoiChain pChain1,
486 pCvVoronoiChain pChain2,
487 CvVoronoiDiagramInt* pVoronoiDiagram);
489 /*--------------------------------------------------------------------------
490 Author : Andrey Sobolev
491 Description : Function finds the nearest site for top vertex
492 (= the most left vertex) of each hole
494 pVoronoiDiagram : in, pointer to struct, which contains the
495 description of Voronoi Diagram
497 --------------------------------------------------------------------------*/
498 static void _cvFindNearestSite(CvVoronoiDiagramInt* pVoronoiDiagram);
500 /*--------------------------------------------------------------------------
501 Author : Andrey Sobolev
502 Description : Function seeks for site, which has common bisector in
503 final VD with top vertex of given hole. It stores in pHole->opposite_site.
504 The search begins from Hole->nearest_site and realizes in clockwise
505 direction around the top vertex of given hole.
507 pVoronoiDiagram : in, pointer to struct, which contains the
508 description of Voronoi Diagram
509 pHole : in, given hole
510 Return : 1, if the search was succesful
511 0, if some error occure
512 --------------------------------------------------------------------------*/
513 static int _cvFindOppositSiteCW(pCvVoronoiHole pHole, CvVoronoiDiagramInt* pVoronoiDiagram);
515 /*--------------------------------------------------------------------------
516 Author : Andrey Sobolev
517 Description : Function seeks for site, which has common bisector in
518 final VD with top vertex of given hole. It stores in pHole->opposite_site.
519 The search begins from Hole->nearest_site and realizes in counterclockwise
520 direction around the top vertex of given hole.
522 pVoronoiDiagram : in, pointer to struct, which contains the
523 description of Voronoi Diagram
524 pHole : in, given hole
525 Return : 1, if the search was succesful
526 0, if some error occure
527 --------------------------------------------------------------------------*/
528 static int _cvFindOppositSiteCCW(pCvVoronoiHole pHole,CvVoronoiDiagramInt* pVoronoiDiagram);
530 /*--------------------------------------------------------------------------
531 Author : Andrey Sobolev
532 Description : Function merges external VD of hole and internal VD, which was
535 pVoronoiDiagram : in, pointer to struct, which contains the
536 description of Voronoi Diagram
537 pHole : in, given hole
538 Return : 1, if merging was succesful
539 0, if some error occure
540 --------------------------------------------------------------------------*/
541 static int _cvMergeVD(pCvVoronoiHole pHole,CvVoronoiDiagramInt* pVoronoiDiagram);
544 /* ///////////////////////////////////////////////////////////////////////////////////////
545 // Computation of bisectors //
546 /////////////////////////////////////////////////////////////////////////////////////// */
548 /*--------------------------------------------------------------------------
549 Author : Andrey Sobolev
550 Description : Compute the bisector of two sites
552 pSite_left,pSite_right: in, given sites
553 pVoronoiDiagram : in, pointer to struct, which contains the
554 description of Voronoi Diagram
555 pEdge : out, bisector
557 --------------------------------------------------------------------------*/
558 void _cvCalcEdge(pCvVoronoiSite pSite_left,
559 pCvVoronoiSite pSite_right,
560 pCvVoronoiEdge pEdge,
561 CvVoronoiDiagramInt* pVoronoiDiagram);
563 /*--------------------------------------------------------------------------
564 Author : Andrey Sobolev
565 Description : Compute the bisector of point and site
569 pVoronoiDiagram : in, pointer to struct, which contains the
570 description of Voronoi Diagram
571 pEdge : out, bisector
573 --------------------------------------------------------------------------*/
574 void _cvCalcEdge(pCvVoronoiSite pSite,
575 pCvVoronoiNode pNode,
576 pCvVoronoiEdge pEdge,
577 CvVoronoiDiagramInt* pVoronoiDiagram);
579 /*--------------------------------------------------------------------------
580 Author : Andrey Sobolev
581 Description : Compute the bisector of point and site
585 pVoronoiDiagram : in, pointer to struct, which contains the
586 description of Voronoi Diagram
587 pEdge : out, bisector
589 --------------------------------------------------------------------------*/
590 void _cvCalcEdge(pCvVoronoiNode pNode,
591 pCvVoronoiSite pSite,
592 pCvVoronoiEdge pEdge,
593 CvVoronoiDiagramInt* pVoronoiDiagram);
595 /*--------------------------------------------------------------------------
596 Author : Andrey Sobolev
597 Description : Compute the direction of bisector of two segments
599 pDirection1: in, direction of first segment
600 pDirection2: in, direction of second segment
601 pVoronoiDiagram : in, pointer to struct, which contains the
602 description of Voronoi Diagram
603 pEdge : out, bisector
605 --------------------------------------------------------------------------*/
607 void _cvCalcEdgeLL(pCvDirection pDirection1,
608 pCvDirection pDirection2,
609 pCvVoronoiEdge pEdge,
610 CvVoronoiDiagramInt* pVoronoiDiagram);
612 /*--------------------------------------------------------------------------
613 Author : Andrey Sobolev
614 Description : Compute the bisector of two points
616 pPoint1, pPoint2: in, given points
617 pVoronoiDiagram : in, pointer to struct, which contains the
618 description of Voronoi Diagram
619 pEdge : out, bisector
621 --------------------------------------------------------------------------*/
623 void _cvCalcEdgePP(pCvPointFloat pPoint1,
624 pCvPointFloat pPoint2,
625 pCvVoronoiEdge pEdge,
626 CvVoronoiDiagramInt* pVoronoiDiagram);
628 /*--------------------------------------------------------------------------
629 Author : Andrey Sobolev
630 Description : Compute the bisector of segment and point. Since
631 it is parabola, it is defined by its focus (site - point)
632 and directrice(site-segment)
634 pFocus : in, point, which defines the focus of parabola
635 pDirectrice: in, site - segment, which defines the directrice of parabola
636 pVoronoiDiagram : in, pointer to struct, which contains the
637 description of Voronoi Diagram
638 pEdge : out, bisector
640 --------------------------------------------------------------------------*/
642 void _cvCalcEdgePL(pCvVoronoiNode pFocus,
643 pCvVoronoiSite pDirectrice,
644 pCvVoronoiEdge pEdge,
645 CvVoronoiDiagramInt* pVoronoiDiagram);
647 /*--------------------------------------------------------------------------
648 Author : Andrey Sobolev
649 Description : Compute the bisector of segment and point. Since
650 it is parabola, it is defined by its focus (site - point)
651 and directrice(site-segment)
653 pFocus : in, point, which defines the focus of parabola
654 pDirectrice: in, site - segment, which defines the directrice of parabola
655 pVoronoiDiagram : in, pointer to struct, which contains the
656 description of Voronoi Diagram
657 pEdge : out, bisector
659 --------------------------------------------------------------------------*/
661 void _cvCalcEdgeLP(pCvVoronoiSite pDirectrice,
662 pCvVoronoiNode pFocus,
663 pCvVoronoiEdge pEdge,
664 CvVoronoiDiagramInt* pVoronoiDiagram);
666 /* ///////////////////////////////////////////////////////////////////////////////////////
667 // Computation of intersections of bisectors //
668 /////////////////////////////////////////////////////////////////////////////////////// */
670 /*--------------------------------------------------------------------------
671 Author : Andrey Sobolev
672 Description : Function computes intersection of two edges. Intersection
673 must be the nearest to the marked point on pEdge1
674 (this marked point is pEdge1->node1->node).
676 pEdge1,pEdge2: in, two edges
677 pPoint: out, intersection of pEdge1 and pEdge2
678 Radius: out, distance between pPoint and sites, assosiated
679 with pEdge1 and pEdge2 (pPoint is situated on the equal
680 distance from site, assosiated with pEdge1 and from
681 site,assosiated with pEdge2)
682 Return : distance between pPoint and marked point on pEdge1 or
683 : -1, if edges have no intersections
684 --------------------------------------------------------------------------*/
686 float _cvCalcEdgeIntersection(pCvVoronoiEdge pEdge1,
687 pCvVoronoiEdge pEdge2,
688 CvPointFloat* pPoint,
691 /*--------------------------------------------------------------------------
692 Author : Andrey Sobolev
693 Description : Function computes intersection of two edges. Intersection
694 must be the nearest to the marked point on pEdge1
695 (this marked point is pEdge1->node1->node).
697 pEdge1 : in, straight ray
698 pEdge2: in, straight ray or segment
699 pPoint: out, intersection of pEdge1 and pEdge2
700 Radius: out, distance between pPoint and sites, assosiated
701 with pEdge1 and pEdge2 (pPoint is situated on the equal
702 distance from site, assosiated with pEdge1 and from
703 site,assosiated with pEdge2)
704 Return : distance between pPoint and marked point on pEdge1 or
705 : -1, if edges have no intersections
706 --------------------------------------------------------------------------*/
708 float _cvLine_LineIntersection(pCvVoronoiEdge pEdge1,
709 pCvVoronoiEdge pEdge2,
710 pCvPointFloat pPoint,
713 /*--------------------------------------------------------------------------
714 Author : Andrey Sobolev
715 Description : Function computes intersection of two edges. Intersection
716 must be the nearest to the marked point on pEdge1
717 (this marked point is pEdge1->node1->node).
719 pEdge1 : in, straight ray
720 pEdge2: in, parabolic ray or segment
721 pPoint: out, intersection of pEdge1 and pEdge2
722 Radius: out, distance between pPoint and sites, assosiated
723 with pEdge1 and pEdge2 (pPoint is situated on the equal
724 distance from site, assosiated with pEdge1 and from
725 site,assosiated with pEdge2)
726 Return : distance between pPoint and marked point on pEdge1 or
727 : -1, if edges have no intersections
728 --------------------------------------------------------------------------*/
730 float _cvLine_ParIntersection(pCvVoronoiEdge pEdge1,
731 pCvVoronoiEdge pEdge2,
732 pCvPointFloat pPoint,
735 /*--------------------------------------------------------------------------
736 Author : Andrey Sobolev
737 Description : Function computes intersection of two edges. Intersection
738 must be the nearest to the marked point on pEdge1
739 (this marked point is pEdge1->node1->node).
741 pEdge1 : in, straight ray
742 pEdge2: in, parabolic segment
743 pPoint: out, intersection of pEdge1 and pEdge2
744 Radius: out, distance between pPoint and sites, assosiated
745 with pEdge1 and pEdge2 (pPoint is situated on the equal
746 distance from site, assosiated with pEdge1 and from
747 site,assosiated with pEdge2)
748 Return : distance between pPoint and marked point on pEdge1 or
749 : -1, if edges have no intersections
750 --------------------------------------------------------------------------*/
752 float _cvLine_CloseParIntersection(pCvVoronoiEdge pEdge1,
753 pCvVoronoiEdge pEdge2,
754 pCvPointFloat pPoint,
757 /*--------------------------------------------------------------------------
758 Author : Andrey Sobolev
759 Description : Function computes intersection of two edges. Intersection
760 must be the nearest to the marked point on pEdge1
761 (this marked point is pEdge1->node1->node).
763 pEdge1 : in, straight ray
764 pEdge2: in, parabolic ray
765 pPoint: out, intersection of pEdge1 and pEdge2
766 Radius: out, distance between pPoint and sites, assosiated
767 with pEdge1 and pEdge2 (pPoint is situated on the equal
768 distance from site, assosiated with pEdge1 and from
769 site,assosiated with pEdge2)
770 Return : distance between pPoint and marked point on pEdge1 or
771 : -1, if edges have no intersections
772 --------------------------------------------------------------------------*/
774 float _cvLine_OpenParIntersection(pCvVoronoiEdge pEdge1,
775 pCvVoronoiEdge pEdge2,
776 pCvPointFloat pPoint,
779 /*--------------------------------------------------------------------------
780 Author : Andrey Sobolev
781 Description : Function computes intersection of two edges. Intersection
782 must be the nearest to the marked point on pEdge1
783 (this marked point is pEdge1->node1->node).
785 pEdge1 : in, parabolic ray
786 pEdge2: in, straight ray or segment
787 pPoint: out, intersection of pEdge1 and pEdge2
788 Radius: out, distance between pPoint and sites, assosiated
789 with pEdge1 and pEdge2 (pPoint is situated on the equal
790 distance from site, assosiated with pEdge1 and from
791 site,assosiated with pEdge2)
792 Return : distance between pPoint and marked point on pEdge1 or
793 : -1, if edges have no intersections
794 --------------------------------------------------------------------------*/
796 float _cvPar_LineIntersection(pCvVoronoiEdge pEdge1,
797 pCvVoronoiEdge pEdge2,
798 pCvPointFloat pPoint,
800 /*--------------------------------------------------------------------------
801 Author : Andrey Sobolev
802 Description : Function computes intersection of two edges. Intersection
803 must be the nearest to the marked point on pEdge1
804 (this marked point is pEdge1->node1->node).
806 pEdge1 : in, parabolic ray
807 pEdge2: in, straight ray
808 pPoint: out, intersection of pEdge1 and pEdge2
809 Radius: out, distance between pPoint and sites, assosiated
810 with pEdge1 and pEdge2 (pPoint is situated on the equal
811 distance from site, assosiated with pEdge1 and from
812 site,assosiated with pEdge2)
813 Return : distance between pPoint and marked point on pEdge1 or
814 : -1, if edges have no intersections
815 --------------------------------------------------------------------------*/
817 float _cvPar_OpenLineIntersection(pCvVoronoiEdge pEdge1,
818 pCvVoronoiEdge pEdge2,
819 pCvPointFloat pPoint,
822 /*--------------------------------------------------------------------------
823 Author : Andrey Sobolev
824 Description : Function computes intersection of two edges. Intersection
825 must be the nearest to the marked point on pEdge1
826 (this marked point is pEdge1->node1->node).
828 pEdge1 : in, parabolic ray
829 pEdge2: in, straight segment
830 pPoint: out, intersection of pEdge1 and pEdge2
831 Radius: out, distance between pPoint and sites, assosiated
832 with pEdge1 and pEdge2 (pPoint is situated on the equal
833 distance from site, assosiated with pEdge1 and from
834 site,assosiated with pEdge2)
835 Return : distance between pPoint and marked point on pEdge1 or
836 : -1, if edges have no intersections
837 --------------------------------------------------------------------------*/
839 float _cvPar_CloseLineIntersection(pCvVoronoiEdge pEdge1,
840 pCvVoronoiEdge pEdge2,
841 pCvPointFloat pPoint,
844 /*--------------------------------------------------------------------------
845 Author : Andrey Sobolev
846 Description : Function computes intersection of two edges. Intersection
847 must be the nearest to the marked point on pEdge1
848 (this marked point is pEdge1->node1->node).
850 pEdge1 : in, parabolic ray
851 pEdge2: in, parabolic ray or segment
852 pPoint: out, intersection of pEdge1 and pEdge2
853 Radius: out, distance between pPoint and sites, assosiated
854 with pEdge1 and pEdge2 (pPoint is situated on the equal
855 distance from site, assosiated with pEdge1 and from
856 site,assosiated with pEdge2)
857 Return : distance between pPoint and marked point on pEdge1 or
858 : -1, if edges have no intersections
859 --------------------------------------------------------------------------*/
861 float _cvPar_ParIntersection(pCvVoronoiEdge pEdge1,
862 pCvVoronoiEdge pEdge2,
863 pCvPointFloat pPoint,
867 /*--------------------------------------------------------------------------
868 Author : Andrey Sobolev
869 Description : Function computes intersection of two edges. Intersection
870 must be the nearest to the marked point on pEdge1
871 (this marked point is pEdge1->node1->node).
873 pEdge1 : in, parabolic ray
874 pEdge2: in, parabolic ray
875 pPoint: out, intersection of pEdge1 and pEdge2
876 Radius: out, distance between pPoint and sites, assosiated
877 with pEdge1 and pEdge2 (pPoint is situated on the equal
878 distance from site, assosiated with pEdge1 and from
879 site,assosiated with pEdge2)
880 Return : distance between pPoint and marked point on pEdge1 or
881 : -1, if edges have no intersections
882 --------------------------------------------------------------------------*/
884 float _cvPar_OpenParIntersection(pCvVoronoiEdge pEdge1,
885 pCvVoronoiEdge pEdge2,
886 pCvPointFloat pPoint,
889 /*--------------------------------------------------------------------------
890 Author : Andrey Sobolev
891 Description : Function computes intersection of two edges. Intersection
892 must be the nearest to the marked point on pEdge1
893 (this marked point is pEdge1->node1->node).
895 pEdge1 : in, parabolic ray
896 pEdge2: in, parabolic segment
897 pPoint: out, intersection of pEdge1 and pEdge2
898 Radius: out, distance between pPoint and sites, assosiated
899 with pEdge1 and pEdge2 (pPoint is situated on the equal
900 distance from site, assosiated with pEdge1 and from
901 site,assosiated with pEdge2)
902 Return : distance between pPoint and marked point on pEdge1 or
903 : -1, if edges have no intersections
904 --------------------------------------------------------------------------*/
906 float _cvPar_CloseParIntersection(pCvVoronoiEdge pEdge1,
907 pCvVoronoiEdge pEdge2,
908 pCvPointFloat pPoint,
911 /* ///////////////////////////////////////////////////////////////////////////////////////
912 // Subsidiary functions //
913 /////////////////////////////////////////////////////////////////////////////////////// */
915 /*--------------------------------------------------------------------------
916 Author : Andrey Sobolev
922 --------------------------------------------------------------------------*/
924 void _cvMakeTwinEdge(pCvVoronoiEdge pEdge2,
925 pCvVoronoiEdge pEdge1);
927 /*--------------------------------------------------------------------------
928 Author : Andrey Sobolev
932 pEdge_left_prev : in&out
935 --------------------------------------------------------------------------*/
937 void _cvStickEdgeLeftBegin(pCvVoronoiEdge pEdge,
938 pCvVoronoiEdge pEdge_left_prev,
939 pCvVoronoiSite pSite_left);
941 /*--------------------------------------------------------------------------
942 Author : Andrey Sobolev
946 pEdge_right_next : in&out
949 --------------------------------------------------------------------------*/
951 void _cvStickEdgeRightBegin(pCvVoronoiEdge pEdge,
952 pCvVoronoiEdge pEdge_right_next,
953 pCvVoronoiSite pSite_right);
955 /*--------------------------------------------------------------------------
956 Author : Andrey Sobolev
960 pEdge_left_next : in&out
963 --------------------------------------------------------------------------*/
965 void _cvStickEdgeLeftEnd(pCvVoronoiEdge pEdge,
966 pCvVoronoiEdge pEdge_left_next,
967 pCvVoronoiSite pSite_left);
969 /*--------------------------------------------------------------------------
970 Author : Andrey Sobolev
974 pEdge_right_prev : in&out
977 --------------------------------------------------------------------------*/
979 void _cvStickEdgeRightEnd(pCvVoronoiEdge pEdge,
980 pCvVoronoiEdge pEdge_right_prev,
981 pCvVoronoiSite pSite_right);
983 /*--------------------------------------------------------------------------
984 Author : Andrey Sobolev
990 --------------------------------------------------------------------------*/
992 void _cvTwinNULLLeft(pCvVoronoiEdge pEdge_left_cur,
993 pCvVoronoiEdge pEdge_left);
995 /*--------------------------------------------------------------------------
996 Author : Andrey Sobolev
1002 --------------------------------------------------------------------------*/
1004 void _cvTwinNULLRight(pCvVoronoiEdge pEdge_right_cur,
1005 pCvVoronoiEdge pEdge_right);
1008 /*--------------------------------------------------------------------------
1009 Author : Andrey Sobolev
1010 Description : function initializes the struct CvVoronoiNode
1016 --------------------------------------------------------------------------*/
1017 template <class T> CV_INLINE
1018 void _cvInitVoronoiNode(pCvVoronoiNode pNode,
1019 T pPoint, float radius = 0);
1021 /*--------------------------------------------------------------------------
1022 Author : Andrey Sobolev
1023 Description : function initializes the struct CvVoronoiSite
1026 pNode1,pNode2,pPrev_site : in
1028 --------------------------------------------------------------------------*/
1030 void _cvInitVoronoiSite(pCvVoronoiSite pSite,
1031 pCvVoronoiNode pNode1,
1032 pCvVoronoiNode pNode2,
1033 pCvVoronoiSite pPrev_site);
1035 /*--------------------------------------------------------------------------
1036 Author : Andrey Sobolev
1037 Description : function pushs the element in the end of the sequence
1038 end returns its adress
1040 Seq : in, pointer to the sequence
1042 Return : pointer to the element in the sequence
1043 --------------------------------------------------------------------------*/
1044 template <class T> CV_INLINE
1045 T _cvSeqPush(CvSeq* Seq, T pElem);
1047 /*--------------------------------------------------------------------------
1048 Author : Andrey Sobolev
1049 Description : function pushs the element in the begin of the sequence
1050 end returns its adress
1052 Seq : in, pointer to the sequence
1054 Return : pointer to the element in the sequence
1055 --------------------------------------------------------------------------*/
1056 template <class T> CV_INLINE
1057 T _cvSeqPushFront(CvSeq* Seq, T pElem);
1059 /*--------------------------------------------------------------------------
1060 Author : Andrey Sobolev
1061 Description : function pushs the element pHole in pHoleHierarchy->HoleSeq
1062 so as all elements in this sequence would be normalized
1063 according to field .x_coord of element. pHoleHierarchy->TopHole
1064 points to hole with smallest x_coord.
1066 pHoleHierarchy : in, pointer to the structur
1068 Return : pointer to the element in the sequence
1069 --------------------------------------------------------------------------*/
1071 void _cvSeqPushInOrder(CvVoronoiDiagramInt* pVoronoiDiagram, pCvVoronoiHole pHole);
1073 /*--------------------------------------------------------------------------
1074 Author : Andrey Sobolev
1075 Description : function intersects given edge pEdge (and his twin edge)
1076 by point pNode on two parts
1078 pEdge : in, given edge
1079 pNode : in, given point
1081 Return : one of parts
1082 --------------------------------------------------------------------------*/
1084 pCvVoronoiEdge _cvDivideRightEdge(pCvVoronoiEdge pEdge,
1085 pCvVoronoiNode pNode,
1088 /*--------------------------------------------------------------------------
1089 Author : Andrey Sobolev
1090 Description : function intersects given edge pEdge (and his twin edge)
1091 by point pNode on two parts
1093 pEdge : in, given edge
1094 pNode : in, given point
1096 Return : one of parts
1097 --------------------------------------------------------------------------*/
1099 pCvVoronoiEdge _cvDivideLeftEdge(pCvVoronoiEdge pEdge,
1100 pCvVoronoiNode pNode,
1103 /*--------------------------------------------------------------------------
1104 Author : Andrey Sobolev
1105 Description : function pushs the element in the end of the sequence
1106 end returns its adress
1108 writer: in, writer associated with sequence
1110 Return : pointer to the element in the sequence
1111 --------------------------------------------------------------------------*/
1112 template<class T> CV_INLINE
1113 T _cvWriteSeqElem(T pElem, CvSeqWriter &writer);
1115 /* ///////////////////////////////////////////////////////////////////////////////////////
1116 // Mathematical functions //
1117 /////////////////////////////////////////////////////////////////////////////////////// */
1119 /*--------------------------------------------------------------------------
1120 Author : Andrey Sobolev
1121 Description : Function changes x and y
1125 --------------------------------------------------------------------------*/
1126 template <class T> CV_INLINE
1127 void _cvSwap(T &x, T &y);
1129 /*--------------------------------------------------------------------------
1130 Author : Andrey Sobolev
1131 Description : Function computes the inverse map to the
1132 given ortogonal affine map
1134 A : in, given ortogonal affine map
1135 B : out, inverse map
1136 Return : 1, if inverse map exist
1138 --------------------------------------------------------------------------*/
1139 template <class T> CV_INLINE
1140 int _cvCalcOrtogInverse(T* B, T* A);
1142 /*--------------------------------------------------------------------------
1143 Author : Andrey Sobolev
1144 Description : Function computes the composition of two affine maps
1146 A,B : in, given affine maps
1147 Result: out, composition of A and B (Result = AB)
1149 --------------------------------------------------------------------------*/
1150 template <class T> CV_INLINE
1151 void _cvCalcComposition(T* Result,T* A,T* B);
1153 /*--------------------------------------------------------------------------
1154 Author : Andrey Sobolev
1155 Description : Function computes the image of point under
1159 pPoint : in, pointer to point
1160 pImgPoint:out, pointer to image of point
1162 --------------------------------------------------------------------------*/
1163 template<class T> CV_INLINE
1164 void _cvCalcPointImage(pCvPointFloat pImgPoint,pCvPointFloat pPoint,T* A);
1166 /*--------------------------------------------------------------------------
1167 Author : Andrey Sobolev
1168 Description : Function computes the image of vector under
1172 pVector : in, pointer to vector
1173 pImgVector:out, pointer to image of vector
1175 --------------------------------------------------------------------------*/
1176 template<class T> CV_INLINE
1177 void _cvCalcVectorImage(pCvDirection pImgVector,pCvDirection pVector,T* A);
1179 /*--------------------------------------------------------------------------
1180 Author : Andrey Sobolev
1181 Description : Function computes the distance between the point
1182 and site. Internal function.
1187 --------------------------------------------------------------------------*/
1189 float _cvCalcDist(pCvPointFloat pPoint, pCvVoronoiSite pSite);
1191 /*--------------------------------------------------------------------------
1192 Author : Andrey Sobolev
1193 Description : Function computes the distance between two points
1195 pPoint1,pPoint2 : in, two points
1197 --------------------------------------------------------------------------*/
1199 float _cvPPDist(pCvPointFloat pPoint1,pCvPointFloat pPoint2);
1201 /*--------------------------------------------------------------------------
1202 Author : Andrey Sobolev
1203 Description : Function computes the distance betwin point and
1204 segment. Internal function.
1207 pPoint1,pPoint2 : in, segment [pPoint1,pPoint2]
1209 --------------------------------------------------------------------------*/
1211 float _cvPLDist(pCvPointFloat pPoint,pCvPointFloat pPoint1,pCvDirection pDirection);
1213 /*--------------------------------------------------------------------------
1214 Author : Andrey Sobolev
1215 Description : Function solves the squar equation with real coefficients
1218 c2,c1,c0: in, real coefficients of polynom
1219 X: out, array of roots
1220 Return : number of roots
1221 --------------------------------------------------------------------------*/
1223 int _cvSolveEqu2thR(T c2, T c1, T c0, T* X);
1225 /*--------------------------------------------------------------------------
1226 Author : Andrey Sobolev
1227 Description : Function solves the linear equation with real or complex coefficients
1228 T - float or double or complex
1230 c1,c0: in, real or complex coefficients of polynom
1231 X: out, array of roots
1232 Return : number of roots
1233 --------------------------------------------------------------------------*/
1234 template <class T> CV_INLINE
1235 int _cvSolveEqu1th(T c1, T c0, T* X);
1237 /****************************************************************************************\
1238 * Storage Block Increase *
1239 \****************************************************************************************/
1240 /*--------------------------------------------------------------------------
1241 Author : Andrey Sobolev
1242 Description : For each sequence function creates the memory block sufficient to store
1243 all elements of sequnce
1245 pVoronoiDiagramInt: in, pointer to struct, which contains the
1246 description of Voronoi Diagram.
1247 vertices_number: in, number of vertices in polygon
1249 --------------------------------------------------------------------------*/
1250 static void _cvSetSeqBlockSize(CvVoronoiDiagramInt* pVoronoiDiagramInt,int vertices_number)
1252 int N = 2*vertices_number;
1253 cvSetSeqBlockSize(pVoronoiDiagramInt->SiteSeq,N*pVoronoiDiagramInt->SiteSeq->elem_size);
1254 cvSetSeqBlockSize(pVoronoiDiagramInt->EdgeSeq,3*N*pVoronoiDiagramInt->EdgeSeq->elem_size);
1255 cvSetSeqBlockSize(pVoronoiDiagramInt->NodeSeq,5*N*pVoronoiDiagramInt->NodeSeq->elem_size);
1256 cvSetSeqBlockSize(pVoronoiDiagramInt->ParabolaSeq,N*pVoronoiDiagramInt->ParabolaSeq->elem_size);
1257 cvSetSeqBlockSize(pVoronoiDiagramInt->DirectionSeq,3*N*pVoronoiDiagramInt->DirectionSeq->elem_size);
1258 cvSetSeqBlockSize(pVoronoiDiagramInt->ChainSeq,N*pVoronoiDiagramInt->DirectionSeq->elem_size);
1259 cvSetSeqBlockSize(pVoronoiDiagramInt->HoleSeq,100*pVoronoiDiagramInt->HoleSeq->elem_size);
1262 /****************************************************************************************\
1263 * Function realization *
1264 \****************************************************************************************/
1267 CV_IMPL int cvVoronoiDiagramFromContour(CvSeq* ContourSeq,
1268 CvVoronoiDiagram2D** VoronoiDiagram,
1269 CvMemStorage* VoronoiStorage,
1270 CvLeeParameters contour_type,
1271 int contour_orientation,
1274 CV_FUNCNAME( "cvVoronoiDiagramFromContour" );
1278 CvSet* SiteSeq = NULL;
1279 CvSeq* CurContourSeq = NULL;
1280 CvVoronoiDiagramInt VoronoiDiagramInt;
1281 CvSeqWriter NodeWriter, EdgeWriter;
1282 CvMemStorage* storage;
1284 memset( &VoronoiDiagramInt, 0, sizeof(VoronoiDiagramInt) );
1287 CV_ERROR( CV_StsBadArg,"Contour sequence is empty" );
1290 CV_ERROR( CV_StsBadArg,"Storage is not initialized" );
1292 if( contour_type < 0 || contour_type > 2)
1293 CV_ERROR( CV_StsBadArg,"Unsupported parameter: type" );
1295 if( contour_orientation != 1 && contour_orientation != -1)
1296 CV_ERROR( CV_StsBadArg,"Unsupported parameter: orientation" );
1298 storage = cvCreateChildMemStorage(VoronoiStorage);
1299 (*VoronoiDiagram) = (CvVoronoiDiagram2D*)cvCreateSet(0,sizeof(CvVoronoiDiagram2D),sizeof(CvVoronoiNode2D), storage);
1300 storage = cvCreateChildMemStorage(VoronoiStorage);
1301 (*VoronoiDiagram)->edges = cvCreateSet(0,sizeof(CvSet),sizeof(CvVoronoiEdge2D), storage);
1302 cvStartAppendToSeq((CvSeq*)(*VoronoiDiagram)->edges, &EdgeWriter);
1303 cvStartAppendToSeq((CvSeq*)(*VoronoiDiagram), &NodeWriter);
1305 for(CurContourSeq = ContourSeq;\
1306 CurContourSeq != NULL;\
1307 CurContourSeq = CurContourSeq->h_next)
1309 if(_cvLee(CurContourSeq, &VoronoiDiagramInt,VoronoiStorage,contour_type,contour_orientation,attempt_number))
1312 if(!_cvConvert(*VoronoiDiagram,VoronoiDiagramInt,SiteSeq,NodeWriter,EdgeWriter,VoronoiStorage,contour_orientation))
1315 else if(CurContourSeq->total >= 3)
1319 cvEndWriteSeq(&EdgeWriter);
1320 cvEndWriteSeq(&NodeWriter);
1327 }//end of cvVoronoiDiagramFromContour
1329 CV_IMPL int cvVoronoiDiagramFromImage(IplImage* pImage,
1331 CvVoronoiDiagram2D** VoronoiDiagram,
1332 CvMemStorage* VoronoiStorage,
1333 CvLeeParameters regularization_method,
1334 float approx_precision)
1336 CV_FUNCNAME( "cvVoronoiDiagramFromContour" );
1341 IplImage* pWorkImage = NULL;
1343 int i, multiplicator = 3;
1346 CvMemStorage* ApproxContourStorage = NULL;
1347 CvSeq* ApproxContourSeq = NULL;
1350 CV_ERROR( CV_StsBadArg,"Contour sequence is not initialized" );
1352 if( (*ContourSeq)->total != 0)
1353 CV_ERROR( CV_StsBadArg,"Contour sequence is not empty" );
1356 CV_ERROR( CV_StsBadArg,"Storage is not initialized" );
1359 CV_ERROR( CV_StsBadArg,"Image is not initialized" );
1361 if(pImage->nChannels != 1 || pImage->depth != 8)
1362 CV_ERROR( CV_StsBadArg,"Unsupported image format" );
1364 if(approx_precision<0 && approx_precision != CV_LEE_AUTO)
1365 CV_ERROR( CV_StsBadArg,"Unsupported presision value" );
1367 switch(regularization_method)
1369 case CV_LEE_ERODE: image_size.width = pImage->width;
1370 image_size.height = pImage->height;
1371 pWorkImage = cvCreateImage(image_size,8,1);
1372 cvErode(pImage,pWorkImage,0,1);
1373 approx_method = CV_CHAIN_APPROX_TC89_L1;
1375 case CV_LEE_ZOOM: image_size.width = multiplicator*pImage->width;
1376 image_size.height = multiplicator*pImage->height;
1377 pWorkImage = cvCreateImage(image_size,8,1);
1378 cvResize(pImage, pWorkImage, CV_INTER_NN);
1379 approx_method = CV_CHAIN_APPROX_TC89_L1;
1381 case CV_LEE_NON: pWorkImage = pImage;
1382 approx_method = CV_CHAIN_APPROX_TC89_L1;
1384 default: CV_ERROR( CV_StsBadArg,"Unsupported regularisation method" );
1389 cvFindContours(pWorkImage, (*ContourSeq)->storage, ContourSeq, \
1390 sizeof(CvContour), CV_RETR_CCOMP, approx_method );
1392 if(pWorkImage && pWorkImage != pImage )
1393 cvReleaseImage(&pWorkImage);
1395 ApproxContourStorage = cvCreateMemStorage(0);
1396 if(approx_precision > 0)
1398 ApproxContourSeq = cvApproxPoly(*ContourSeq, sizeof(CvContour), ApproxContourStorage,\
1399 CV_POLY_APPROX_DP,approx_precision,1);
1401 RESULT = cvVoronoiDiagramFromContour(ApproxContourSeq,VoronoiDiagram,VoronoiStorage,CV_LEE_INT,-1,10);
1403 else if(approx_precision == CV_LEE_AUTO)
1405 ApproxContourSeq = *ContourSeq;
1406 for(i = 1; i < 50; i++)
1408 RESULT = cvVoronoiDiagramFromContour(ApproxContourSeq,VoronoiDiagram,VoronoiStorage,CV_LEE_INT,-1,1);
1411 ApproxContourSeq = cvApproxPoly(ApproxContourSeq, sizeof(CvContour),ApproxContourStorage,\
1412 CV_POLY_APPROX_DP,(float)i,1);
1416 RESULT = cvVoronoiDiagramFromContour(*ContourSeq,VoronoiDiagram,VoronoiStorage,CV_LEE_INT,-1,10);
1418 if(ApproxContourSeq)
1420 cvClearMemStorage( (*ContourSeq)->storage );
1421 *ContourSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvPoint),(*ContourSeq)->storage);
1425 cvStartAppendToSeq(*ContourSeq, &writer);
1426 cvStartReadSeq(ApproxContourSeq, &reader);
1427 for(int i = 0;i < ApproxContourSeq->total;i++)
1429 CV_READ_SEQ_ELEM(Point,reader);
1430 Point.y = 600 - Point.y;
1431 CV_WRITE_SEQ_ELEM(Point,writer);
1433 cvEndWriteSeq(&writer);
1437 cvReleaseMemStorage(&ApproxContourStorage);
1442 }//end of cvVoronoiDiagramFromImage
1444 CV_IMPL void cvReleaseVoronoiStorage(CvVoronoiDiagram2D* VoronoiDiagram,
1445 CvMemStorage** pVoronoiStorage)
1447 /*CV_FUNCNAME( "cvReleaseVoronoiStorage" );*/
1452 if(VoronoiDiagram->storage)
1453 cvReleaseMemStorage(&VoronoiDiagram->storage);
1454 for(Seq = (CvSeq*)VoronoiDiagram->sites; Seq != NULL; Seq = Seq->h_next)
1456 cvReleaseMemStorage(&Seq->storage);
1457 for(Seq = (CvSeq*)VoronoiDiagram->edges; Seq != NULL; Seq = Seq->h_next)
1459 cvReleaseMemStorage(&Seq->storage);
1461 if(*pVoronoiStorage)
1462 cvReleaseMemStorage(pVoronoiStorage);
1465 }//end of cvReleaseVoronoiStorage
1467 static int _cvLee(CvSeq* ContourSeq,
1468 CvVoronoiDiagramInt* pVoronoiDiagramInt,
1469 CvMemStorage* VoronoiStorage,
1470 CvLeeParameters contour_type,
1471 int contour_orientation,
1474 //orientation = 1 for left coordinat system
1475 //orientation = -1 for right coordinat system
1476 if(ContourSeq->total<3)
1480 CvVoronoiStorageInt VoronoiStorageInt;
1482 srand((int)cvGetTickCount());
1485 VoronoiStorageInt.SiteStorage = cvCreateChildMemStorage(VoronoiStorage);
1486 VoronoiStorageInt.NodeStorage = cvCreateChildMemStorage(VoronoiStorage);
1487 VoronoiStorageInt.EdgeStorage = cvCreateChildMemStorage(VoronoiStorage);
1488 VoronoiStorageInt.ParabolaStorage = cvCreateMemStorage(0);
1489 VoronoiStorageInt.ChainStorage = cvCreateMemStorage(0);
1490 VoronoiStorageInt.DirectionStorage = cvCreateMemStorage(0);
1491 VoronoiStorageInt.HoleStorage = cvCreateMemStorage(0);
1493 pVoronoiDiagramInt->SiteSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvVoronoiSiteInt),VoronoiStorageInt.SiteStorage);
1494 pVoronoiDiagramInt->NodeSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvVoronoiNodeInt),VoronoiStorageInt.NodeStorage);
1495 pVoronoiDiagramInt->EdgeSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvVoronoiEdgeInt),VoronoiStorageInt.EdgeStorage);
1496 pVoronoiDiagramInt->ChainSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvVoronoiChainInt),VoronoiStorageInt.ChainStorage);
1497 pVoronoiDiagramInt->DirectionSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvDirection),VoronoiStorageInt.DirectionStorage);
1498 pVoronoiDiagramInt->ParabolaSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvVoronoiParabolaInt),VoronoiStorageInt.ParabolaStorage);
1499 pVoronoiDiagramInt->HoleSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvVoronoiHoleInt),VoronoiStorageInt.HoleStorage);
1501 _cvSetSeqBlockSize(pVoronoiDiagramInt,ContourSeq->total);
1503 if(!_cvConstuctSites(ContourSeq, pVoronoiDiagramInt, contour_type,contour_orientation))
1505 attempt = attempt_number;
1508 _cvRandomModification(pVoronoiDiagramInt, 0,pVoronoiDiagramInt->NodeSeq->total,0.2f);
1510 if(!_cvConstructChains(pVoronoiDiagramInt))
1512 attempt = attempt_number;
1516 if(!_cvConstructSkeleton(pVoronoiDiagramInt))
1519 _cvConstructSiteTree(pVoronoiDiagramInt);
1522 _cvReleaseVoronoiStorage(&VoronoiStorageInt,0,1);
1526 _cvReleaseVoronoiStorage(&VoronoiStorageInt,1,1);
1527 if(++attempt < attempt_number)
1533 static int _cvConstuctSites(CvSeq* ContourSeq,
1534 CvVoronoiDiagramInt* pVoronoiDiagram,
1535 CvLeeParameters contour_type,
1536 int contour_orientation)
1538 pVoronoiDiagram->reflex_site = NULL;
1539 pVoronoiDiagram->top_hole = NULL;
1542 switch(contour_type)
1544 case CV_LEE_INT : result = _cvConstructExtSites(pVoronoiDiagram,ContourSeq,contour_orientation,(int)1);
1546 case CV_LEE_FLOAT : result = _cvConstructExtSites(pVoronoiDiagram,ContourSeq,contour_orientation,(float)1);
1548 case CV_LEE_DOUBLE : result = _cvConstructExtSites(pVoronoiDiagram,ContourSeq,contour_orientation,(double)1);
1557 CvVoronoiHoleInt Hole = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,0};
1558 pCvVoronoiSite pTopSite = 0;
1559 for(CvSeq* CurContourSeq = ContourSeq->v_next;\
1560 CurContourSeq != NULL;\
1561 CurContourSeq = CurContourSeq->h_next)
1563 if(CurContourSeq->total == 0)
1566 CurSiteSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvVoronoiSiteInt),pVoronoiDiagram->SiteSeq->storage);
1567 switch(contour_type)
1569 case CV_LEE_INT : result = _cvConstructIntSites(pVoronoiDiagram,CurSiteSeq,CurContourSeq,pTopSite,contour_orientation,(int)1);
1571 case CV_LEE_FLOAT : result = _cvConstructIntSites(pVoronoiDiagram,CurSiteSeq,CurContourSeq,pTopSite,contour_orientation,(float)1);
1573 case CV_LEE_DOUBLE :result = _cvConstructIntSites(pVoronoiDiagram,CurSiteSeq,CurContourSeq,pTopSite,contour_orientation,(double)1);
1575 default: result = 0;
1580 Hole.SiteSeq = CurSiteSeq;
1581 Hole.site_top = pTopSite;
1582 Hole.x_coord = pTopSite->node1->node.x;
1584 _cvSeqPushInOrder(pVoronoiDiagram, &Hole);
1587 }//end of _cvConstuctSites
1589 static int _cvConstructChains(CvVoronoiDiagramInt* pVoronoiDiagram)
1591 if(!_cvConstructExtChains(pVoronoiDiagram))
1594 CvSeq* CurrChainSeq;
1595 for(pCvVoronoiHole pHole = pVoronoiDiagram->top_hole;\
1597 pHole = pHole->next_hole)
1599 pHole->error = false;
1600 CurrChainSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvVoronoiChainInt),pVoronoiDiagram->ChainSeq->storage);
1601 _cvConstructIntChains(pVoronoiDiagram,CurrChainSeq,pHole->SiteSeq,pHole->site_top);
1602 pHole->ChainSeq = CurrChainSeq;
1605 }//end of _cvConstructChains
1607 static int _cvConstructSkeleton(CvVoronoiDiagramInt* pVoronoiDiagram)
1609 if(!_cvConstructExtVD(pVoronoiDiagram))
1611 _cvConstructIntVD(pVoronoiDiagram);
1612 _cvFindNearestSite(pVoronoiDiagram);
1616 for(pCvVoronoiHole pHole = pVoronoiDiagram->top_hole;\
1617 pHole != NULL; pHole = pHole->next_hole)
1621 dx = pHole->node->node.x - pHole->site_top->node1->node.x;
1622 dy = pHole->node->node.y - pHole->site_top->node1->node.y;
1624 if(fabs(dy) < 0.01 && dx < 0)
1625 pHole->site_opposite = pHole->site_nearest;
1629 result = _cvFindOppositSiteCCW(pHole,pVoronoiDiagram);
1631 result = _cvFindOppositSiteCW(pHole,pVoronoiDiagram);
1635 pHole->error = true;
1640 if(!_cvMergeVD(pHole,pVoronoiDiagram))
1644 }//end of _cvConstructSkeleton
1646 static void _cvConstructSiteTree(CvVoronoiDiagramInt* pVoronoiDiagram)
1648 CvSeq* CurSeq = pVoronoiDiagram->SiteSeq;
1649 for(pCvVoronoiHole pHole = pVoronoiDiagram->top_hole;\
1650 pHole != NULL; pHole = pHole->next_hole)
1654 if(CurSeq == pVoronoiDiagram->SiteSeq)
1656 CurSeq->v_next = pHole->SiteSeq;
1657 pHole->SiteSeq->v_prev = CurSeq;
1661 CurSeq->h_next = pHole->SiteSeq;
1662 pHole->SiteSeq->h_prev = CurSeq;
1663 pHole->SiteSeq->v_prev = pVoronoiDiagram->SiteSeq;
1665 CurSeq = pHole->SiteSeq;
1667 CurSeq->h_next = NULL;
1668 }//end of _cvConstructSiteTree
1670 static void _cvRandomModification(CvVoronoiDiagramInt* pVoronoiDiagram, int begin, int end, float shift)
1673 pCvVoronoiNode pNode;
1674 const float rnd_const = shift/RAND_MAX;
1677 cvStartReadSeq(pVoronoiDiagram->NodeSeq, &Reader,0);
1678 for( i = begin; i < end; i++)
1680 pNode = (pCvVoronoiNode)Reader.ptr;
1681 pNode->node.x = (float)cvFloor(pNode->node.x) + rand()*rnd_const;
1682 pNode->node.y = (float)cvFloor(pNode->node.y) + rand()*rnd_const;
1683 CV_NEXT_SEQ_ELEM( sizeof(CvVoronoiNodeInt), Reader );
1686 for(pCvVoronoiHole pHole = pVoronoiDiagram->top_hole;\
1688 pHole = pHole->next_hole)
1690 pHole->site_top->node1->node.x = (float)cvFloor(pHole->site_top->node1->node.x);
1693 }//end of _cvRandomModification
1695 static void _cvReleaseVoronoiStorage(CvVoronoiStorageInt* pVoronoiStorage, int group1, int group2)
1697 //if group1 = 1 then SiteSeq, NodeSeq, EdgeSeq released
1698 //if group2 = 1 then DirectionSeq, ParabolaSeq, ChainSeq, HoleSeq released
1701 if(pVoronoiStorage->SiteStorage!=NULL)
1702 cvReleaseMemStorage(&pVoronoiStorage->SiteStorage);
1703 if(pVoronoiStorage->EdgeStorage!=NULL)
1704 cvReleaseMemStorage(&pVoronoiStorage->EdgeStorage);
1705 if(pVoronoiStorage->NodeStorage!=NULL)
1706 cvReleaseMemStorage(&pVoronoiStorage->NodeStorage);
1710 if(pVoronoiStorage->ParabolaStorage!=NULL)
1711 cvReleaseMemStorage(&pVoronoiStorage->ParabolaStorage);
1712 if(pVoronoiStorage->ChainStorage!=NULL)
1713 cvReleaseMemStorage(&pVoronoiStorage->ChainStorage);
1714 if(pVoronoiStorage->DirectionStorage!=NULL)
1715 cvReleaseMemStorage(&pVoronoiStorage->DirectionStorage);
1716 if(pVoronoiStorage->HoleStorage != NULL)
1717 cvReleaseMemStorage(&pVoronoiStorage->HoleStorage);
1719 }// end of _cvReleaseVoronoiStorage
1721 static int _cvConvert(CvVoronoiDiagram2D* VoronoiDiagram,
1722 CvVoronoiDiagramInt VoronoiDiagramInt,
1724 CvSeqWriter &NodeWriter,
1725 CvSeqWriter &EdgeWriter,
1726 CvMemStorage* VoronoiStorage,
1727 int contour_orientation)
1729 if(contour_orientation == 1)
1730 return _cvConvertSameOrientation(VoronoiDiagram,VoronoiDiagramInt,SiteSeq,NodeWriter,
1731 EdgeWriter,VoronoiStorage);
1733 return _cvConvertChangeOrientation(VoronoiDiagram,VoronoiDiagramInt,SiteSeq,NodeWriter,
1734 EdgeWriter,VoronoiStorage);
1735 }// end of _cvConvert
1737 static int _cvConvertSameOrientation(CvVoronoiDiagram2D* VoronoiDiagram,
1738 CvVoronoiDiagramInt VoronoiDiagramInt,
1739 CvSet* &NewSiteSeqPrev,
1740 CvSeqWriter &NodeWriter,
1741 CvSeqWriter &EdgeWriter,
1742 CvMemStorage* VoronoiStorage)
1744 CvSeq* SiteSeq = VoronoiDiagramInt.SiteSeq;
1745 CvSeq* EdgeSeq = VoronoiDiagramInt.EdgeSeq;
1746 CvSeq* NodeSeq = VoronoiDiagramInt.NodeSeq;
1749 CvMemStorage *NewSiteStorage = cvCreateChildMemStorage(VoronoiStorage);
1750 CvSet *NewSiteSeq = NULL,*CurrNewSiteSeq = NULL, *PrevNewSiteSeq = NULL;;
1751 CvSeqWriter SiteWriter;
1753 CvVoronoiSite2D NewSite = {{0,0},{0,0},{0,0}},NewSite_prev = {{0,0},{0,0},{0,0}};
1754 CvVoronoiSite2D *pNewSite, *pNewSite_prev = &NewSite_prev;
1755 pCvVoronoiSite pSite,pFirstSite;
1757 CvVoronoiEdge2D NewEdge = {{0,0},{0,0},{0,0,0,0}};
1758 CvVoronoiEdge2D *pNewEdge1, *pNewEdge2;
1759 pCvVoronoiEdge pEdge;
1761 CvVoronoiNode2D* pNode1, *pNode2;
1762 CvVoronoiNode2D Node;
1763 Node.next_free = NULL;
1765 for(CvSeq* CurrSiteSeq = SiteSeq;\
1766 CurrSiteSeq != NULL;\
1767 CurrSiteSeq = NEXT_SEQ(CurrSiteSeq,SiteSeq))
1769 CurrNewSiteSeq = cvCreateSet(0,sizeof(CvSet),sizeof(CvVoronoiSite2D), NewSiteStorage);
1771 NewSiteSeq = PrevNewSiteSeq = CurrNewSiteSeq;
1772 else if(PrevNewSiteSeq->v_prev == NULL)
1774 PrevNewSiteSeq->v_next = (CvSeq*)CurrNewSiteSeq;
1775 CurrNewSiteSeq->v_prev = (CvSeq*)PrevNewSiteSeq;
1779 PrevNewSiteSeq->h_next = (CvSeq*)CurrNewSiteSeq;
1780 CurrNewSiteSeq->h_prev = (CvSeq*)PrevNewSiteSeq;
1781 CurrNewSiteSeq->v_prev = (CvSeq*)PrevNewSiteSeq->v_prev;
1783 PrevNewSiteSeq = CurrNewSiteSeq;
1785 pSite = pFirstSite = (pCvVoronoiSite)cvGetSeqElem(CurrSiteSeq, 0);
1786 while(pSite->prev_site->node1 == pSite->prev_site->node2)\
1787 pSite = pSite->next_site;
1790 pNewSite_prev = &NewSite_prev;
1791 cvStartAppendToSeq((CvSeq*)CurrNewSiteSeq, &SiteWriter);
1794 pNewSite = _cvWriteSeqElem(&NewSite,SiteWriter);
1795 pNewSite->next[0] = pNewSite_prev;
1796 pNewSite_prev->next[1] = pNewSite;
1797 pEdge = pSite->edge1;
1798 if(!pEdge || !pEdge->node1 || !pEdge->node2)
1801 if(pEdge->site == NULL)
1803 pNewEdge1 = (CvVoronoiEdge2D*)pEdge->twin_edge;
1804 pNewEdge1->site[1] = pNewSite;
1805 pNewSite->node[0] = pNewEdge1->node[0];
1809 pNewEdge1 = _cvWriteSeqElem(&NewEdge,EdgeWriter);
1810 pNewEdge1->site[0] = pNewSite;
1812 pNode1 = _cvWriteSeqElem(&Node,NodeWriter);
1813 pNode2 = _cvWriteSeqElem(&Node,NodeWriter);
1814 pNode1->pt.x = pEdge->node1->node.x;
1815 pNode1->pt.y = pEdge->node1->node.y;
1816 pNode1->radius = pEdge->node1->radius;
1817 pNode2->pt.x = pEdge->node2->node.x;
1818 pNode2->pt.y = pEdge->node2->node.y;
1819 pNode2->radius = pEdge->node2->radius;
1820 pNewEdge1->node[0] = pNode1;
1821 pNewEdge1->node[1] = pNode2;
1823 pNewSite->node[0] = pNewEdge1->node[1];
1825 if(!pNewEdge1->node[0] || !pNewEdge1->node[1])
1827 pEdge->twin_edge->site = NULL;
1828 pEdge->twin_edge->twin_edge = (pCvVoronoiEdge)pNewEdge1;
1830 pNewSite->edge[1] = pNewEdge1;
1831 pEdge = pEdge->prev_edge;
1832 while((pEdge != NULL && CurrSiteSeq->total>1) ||
1833 (pEdge != pSite->edge2 && CurrSiteSeq->total == 1))
1835 if(pEdge->site == NULL)
1837 pNewEdge2 = (CvVoronoiEdge2D*)pEdge->twin_edge;
1838 pNewEdge2->site[1] = pNewSite;
1839 if(CV_VORONOIEDGE2D_BEGINNODE(pNewEdge1,pNewSite) != pNewEdge2->node[0])
1841 cvFlushSeqWriter(&NodeWriter);
1842 // cvSetRemove((CvSet*)VoronoiDiagram,VoronoiDiagram->total-1);
1843 pNewEdge1->node[0] = pNewEdge2->node[0];
1848 pNewEdge2 = _cvWriteSeqElem(&NewEdge,EdgeWriter);
1849 pNewEdge2->site[0] = pNewSite;
1851 pNode1 = _cvWriteSeqElem(&Node,NodeWriter);
1852 pNode1->pt.x = pEdge->node1->node.x;
1853 pNode1->pt.y = pEdge->node1->node.y;
1854 pNode1->radius = pEdge->node1->radius;
1855 pNewEdge2->node[0] = pNode1;
1857 if(pNewEdge1->site[0] == pNewSite)
1858 pNewEdge2->node[1] = pNewEdge1->node[0];
1860 pNewEdge2->node[1] = pNewEdge1->node[1];
1862 if(!pNewEdge1->node[0] || !pNewEdge1->node[1])
1864 pEdge->twin_edge->site = NULL;
1865 pEdge->twin_edge->twin_edge = (pCvVoronoiEdge)pNewEdge2;
1867 if(pNewEdge1->site[0] == pNewSite)
1868 pNewEdge1->next[2] = pNewEdge2;
1870 pNewEdge1->next[3] = pNewEdge2;
1872 if(pNewEdge2->site[0] == pNewSite)
1873 pNewEdge2->next[0] = pNewEdge1;
1875 pNewEdge2->next[1] = pNewEdge1;
1877 pEdge = pEdge->prev_edge;
1878 pNewEdge1 = pNewEdge2;
1880 pNewSite->edge[0] = pNewEdge1;
1881 pNewSite->node[1] = pNewEdge1->node[0];
1883 if(pSite->node1 == pSite->node2 && pSite != pSite->next_site && pNewEdge1->node[0] != pNewEdge1->node[1])
1885 cvFlushSeqWriter(&NodeWriter);
1886 // cvSetRemove((CvSet*)VoronoiDiagram,VoronoiDiagram->total-1);
1887 pNewSite->node[1] = pNewEdge1->node[0] = pNewSite->node[0];
1890 pNewSite_prev = pNewSite;
1891 pSite = pSite->next_site;
1892 }while(pSite != pFirstSite);
1893 pNewSite->node[1] = pNewEdge1->node[1];
1894 if(pSite == pSite->next_site)
1896 Node.pt.x = pSite->node1->node.x;
1897 Node.pt.y = pSite->node1->node.y;
1899 pNewSite->node[0] = pNewSite->node[1] = _cvWriteSeqElem(&Node,NodeWriter);
1902 cvEndWriteSeq(&SiteWriter);
1903 pNewSite = (CvVoronoiSite2D*)cvGetSetElem(CurrNewSiteSeq, 0);
1904 pNewSite->next[0] = pNewSite_prev;
1905 pNewSite_prev->next[1] = pNewSite;
1908 cvReleaseMemStorage(&(SiteSeq->storage));
1909 cvReleaseMemStorage(&(EdgeSeq->storage));
1910 cvReleaseMemStorage(&(NodeSeq->storage));
1912 if(NewSiteSeqPrev == NULL)
1913 VoronoiDiagram->sites = NewSiteSeq;
1916 NewSiteSeqPrev->h_next = (CvSeq*)NewSiteSeq;
1917 NewSiteSeq->h_prev = (CvSeq*)NewSiteSeqPrev;
1920 NewSiteSeqPrev = NewSiteSeq;
1922 }//end of _cvConvertSameOrientation
1924 static int _cvConvertChangeOrientation(CvVoronoiDiagram2D* VoronoiDiagram,
1925 CvVoronoiDiagramInt VoronoiDiagramInt,
1926 CvSet* &NewSiteSeqPrev,
1927 CvSeqWriter &NodeWriter,
1928 CvSeqWriter &EdgeWriter,
1929 CvMemStorage* VoronoiStorage)
1931 // pNewSite->edge[1] = pSite->edge2
1932 // pNewSite->edge[0] = pSite->edge1
1934 CvSeq* SiteSeq = VoronoiDiagramInt.SiteSeq;
1935 CvSeq* EdgeSeq = VoronoiDiagramInt.EdgeSeq;
1936 CvSeq* NodeSeq = VoronoiDiagramInt.NodeSeq;
1939 CvMemStorage *NewSiteStorage = cvCreateChildMemStorage(VoronoiStorage);
1940 CvSet *NewSiteSeq = NULL,*CurrNewSiteSeq = NULL, *PrevNewSiteSeq = NULL;;
1941 CvSeqWriter SiteWriter;
1943 CvVoronoiSite2D NewSite = {{0,0},{0,0},{0,0}},NewSite_prev = {{0,0},{0,0},{0,0}};
1944 CvVoronoiSite2D *pNewSite, *pNewSite_prev = &NewSite_prev;
1945 pCvVoronoiSite pSite,pFirstSite;
1947 CvVoronoiEdge2D NewEdge = {{0,0},{0,0},{0,0,0,0}};
1948 CvVoronoiEdge2D *pNewEdge1, *pNewEdge2;
1949 pCvVoronoiEdge pEdge;
1951 CvVoronoiNode2D* pNode1, *pNode2;
1952 CvVoronoiNode2D Node;
1953 Node.next_free = NULL;
1955 for(CvSeq* CurrSiteSeq = SiteSeq;\
1956 CurrSiteSeq != NULL;\
1957 CurrSiteSeq = NEXT_SEQ(CurrSiteSeq,SiteSeq))
1959 CurrNewSiteSeq = cvCreateSet(0,sizeof(CvSet),sizeof(CvVoronoiSite2D), NewSiteStorage);
1961 NewSiteSeq = PrevNewSiteSeq = CurrNewSiteSeq;
1962 else if(PrevNewSiteSeq->v_prev == NULL)
1964 PrevNewSiteSeq->v_next = (CvSeq*)CurrNewSiteSeq;
1965 CurrNewSiteSeq->v_prev = (CvSeq*)PrevNewSiteSeq;
1969 PrevNewSiteSeq->h_next = (CvSeq*)CurrNewSiteSeq;
1970 CurrNewSiteSeq->h_prev = (CvSeq*)PrevNewSiteSeq;
1971 CurrNewSiteSeq->v_prev = (CvSeq*)PrevNewSiteSeq->v_prev;
1973 PrevNewSiteSeq = CurrNewSiteSeq;
1975 pSite = (pCvVoronoiSite)cvGetSeqElem(CurrSiteSeq, 0);
1976 while(pSite->next_site->node1 == pSite->next_site->node2)\
1977 pSite = pSite->next_site;
1980 pNewSite_prev = &NewSite_prev;
1981 cvStartAppendToSeq((CvSeq*)CurrNewSiteSeq, &SiteWriter);
1984 pNewSite = _cvWriteSeqElem(&NewSite,SiteWriter);
1985 pNewSite->next[0] = pNewSite_prev;
1986 pNewSite_prev->next[1] = pNewSite;
1988 pEdge = pSite->edge2;
1989 if(!pEdge || !pEdge->node1 || !pEdge->node2)
1992 if(pEdge->site == NULL)
1994 pNewEdge1 = (CvVoronoiEdge2D*)pEdge->twin_edge;
1995 pNewEdge1->site[1] = pNewSite;
1996 pNewSite->node[0] = pNewEdge1->node[0];
2000 pNewEdge1 = _cvWriteSeqElem(&NewEdge,EdgeWriter);
2001 pNewEdge1->site[0] = pNewSite;
2003 pNode1 = _cvWriteSeqElem(&Node,NodeWriter);
2004 pNode2 = _cvWriteSeqElem(&Node,NodeWriter);
2005 pNode1->pt.x = pEdge->node1->node.x;
2006 pNode1->pt.y = pEdge->node1->node.y;
2007 pNode1->radius = pEdge->node1->radius;
2008 pNode2->pt.x = pEdge->node2->node.x;
2009 pNode2->pt.y = pEdge->node2->node.y;
2010 pNode2->radius = pEdge->node2->radius;
2011 pNewEdge1->node[0] = pNode2;
2012 pNewEdge1->node[1] = pNode1;
2014 pNewSite->node[0] = pNewEdge1->node[1];
2016 if(!pNewEdge1->node[0] || !pNewEdge1->node[1])
2018 pEdge->twin_edge->site = NULL;
2019 pEdge->twin_edge->twin_edge = (pCvVoronoiEdge)pNewEdge1;
2021 pNewSite->edge[1] = pNewEdge1;
2024 pEdge = pEdge->next_edge;
2025 while((pEdge != NULL && CurrSiteSeq->total>1) ||
2026 (pEdge != pSite->edge1 && CurrSiteSeq->total == 1))
2028 if(pEdge->site == NULL)
2030 pNewEdge2 = (CvVoronoiEdge2D*)pEdge->twin_edge;
2031 pNewEdge2->site[1] = pNewSite;
2032 if(CV_VORONOIEDGE2D_BEGINNODE(pNewEdge1,pNewSite) != pNewEdge2->node[0])
2034 cvFlushSeqWriter(&NodeWriter);
2035 // cvSetRemove((CvSet*)VoronoiDiagram,VoronoiDiagram->total-1);
2036 pNewEdge1->node[0] = pNewEdge2->node[0];
2041 pNewEdge2 = _cvWriteSeqElem(&NewEdge,EdgeWriter);
2042 pNewEdge2->site[0] = pNewSite;
2044 pNode2 = _cvWriteSeqElem(&Node,NodeWriter);
2045 pNode2->pt.x = pEdge->node2->node.x;
2046 pNode2->pt.y = pEdge->node2->node.y;
2047 pNode2->radius = pEdge->node2->radius;
2048 pNewEdge2->node[0] = pNode2;
2050 if(pNewEdge1->site[0] == pNewSite)
2051 pNewEdge2->node[1] = pNewEdge1->node[0];
2053 pNewEdge2->node[1] = pNewEdge1->node[1];
2055 if(!pNewEdge1->node[0] || !pNewEdge1->node[1])
2057 pEdge->twin_edge->site = NULL;
2058 pEdge->twin_edge->twin_edge = (pCvVoronoiEdge)pNewEdge2;
2060 if(pNewEdge1->site[0] == pNewSite)
2061 pNewEdge1->next[2] = pNewEdge2;
2063 pNewEdge1->next[3] = pNewEdge2;
2065 if(pNewEdge2->site[0] == pNewSite)
2066 pNewEdge2->next[0] = pNewEdge1;
2068 pNewEdge2->next[1] = pNewEdge1;
2070 pEdge = pEdge->next_edge;
2071 pNewEdge1 = pNewEdge2;
2073 pNewSite->edge[0] = pNewEdge1;
2074 pNewSite->node[1] = pNewEdge1->node[0];
2076 if(pSite->node1 == pSite->node2 && pSite != pSite->next_site && pNewEdge1->node[0] != pNewEdge1->node[1])
2078 cvFlushSeqWriter(&NodeWriter);
2079 // cvSetRemove((CvSet*)VoronoiDiagram,VoronoiDiagram->total-1);
2080 pNewSite->node[1] = pNewEdge1->node[0] = pNewSite->node[0];
2083 pNewSite_prev = pNewSite;
2084 pSite = pSite->prev_site;
2085 }while(pSite != pFirstSite);
2086 pNewSite->node[1] = pNewEdge1->node[1];
2087 if(pSite == pSite->next_site)
2089 Node.pt.x = pSite->node1->node.x;
2090 Node.pt.y = pSite->node1->node.y;
2092 pNewSite->node[0] = pNewSite->node[1] = _cvWriteSeqElem(&Node,NodeWriter);
2095 cvEndWriteSeq(&SiteWriter);
2096 pNewSite = (CvVoronoiSite2D*)cvGetSetElem(CurrNewSiteSeq, 0);
2097 pNewSite->next[0] = pNewSite_prev;
2098 pNewSite_prev->next[1] = pNewSite;
2101 cvReleaseMemStorage(&(SiteSeq->storage));
2102 cvReleaseMemStorage(&(EdgeSeq->storage));
2103 cvReleaseMemStorage(&(NodeSeq->storage));
2105 if(NewSiteSeqPrev == NULL)
2106 VoronoiDiagram->sites = NewSiteSeq;
2109 NewSiteSeqPrev->h_next = (CvSeq*)NewSiteSeq;
2110 NewSiteSeq->h_prev = (CvSeq*)NewSiteSeqPrev;
2112 NewSiteSeqPrev = NewSiteSeq;
2114 }//end of _cvConvert
2117 int _cvConstructExtSites(CvVoronoiDiagramInt* pVoronoiDiagram,
2122 const double angl_eps = 0.03;
2123 CvSeq* SiteSeq = pVoronoiDiagram->SiteSeq;
2124 CvSeq* NodeSeq = pVoronoiDiagram->NodeSeq;
2125 //CvSeq* DirectionSeq = pVoronoiDiagram->DirectionSeq;
2126 CvPointFloat Vertex1,Vertex2,Vertex3;
2127 CvLeePoint<T> VertexT1,VertexT2,VertexT3;
2129 CvSeqReader ContourReader;
2130 CvVoronoiSiteInt Site = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
2131 CvVoronoiSiteInt SiteTemp = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
2132 CvVoronoiNodeInt Node;
2133 pCvVoronoiNode pNode1,pNode2;
2134 pCvVoronoiSite pSite = &SiteTemp,pSite_prev = &SiteTemp;
2135 pCvVoronoiSite pReflexSite = NULL;
2136 int NReflexSite = 0;
2138 float delta_x_rc, delta_x_cl, delta_y_rc, delta_y_cl;
2139 float norm_cl,norm_rc, mult_cl_rc;
2143 if(orientation == 1)
2145 cvStartReadSeq(ContourSeq, &ContourReader,0);
2146 CV_READ_SEQ_ELEM(VertexT1,ContourReader);
2147 CV_READ_SEQ_ELEM(VertexT2,ContourReader);
2151 cvStartReadSeq(ContourSeq, &ContourReader,1);
2152 CV_REV_READ_SEQ_ELEM(VertexT1,ContourReader);
2153 CV_REV_READ_SEQ_ELEM(VertexT2,ContourReader);
2156 Vertex1.x = (float)VertexT1.x;
2157 Vertex1.y = (float)VertexT1.y;
2158 Vertex2.x = (float)VertexT2.x;
2159 Vertex2.y = (float)VertexT2.y;
2161 _cvInitVoronoiNode(&Node, &Vertex2);
2162 pNode1 = _cvSeqPush(NodeSeq, &Node);
2164 delta_x_cl = Vertex2.x - Vertex1.x;
2165 delta_y_cl = Vertex2.y - Vertex1.y;
2166 norm_cl = (float)sqrt((double)delta_x_cl*delta_x_cl + delta_y_cl*delta_y_cl);
2168 for( i = 0;i<ContourSeq->total;i++)
2170 if(orientation == 1)
2172 CV_READ_SEQ_ELEM(VertexT3,ContourReader);
2176 CV_REV_READ_SEQ_ELEM(VertexT3,ContourReader);
2179 Vertex3.x = (float)VertexT3.x;
2180 Vertex3.y = (float)VertexT3.y;
2182 _cvInitVoronoiNode(&Node, &Vertex3);
2183 pNode2 = _cvSeqPush(NodeSeq, &Node);
2185 delta_x_rc = Vertex3.x - Vertex2.x;
2186 delta_y_rc = Vertex3.y - Vertex2.y;
2187 norm_rc = (float)sqrt((double)delta_x_rc*delta_x_rc + delta_y_rc*delta_y_rc);
2191 mult_cl_rc = norm_cl*norm_rc;
2192 _sin = (delta_y_rc* delta_x_cl - delta_x_rc* delta_y_cl)/mult_cl_rc;
2193 _cos = -(delta_x_cl*delta_x_rc + delta_y_cl*delta_y_rc)/mult_cl_rc;
2195 if((_sin > angl_eps) || (_sin > 0 && _cos > 0))
2197 pSite = _cvSeqPush(SiteSeq, &Site);
2198 _cvInitVoronoiSite(pSite,pNode1,pNode2,pSite_prev);
2199 pSite_prev->next_site = pSite;
2201 else if((_sin < -angl_eps) || (_sin < 0 && _cos > 0))
2203 pSite = _cvSeqPush(SiteSeq, &Site);
2204 _cvInitVoronoiSite(pSite,pNode1,pNode1,pSite_prev);
2205 pReflexSite = pSite;
2207 pSite_prev->next_site = pSite;
2210 pSite = _cvSeqPush(SiteSeq, &Site);
2211 _cvInitVoronoiSite(pSite,pNode1,pNode2,pSite_prev);
2212 pSite_prev->next_site = pSite;
2217 delta_y_rc = delta_y_cl + delta_y_rc;
2218 delta_x_rc = delta_x_cl + delta_x_rc;
2219 pSite->node2 = pNode2;
2221 norm_rc = (float)sqrt((double)delta_y_rc*delta_y_rc + delta_x_rc*delta_x_rc);
2224 delta_y_cl= delta_y_rc;
2225 delta_x_cl= delta_x_rc;
2231 if(SiteTemp.next_site==NULL)
2234 if(ContourSeq->total - NReflexSite<2)
2237 if(SiteSeq->total<3)
2240 pSite->node2 = SiteTemp.next_site->node1;
2241 pSite->next_site = SiteTemp.next_site;
2242 SiteTemp.next_site->prev_site = pSite;
2245 if(pReflexSite!=NULL)
2246 for(i=0; i<SiteSeq->total; i++)
2248 if(pReflexSite->next_site->next_site->node1 !=
2249 pReflexSite->next_site->next_site->node2)
2252 pReflexSite = pReflexSite->next_site->next_site;
2254 pVoronoiDiagram->reflex_site = pReflexSite;
2255 return (i<SiteSeq->total);
2256 }//end of _cvConstructExtSites
2259 int _cvConstructIntSites(CvVoronoiDiagramInt* pVoronoiDiagram,
2261 CvSeq* CurrContourSeq,
2262 pCvVoronoiSite &pTopSite,
2266 const double angl_eps = 0.03;
2267 float min_x = (float)999999999;
2268 CvSeq* SiteSeq = CurrSiteSeq;
2269 CvSeq* NodeSeq = pVoronoiDiagram->NodeSeq;
2270 //CvSeq* DirectionSeq = pVoronoiDiagram->DirectionSeq;
2271 CvPointFloat Vertex1,Vertex2,Vertex3;
2272 CvLeePoint<T> VertexT1,VertexT2,VertexT3;
2274 CvSeqReader ContourReader;
2275 CvVoronoiSiteInt Site = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
2276 CvVoronoiSiteInt SiteTemp = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
2277 CvVoronoiNodeInt Node;
2278 pCvVoronoiNode pNode1,pNode2;
2279 pCvVoronoiSite pSite = &SiteTemp,pSite_prev = &SiteTemp;
2281 int NReflexSite = 0;
2283 if(CurrContourSeq->total == 1)
2285 cvStartReadSeq(CurrContourSeq, &ContourReader,0);
2286 CV_READ_SEQ_ELEM(VertexT1,ContourReader);
2287 Vertex1.x = (float)VertexT1.x;
2288 Vertex1.y = (float)VertexT1.y;
2290 _cvInitVoronoiNode(&Node, &Vertex1);
2291 pNode1 = _cvSeqPush(NodeSeq, &Node);
2292 pTopSite = pSite = _cvSeqPush(SiteSeq, &Site);
2293 _cvInitVoronoiSite(pSite,pNode1,pNode1,pSite);
2294 pSite->next_site = pSite;
2298 float delta_x_rc, delta_x_cl, delta_y_rc, delta_y_cl;
2299 float norm_cl,norm_rc, mult_cl_rc;
2303 if(orientation == 1)
2305 cvStartReadSeq(CurrContourSeq, &ContourReader,0);
2306 CV_READ_SEQ_ELEM(VertexT1,ContourReader);
2307 CV_READ_SEQ_ELEM(VertexT2,ContourReader);
2311 cvStartReadSeq(CurrContourSeq, &ContourReader,1);
2312 CV_REV_READ_SEQ_ELEM(VertexT1,ContourReader);
2313 CV_REV_READ_SEQ_ELEM(VertexT2,ContourReader);
2316 Vertex1.x = (float)VertexT1.x;
2317 Vertex1.y = (float)VertexT1.y;
2318 Vertex2.x = (float)VertexT2.x;
2319 Vertex2.y = (float)VertexT2.y;
2321 _cvInitVoronoiNode(&Node, &Vertex2);
2322 pNode1 = _cvSeqPush(NodeSeq, &Node);
2324 delta_x_cl = Vertex2.x - Vertex1.x;
2325 delta_y_cl = Vertex2.y - Vertex1.y;
2326 norm_cl = (float)sqrt((double)delta_x_cl*delta_x_cl + delta_y_cl*delta_y_cl);
2327 for( i = 0;i<CurrContourSeq->total;i++)
2329 if(orientation == 1)
2331 CV_READ_SEQ_ELEM(VertexT3,ContourReader);
2335 CV_REV_READ_SEQ_ELEM(VertexT3,ContourReader);
2337 Vertex3.x = (float)VertexT3.x;
2338 Vertex3.y = (float)VertexT3.y;
2340 _cvInitVoronoiNode(&Node, &Vertex3);
2341 pNode2 = _cvSeqPush(NodeSeq, &Node);
2343 delta_x_rc = Vertex3.x - Vertex2.x;
2344 delta_y_rc = Vertex3.y - Vertex2.y;
2345 norm_rc = (float)sqrt((double)delta_x_rc*delta_x_rc + delta_y_rc*delta_y_rc);
2349 mult_cl_rc = norm_cl*norm_rc;
2350 _sin = (delta_y_rc* delta_x_cl - delta_x_rc* delta_y_cl)/mult_cl_rc;
2351 _cos = -(delta_x_cl*delta_x_rc + delta_y_cl*delta_y_rc)/mult_cl_rc;
2352 if((_sin > angl_eps) || (_sin > 0 && _cos > 0))
2354 pSite = _cvSeqPush(SiteSeq, &Site);
2355 _cvInitVoronoiSite(pSite,pNode1,pNode2,pSite_prev);
2356 pSite_prev->next_site = pSite;
2358 else if((_sin < -angl_eps) || (_sin < 0 && _cos > 0) || (_sin == 0 && CurrContourSeq->total == 2))
2360 pSite = _cvSeqPush(SiteSeq, &Site);
2361 _cvInitVoronoiSite(pSite,pNode1,pNode1,pSite_prev);
2362 if(pNode1->node.x < min_x)
2364 min_x = pNode1->node.x;
2368 pSite_prev->next_site = pSite;
2371 pSite = _cvSeqPush(SiteSeq, &Site);
2372 _cvInitVoronoiSite(pSite,pNode1,pNode2,pSite_prev);
2373 pSite_prev->next_site = pSite;
2378 delta_y_rc = delta_y_cl + delta_y_rc;
2379 delta_x_rc = delta_x_cl + delta_x_rc;
2380 norm_rc = (float)sqrt((double)delta_y_rc*delta_y_rc + delta_x_rc*delta_x_rc);
2381 pSite->node2 = pNode2;
2386 delta_y_cl= delta_y_rc;
2387 delta_x_cl= delta_x_rc;
2393 if(SiteTemp.next_site==NULL)
2396 if((NReflexSite < 3 && CurrContourSeq->total > 2) || NReflexSite < 2)
2399 pSite->node2 = SiteTemp.next_site->node1;
2400 pSite->next_site = SiteTemp.next_site;
2401 SiteTemp.next_site->prev_site = pSite;
2404 }//end of _cvConstructIntSites
2406 static int _cvConstructExtChains(CvVoronoiDiagramInt* pVoronoiDiagram)
2408 CvSeq* SiteSeq = pVoronoiDiagram->SiteSeq;
2409 CvSeq* ChainSeq = pVoronoiDiagram->ChainSeq;
2411 CvVoronoiChainInt Chain;
2412 pCvVoronoiChain pChain,pChainFirst;
2413 pCvVoronoiSite pSite, pSite_prev, pSiteFirst,pReflexSite = pVoronoiDiagram->reflex_site;
2415 if(pReflexSite==NULL)
2416 pSite = pSiteFirst = (pCvVoronoiSite)cvGetSeqElem(SiteSeq, 0);
2419 while(pReflexSite->next_site->next_site->node1==
2420 pReflexSite->next_site->next_site->node2)
2421 pReflexSite = pReflexSite->next_site->next_site;
2423 pSite = pSiteFirst = pReflexSite->next_site;
2426 Chain.last_site = pSite;
2427 _cvConstructEdges(pSite,pVoronoiDiagram);
2429 pSite = pSite->prev_site;
2432 if(pSite->node1!=pSite->node2)
2434 Chain.first_site = pSite_prev;
2435 pChain = _cvSeqPushFront(ChainSeq,&Chain);
2437 _cvConstructEdges(pSite,pVoronoiDiagram);
2438 Chain.last_site = pSite;
2439 Chain.next_chain = pChain;
2443 pSite=pSite->prev_site;
2444 _cvConstructEdges(pSite,pVoronoiDiagram);
2445 _cvConstructEdges(pSite->next_site,pVoronoiDiagram);
2448 pSite = pSite->prev_site;
2449 }while(pSite!=pSiteFirst);
2451 Chain.first_site = pSite_prev;
2452 pChain = _cvSeqPushFront(ChainSeq,&Chain);
2453 pChainFirst = (pCvVoronoiChain)cvGetSeqElem(ChainSeq,ChainSeq->total - 1);
2454 pChainFirst->next_chain = pChain;
2455 if(ChainSeq->total < 3)
2459 }// end of _cvConstructExtChains
2461 static void _cvConstructIntChains(CvVoronoiDiagramInt* pVoronoiDiagram,
2462 CvSeq* CurrChainSeq,
2464 pCvVoronoiSite pTopSite)
2466 CvSeq* ChainSeq = CurrChainSeq;
2468 if(CurrSiteSeq->total == 1)
2471 CvVoronoiChainInt Chain = {NULL,NULL,NULL};
2472 pCvVoronoiChain pChain,pChainFirst;;
2473 pCvVoronoiSite pSite, pSite_prev, pSiteFirst;
2474 pSite = pSiteFirst = pTopSite->next_site;
2476 Chain.last_site = pSite;
2477 _cvConstructEdges(pSite,pVoronoiDiagram);
2479 pSite = pSite->prev_site;
2482 if(pSite->node1!=pSite->node2)
2484 Chain.first_site = pSite_prev;
2485 pChain = _cvSeqPushFront(ChainSeq,&Chain);
2487 _cvConstructEdges(pSite,pVoronoiDiagram);
2488 Chain.last_site = pSite;
2489 Chain.next_chain = pChain;
2493 pSite=pSite->prev_site;
2494 if(pSite != pSiteFirst)
2495 _cvConstructEdges(pSite,pVoronoiDiagram);
2496 _cvConstructEdges(pSite->next_site,pVoronoiDiagram);
2499 pSite = pSite->prev_site;
2500 }while(pSite!=pSiteFirst && pSite!= pSiteFirst->prev_site);
2502 if(pSite == pSiteFirst->prev_site && ChainSeq->total == 0)
2505 Chain.first_site = pSite_prev;
2506 if(pSite == pSiteFirst->prev_site)
2508 pChainFirst = (pCvVoronoiChain)cvGetSeqElem(ChainSeq,ChainSeq->total - 1);
2509 pChainFirst->last_site = Chain.last_site;
2510 pChainFirst->next_chain = Chain.next_chain;
2515 pChain = _cvSeqPushFront(ChainSeq,&Chain);
2516 pChainFirst = (pCvVoronoiChain)cvGetSeqElem(ChainSeq,ChainSeq->total - 1);
2517 pChainFirst->next_chain = pChain;
2520 }// end of _cvConstructIntChains
2522 CV_INLINE void _cvConstructEdges(pCvVoronoiSite pSite,CvVoronoiDiagramInt* pVoronoiDiagram)
2524 CvSeq* EdgeSeq = pVoronoiDiagram->EdgeSeq;
2525 CvSeq* DirectionSeq = pVoronoiDiagram->DirectionSeq;
2526 CvVoronoiEdgeInt Edge = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
2527 pCvVoronoiEdge pEdge1,pEdge2;
2528 CvDirection EdgeDirection,SiteDirection;
2532 if(pSite->node1!=pSite->node2)
2534 SiteDirection.x = pSite->node2->node.x - pSite->node1->node.x;
2535 SiteDirection.y = pSite->node2->node.y - pSite->node1->node.y;
2536 site_lengh = (float)sqrt((double)SiteDirection.x*SiteDirection.x + SiteDirection.y * SiteDirection.y);
2537 SiteDirection.x /= site_lengh;
2538 SiteDirection.y /= site_lengh;
2539 EdgeDirection.x = -SiteDirection.y;
2540 EdgeDirection.y = SiteDirection.x;
2541 Edge.direction = _cvSeqPush(DirectionSeq,&EdgeDirection);
2542 pSite->direction = _cvSeqPush(DirectionSeq,&SiteDirection);
2544 pEdge1 = _cvSeqPush(EdgeSeq,&Edge);
2545 pEdge2 = _cvSeqPush(EdgeSeq,&Edge);
2549 pCvVoronoiSite pSite_prev = pSite->prev_site;
2550 pCvVoronoiSite pSite_next = pSite->next_site;
2552 pEdge1 = _cvSeqPush(EdgeSeq,&Edge);
2553 pEdge2 = _cvSeqPush(EdgeSeq,&Edge);
2555 pEdge2->direction = pSite_next->edge1->direction;
2556 pEdge2->twin_edge = pSite_next->edge1;
2557 pSite_next->edge1->twin_edge = pEdge2;
2559 pEdge1->direction = pSite_prev->edge2->direction;
2560 pEdge1->twin_edge = pSite_prev->edge2;
2561 pSite_prev->edge2->twin_edge = pEdge1;
2564 pEdge2->node1 = pSite->node2;
2565 pEdge1->node2 = pSite->node1;
2566 pSite->edge1 = pEdge1;
2567 pSite->edge2 = pEdge2;
2568 pEdge2->next_edge = pEdge1;
2569 pEdge1->prev_edge = pEdge2;
2570 }// end of _cvConstructEdges
2572 static int _cvConstructExtVD(CvVoronoiDiagramInt* pVoronoiDiagram)
2574 pCvVoronoiSite pSite_right = 0,pSite_left = 0;
2575 pCvVoronoiEdge pEdge_left,pEdge_right;
2576 pCvVoronoiChain pChain1, pChain2;
2578 pChain1 = (pCvVoronoiChain)cvGetSeqElem(pVoronoiDiagram->ChainSeq,0);
2581 pChain2 = pChain1->next_chain;
2582 if(pChain2->next_chain==pChain1)
2584 pSite_right = pChain1->first_site;
2585 pSite_left = pChain2->last_site;
2586 pEdge_left = pSite_left->edge2->next_edge;
2587 pEdge_right = pSite_right->edge1->prev_edge;
2588 pEdge_left->prev_edge = NULL;
2589 pEdge_right->next_edge = NULL;
2590 pSite_right->edge1 = NULL;
2591 pSite_left->edge2 = NULL;
2594 if(!_cvJoinChains(pChain1,pChain2,pVoronoiDiagram))
2597 pChain1->last_site = pChain2->last_site;
2598 pChain1->next_chain = pChain2->next_chain;
2599 pChain1 = pChain1->next_chain;
2600 }while(pChain1->next_chain != pChain1);
2602 pCvVoronoiNode pEndNode = pSite_left->node2;
2603 if(pSite_right->edge1==NULL)
2606 pSite_right->edge1->node2 = pEndNode;
2608 if(pSite_left->edge2==NULL)
2611 pSite_left->edge2->node1 = pEndNode;
2614 }//end of _cvConstructExtVD
2616 static int _cvJoinChains(pCvVoronoiChain pChain1,
2617 pCvVoronoiChain pChain2,
2618 CvVoronoiDiagramInt* pVoronoiDiagram)
2620 const double dist_eps = 0.05;
2621 if(pChain1->first_site == NULL || pChain1->last_site == NULL ||
2622 pChain2->first_site == NULL || pChain2->last_site == NULL)
2625 CvVoronoiEdgeInt EdgeNULL = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
2627 CvSeq* NodeSeq = pVoronoiDiagram->NodeSeq;
2628 CvSeq* EdgeSeq = pVoronoiDiagram->EdgeSeq;
2630 pCvVoronoiSite pSite_left = pChain1->last_site;
2631 pCvVoronoiSite pSite_right = pChain2->first_site;
2633 pCvVoronoiEdge pEdge_left = pSite_left->edge2->next_edge;
2634 pCvVoronoiEdge pEdge_right = pSite_right->edge1->prev_edge;
2636 pCvVoronoiEdge pEdge_left_cur = pEdge_left;
2637 pCvVoronoiEdge pEdge_right_cur = pEdge_right;
2639 pCvVoronoiEdge pEdge_left_prev = NULL;
2640 pCvVoronoiEdge pEdge_right_next = NULL;
2642 pCvVoronoiNode pNode_siteleft = pChain1->first_site->node1;
2643 pCvVoronoiNode pNode_siteright = pChain2->last_site->node2;
2644 /*CvVoronoiSiteInt Site_left_chain = {pNode_siteleft,pNode_siteleft,NULL,NULL,NULL,NULL};
2645 CvVoronoiSiteInt Site_right_chain = {pNode_siteright,pNode_siteright,NULL,NULL,NULL,NULL};*/
2647 pCvVoronoiEdge pEdge1,pEdge2;
2648 CvPointFloat Point1 = {0,0}, Point2 = {0,0};
2650 float radius1,radius2,dist1,dist2;
2651 bool left = true,right = true;
2653 CvVoronoiNodeInt Node;
2654 pCvVoronoiNode pNode_begin = pSite_left->node2;
2656 pEdge1 = pSite_left->edge2;
2657 pEdge1->node2 = NULL;
2658 pEdge2 = pSite_right->edge1;
2659 pEdge2->node1 = NULL;
2665 pEdge1->node1 = pNode_begin;
2667 pEdge2->node2 = pNode_begin;
2669 pEdge_left = pEdge_left_cur;
2670 pEdge_right = pEdge_right_cur;
2674 _cvCalcEdge(pSite_left,pSite_right,pEdge1,pVoronoiDiagram);
2675 _cvMakeTwinEdge(pEdge2,pEdge1);
2676 _cvStickEdgeLeftBegin(pEdge1,pEdge_left_prev,pSite_left);
2677 _cvStickEdgeRightBegin(pEdge2,pEdge_right_next,pSite_right);
2681 _cvCalcEdge(pNode_siteleft,pSite_right,pEdge2,pVoronoiDiagram);
2682 _cvStickEdgeRightBegin(pEdge2,pEdge_right_next,pSite_right);
2686 _cvCalcEdge(pSite_left,pNode_siteright,pEdge1,pVoronoiDiagram);
2687 _cvStickEdgeLeftBegin(pEdge1,pEdge_left_prev,pSite_left);
2691 radius1 = -1; radius2 = -2;
2693 while(pEdge_left!=NULL)
2695 if(pEdge_left->node2 == NULL)
2697 pEdge_left_cur = pEdge_left = pEdge_left->next_edge;
2698 if(pEdge_left == NULL)
2703 dist1 = _cvCalcEdgeIntersection(pEdge1, pEdge_left, &Point1,radius1);
2705 dist1 = _cvCalcEdgeIntersection(pEdge2, pEdge_left, &Point1,radius1);
2710 pEdge_left = pEdge_left->next_edge;
2713 while(pEdge_right!=NULL)
2715 if(pEdge_right->node1 == NULL)
2717 pEdge_right_cur = pEdge_right = pEdge_right->prev_edge;
2718 if(pEdge_right == NULL)
2723 dist2 = _cvCalcEdgeIntersection(pEdge1, pEdge_right, &Point2, radius2);
2725 dist2 = _cvCalcEdgeIntersection(pEdge2, pEdge_right, &Point2, radius2);
2730 pEdge_right = pEdge_right->prev_edge;
2733 if(dist1<0&&dist2<0)
2737 pEdge_left = pSite_left->edge1;
2738 if(pEdge_left==NULL)
2739 _cvStickEdgeLeftEnd(pEdge1,NULL,pSite_left);
2742 while(pEdge_left->node1!=NULL
2743 &&pEdge_left->node1==pEdge_left->prev_edge->node2)
2745 pEdge_left = pEdge_left->prev_edge;
2746 if(pEdge_left==NULL || pEdge_left->prev_edge == NULL)
2749 _cvStickEdgeLeftEnd(pEdge1,pEdge_left,pSite_left);
2754 pEdge_right = pSite_right->edge2;
2755 if(pEdge_right==NULL)
2756 _cvStickEdgeRightEnd(pEdge2,NULL,pSite_right);
2759 while(pEdge_right->node2!=NULL
2760 && pEdge_right->node2==pEdge_right->next_edge->node1)
2762 pEdge_right = pEdge_right->next_edge;
2763 if(pEdge_right==NULL || pEdge_right->next_edge == NULL )
2766 _cvStickEdgeRightEnd(pEdge2,pEdge_right,pSite_right);
2772 if(fabs(dist1 - dist2)<dist_eps)
2774 pNode_begin = _cvSeqPush(NodeSeq,&Node);
2775 _cvInitVoronoiNode(pNode_begin, &Point2,radius2);
2777 pEdge1->node2 = pNode_begin;
2778 pEdge2->node1 = pNode_begin;
2780 _cvStickEdgeLeftEnd(pEdge1,pEdge_left,pSite_left);
2781 _cvTwinNULLLeft(pEdge_left_cur,pEdge_left);
2783 _cvStickEdgeRightEnd(pEdge2,pEdge_right,pSite_right);
2784 _cvTwinNULLRight(pEdge_right_cur,pEdge_right);
2786 if(pEdge_left->twin_edge!=NULL&&pEdge_right->twin_edge!=NULL)
2788 pEdge_left_prev = pEdge_left->twin_edge;
2789 if(!pEdge_left_prev)
2791 pEdge_left_cur = pEdge_left_prev->next_edge;
2792 pEdge_right_next = pEdge_right->twin_edge;
2793 if(!pEdge_right_next)
2795 pEdge_right_cur = pEdge_right_next->prev_edge;
2796 pSite_right = pEdge_right_next->site;
2797 pEdge2 = _cvSeqPush(EdgeSeq, &EdgeNULL);
2798 pSite_left = pEdge_left_prev->site;
2799 pEdge1 = _cvSeqPush(EdgeSeq, &EdgeNULL);
2803 if(pEdge_left->twin_edge==NULL&&pEdge_right->twin_edge!=NULL)
2805 pEdge_right_next = pEdge_right->twin_edge;
2806 if(!pEdge_right_next)
2808 pEdge_right_cur = pEdge_right_next->prev_edge;
2809 pSite_right = pEdge_right_next->site;
2810 pEdge2 = _cvSeqPush(EdgeSeq, &EdgeNULL);
2811 pEdge_left_cur = NULL;
2816 if(pEdge_left->twin_edge!=NULL&&pEdge_right->twin_edge==NULL)
2818 pEdge_left_prev = pEdge_left->twin_edge;
2819 if(!pEdge_left_prev)
2821 pEdge_left_cur = pEdge_left_prev->next_edge;
2822 pSite_left = pEdge_left_prev->site;
2823 pEdge1 = _cvSeqPush(EdgeSeq, &EdgeNULL);
2824 pEdge_right_cur = NULL;
2828 if(pEdge_left->twin_edge==NULL&&pEdge_right->twin_edge==NULL)
2832 if((dist1<dist2&&dist1>=0)||(dist1>=0&&dist2<0))
2835 pNode_begin = _cvSeqPush(NodeSeq,&Node);
2836 _cvInitVoronoiNode(pNode_begin, &Point1,radius1);
2837 pEdge1->node2 = pNode_begin;
2838 _cvTwinNULLLeft(pEdge_left_cur,pEdge_left);
2839 _cvStickEdgeLeftEnd(pEdge1,pEdge_left,pSite_left);
2842 pEdge2->node1 = pNode_begin;
2843 pEdge_right_next = pEdge2;
2844 pEdge2 = _cvSeqPush(EdgeSeq, &EdgeNULL);
2845 if(pEdge_left->twin_edge!=NULL)
2847 pEdge_left_prev = pEdge_left->twin_edge;
2848 if(!pEdge_left_prev)
2850 pEdge_left_cur = pEdge_left_prev->next_edge;
2851 pSite_left = pEdge_left_prev->site;
2852 pEdge1 = _cvSeqPush(EdgeSeq, &EdgeNULL);
2857 pEdge_left_cur = NULL;
2864 if(pEdge_left->twin_edge!=NULL)
2866 pEdge_left_prev = pEdge_left->twin_edge;
2867 if(!pEdge_left_prev)
2869 pEdge_left_cur = pEdge_left_prev->next_edge;
2870 pSite_left = pEdge_left_prev->site;
2871 pEdge1 = _cvSeqPush(EdgeSeq, &EdgeNULL);
2881 if((dist1>dist2&&dist2>=0)||(dist1<0&&dist2>=0))
2883 pNode_begin = _cvSeqPush(NodeSeq,&Node);
2884 _cvInitVoronoiNode(pNode_begin, &Point2,radius2);
2885 pEdge2->node1 = pNode_begin;
2886 _cvTwinNULLRight(pEdge_right_cur,pEdge_right);
2887 _cvStickEdgeRightEnd(pEdge2,pEdge_right,pSite_right);
2890 pEdge1->node2 = pNode_begin;
2891 pEdge_left_prev = pEdge1;
2892 pEdge1 = _cvSeqPush(EdgeSeq, &EdgeNULL);
2893 if(pEdge_right->twin_edge!=NULL)
2895 pEdge_right_next = pEdge_right->twin_edge;
2896 if(!pEdge_right_next)
2898 pEdge_right_cur = pEdge_right_next->prev_edge;
2899 pSite_right = pEdge_right_next->site;
2900 pEdge2 = _cvSeqPush(EdgeSeq, &EdgeNULL);
2905 pEdge_right_cur = NULL;
2912 if(pEdge_right->twin_edge!=NULL)
2914 pEdge_right_next = pEdge_right->twin_edge;
2915 if(!pEdge_right_next)
2917 pEdge_right_cur = pEdge_right_next->prev_edge;
2918 pSite_right = pEdge_right_next->site;
2919 pEdge2 = _cvSeqPush(EdgeSeq, &EdgeNULL);
2929 }// end of _cvJoinChains
2931 static void _cvFindNearestSite(CvVoronoiDiagramInt* pVoronoiDiagram)
2933 pCvVoronoiHole pCurrHole, pHole = pVoronoiDiagram->top_hole;
2934 pCvPointFloat pTopPoint,pPoint1,pPoint2;
2935 CvPointFloat Direction;
2936 pCvVoronoiSite pSite;
2937 CvVoronoiNodeInt Node;
2939 float min_distance,distance;
2941 for(;pHole != NULL; pHole = pHole->next_hole)
2945 pTopPoint = &pHole->site_top->node1->node;
2947 CurrSeq = pVoronoiDiagram->SiteSeq;
2948 min_distance = (float)3e+34;
2949 while(pCurrHole != pHole)
2951 if(pCurrHole && pCurrHole->error)
2953 pSite = (pCvVoronoiSite)cvGetSeqElem(CurrSeq,0);
2954 if(CurrSeq->total == 1)
2956 distance = _cvCalcDist(pTopPoint, pSite);
2957 if(distance < min_distance)
2959 min_distance = distance;
2960 pHole->site_nearest = pSite;
2965 for(i = 0; i < CurrSeq->total;i++, pSite = pSite->next_site)
2967 if(pSite->node1 != pSite->node2)
2969 pPoint1 = &pSite->node1->node;
2970 pPoint2 = &pSite->node2->node;
2972 Direction.x = -pSite->direction->y;
2973 Direction.y = pSite->direction->x;
2976 (pTopPoint->x - pPoint2->x)*Direction.y -
2977 (pTopPoint->y - pPoint2->y)*Direction.x > 0
2979 (pTopPoint->x - pPoint1->x)*Direction.y -
2980 (pTopPoint->y - pPoint1->y)*Direction.x < 0
2982 (pTopPoint->x - pPoint1->x)*pSite->direction->y -
2983 (pTopPoint->y - pPoint1->y)*pSite->direction->x > 0
2987 distance = _cvCalcDist(pTopPoint, pSite);
2991 pPoint1 = &pSite->node1->node;
2993 (pTopPoint->x - pPoint1->x)*pSite->edge2->direction->y -
2994 (pTopPoint->y - pPoint1->y)*pSite->edge2->direction->x > 0
2996 (pTopPoint->x - pPoint1->x)*pSite->edge1->direction->y -
2997 (pTopPoint->y - pPoint1->y)*pSite->edge1->direction->x < 0
3001 distance = _cvCalcDist(pTopPoint, pSite);
3005 if(distance < min_distance)
3007 min_distance = distance;
3008 pHole->site_nearest = pSite;
3013 if(pCurrHole == NULL)
3014 pCurrHole = pVoronoiDiagram->top_hole;
3016 pCurrHole = pCurrHole->next_hole;
3018 CurrSeq = pCurrHole->SiteSeq;
3020 pHole->x_coord = min_distance;
3022 if(pHole->site_nearest->node1 == pHole->site_nearest->node2)
3024 Direction.x = (pHole->site_nearest->node1->node.x - pHole->site_top->node1->node.x)/2;
3025 Direction.y = (pHole->site_nearest->node1->node.y - pHole->site_top->node1->node.y)/2;
3030 Direction.x = pHole->site_nearest->direction->y * min_distance / 2;
3031 Direction.y = - pHole->site_nearest->direction->x * min_distance / 2;
3034 Node.node.x = pHole->site_top->node1->node.x + Direction.x;
3035 Node.node.y = pHole->site_top->node1->node.y + Direction.y;
3036 pHole->node = _cvSeqPush(pVoronoiDiagram->NodeSeq, &Node);
3038 }//end of _cvFindNearestSite
3040 static void _cvConstructIntVD(CvVoronoiDiagramInt* pVoronoiDiagram)
3042 pCvVoronoiChain pChain1, pChain2;
3043 pCvVoronoiHole pHole;
3046 pHole = pVoronoiDiagram->top_hole;
3048 for(;pHole != NULL; pHole = pHole->next_hole)
3050 if(pHole->ChainSeq->total == 0)
3052 pChain1 = (pCvVoronoiChain)cvGetSeqElem(pHole->ChainSeq,0);
3053 for(i = pHole->ChainSeq->total; i > 0;i--)
3055 pChain2 = pChain1->next_chain;
3056 if(!_cvJoinChains(pChain1,pChain2,pVoronoiDiagram))
3058 pHole->error = true;
3062 pChain1->last_site = pChain2->last_site;
3063 pChain1->next_chain = pChain2->next_chain;
3064 pChain1 = pChain1->next_chain;
3067 }// end of _cvConstructIntVD
3069 static int _cvFindOppositSiteCW(pCvVoronoiHole pHole, CvVoronoiDiagramInt* pVoronoiDiagram)
3071 pCvVoronoiSite pSite_left = pHole->site_nearest;
3072 pCvVoronoiSite pSite_right = pHole->site_top;
3073 pCvVoronoiNode pNode = pHole->node;
3075 CvDirection Direction = {-1,0};
3076 CvVoronoiEdgeInt Edge_right = {NULL,pSite_right->node1,pSite_right,NULL,NULL,NULL,NULL,&Direction};
3078 pCvVoronoiEdge pEdge_left = pSite_left->edge2->next_edge;
3079 pCvVoronoiEdge pEdge_right = &Edge_right;
3081 CvVoronoiEdgeInt Edge = {NULL,pNode,pSite_right,NULL,NULL,NULL,NULL,NULL};
3082 CvVoronoiEdgeInt Edge_cur = {NULL,NULL, NULL, NULL,NULL,NULL,NULL,NULL};
3083 pCvVoronoiEdge pEdge = &Edge;
3085 float radius1, radius2,dist1, dist2;
3086 CvPointFloat Point1 = {0,0}, Point2 = {0,0};
3090 pEdge->direction = NULL;
3091 pEdge->parabola = NULL;
3092 _cvCalcEdge(pSite_left,pSite_right,pEdge,pVoronoiDiagram);
3095 radius1 = -1; radius2 = -2;
3096 while(pEdge_left!=NULL)
3098 dist1 = _cvCalcEdgeIntersection(pEdge, pEdge_left, &Point1,radius1);
3101 pEdge_left = pEdge_left->next_edge;
3104 dist2 = _cvCalcEdgeIntersection(pEdge, pEdge_right, &Point2, radius2);
3105 if(dist2>=0 && dist1 >= dist2)
3107 pHole->site_opposite = pSite_left;
3108 pNode->node = Point2;
3115 Edge_cur = *pEdge_left->twin_edge;
3116 Edge_cur.node1 = pNode;
3117 pEdge_left = &Edge_cur;
3119 pSite_left = pEdge_left->site;
3120 pNode->node = Point1;
3122 }//end of _cvFindOppositSiteCW
3124 static int _cvFindOppositSiteCCW(pCvVoronoiHole pHole,CvVoronoiDiagramInt* pVoronoiDiagram)
3126 pCvVoronoiSite pSite_right = pHole->site_nearest;
3127 pCvVoronoiSite pSite_left = pHole->site_top;
3128 pCvVoronoiNode pNode = pHole->node;
3130 CvDirection Direction = {-1,0};
3131 CvVoronoiEdgeInt Edge_left = {pSite_left->node1,NULL,pSite_left,NULL,NULL,NULL, NULL, &Direction};
3133 pCvVoronoiEdge pEdge_left = &Edge_left;
3134 pCvVoronoiEdge pEdge_right = pSite_right->edge1->prev_edge;
3136 CvVoronoiEdgeInt Edge = {NULL,pNode,pSite_left,NULL,NULL,NULL,NULL,NULL};
3137 CvVoronoiEdgeInt Edge_cur = {NULL,NULL, NULL, NULL,NULL,NULL,NULL,NULL};
3138 pCvVoronoiEdge pEdge = &Edge;
3140 double dist1, dist2;
3141 float radius1, radius2;
3142 CvPointFloat Point1 = {0,0}, Point2 = {0,0};
3146 pEdge->direction = NULL;
3147 pEdge->parabola = NULL;
3148 _cvCalcEdge(pSite_left,pSite_right,pEdge,pVoronoiDiagram);
3151 radius1 = -1; radius2 = -2;
3152 while(pEdge_right!=NULL)
3154 dist1 = _cvCalcEdgeIntersection(pEdge, pEdge_right, &Point1,radius2);
3157 pEdge_right = pEdge_right->prev_edge;
3160 dist2 = _cvCalcEdgeIntersection(pEdge, pEdge_left, &Point2, radius1);
3161 if(dist2>=0 && dist1 > dist2)
3163 pHole->site_opposite = pSite_right;
3164 pNode->node = Point2;
3171 Edge_cur = *pEdge_right->twin_edge;
3172 Edge_cur.node2 = pNode;
3173 pEdge_right = &Edge_cur;
3175 pSite_right = pEdge_right->site;
3176 pNode->node = Point1;
3178 }//end of _cvFindOppositSiteCCW
3180 static int _cvMergeVD(pCvVoronoiHole pHole,CvVoronoiDiagramInt* pVoronoiDiagram)
3182 pCvVoronoiSite pSite_left_first = pHole->site_top;
3183 pCvVoronoiSite pSite_right_first = pHole->site_opposite;
3184 pCvVoronoiNode pNode_begin = pHole->node;
3185 if(pSite_left_first == NULL || pSite_right_first == NULL || pNode_begin == NULL)
3188 pCvVoronoiSite pSite_left = pSite_left_first;
3189 pCvVoronoiSite pSite_right = pSite_right_first;
3191 const double dist_eps = 0.05;
3192 CvVoronoiEdgeInt EdgeNULL = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
3194 CvSeq* NodeSeq = pVoronoiDiagram->NodeSeq;
3195 CvSeq* EdgeSeq = pVoronoiDiagram->EdgeSeq;
3197 pCvVoronoiEdge pEdge_left = NULL;
3198 if(pSite_left->edge2 != NULL)
3199 pEdge_left = pSite_left->edge2->next_edge;
3201 pCvVoronoiEdge pEdge_right = pSite_right->edge1;
3202 pCvVoronoiEdge pEdge_left_cur = pEdge_left;
3203 pCvVoronoiEdge pEdge_right_cur = pEdge_right;
3205 pCvVoronoiEdge pEdge_left_prev = NULL;
3206 pCvVoronoiEdge pEdge_right_next = NULL;
3208 pCvVoronoiEdge pEdge1,pEdge2,pEdge1_first, pEdge2_first;
3209 CvPointFloat Point1 = {0,0}, Point2 = {0,0};
3211 float radius1,radius2,dist1,dist2;
3213 CvVoronoiNodeInt Node;
3215 pEdge1_first = pEdge1 = _cvSeqPush(EdgeSeq, &EdgeNULL);;
3216 pEdge2_first = pEdge2 = _cvSeqPush(EdgeSeq, &EdgeNULL);;
3217 pEdge1->site = pSite_left_first;
3218 pEdge2->site = pSite_right_first;
3222 pEdge1->node1 = pEdge2->node2 = pNode_begin;
3224 pEdge_left = pEdge_left_cur;
3225 pEdge_right = pEdge_right_cur->prev_edge;
3227 _cvCalcEdge(pSite_left,pSite_right,pEdge1,pVoronoiDiagram);
3228 _cvMakeTwinEdge(pEdge2,pEdge1);
3230 if(pEdge_left_prev != NULL)
3231 _cvStickEdgeLeftBegin(pEdge1,pEdge_left_prev,pSite_left);
3232 if(pEdge_right_next != NULL)
3233 _cvStickEdgeRightBegin(pEdge2,pEdge_right_next,pSite_right);
3236 radius1 = -1; radius2 = -2;
3239 while(pEdge_left!=NULL)
3241 if(pEdge_left->node2 == NULL)
3242 pEdge_left_cur = pEdge_left = pEdge_left->next_edge;
3244 dist1 = _cvCalcEdgeIntersection(pEdge1, pEdge_left, &Point1,radius1);
3247 pEdge_left = pEdge_left->next_edge;
3251 while(pEdge_right!=NULL)
3253 dist2 = _cvCalcEdgeIntersection(pEdge1, pEdge_right, &Point2,radius2);
3255 goto RESULTHANDLING;
3257 pEdge_right = pEdge_right->prev_edge;
3259 pEdge_right = pEdge_right_cur;
3260 dist2 = _cvCalcEdgeIntersection(pEdge1, pEdge_right, &Point2, radius2);
3263 if(dist1<0&&dist2<0)
3266 if(fabs(dist1 - dist2)<dist_eps)
3268 pNode_begin = _cvSeqPush(NodeSeq,&Node);
3269 _cvInitVoronoiNode(pNode_begin, &Point2,radius2);
3271 pEdge1->node2 = pNode_begin;
3272 pEdge2->node1 = pNode_begin;
3274 pEdge_right_cur = _cvDivideRightEdge(pEdge_right,pNode_begin,EdgeSeq);
3276 _cvStickEdgeLeftEnd(pEdge1,pEdge_left,pSite_left);
3277 _cvStickEdgeRightEnd(pEdge2,pEdge_right,pSite_right);
3279 pEdge_left_prev = pEdge_left->twin_edge;
3280 if(!pEdge_left_prev)
3282 pEdge_left_cur = pEdge_left_prev->next_edge;
3283 pSite_left = pEdge_left_prev->site;
3284 pEdge1 = _cvSeqPush(EdgeSeq, &EdgeNULL);
3286 pEdge_right_next = pEdge_right->twin_edge;
3287 if(!pEdge_right_next)
3289 pSite_right = pEdge_right_next->site;
3290 pEdge2 = _cvSeqPush(EdgeSeq, &EdgeNULL);
3295 if((dist1<dist2&&dist1>=0)||(dist1>=0&&dist2<0))
3297 pNode_begin = _cvSeqPush(NodeSeq,&Node);
3298 _cvInitVoronoiNode(pNode_begin, &Point1,radius1);
3300 pEdge1->node2 = pNode_begin;
3301 _cvStickEdgeLeftEnd(pEdge1,pEdge_left,pSite_left);
3303 pEdge2->node1 = pNode_begin;
3304 pEdge_right_next = pEdge2;
3305 pEdge2 = _cvSeqPush(EdgeSeq, &EdgeNULL);
3307 pEdge_left_prev = pEdge_left->twin_edge;
3308 if(!pEdge_left_prev)
3310 pEdge_left_cur = pEdge_left_prev->next_edge;
3311 pSite_left = pEdge_left_prev->site;
3312 pEdge1 = _cvSeqPush(EdgeSeq, &EdgeNULL);
3317 if((dist1>dist2&&dist2>=0)||(dist1<0&&dist2>=0))
3319 pNode_begin = _cvSeqPush(NodeSeq,&Node);
3320 _cvInitVoronoiNode(pNode_begin, &Point2,radius2);
3322 pEdge_right_cur = _cvDivideRightEdge(pEdge_right,pNode_begin,EdgeSeq);
3324 pEdge2->node1 = pNode_begin;
3325 _cvStickEdgeRightEnd(pEdge2,pEdge_right,pSite_right);
3327 pEdge1->node2 = pNode_begin;
3328 pEdge_left_prev = pEdge1;
3329 pEdge1 = _cvSeqPush(EdgeSeq, &EdgeNULL);
3331 pEdge_right_next = pEdge_right->twin_edge;
3332 if(!pEdge_right_next)
3334 pSite_right = pEdge_right_next->site;
3335 pEdge2 = _cvSeqPush(EdgeSeq, &EdgeNULL);
3340 }while(!(pSite_left == pSite_left_first && pSite_right == pSite_right_first));
3342 pEdge1_first->node1 = pNode_begin;
3343 pEdge2_first->node2 = pNode_begin;
3344 _cvStickEdgeLeftBegin(pEdge1_first,pEdge_left_prev,pSite_left_first);
3345 _cvStickEdgeRightBegin(pEdge2_first,pEdge_right_next,pSite_right_first);
3347 if(pSite_left_first->edge2 == NULL)
3348 pSite_left_first->edge2 = pSite_left_first->edge1 = pEdge1_first;
3350 }// end of _cvMergeVD
3353 /* ///////////////////////////////////////////////////////////////////////////////////////
3354 // Computation of bisectors //
3355 /////////////////////////////////////////////////////////////////////////////////////// */
3357 void _cvCalcEdge(pCvVoronoiSite pSite_left,
3358 pCvVoronoiSite pSite_right,
3359 pCvVoronoiEdge pEdge,
3360 CvVoronoiDiagramInt* pVoronoiDiagram)
3362 if((pSite_left->node1!=pSite_left->node2)&&
3363 (pSite_right->node1!=pSite_right->node2))
3364 _cvCalcEdgeLL(pSite_left->direction,
3365 pSite_right->direction,
3366 pEdge,pVoronoiDiagram);
3368 else if((pSite_left->node1!=pSite_left->node2)&&
3369 (pSite_right->node1 == pSite_right->node2))
3370 _cvCalcEdgeLP(pSite_left,pSite_right->node1,pEdge,pVoronoiDiagram);
3372 else if((pSite_left->node1==pSite_left->node2)&&
3373 (pSite_right->node1!=pSite_right->node2))
3374 _cvCalcEdgePL(pSite_left->node1,pSite_right,pEdge,pVoronoiDiagram);
3377 _cvCalcEdgePP(&(pSite_left->node1->node),
3378 &(pSite_right->node1->node),
3379 pEdge,pVoronoiDiagram);
3380 }//end of _cvCalcEdge
3382 void _cvCalcEdge(pCvVoronoiSite pSite,
3383 pCvVoronoiNode pNode,
3384 pCvVoronoiEdge pEdge,
3385 CvVoronoiDiagramInt* pVoronoiDiagram)
3387 if(pSite->node1!=pSite->node2)
3388 _cvCalcEdgeLP(pSite, pNode, pEdge,pVoronoiDiagram);
3390 _cvCalcEdgePP(&(pSite->node1->node),
3392 pEdge,pVoronoiDiagram);
3393 }//end of _cvCalcEdge
3395 void _cvCalcEdge(pCvVoronoiNode pNode,
3396 pCvVoronoiSite pSite,
3397 pCvVoronoiEdge pEdge,
3398 CvVoronoiDiagramInt* pVoronoiDiagram)
3400 if(pSite->node1!=pSite->node2)
3401 _cvCalcEdgePL(pNode,pSite,pEdge,pVoronoiDiagram);
3403 _cvCalcEdgePP(&pNode->node,&pSite->node1->node,pEdge,pVoronoiDiagram);
3404 }//end of _cvCalcEdge
3407 void _cvCalcEdgeLL(pCvDirection pDirection1,
3408 pCvDirection pDirection2,
3409 pCvVoronoiEdge pEdge,
3410 CvVoronoiDiagramInt* pVoronoiDiagram)
3412 CvDirection Direction = {pDirection2->x - pDirection1->x, pDirection2->y - pDirection1->y};
3413 if((fabs(Direction.x)<LEE_CONST_ZERO)&&(fabs(Direction.y)<LEE_CONST_ZERO))
3414 Direction = *pDirection2;
3415 pEdge->direction = _cvSeqPush(pVoronoiDiagram->DirectionSeq,&Direction);;
3416 }//end of _cvCalcEdgeLL
3419 void _cvCalcEdgePP(pCvPointFloat pPoint1,
3420 pCvPointFloat pPoint2,
3421 pCvVoronoiEdge pEdge,
3422 CvVoronoiDiagramInt* pVoronoiDiagram)
3424 CvDirection Direction = {pPoint1->y - pPoint2->y,pPoint2->x - pPoint1->x};
3425 pEdge->direction = _cvSeqPush(pVoronoiDiagram->DirectionSeq,&Direction);
3426 }//end of _cvCalcEdgePP
3429 void _cvCalcEdgePL(pCvVoronoiNode pFocus,
3430 pCvVoronoiSite pDirectrice,
3431 pCvVoronoiEdge pEdge,
3432 CvVoronoiDiagramInt* pVoronoiDiagram)
3434 pCvPointFloat pPoint0 = &pFocus->node;
3435 pCvPointFloat pPoint1 = &pDirectrice->node1->node;
3437 CvDirection Vector01 = {pPoint0->x - pPoint1->x,pPoint0->y - pPoint1->y};
3438 float half_h = (Vector01.y*pDirectrice->direction->x - Vector01.x*pDirectrice->direction->y)/2;
3439 CvDirection Normal = {-pDirectrice->direction->y,pDirectrice->direction->x};
3440 if(half_h < LEE_CONST_ZERO)
3442 pEdge->direction = _cvSeqPush(pVoronoiDiagram->DirectionSeq,&Normal);
3445 CvVoronoiParabolaInt Parabola;
3446 pCvVoronoiParabola pParabola = _cvSeqPush(pVoronoiDiagram->ParabolaSeq,&Parabola);
3447 float* map = pParabola->map;
3453 map[2] = pPoint0->x - Normal.x*half_h;
3454 map[5] = pPoint0->y - Normal.y*half_h;
3456 pParabola->a = 1/(4*half_h);
3457 pParabola->focus = pFocus;
3458 pParabola->directrice = pDirectrice;
3459 pEdge->parabola = pParabola;
3460 }//end of _cvCalcEdgePL
3463 void _cvCalcEdgeLP(pCvVoronoiSite pDirectrice,
3464 pCvVoronoiNode pFocus,
3465 pCvVoronoiEdge pEdge,
3466 CvVoronoiDiagramInt* pVoronoiDiagram)
3468 pCvPointFloat pPoint0 = &pFocus->node;
3469 pCvPointFloat pPoint1 = &pDirectrice->node1->node;
3471 CvDirection Vector01 = {pPoint0->x - pPoint1->x,pPoint0->y - pPoint1->y};
3472 float half_h = (Vector01.y*pDirectrice->direction->x - Vector01.x*pDirectrice->direction->y)/2;
3473 CvDirection Normal = {-pDirectrice->direction->y,pDirectrice->direction->x};
3474 if(half_h < LEE_CONST_ZERO)
3476 pEdge->direction = _cvSeqPush(pVoronoiDiagram->DirectionSeq,&Normal);
3479 CvVoronoiParabolaInt Parabola;
3480 pCvVoronoiParabola pParabola = _cvSeqPush(pVoronoiDiagram->ParabolaSeq,&Parabola);
3481 float* map = pParabola->map;
3487 map[2] = pPoint0->x - Normal.x*half_h;
3488 map[5] = pPoint0->y - Normal.y*half_h;
3490 pParabola->a = 1/(4*half_h);
3491 pParabola->focus = pFocus;
3492 pParabola->directrice = pDirectrice;
3493 pEdge->parabola = pParabola;
3494 }//end of _cvCalcEdgeLP
3496 /* ///////////////////////////////////////////////////////////////////////////////////////
3497 // Computation of intersections of bisectors //
3498 /////////////////////////////////////////////////////////////////////////////////////// */
3501 float _cvCalcEdgeIntersection(pCvVoronoiEdge pEdge1,
3502 pCvVoronoiEdge pEdge2,
3503 CvPointFloat* pPoint,
3506 if((pEdge1->parabola==NULL)&&(pEdge2->parabola==NULL))
3507 return _cvLine_LineIntersection(pEdge1,pEdge2,pPoint,Radius);
3508 if((pEdge1->parabola==NULL)&&(pEdge2->parabola!=NULL))
3509 return _cvLine_ParIntersection(pEdge1,pEdge2,pPoint,Radius);
3510 if((pEdge1->parabola!=NULL)&&(pEdge2->parabola==NULL))
3511 return _cvPar_LineIntersection(pEdge1,pEdge2,pPoint,Radius);
3512 //if((pEdge1->parabola!=NULL)&&(pEdge2->parabola!=NULL))
3513 return _cvPar_ParIntersection(pEdge1,pEdge2,pPoint,Radius);
3515 }//end of _cvCalcEdgeIntersection
3518 float _cvLine_LineIntersection(pCvVoronoiEdge pEdge1,
3519 pCvVoronoiEdge pEdge2,
3520 pCvPointFloat pPoint,
3523 if(((pEdge1->node1 == pEdge2->node1 ||
3524 pEdge1->node1 == pEdge2->node2) &&
3525 pEdge1->node1 != NULL)||
3526 ((pEdge1->node2 == pEdge2->node1 ||
3527 pEdge1->node2 == pEdge2->node2) &&
3528 pEdge1->node2 != NULL))
3531 CvPointFloat Point1,Point3;
3534 float x21,x43,y43,y21,x31,y31;
3536 if(pEdge1->node1!=NULL)
3538 Point1.x = pEdge1->node1->node.x;
3539 Point1.y = pEdge1->node1->node.y;
3543 Point1.x = pEdge1->node2->node.x;
3544 Point1.y = pEdge1->node2->node.y;
3546 x21 = pEdge1->direction->x;
3547 y21 = pEdge1->direction->y;
3549 if(pEdge2->node2==NULL)
3551 Point3.x = pEdge2->node1->node.x;
3552 Point3.y = pEdge2->node1->node.y;
3553 x43 = pEdge2->direction->x;
3554 y43 = pEdge2->direction->y;
3557 else if(pEdge2->node1==NULL)
3559 Point3.x = pEdge2->node2->node.x;
3560 Point3.y = pEdge2->node2->node.y;
3561 x43 = pEdge2->direction->x;
3562 y43 = pEdge2->direction->y;
3566 Point3.x = pEdge2->node1->node.x;
3567 Point3.y = pEdge2->node1->node.y;
3568 x43 = pEdge2->node2->node.x - Point3.x;
3569 y43 = pEdge2->node2->node.y - Point3.y;
3572 x31 = Point3.x - Point1.x;
3573 y31 = Point3.y - Point1.y;
3575 det = y21*x43 - x21*y43;
3576 if(fabs(det) < LEE_CONST_ZERO)
3579 k = (x43*y31 - y43*x31)/det;
3580 m = (x21*y31 - y21*x31)/det;
3582 if(k<-LEE_CONST_ACCEPTABLE_ERROR||m<-LEE_CONST_ACCEPTABLE_ERROR)
3584 if(((pEdge1->node2!=NULL)&&(pEdge1->node1!=NULL))&&(k>1.f+LEE_CONST_ACCEPTABLE_ERROR))
3586 if(((pEdge2->node2!=NULL)&&(pEdge2->node1!=NULL))&&(m>1.f+LEE_CONST_ACCEPTABLE_ERROR))
3589 pPoint->x = (float)(k*x21) + Point1.x;
3590 pPoint->y = (float)(k*y21) + Point1.y;
3592 Radius = _cvCalcDist(pPoint,pEdge1->site);
3593 return _cvPPDist(pPoint,&Point1);;
3594 }//end of _cvLine_LineIntersection
3597 float _cvLine_ParIntersection(pCvVoronoiEdge pEdge1,
3598 pCvVoronoiEdge pEdge2,
3599 pCvPointFloat pPoint,
3602 if(pEdge2->node1==NULL||pEdge2->node2==NULL)
3603 return _cvLine_OpenParIntersection(pEdge1,pEdge2,pPoint,Radius);
3604 return _cvLine_CloseParIntersection(pEdge1,pEdge2,pPoint,Radius);
3605 }//end of _cvLine_ParIntersection
3608 float _cvLine_OpenParIntersection(pCvVoronoiEdge pEdge1,
3609 pCvVoronoiEdge pEdge2,
3610 pCvPointFloat pPoint,
3613 int IntersectionNumber = 1;
3614 if(((pEdge1->node1 == pEdge2->node1 ||
3615 pEdge1->node1 == pEdge2->node2) &&
3616 pEdge1->node1 != NULL)||
3617 ((pEdge1->node2 == pEdge2->node1 ||
3618 pEdge1->node2 == pEdge2->node2) &&
3619 pEdge1->node2 != NULL))
3620 IntersectionNumber = 2;
3622 pCvPointFloat pRayPoint1;
3623 if(pEdge1->node1!=NULL)
3624 pRayPoint1 = &(pEdge1->node1->node);
3626 pRayPoint1 = &(pEdge1->node2->node);
3628 pCvDirection pDirection = pEdge1->direction;
3629 float* Parabola = pEdge2->parabola->map;
3631 pCvPointFloat pParPoint1;
3632 if(pEdge2->node1==NULL)
3633 pParPoint1 = &(pEdge2->node2->node);
3635 pParPoint1 = &(pEdge2->node1->node);
3637 float InversParabola[6]={0,0,0,0,0,0};
3638 _cvCalcOrtogInverse(InversParabola, Parabola);
3640 CvPointFloat Point,ParPoint1_img,RayPoint1_img;
3641 CvDirection Direction_img;
3642 _cvCalcPointImage(&RayPoint1_img, pRayPoint1, InversParabola);
3643 _cvCalcVectorImage(&Direction_img,pDirection, InversParabola);
3645 float c2 = pEdge2->parabola->a*Direction_img.x;
3646 float c1 = -Direction_img.y;
3647 float c0 = Direction_img.y* RayPoint1_img.x - Direction_img.x*RayPoint1_img.y;
3649 int N = _cvSolveEqu2thR(c2,c1,c0,X);
3653 _cvCalcPointImage(&ParPoint1_img, pParPoint1, InversParabola);
3654 int sign_x = SIGN(Direction_img.x);
3655 int sign_y = SIGN(Direction_img.y);
3658 if(X[0]<ParPoint1_img.x - LEE_CONST_ACCEPTABLE_ERROR)
3660 float pr0 = (X[0]-RayPoint1_img.x)*sign_x + \
3661 (pEdge2->parabola->a*X[0]*X[0]-RayPoint1_img.y)*sign_y;
3662 if(pr0 <= -LEE_CONST_ACCEPTABLE_ERROR)
3667 if(X[1]<ParPoint1_img.x - LEE_CONST_ACCEPTABLE_ERROR)
3669 float pr0 = (X[0]-RayPoint1_img.x)*sign_x + \
3670 (pEdge2->parabola->a*X[0]*X[0]-RayPoint1_img.y)*sign_y;
3671 float pr1 = (X[1]-RayPoint1_img.x)*sign_x + \
3672 (pEdge2->parabola->a*X[1]*X[1]-RayPoint1_img.y)*sign_y;
3674 if(pr0 <= -LEE_CONST_ACCEPTABLE_ERROR &&pr1 <= -LEE_CONST_ACCEPTABLE_ERROR)
3677 if(pr0 >- LEE_CONST_ACCEPTABLE_ERROR && pr1 >- LEE_CONST_ACCEPTABLE_ERROR)
3679 if(X[0] >= ParPoint1_img.x - LEE_CONST_ACCEPTABLE_ERROR)
3690 else if(pr0 >- LEE_CONST_ACCEPTABLE_ERROR)
3693 if(X[0] < ParPoint1_img.x - LEE_CONST_ACCEPTABLE_ERROR)
3696 else if(pr1 >- LEE_CONST_ACCEPTABLE_ERROR)
3705 Point.x = X[(N-1)*(IntersectionNumber - 1)];
3706 Point.y = pEdge2->parabola->a*Point.x*Point.x;
3708 Radius = Point.y + 1.f/(4*pEdge2->parabola->a);
3709 _cvCalcPointImage(pPoint,&Point,Parabola);
3710 float dist = _cvPPDist(pPoint, pRayPoint1);
3711 if(IntersectionNumber == 2 && dist < LEE_CONST_DIFF_POINTS)
3715 }// end of _cvLine_OpenParIntersection
3718 float _cvLine_CloseParIntersection(pCvVoronoiEdge pEdge1,
3719 pCvVoronoiEdge pEdge2,
3720 pCvPointFloat pPoint,
3723 int IntersectionNumber = 1;
3724 if(((pEdge1->node1 == pEdge2->node1 ||
3725 pEdge1->node1 == pEdge2->node2) &&
3726 pEdge1->node1 != NULL)||
3727 ((pEdge1->node2 == pEdge2->node1 ||
3728 pEdge1->node2 == pEdge2->node2) &&
3729 pEdge1->node2 != NULL))
3730 IntersectionNumber = 2;
3732 pCvPointFloat pRayPoint1;
3733 if(pEdge1->node1!=NULL)
3734 pRayPoint1 = &(pEdge1->node1->node);
3736 pRayPoint1 = &(pEdge1->node2->node);
3738 pCvDirection pDirection = pEdge1->direction;
3739 float* Parabola = pEdge2->parabola->map;
3741 pCvPointFloat pParPoint1,pParPoint2;
3742 pParPoint2 = &(pEdge2->node1->node);
3743 pParPoint1 = &(pEdge2->node2->node);
3746 float InversParabola[6]={0,0,0,0,0,0};
3747 _cvCalcOrtogInverse(InversParabola, Parabola);
3749 CvPointFloat Point,ParPoint1_img,ParPoint2_img,RayPoint1_img;
3750 CvDirection Direction_img;
3751 _cvCalcPointImage(&RayPoint1_img, pRayPoint1, InversParabola);
3752 _cvCalcVectorImage(&Direction_img,pDirection, InversParabola);
3754 float c2 = pEdge2->parabola->a*Direction_img.x;
3755 float c1 = -Direction_img.y;
3756 float c0 = Direction_img.y* RayPoint1_img.x - Direction_img.x*RayPoint1_img.y;
3758 int N = _cvSolveEqu2thR(c2,c1,c0,X);
3762 _cvCalcPointImage(&ParPoint1_img, pParPoint1, InversParabola);
3763 _cvCalcPointImage(&ParPoint2_img, pParPoint2, InversParabola);
3764 if(ParPoint1_img.x>ParPoint2_img.x)
3765 _cvSwap(ParPoint1_img,ParPoint2_img);
3766 int sign_x = SIGN(Direction_img.x);
3767 int sign_y = SIGN(Direction_img.y);
3770 if((X[0]<ParPoint1_img.x - LEE_CONST_ACCEPTABLE_ERROR) ||
3771 (X[0]>ParPoint2_img.x + LEE_CONST_ACCEPTABLE_ERROR))
3773 float pr0 = (X[0]-RayPoint1_img.x)*sign_x + \
3774 (pEdge2->parabola->a*X[0]*X[0]-RayPoint1_img.y)*sign_y;
3775 if(pr0 <= -LEE_CONST_ACCEPTABLE_ERROR)
3780 if((X[1]<ParPoint1_img.x - LEE_CONST_ACCEPTABLE_ERROR) ||
3781 (X[0]>ParPoint2_img.x + LEE_CONST_ACCEPTABLE_ERROR))
3784 if((X[0]<ParPoint1_img.x - LEE_CONST_ACCEPTABLE_ERROR) &&
3785 (X[1]>ParPoint2_img.x + LEE_CONST_ACCEPTABLE_ERROR))
3788 float pr0 = (X[0]-RayPoint1_img.x)*sign_x + \
3789 (pEdge2->parabola->a*X[0]*X[0]-RayPoint1_img.y)*sign_y;
3790 float pr1 = (X[1]-RayPoint1_img.x)*sign_x + \
3791 (pEdge2->parabola->a*X[1]*X[1]-RayPoint1_img.y)*sign_y;
3793 if(pr0 <= -LEE_CONST_ACCEPTABLE_ERROR && pr1 <= -LEE_CONST_ACCEPTABLE_ERROR)
3796 if(pr0 > -LEE_CONST_ACCEPTABLE_ERROR && pr1 > -LEE_CONST_ACCEPTABLE_ERROR)
3798 if(X[0] >= ParPoint1_img.x - LEE_CONST_ACCEPTABLE_ERROR)
3800 if(X[1] <= ParPoint2_img.x + LEE_CONST_ACCEPTABLE_ERROR)
3803 _cvSwap(X[0], X[1]);
3814 else if(pr0 > -LEE_CONST_ACCEPTABLE_ERROR)
3817 if(X[0] >= ParPoint1_img.x - LEE_CONST_ACCEPTABLE_ERROR)
3822 else if(pr1 > -LEE_CONST_ACCEPTABLE_ERROR)
3824 if(X[1] <= ParPoint2_img.x + LEE_CONST_ACCEPTABLE_ERROR)
3836 Point.x = X[(N-1)*(IntersectionNumber - 1)];
3837 Point.y = pEdge2->parabola->a*Point.x*Point.x;
3838 Radius = Point.y + 1.f/(4*pEdge2->parabola->a);
3839 _cvCalcPointImage(pPoint,&Point,Parabola);
3840 float dist = _cvPPDist(pPoint, pRayPoint1);
3841 if(IntersectionNumber == 2 && dist < LEE_CONST_DIFF_POINTS)
3845 }// end of _cvLine_CloseParIntersection
3848 float _cvPar_LineIntersection(pCvVoronoiEdge pEdge1,
3849 pCvVoronoiEdge pEdge2,
3850 pCvPointFloat pPoint,
3853 if(pEdge2->node1==NULL||pEdge2->node2==NULL)
3854 return _cvPar_OpenLineIntersection(pEdge1,pEdge2,pPoint,Radius);
3855 return _cvPar_CloseLineIntersection(pEdge1,pEdge2,pPoint,Radius);
3856 }//end _cvPar_LineIntersection
3859 float _cvPar_OpenLineIntersection(pCvVoronoiEdge pEdge1,
3860 pCvVoronoiEdge pEdge2,
3861 pCvPointFloat pPoint,
3864 int i, IntersectionNumber = 1;
3865 if(((pEdge1->node1 == pEdge2->node1 ||
3866 pEdge1->node1 == pEdge2->node2) &&
3867 pEdge1->node1 != NULL)||
3868 ((pEdge1->node2 == pEdge2->node1 ||
3869 pEdge1->node2 == pEdge2->node2) &&
3870 pEdge1->node2 != NULL))
3871 IntersectionNumber = 2;
3873 float* Parabola = pEdge1->parabola->map;
3874 pCvPointFloat pParPoint1;
3875 if(pEdge1->node1!=NULL)
3876 pParPoint1 = &(pEdge1->node1->node);
3878 pParPoint1 = &(pEdge1->node2->node);
3880 pCvPointFloat pRayPoint1;
3881 if(pEdge2->node1==NULL)
3882 pRayPoint1 = &(pEdge2->node2->node);
3884 pRayPoint1 = &(pEdge2->node1->node);
3885 pCvDirection pDirection = pEdge2->direction;
3888 float InversParabola[6]={0,0,0,0,0,0};
3889 _cvCalcOrtogInverse(InversParabola, Parabola);
3891 CvPointFloat Point = {0,0},ParPoint1_img,RayPoint1_img;
3892 CvDirection Direction_img;
3893 _cvCalcVectorImage(&Direction_img,pDirection, InversParabola);
3894 _cvCalcPointImage(&RayPoint1_img, pRayPoint1, InversParabola);
3897 float q = RayPoint1_img.y - pEdge1->parabola->a*RayPoint1_img.x*RayPoint1_img.x;
3898 if((pEdge2->site->node1 == pEdge2->site->node2 && q < 0) ||
3899 (pEdge2->site->node1 != pEdge2->site->node2 && q > 0))
3902 float c2 = pEdge1->parabola->a*Direction_img.x;
3903 float c1 = -Direction_img.y;
3904 float c0 = Direction_img.y* RayPoint1_img.x - Direction_img.x*RayPoint1_img.y;
3906 int N = _cvSolveEqu2thR(c2,c1,c0,X);
3910 _cvCalcPointImage(&ParPoint1_img, pParPoint1, InversParabola);
3911 int sign_x = SIGN(Direction_img.x);
3912 int sign_y = SIGN(Direction_img.y);
3915 if(N==2 && IntersectionNumber == 2)
3916 _cvSwap(X[0], X[1]);
3920 if(X[i]<=ParPoint1_img.x - LEE_CONST_ACCEPTABLE_ERROR)
3922 pr = (X[i]-RayPoint1_img.x)*sign_x +
3923 (pEdge1->parabola->a*X[i]*X[i]-RayPoint1_img.y)*sign_y;
3924 if(pr <= -LEE_CONST_ACCEPTABLE_ERROR)
3936 Point.y = pEdge1->parabola->a*Point.x*Point.x;
3937 Radius = Point.y + 1.f/(4*pEdge1->parabola->a);
3938 _cvCalcPointImage(pPoint,&Point,Parabola);
3939 float dist = Point.x - ParPoint1_img.x;
3940 if(IntersectionNumber == 2 && dist < LEE_CONST_DIFF_POINTS)
3944 }// end of _cvPar_OpenLineIntersection
3947 float _cvPar_CloseLineIntersection(pCvVoronoiEdge pEdge1,
3948 pCvVoronoiEdge pEdge2,
3949 pCvPointFloat pPoint,
3952 int i, IntersectionNumber = 1;
3953 if(((pEdge1->node1 == pEdge2->node1 ||
3954 pEdge1->node1 == pEdge2->node2) &&
3955 pEdge1->node1 != NULL)||
3956 ((pEdge1->node2 == pEdge2->node1 ||
3957 pEdge1->node2 == pEdge2->node2) &&
3958 pEdge1->node2 != NULL))
3959 IntersectionNumber = 2;
3961 float* Parabola = pEdge1->parabola->map;
3962 pCvPointFloat pParPoint1;
3963 if(pEdge1->node1!=NULL)
3964 pParPoint1 = &(pEdge1->node1->node);
3966 pParPoint1 = &(pEdge1->node2->node);
3968 pCvPointFloat pRayPoint1,pRayPoint2;
3969 pRayPoint2 = &(pEdge2->node1->node);
3970 pRayPoint1 = &(pEdge2->node2->node);
3972 pCvDirection pDirection = pEdge2->direction;
3973 float InversParabola[6]={0,0,0,0,0,0};
3974 _cvCalcOrtogInverse(InversParabola, Parabola);
3976 CvPointFloat Point={0,0},ParPoint1_img,RayPoint1_img,RayPoint2_img;
3977 CvDirection Direction_img;
3978 _cvCalcPointImage(&RayPoint1_img, pRayPoint1, InversParabola);
3979 _cvCalcPointImage(&RayPoint2_img, pRayPoint2, InversParabola);
3984 q = RayPoint1_img.y - pEdge1->parabola->a*RayPoint1_img.x*RayPoint1_img.x;
3985 if((pEdge2->site->node1 == pEdge2->site->node2 && q < 0) ||
3986 (pEdge2->site->node1 != pEdge2->site->node2 && q > 0))
3991 q = RayPoint2_img.y - pEdge1->parabola->a*RayPoint2_img.x*RayPoint2_img.x;
3992 if((pEdge2->site->node1 == pEdge2->site->node2 && q < 0) ||
3993 (pEdge2->site->node1 != pEdge2->site->node2 && q > 0))
3997 _cvCalcPointImage(&ParPoint1_img, pParPoint1, InversParabola);
3998 _cvCalcVectorImage(&Direction_img,pDirection, InversParabola);
4000 float c2 = pEdge1->parabola->a*Direction_img.x;
4001 float c1 = -Direction_img.y;
4002 float c0 = Direction_img.y* RayPoint1_img.x - Direction_img.x*RayPoint1_img.y;
4004 int N = _cvSolveEqu2thR(c2,c1,c0,X);
4007 int sign_x = SIGN(RayPoint2_img.x - RayPoint1_img.x);
4008 int sign_y = SIGN(RayPoint2_img.y - RayPoint1_img.y);
4009 float pr_dir = (RayPoint2_img.x - RayPoint1_img.x)*sign_x +
4010 (RayPoint2_img.y - RayPoint1_img.y)*sign_y;
4013 if(N==2 && IntersectionNumber == 2)
4014 _cvSwap(X[0], X[1]);
4018 if(X[i] <= ParPoint1_img.x - LEE_CONST_ACCEPTABLE_ERROR)
4020 pr = (X[i]-RayPoint1_img.x)*sign_x + \
4021 (pEdge1->parabola->a*X[i]*X[i]-RayPoint1_img.y)*sign_y;
4022 if(pr <= -LEE_CONST_ACCEPTABLE_ERROR || pr>=pr_dir + LEE_CONST_ACCEPTABLE_ERROR)
4034 Point.y = pEdge1->parabola->a*Point.x*Point.x;
4035 Radius = Point.y + 1.f/(4*pEdge1->parabola->a);
4036 _cvCalcPointImage(pPoint,&Point,Parabola);
4037 float dist = Point.x - ParPoint1_img.x;
4038 if(IntersectionNumber == 2 && dist < LEE_CONST_DIFF_POINTS)
4042 }// end of _cvPar_CloseLineIntersection
4045 float _cvPar_ParIntersection(pCvVoronoiEdge pEdge1,
4046 pCvVoronoiEdge pEdge2,
4047 pCvPointFloat pPoint,
4050 if(pEdge2->node1==NULL||pEdge2->node2==NULL)
4051 return _cvPar_OpenParIntersection(pEdge1,pEdge2,pPoint,Radius);
4052 return _cvPar_CloseParIntersection(pEdge1,pEdge2,pPoint,Radius);
4053 }// end of _cvPar_ParIntersection
4056 float _cvPar_OpenParIntersection(pCvVoronoiEdge pEdge1,
4057 pCvVoronoiEdge pEdge2,
4058 pCvPointFloat pPoint,
4061 int i, IntersectionNumber = 1;
4062 if(((pEdge1->node1 == pEdge2->node1 ||
4063 pEdge1->node1 == pEdge2->node2) &&
4064 pEdge1->node1 != NULL)||
4065 ((pEdge1->node2 == pEdge2->node1 ||
4066 pEdge1->node2 == pEdge2->node2) &&
4067 pEdge1->node2 != NULL))
4068 IntersectionNumber = 2;
4070 float* Parabola1 = pEdge1->parabola->map;
4071 pCvPointFloat pPar1Point1;
4072 if(pEdge1->node1!=NULL)
4073 pPar1Point1 = &(pEdge1->node1->node);
4075 pPar1Point1 = &(pEdge1->node2->node);
4077 float* Parabola2 = pEdge2->parabola->map;
4078 pCvPointFloat pPar2Point1;
4079 if(pEdge2->node1!=NULL)
4080 pPar2Point1 = &(pEdge2->node1->node);
4082 pPar2Point1 = &(pEdge2->node2->node);
4085 CvDirection Direction;
4086 if(pEdge1->parabola->directrice==pEdge2->parabola->directrice) //common site is segment -> different focuses
4088 pCvPointFloat pFocus1 = &(pEdge1->parabola->focus->node);
4089 pCvPointFloat pFocus2 = &(pEdge2->parabola->focus->node);
4091 Point.x = (pFocus1->x + pFocus2->x)/2;
4092 Point.y = (pFocus1->y + pFocus2->y)/2;
4093 Direction.x = pFocus1->y - pFocus2->y;
4094 Direction.y = pFocus2->x - pFocus1->x;
4096 else//common site is focus -> different directrices
4098 pCvVoronoiSite pDirectrice1 = pEdge1->parabola->directrice;
4099 pCvPointFloat pPoint1 = &(pDirectrice1->node1->node);
4100 pCvDirection pVector21 = pDirectrice1->direction;
4102 pCvVoronoiSite pDirectrice2 = pEdge2->parabola->directrice;
4103 pCvPointFloat pPoint3 = &(pDirectrice2->node1->node);
4104 pCvDirection pVector43 = pDirectrice2->direction;
4106 Direction.x = pVector43->x - pVector21->x;
4107 Direction.y = pVector43->y - pVector21->y;
4109 if((fabs(Direction.x) < LEE_CONST_ZERO) &&
4110 (fabs(Direction.y) < LEE_CONST_ZERO))
4111 Direction = *pVector43;
4113 float det = pVector21->y * pVector43->x - pVector21->x * pVector43->y;
4114 if(fabs(det) < LEE_CONST_ZERO)
4116 Point.x = (pPoint1->x + pPoint3->x)/2;
4117 Point.y = (pPoint1->y + pPoint3->y)/2;
4121 float d1 = pVector21->y*pPoint1->x - pVector21->x*pPoint1->y;
4122 float d2 = pVector43->y*pPoint3->x - pVector43->x*pPoint3->y;
4123 Point.x = (float)((pVector43->x*d1 - pVector21->x*d2)/det);
4124 Point.y = (float)((pVector43->y*d1 - pVector21->y*d2)/det);
4128 float InversParabola2[6]={0,0,0,0,0,0};
4129 _cvCalcOrtogInverse(InversParabola2, Parabola2);
4131 CvPointFloat Par2Point1_img,Point_img;
4132 CvDirection Direction_img;
4133 _cvCalcVectorImage(&Direction_img,&Direction, InversParabola2);
4134 _cvCalcPointImage(&Point_img, &Point, InversParabola2);
4136 float a1 = pEdge1->parabola->a;
4137 float a2 = pEdge2->parabola->a;
4138 float c2 = a2*Direction_img.x;
4139 float c1 = -Direction_img.y;
4140 float c0 = Direction_img.y* Point_img.x - Direction_img.x*Point_img.y;
4142 int N = _cvSolveEqu2thR(c2,c1,c0,X);
4147 _cvCalcPointImage(&Par2Point1_img, pPar2Point1, InversParabola2);
4149 if(X[N-1]<Par2Point1_img.x)
4152 if(X[0]<Par2Point1_img.x)
4158 float InversParabola1[6]={0,0,0,0,0,0};
4159 CvPointFloat Par1Point1_img;
4160 _cvCalcOrtogInverse(InversParabola1, Parabola1);
4161 _cvCalcPointImage(&Par1Point1_img, pPar1Point1, InversParabola1);
4162 float InvPar1_Par2[6];
4163 _cvCalcComposition(InvPar1_Par2,InversParabola1,Parabola2);
4165 X[i] = (InvPar1_Par2[1]*a2*X[i] + InvPar1_Par2[0])*X[i] + InvPar1_Par2[2];
4169 if((X[0]>X[1] && IntersectionNumber == 1)||
4170 (X[0]<X[1] && IntersectionNumber == 2))
4171 _cvSwap(X[0], X[1]);
4177 Point.y = a1*Point.x*Point.x;
4178 if(Point.x < Par1Point1_img.x - LEE_CONST_ACCEPTABLE_ERROR)
4187 Radius = Point.y + 1.f/(4*pEdge1->parabola->a);
4188 _cvCalcPointImage(pPoint,&Point,Parabola1);
4189 float dist = Point.x - Par1Point1_img.x;
4190 if(IntersectionNumber == 2 && dist < LEE_CONST_DIFF_POINTS)
4194 }// end of _cvPar_OpenParIntersection
4197 float _cvPar_CloseParIntersection(pCvVoronoiEdge pEdge1,
4198 pCvVoronoiEdge pEdge2,
4199 pCvPointFloat pPoint,
4202 int i, IntersectionNumber = 1;
4203 if(((pEdge1->node1 == pEdge2->node1 ||
4204 pEdge1->node1 == pEdge2->node2) &&
4205 pEdge1->node1 != NULL)||
4206 ((pEdge1->node2 == pEdge2->node1 ||
4207 pEdge1->node2 == pEdge2->node2) &&
4208 pEdge1->node2 != NULL))
4209 IntersectionNumber = 2;
4211 float* Parabola1 = pEdge1->parabola->map;
4212 float* Parabola2 = pEdge2->parabola->map;
4213 pCvPointFloat pPar1Point1;
4214 if(pEdge1->node1!=NULL)
4215 pPar1Point1 = &(pEdge1->node1->node);
4217 pPar1Point1 = &(pEdge1->node2->node);
4219 pCvPointFloat pPar2Point1 = &(pEdge2->node1->node);
4220 pCvPointFloat pPar2Point2 = &(pEdge2->node2->node);
4223 CvDirection Direction;
4224 if(pEdge1->parabola->directrice==pEdge2->parabola->directrice) //common site is segment -> different focuses
4226 pCvPointFloat pFocus1 = &(pEdge1->parabola->focus->node);
4227 pCvPointFloat pFocus2 = &(pEdge2->parabola->focus->node);
4229 Point.x = (pFocus1->x + pFocus2->x)/2;
4230 Point.y = (pFocus1->y + pFocus2->y)/2;
4231 Direction.x = pFocus1->y - pFocus2->y;
4232 Direction.y = pFocus2->x - pFocus1->x;
4234 else//common site is focus -> different directrices
4236 pCvVoronoiSite pDirectrice1 = pEdge1->parabola->directrice;
4237 pCvPointFloat pPoint1 = &(pDirectrice1->node1->node);
4238 pCvDirection pVector21 = pDirectrice1->direction;
4240 pCvVoronoiSite pDirectrice2 = pEdge2->parabola->directrice;
4241 pCvPointFloat pPoint3 = &(pDirectrice2->node1->node);
4242 pCvDirection pVector43 = pDirectrice2->direction;
4244 Direction.x = pVector43->x - pVector21->x;
4245 Direction.y = pVector43->y - pVector21->y;
4247 if((fabs(Direction.x) < LEE_CONST_ZERO) &&
4248 (fabs(Direction.y) < LEE_CONST_ZERO))
4249 Direction = *pVector43;
4251 float det = pVector21->y * pVector43->x - pVector21->x * pVector43->y;
4252 if(fabs(det) < LEE_CONST_ZERO)
4254 Point.x = (pPoint1->x + pPoint3->x)/2;
4255 Point.y = (pPoint1->y + pPoint3->y)/2;
4259 float d1 = pVector21->y*pPoint1->x - pVector21->x*pPoint1->y;
4260 float d2 = pVector43->y*pPoint3->x - pVector43->x*pPoint3->y;
4261 Point.x = (float)((pVector43->x*d1 - pVector21->x*d2)/det);
4262 Point.y = (float)((pVector43->y*d1 - pVector21->y*d2)/det);
4268 float InversParabola2[6]={0,0,0,0,0,0};
4269 _cvCalcOrtogInverse(InversParabola2, Parabola2);
4271 CvPointFloat Par2Point1_img,Par2Point2_img,Point_img;
4272 CvDirection Direction_img;
4273 _cvCalcVectorImage(&Direction_img,&Direction, InversParabola2);
4274 _cvCalcPointImage(&Point_img, &Point, InversParabola2);
4276 float a1 = pEdge1->parabola->a;
4277 float a2 = pEdge2->parabola->a;
4278 float c2 = a2*Direction_img.x;
4279 float c1 = -Direction_img.y;
4280 float c0 = Direction_img.y* Point_img.x - Direction_img.x*Point_img.y;
4282 int N = _cvSolveEqu2thR(c2,c1,c0,X);
4287 _cvCalcPointImage(&Par2Point1_img, pPar2Point1, InversParabola2);
4288 _cvCalcPointImage(&Par2Point2_img, pPar2Point2, InversParabola2);
4289 if(Par2Point1_img.x>Par2Point2_img.x)
4290 _cvSwap(Par2Point1_img,Par2Point2_img);
4292 if(X[0]>Par2Point2_img.x||X[N-1]<Par2Point1_img.x)
4295 if(X[0]<Par2Point1_img.x)
4297 if(X[1]<Par2Point2_img.x)
4305 else if(X[N-1]>Par2Point2_img.x)
4308 float InversParabola1[6]={0,0,0,0,0,0};
4309 CvPointFloat Par1Point1_img;
4310 _cvCalcOrtogInverse(InversParabola1, Parabola1);
4311 _cvCalcPointImage(&Par1Point1_img, pPar1Point1, InversParabola1);
4312 float InvPar1_Par2[6];
4313 _cvCalcComposition(InvPar1_Par2,InversParabola1,Parabola2);
4315 X[i] = (InvPar1_Par2[1]*a2*X[i] + InvPar1_Par2[0])*X[i] + InvPar1_Par2[2];
4319 if((X[0]>X[1] && IntersectionNumber == 1)||
4320 (X[0]<X[1] && IntersectionNumber == 2))
4321 _cvSwap(X[0], X[1]);
4327 Point.x = (float)X[i];
4328 Point.y = (float)a1*Point.x*Point.x;
4329 if(Point.x < Par1Point1_img.x - LEE_CONST_ACCEPTABLE_ERROR)
4338 Radius = Point.y + 1.f/(4*a1);
4339 _cvCalcPointImage(pPoint,&Point,Parabola1);
4340 float dist = Point.x - Par1Point1_img.x;
4341 if(IntersectionNumber == 2 && dist < LEE_CONST_DIFF_POINTS)
4345 }// end of _cvPar_CloseParIntersection
4347 /* ///////////////////////////////////////////////////////////////////////////////////////
4348 // Subsidiary functions //
4349 /////////////////////////////////////////////////////////////////////////////////////// */
4352 void _cvMakeTwinEdge(pCvVoronoiEdge pEdge2,
4353 pCvVoronoiEdge pEdge1)
4355 pEdge2->direction = pEdge1->direction;
4356 pEdge2->parabola = pEdge1->parabola;
4357 pEdge2->node1 = pEdge1->node2;
4358 pEdge2->twin_edge = pEdge1;
4359 pEdge1->twin_edge = pEdge2;
4360 }//end of _cvMakeTwinEdge
4363 void _cvStickEdgeLeftBegin(pCvVoronoiEdge pEdge,
4364 pCvVoronoiEdge pEdge_left_prev,
4365 pCvVoronoiSite pSite_left)
4367 pEdge->prev_edge = pEdge_left_prev;
4368 pEdge->site = pSite_left;
4369 if(pEdge_left_prev == NULL)
4370 pSite_left->edge2 = pEdge;
4373 pEdge_left_prev->node2 = pEdge->node1;
4374 pEdge_left_prev->next_edge = pEdge;
4376 }//end of _cvStickEdgeLeftBegin
4379 void _cvStickEdgeRightBegin(pCvVoronoiEdge pEdge,
4380 pCvVoronoiEdge pEdge_right_next,
4381 pCvVoronoiSite pSite_right)
4383 pEdge->next_edge = pEdge_right_next;
4384 pEdge->site = pSite_right;
4385 if(pEdge_right_next == NULL)
4386 pSite_right->edge1 = pEdge;
4389 pEdge_right_next->node1 = pEdge->node2;
4390 pEdge_right_next->prev_edge = pEdge;
4392 }// end of _cvStickEdgeRightBegin
4395 void _cvStickEdgeLeftEnd(pCvVoronoiEdge pEdge,
4396 pCvVoronoiEdge pEdge_left_next,
4397 pCvVoronoiSite pSite_left)
4399 pEdge->next_edge = pEdge_left_next;
4400 if(pEdge_left_next == NULL)
4401 pSite_left->edge1 = pEdge;
4404 pEdge_left_next->node1 = pEdge->node2;
4405 pEdge_left_next->prev_edge = pEdge;
4407 }//end of _cvStickEdgeLeftEnd
4410 void _cvStickEdgeRightEnd(pCvVoronoiEdge pEdge,
4411 pCvVoronoiEdge pEdge_right_prev,
4412 pCvVoronoiSite pSite_right)
4414 pEdge->prev_edge = pEdge_right_prev;
4415 if(pEdge_right_prev == NULL)
4416 pSite_right->edge2 = pEdge;
4419 pEdge_right_prev->node2 = pEdge->node1;
4420 pEdge_right_prev->next_edge = pEdge;
4422 }//end of _cvStickEdgeRightEnd
4424 template <class T> CV_INLINE
4425 void _cvInitVoronoiNode(pCvVoronoiNode pNode,
4429 pNode->node.x = (float)pPoint->x;
4430 pNode->node.y = (float)pPoint->y;
4431 pNode->radius = radius;
4432 }//end of _cvInitVoronoiNode
4435 void _cvInitVoronoiSite(pCvVoronoiSite pSite,
4436 pCvVoronoiNode pNode1,
4437 pCvVoronoiNode pNode2,
4438 pCvVoronoiSite pPrev_site)
4440 pSite->node1 = pNode1;
4441 pSite->node2 = pNode2;
4442 pSite->prev_site = pPrev_site;
4443 }//end of _cvInitVoronoiSite
4445 template <class T> CV_INLINE
4446 T _cvSeqPush(CvSeq* Seq, T pElem)
4448 cvSeqPush(Seq, pElem);
4449 return (T)(Seq->ptr - Seq->elem_size);
4450 // return (T)cvGetSeqElem(Seq, Seq->total - 1,NULL);
4451 }//end of _cvSeqPush
4453 template <class T> CV_INLINE
4454 T _cvSeqPushFront(CvSeq* Seq, T pElem)
4456 cvSeqPushFront(Seq,pElem);
4457 return (T)Seq->first->data;
4458 // return (T)cvGetSeqElem(Seq,0,NULL);
4459 }//end of _cvSeqPushFront
4462 void _cvTwinNULLLeft(pCvVoronoiEdge pEdge_left_cur,
4463 pCvVoronoiEdge pEdge_left)
4465 while(pEdge_left_cur!=pEdge_left)
4467 if(pEdge_left_cur->twin_edge!=NULL)
4468 pEdge_left_cur->twin_edge->twin_edge = NULL;
4469 pEdge_left_cur = pEdge_left_cur->next_edge;
4471 }//end of _cvTwinNULLLeft
4474 void _cvTwinNULLRight(pCvVoronoiEdge pEdge_right_cur,
4475 pCvVoronoiEdge pEdge_right)
4477 while(pEdge_right_cur!=pEdge_right)
4479 if(pEdge_right_cur->twin_edge!=NULL)
4480 pEdge_right_cur->twin_edge->twin_edge = NULL;
4481 pEdge_right_cur = pEdge_right_cur->prev_edge;
4483 }//end of _cvTwinNULLRight
4486 void _cvSeqPushInOrder(CvVoronoiDiagramInt* pVoronoiDiagram, pCvVoronoiHole pHole)
4488 pHole = _cvSeqPush(pVoronoiDiagram->HoleSeq, pHole);
4489 if(pVoronoiDiagram->HoleSeq->total == 1)
4491 pVoronoiDiagram->top_hole = pHole;
4495 pCvVoronoiHole pTopHole = pVoronoiDiagram->top_hole;
4496 pCvVoronoiHole pCurrHole;
4497 if(pTopHole->x_coord >= pHole->x_coord)
4499 pHole->next_hole = pTopHole;
4500 pVoronoiDiagram->top_hole = pHole;
4504 for(pCurrHole = pTopHole; \
4505 pCurrHole->next_hole != NULL; \
4506 pCurrHole = pCurrHole->next_hole)
4507 if(pCurrHole->next_hole->x_coord >= pHole->x_coord)
4509 pHole->next_hole = pCurrHole->next_hole;
4510 pCurrHole->next_hole = pHole;
4511 }//end of _cvSeqPushInOrder
4514 pCvVoronoiEdge _cvDivideRightEdge(pCvVoronoiEdge pEdge,pCvVoronoiNode pNode, CvSeq* EdgeSeq)
4516 CvVoronoiEdgeInt Edge1 = *pEdge;
4517 CvVoronoiEdgeInt Edge2 = *pEdge->twin_edge;
4518 pCvVoronoiEdge pEdge1, pEdge2;
4520 pEdge1 = _cvSeqPush(EdgeSeq, &Edge1);
4521 pEdge2 = _cvSeqPush(EdgeSeq, &Edge2);
4523 if(pEdge1->next_edge != NULL)
4524 pEdge1->next_edge->prev_edge = pEdge1;
4525 pEdge1->prev_edge = NULL;
4527 if(pEdge2->prev_edge != NULL)
4528 pEdge2->prev_edge->next_edge = pEdge2;
4529 pEdge2->next_edge = NULL;
4531 pEdge1->node1 = pEdge2->node2= pNode;
4532 pEdge1->twin_edge = pEdge2;
4533 pEdge2->twin_edge = pEdge1;
4535 }//end of _cvDivideRightEdge
4538 pCvVoronoiEdge _cvDivideLeftEdge(pCvVoronoiEdge pEdge,pCvVoronoiNode pNode, CvSeq* EdgeSeq)
4540 CvVoronoiEdgeInt Edge1 = *pEdge;
4541 CvVoronoiEdgeInt Edge2 = *pEdge->twin_edge;
4542 pCvVoronoiEdge pEdge1, pEdge2;
4544 pEdge1 = _cvSeqPush(EdgeSeq, &Edge1);
4545 pEdge2 = _cvSeqPush(EdgeSeq, &Edge2);
4547 if(pEdge2->next_edge != NULL)
4548 pEdge2->next_edge->prev_edge = pEdge2;
4549 pEdge2->prev_edge = NULL;
4551 if(pEdge1->prev_edge != NULL)
4552 pEdge1->prev_edge->next_edge = pEdge1;
4553 pEdge1->next_edge = NULL;
4555 pEdge1->node2 = pEdge2->node1= pNode;
4556 pEdge1->twin_edge = pEdge2;
4557 pEdge2->twin_edge = pEdge1;
4559 }//end of _cvDivideLeftEdge
4561 template<class T> CV_INLINE
4562 T _cvWriteSeqElem(T pElem, CvSeqWriter &writer)
4564 if( writer.ptr >= writer.block_max )
4565 cvCreateSeqBlock( &writer);
4567 T ptr = (T)writer.ptr;
4568 memcpy(writer.ptr, pElem, sizeof(*pElem));
4569 writer.ptr += sizeof(*pElem);
4571 }//end of _cvWriteSeqElem
4573 /* ///////////////////////////////////////////////////////////////////////////////////////
4574 // Mathematical functions //
4575 /////////////////////////////////////////////////////////////////////////////////////// */
4577 template<class T> CV_INLINE
4578 void _cvCalcPointImage(pCvPointFloat pImgPoint,pCvPointFloat pPoint,T* A)
4580 pImgPoint->x = (float)(A[0]*pPoint->x + A[1]*pPoint->y + A[2]);
4581 pImgPoint->y = (float)(A[3]*pPoint->x + A[4]*pPoint->y + A[5]);
4582 }//end of _cvCalcPointImage
4584 template <class T> CV_INLINE
4585 void _cvSwap(T &x, T &y)
4590 template <class T> CV_INLINE
4591 int _cvCalcOrtogInverse(T* B, T* A)
4593 int sign_det = SIGN(A[0]*A[4] - A[1]*A[3]);
4597 B[0] = A[4]*sign_det;
4598 B[1] = -A[1]*sign_det;
4599 B[3] = -A[3]*sign_det;
4600 B[4] = A[0]*sign_det;
4601 B[2] = - (B[0]*A[2]+B[1]*A[5]);
4602 B[5] = - (B[3]*A[2]+B[4]*A[5]);
4607 }//end of _cvCalcOrtogInverse
4609 template<class T> CV_INLINE
4610 void _cvCalcVectorImage(pCvDirection pImgVector,pCvDirection pVector,T* A)
4612 pImgVector->x = A[0]*pVector->x + A[1]*pVector->y;
4613 pImgVector->y = A[3]*pVector->x + A[4]*pVector->y;
4614 }//end of _cvCalcVectorImage
4616 template <class T> CV_INLINE
4617 void _cvCalcComposition(T* Result,T* A,T* B)
4619 Result[0] = A[0]*B[0] + A[1]*B[3];
4620 Result[1] = A[0]*B[1] + A[1]*B[4];
4621 Result[3] = A[3]*B[0] + A[4]*B[3];
4622 Result[4] = A[3]*B[1] + A[4]*B[4];
4623 Result[2] = A[0]*B[2] + A[1]*B[5] + A[2];
4624 Result[5] = A[3]*B[2] + A[4]*B[5] + A[5];
4625 }//end of _cvCalcComposition
4628 float _cvCalcDist(pCvPointFloat pPoint, pCvVoronoiSite pSite)
4630 if(pSite->node1==pSite->node2)
4631 return _cvPPDist(pPoint,&(pSite->node1->node));
4633 return _cvPLDist(pPoint,&(pSite->node1->node),pSite->direction);
4634 }//end of _cvCalcComposition
4637 float _cvPPDist(pCvPointFloat pPoint1,pCvPointFloat pPoint2)
4639 float delta_x = pPoint1->x - pPoint2->x;
4640 float delta_y = pPoint1->y - pPoint2->y;
4641 return (float)sqrt((double)delta_x*delta_x + delta_y*delta_y);
4646 float _cvPLDist(pCvPointFloat pPoint,pCvPointFloat pPoint1,pCvDirection pDirection)
4648 return (float)fabs(pDirection->x*(pPoint->y - pPoint1->y) -
4649 pDirection->y*(pPoint->x - pPoint1->x));
4653 int _cvSolveEqu2thR(T c2, T c1, T c0, T* X)
4655 const T eps = (T)1e-6;
4657 return _cvSolveEqu1th(c1,c0,X);
4659 T Discr = c1*c1 - c2*c0*4;
4662 Discr = (T)sqrt((double)fabs(Discr));
4677 X[0] = (-c1 - Discr)/(2*c2);
4678 X[1] = -2*c0/(c1+Discr);
4683 X[1] = (-c1 - Discr)/(2*c2);
4684 X[0] = -2*c0/(c1+Discr);
4692 X[1] = (-c1 + Discr)/(2*c2);
4693 X[0] = -2*c0/(c1-Discr);
4698 X[0] = (-c1 + Discr)/(2*c2);
4699 X[1] = -2*c0/(c1-Discr);
4704 }//end of _cvSolveEqu2thR
4706 template <class T> CV_INLINE
4707 int _cvSolveEqu1th(T c1, T c0, T* X)
4709 const T eps = (T)1e-6;
4715 }//end of _cvSolveEqu1th