16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M///////////////////////////////////////////////////////////////////////////////////////
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  By downloading, copying, installing or using the software you agree to this license.
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  If you do not agree to this license, do not download, install,
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  copy or use the software.
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                        Intel License Agreement
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                For Open Source Computer Vision Library
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved.
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners.
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification,
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met:
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's of source code must retain the above copyright notice,
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer.
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's in binary form must reproduce the above copyright notice,
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer in the documentation
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     and/or other materials provided with the distribution.
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * The name of Intel Corporation may not be used to endorse or promote products
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     derived from this software without specific prior written permission.
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed.
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct,
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services;
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability,
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage.
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Hybrid linear-contour model reconstruction */
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cvaux.h"
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_IMPL CV_EXTERN_C
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennconst float LCM_CONST_ZERO = 1e-6f;
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                                    Auxiliary struct definitions                                 *
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvLCM
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraph* Graph;
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiDiagram2D* VoronoiDiagram;
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* ContourStorage;
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* EdgeStorage;
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float maxWidth;
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} CvLCM;
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvLCMComplexNodeData
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiNode2D edge_node;
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint2D32f site_first_pt;
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint2D32f site_last_pt;
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiSite2D* site_first;
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiSite2D* site_last;
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiEdge2D* edge;
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} CvLCMComplexNodeData;
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvLCMData
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiNode2D* pnode;
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiSite2D* psite;
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiEdge2D* pedge;
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} CvLCMData;
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                                    Function definitions                                *
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define _CV_READ_SEQ_ELEM( elem, reader, type )                       \
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{                                                              \
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( (reader).seq->elem_size == sizeof(*elem));         \
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem = (type)(reader).ptr;                                 \
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_NEXT_SEQ_ELEM( sizeof(*elem), reader )                  \
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define _CV_IS_SITE_REFLEX( SITE )  ((SITE) ->node[0] == (SITE) ->node[1])
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define _CV_IS_EDGE_REFLEX( EDGE )  (( (EDGE)->site[0]->node[0] == (EDGE)->site[0]->node[0] ) || \
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                      ( (EDGE)->site[1]->node[0] == (EDGE)->site[1]->node[0] ) )
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define _CV_INITIALIZE_CVLCMDATA(STRUCT,SITE,EDGE,NODE)\
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ (STRUCT)->psite = SITE ; (STRUCT)->pedge = EDGE; (STRUCT)->pnode = NODE;}
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F///////////////////////////////////////////////////////////////////////////////////////
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Author:  Andrey Sobolev
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Name:    _cvConstructLCM
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Purpose: Function constructs hybrid model
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Context:
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Parameters:
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      LCM : in&out.
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Returns: 1, if hybrid model was succesfully constructed
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//             0, if some error occures
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint _cvConstructLCM(CvLCM* LCM);
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F///////////////////////////////////////////////////////////////////////////////////////
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Author:  Andrey Sobolev
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Name:    _cvConstructLCMComplexNode
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Purpose: Function constructs Complex Node (node, which consists of
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//             two points and more) of hybrid model
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Context:
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Parameters:
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCM : in&out.
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCMEdge: in, input edge of hybrid model
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCMInputData: in, input parameters
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Returns: pointer to constructed node
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLCMNode* _cvConstructLCMComplexNode(CvLCM* pLCM,
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                      CvLCMEdge* pLCMEdge,
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                      CvLCMData* pLCMInputData);
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F///////////////////////////////////////////////////////////////////////////////////////
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Author:  Andrey Sobolev
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Name:    _cvConstructLCMSimpleNode
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Purpose: Function constructs Simple Node (node, which consists of
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//             one point) of hybrid model
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Context:
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Parameters:
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCM : in&out.
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCMEdge: in, input edge of hybrid model
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCMInputData: in, input parameters
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Returns: pointer to constructed node
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLCMNode* _cvConstructLCMSimpleNode(CvLCM* pLCM,
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    CvLCMEdge* pLCMEdge,
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    CvLCMData* pLCMInputData);
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F///////////////////////////////////////////////////////////////////////////////////////
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Author:  Andrey Sobolev
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Name:    _cvConstructLCMSimpleNode
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Purpose: Function constructs Edge of hybrid model
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Context:
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Parameters:
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCM : in&out.
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCMInputData: in, input parameters
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Returns: pointer to constructed edge
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLCMEdge* _cvConstructLCMEdge(CvLCM* pLCM,
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               CvLCMData* pLCMInputData);
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F///////////////////////////////////////////////////////////////////////////////////////
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Author:  Andrey Sobolev
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Name:    _cvTreatExeptionalCase
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Purpose: Function treats triangles and regular polygons
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Context:
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Parameters:
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCM : in, information about graph
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCMInputData: in, input parameters
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Returns: pointer to graph node
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLCMNode* _cvTreatExeptionalCase(CvLCM* pLCM,
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  CvLCMData* pLCMInputData);
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F///////////////////////////////////////////////////////////////////////////////////////
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Author:  Andrey Sobolev
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Name:    _cvNodeMultyplicity
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Purpose: Function seeks all non-boundary edges incident to
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//              given node and correspondent incident sites
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Context:
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Parameters:
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pEdge : in, original edge
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pNode : in, given node
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      LinkedEdges : out, matrix of incident edges
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      LinkedSites : out, matrix of incident sites
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pSite: in, original site (pNode must be the begin point of pEdge
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//              for this pSite, this property hold out far all edges)
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Returns: number of incident edges (must be less than 10)
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint _cvNodeMultyplicity(CvVoronoiSite2D* pSite,
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvVoronoiEdge2D* pEdge,
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvVoronoiNode2D* pNode,
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvVoronoiEdge2D** LinkedEdges,
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvVoronoiSite2D** LinkedSites);
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F///////////////////////////////////////////////////////////////////////////////////////
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Author:  Andrey Sobolev
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Name:    _cvCreateLCMNode
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Purpose: Function create graph node
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Context:
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Parameters:
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCM : in, information about graph
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Returns: pointer to graph node
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLCMNode* _cvCreateLCMNode(CvLCM* pLCM);
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F///////////////////////////////////////////////////////////////////////////////////////
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Author:  Andrey Sobolev
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Name:    _cvCreateLCMEdge
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Purpose: Function create graph edge
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Context:
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Parameters:
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCM : in, information about graph
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Returns: pointer to graph edge
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLCMEdge* _cvCreateLCMEdge(CvLCM* pLCM);
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F///////////////////////////////////////////////////////////////////////////////////////
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Author:  Andrey Sobolev
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Name:    _cvCreateLCMNode
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Purpose: Function establishs the connection between node and ege
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Context:
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Parameters:
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      LCMNode : in, graph node
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      LCMEdge : in, graph edge
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      LCMEdge_prev : in&out, previous edge, connected with given node
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      index: in,
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      i    : =0, if node is initial for edge
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//             =1, if node  is terminal for edge
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Returns:
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid _cvAttachLCMEdgeToLCMNode(CvLCMNode* LCMNode,
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               CvLCMEdge* LCMEdge,
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               CvLCMEdge* &LCMEdge_prev,
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               int index,
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               int i);
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F///////////////////////////////////////////////////////////////////////////////////////
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Author:  Andrey Sobolev
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Name:    _cvProjectionPointToSegment
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Purpose: Function computes the ortogonal projection of PointO to
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//             to segment[PointA, PointB]
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Context:
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Parameters:
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      PointO, PointA,PointB: in, given points
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      PrPoint : out, projection
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      dist : distance from PointO to PrPoint
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Returns:
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid _cvProjectionPointToSegment(CvPoint2D32f* PointO,
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 CvPoint2D32f* PointA,
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 CvPoint2D32f* PointB,
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 CvPoint2D32f* PrPoint,
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 float* dist);
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F///////////////////////////////////////////////////////////////////////////////////////
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Author:  Andrey Sobolev
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Name:    _cvPrepareData
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Purpose: Function fills up the struct CvLCMComplexNodeData
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Context:
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Parameters:
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCMData : in
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      pLCMCCNData : out
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    Returns:
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid _cvPrepareData(CvLCMComplexNodeData* pLCMCCNData,
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CvLCMData* pLCMData);
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                                    Function realization                               *
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvGraph* cvLinearContorModelFromVoronoiDiagram(CvVoronoiDiagram2D* VoronoiDiagram,
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                       float maxWidth)
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* LCMstorage;
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSet* SiteSet;
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCM LCM = {NULL, VoronoiDiagram,NULL,NULL,maxWidth};
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvLinearContorModelFromVoronoiDiagram" );
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     __BEGIN__;
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !VoronoiDiagram )
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg,"Voronoi Diagram is not defined" );
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( maxWidth < 0 )
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg,"Treshold parameter must be non negative" );
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(SiteSet = VoronoiDiagram->sites;
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        SiteSet != NULL;
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        SiteSet = (CvSet*)SiteSet->h_next)
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if(SiteSet->v_next)
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg,"Can't operate with multiconnected domains" );
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if(SiteSet->total > 70000)
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg,"Can't operate with large domains" );
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    LCMstorage = cvCreateMemStorage(0);
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    LCM.EdgeStorage = cvCreateChildMemStorage(LCMstorage);
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    LCM.ContourStorage = cvCreateChildMemStorage(LCMstorage);
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    LCM.Graph = cvCreateGraph(CV_SEQ_KIND_GRAPH|CV_GRAPH_FLAG_ORIENTED,
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              sizeof(CvGraph),
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              sizeof(CvLCMNode),
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              sizeof(CvLCMEdge),
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              LCMstorage);
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(!_cvConstructLCM(&LCM))
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvReleaseLinearContorModelStorage(&LCM.Graph);
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return LCM.Graph;
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of cvLinearContorModelFromVoronoiDiagram
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int cvReleaseLinearContorModelStorage(CvGraph** Graph)
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* LCMNodeSeq, *LCMEdgeSeq;
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMNode* pLCMNode;
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMEdge* pLCMEdge;
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /*CV_FUNCNAME( "cvReleaseLinearContorModelStorage" );*/
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     __BEGIN__;
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(!Graph || !(*Graph))
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return 0;
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    LCMNodeSeq = (CvSeq*)(*Graph);
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    LCMEdgeSeq = (CvSeq*)(*Graph)->edges;
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(LCMNodeSeq->total > 0)
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pLCMNode = (CvLCMNode*)cvGetSeqElem(LCMNodeSeq,0);
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if(pLCMNode->contour->storage)
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvReleaseMemStorage(&pLCMNode->contour->storage);
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(LCMEdgeSeq->total > 0)
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pLCMEdge = (CvLCMEdge*)cvGetSeqElem(LCMEdgeSeq,0);
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if(pLCMEdge->chain->storage)
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvReleaseMemStorage(&pLCMEdge->chain->storage);
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if((*Graph)->storage)
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvReleaseMemStorage(&(*Graph)->storage);
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *Graph = NULL;
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return 1;
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of cvReleaseLinearContorModelStorage
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint _cvConstructLCM(CvLCM* LCM)
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiSite2D* pSite = 0;
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiEdge2D* pEdge = 0, *pEdge1;
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiNode2D* pNode, *pNode1;
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiEdge2D* LinkedEdges[10];
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiSite2D* LinkedSites[10];
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMData LCMdata;
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(CvSet* SiteSet = LCM->VoronoiDiagram->sites;
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        SiteSet != NULL;
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        SiteSet = (CvSet*)SiteSet->h_next)
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartReadSeq((CvSeq*)SiteSet, &reader);
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for(i = 0; i < SiteSet->total; i++)
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            _CV_READ_SEQ_ELEM(pSite,reader,CvVoronoiSite2D*);
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if(pSite->node[0] == pSite->node[1])
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                continue;
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            pEdge = CV_LAST_VORONOIEDGE2D(pSite);
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            pNode = CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite);
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if(pNode->radius > LCM->maxWidth)
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                goto PREPARECOMPLEXNODE;
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            pEdge1 = CV_PREV_VORONOIEDGE2D(pEdge,pSite);
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            pNode1 = CV_VORONOIEDGE2D_BEGINNODE(pEdge1,pSite);
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if(pNode1->radius > LCM->maxWidth)
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                goto PREPARECOMPLEXNODE;
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if(pNode1->radius == 0)
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                continue;
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if(_cvNodeMultyplicity(pSite, pEdge,pNode,LinkedEdges,LinkedSites) == 1)
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                goto PREPARESIMPLENODE;
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// treate triangle or regular polygon
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _CV_INITIALIZE_CVLCMDATA(&LCMdata,pSite,pEdge,CV_VORONOIEDGE2D_ENDNODE(pEdge,pSite));
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if(!_cvTreatExeptionalCase(LCM,&LCMdata))
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return 0;
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        continue;
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennPREPARECOMPLEXNODE:
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _CV_INITIALIZE_CVLCMDATA(&LCMdata,pSite,pEdge,CV_VORONOIEDGE2D_ENDNODE(pEdge,pSite));
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if(!_cvConstructLCMComplexNode(LCM,NULL,&LCMdata))
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return 0;
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        continue;
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennPREPARESIMPLENODE:
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _CV_INITIALIZE_CVLCMDATA(&LCMdata,pSite,pEdge,CV_VORONOIEDGE2D_ENDNODE(pEdge,pSite));
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if(!_cvConstructLCMSimpleNode(LCM,NULL,&LCMdata))
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return 0;
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        continue;
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return 1;
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of _cvConstructLCM
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLCMNode* _cvConstructLCMComplexNode(CvLCM* pLCM,
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                      CvLCMEdge* pLCMEdge,
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                      CvLCMData* pLCMInputData)
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMNode* pLCMNode;
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMEdge* pLCMEdge_prev = NULL;
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqWriter writer;
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiSite2D* pSite, *pSite_first, *pSite_last;
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiEdge2D* pEdge, *pEdge_stop;
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiNode2D* pNode0, *pNode1;
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMData LCMOutputData;
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMComplexNodeData LCMCCNData;
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int index = 0;
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _cvPrepareData(&LCMCCNData,pLCMInputData);
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pLCMNode = _cvCreateLCMNode(pLCM);
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _cvAttachLCMEdgeToLCMNode(pLCMNode,pLCMEdge,pLCMEdge_prev,1,1);
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartAppendToSeq((CvSeq*)pLCMNode->contour,&writer);
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_WRITE_SEQ_ELEM(LCMCCNData.site_last_pt, writer);
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    index++;
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(pLCMEdge)
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_WRITE_SEQ_ELEM(LCMCCNData.edge_node.pt, writer );
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_WRITE_SEQ_ELEM(LCMCCNData.site_first_pt, writer );
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        index+=2;
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pSite_first = LCMCCNData.site_first;
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pSite_last = LCMCCNData.site_last;
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pEdge = LCMCCNData.edge;
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(pSite = pSite_first;
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pSite != pSite_last;
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pSite = CV_NEXT_VORONOISITE2D(pSite),
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pEdge = CV_PREV_VORONOIEDGE2D(CV_LAST_VORONOIEDGE2D(pSite),pSite))
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pEdge_stop = CV_FIRST_VORONOIEDGE2D(pSite);
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for(;pEdge && pEdge != pEdge_stop;
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn             pEdge = CV_PREV_VORONOIEDGE2D(pEdge,pSite))
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            pNode0 = CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite);
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            pNode1 = CV_VORONOIEDGE2D_ENDNODE(pEdge,pSite);
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if(pNode0->radius <= pLCM->maxWidth && pNode1->radius <= pLCM->maxWidth)
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                _CV_INITIALIZE_CVLCMDATA(&LCMOutputData,pSite,pEdge,pNode1);
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                _cvPrepareData(&LCMCCNData,&LCMOutputData);
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_WRITE_SEQ_ELEM(LCMCCNData.site_first_pt, writer);
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_WRITE_SEQ_ELEM(LCMCCNData.edge_node.pt, writer );
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                index+=2;
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                pLCMEdge = _cvConstructLCMEdge(pLCM,&LCMOutputData);
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                _cvAttachLCMEdgeToLCMNode(pLCMNode,pLCMEdge,pLCMEdge_prev,index - 1,0);
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_WRITE_SEQ_ELEM(LCMCCNData.site_last_pt, writer);
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                index++;
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                pSite = CV_TWIN_VORONOISITE2D(pSite,pEdge);
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                pEdge_stop = CV_FIRST_VORONOIEDGE2D(pSite);
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if(pSite == pSite_last)
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if(pSite == pSite_last)
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_WRITE_SEQ_ELEM(pSite->node[1]->pt, writer);
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        index++;
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(pLCMEdge_prev)
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pLCMEdge_prev->next[(pLCMEdge_prev == (CvLCMEdge*)pLCMNode->first)] = pLCMNode->first;
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteSeq(&writer);
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return pLCMNode;
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of _cvConstructLCMComplexNode
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLCMNode* _cvConstructLCMSimpleNode(CvLCM* pLCM,
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                     CvLCMEdge* pLCMEdge,
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                     CvLCMData* pLCMInputData)
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiEdge2D* pEdge = pLCMInputData->pedge;
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiSite2D* pSite = pLCMInputData->psite;
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiNode2D* pNode = CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite);
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiEdge2D* LinkedEdges[10];
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiSite2D* LinkedSites[10];
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int multyplicity = _cvNodeMultyplicity(pSite,pEdge,pNode,LinkedEdges,LinkedSites);
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(multyplicity == 2)
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pLCMInputData->pedge = LinkedEdges[1];
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pLCMInputData->psite = CV_TWIN_VORONOISITE2D(LinkedSites[1],LinkedEdges[1]);
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return NULL;
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMEdge* pLCMEdge_prev = NULL;
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMNode* pLCMNode;
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMData LCMOutputData;
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pLCMNode = _cvCreateLCMNode(pLCM);
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSeqPush((CvSeq*)pLCMNode->contour,&pNode->pt);
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _cvAttachLCMEdgeToLCMNode(pLCMNode,pLCMEdge,pLCMEdge_prev,0,1);
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(int i = (int)(pLCMEdge != NULL);i < multyplicity; i++)
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pEdge = LinkedEdges[i];
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pSite = LinkedSites[i];
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _CV_INITIALIZE_CVLCMDATA(&LCMOutputData,CV_TWIN_VORONOISITE2D(pSite,pEdge),pEdge,pNode);
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pLCMEdge = _cvConstructLCMEdge(pLCM,&LCMOutputData);
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _cvAttachLCMEdgeToLCMNode(pLCMNode,pLCMEdge,pLCMEdge_prev,0,0);
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pLCMEdge_prev->next[(pLCMEdge_prev == (CvLCMEdge*)pLCMNode->first)] = pLCMNode->first;
5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return pLCMNode;
5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of _cvConstructLCMSimpleNode
5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLCMEdge* _cvConstructLCMEdge(CvLCM* pLCM,
5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               CvLCMData* pLCMInputData)
5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiEdge2D* pEdge = pLCMInputData->pedge;
5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiSite2D* pSite = pLCMInputData->psite;
5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float width = 0;
5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMData LCMData;
5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiNode2D* pNode0,*pNode1;
5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMEdge* pLCMEdge = _cvCreateLCMEdge(pLCM);
5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqWriter writer;
5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartAppendToSeq(pLCMEdge->chain,&writer );
5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pNode0 = pNode1 = pLCMInputData->pnode;
5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_WRITE_SEQ_ELEM(pNode0->pt, writer);
5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width += pNode0->radius;
5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(int counter = 0;
5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            counter < pLCM->VoronoiDiagram->edges->total;
5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            counter++)
5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pNode1 = CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite);
5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if(pNode1->radius >= pLCM->maxWidth)
5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            goto CREATECOMPLEXNODE;
5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_WRITE_SEQ_ELEM(pNode1->pt,writer);
5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        width += pNode1->radius;
5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _CV_INITIALIZE_CVLCMDATA(&LCMData,pSite,pEdge,pNode1);
5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if(_cvConstructLCMSimpleNode(pLCM,pLCMEdge,&LCMData))
5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            goto LCMEDGEEXIT;
5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pEdge = LCMData.pedge; pSite = LCMData.psite;
5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pNode0 = pNode1;
5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return NULL;
5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCREATECOMPLEXNODE:
5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _CV_INITIALIZE_CVLCMDATA(&LCMData,pSite,pEdge,pNode0);
5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_WRITE_SEQ_ELEM(LCMData.pnode->pt,writer);
5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width += LCMData.pnode->radius;
5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _cvConstructLCMComplexNode(pLCM,pLCMEdge,&LCMData);
5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennLCMEDGEEXIT:
5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteSeq(&writer);
5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pLCMEdge->width = width/pLCMEdge->chain->total;
5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return pLCMEdge;
5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of _cvConstructLCMEdge
5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLCMNode* _cvTreatExeptionalCase(CvLCM* pLCM,
5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  CvLCMData* pLCMInputData)
5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiEdge2D* pEdge = pLCMInputData->pedge;
5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiSite2D* pSite = pLCMInputData->psite;
5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiNode2D* pNode = CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite);
5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMNode* pLCMNode = _cvCreateLCMNode(pLCM);
5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSeqPush((CvSeq*)pLCMNode->contour,&pNode->pt);
5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return pLCMNode;
5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of _cvConstructLCMEdge
5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_INLINE
5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLCMNode* _cvCreateLCMNode(CvLCM* pLCM)
5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMNode* pLCMNode;
5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSetAdd((CvSet*)pLCM->Graph, NULL, (CvSetElem**)&pLCMNode );
5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pLCMNode->contour = (CvContour*)cvCreateSeq(0, sizeof(CvContour),
5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                   sizeof(CvPoint2D32f),pLCM->ContourStorage);
5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pLCMNode->first = NULL;
5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return pLCMNode;
5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of _cvCreateLCMNode
5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_INLINE
5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLCMEdge* _cvCreateLCMEdge(CvLCM* pLCM)
5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLCMEdge* pLCMEdge;
5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSetAdd( (CvSet*)(pLCM->Graph->edges), 0, (CvSetElem**)&pLCMEdge );
5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pLCMEdge->chain = cvCreateSeq(0, sizeof(CvSeq),sizeof(CvPoint2D32f),pLCM->EdgeStorage);
6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pLCMEdge->next[0] = pLCMEdge->next[1] = NULL;
6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pLCMEdge->vtx[0] =  pLCMEdge->vtx[1] = NULL;
6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pLCMEdge->index1 =  pLCMEdge->index2 = -1;
6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return pLCMEdge;
6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of _cvCreateLCMEdge
6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_INLINE
6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid _cvAttachLCMEdgeToLCMNode(CvLCMNode* LCMNode,
6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               CvLCMEdge* LCMEdge,
6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               CvLCMEdge* &LCMEdge_prev,
6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               int index,
6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               int i)
6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(!LCMEdge)
6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return;
6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(i==0)
6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        LCMEdge->index1 = index;
6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        LCMEdge->index2 = index;
6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    LCMEdge->vtx[i] = (CvGraphVtx*)LCMNode;
6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(!LCMEdge_prev)
6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        LCMNode->first = (CvGraphEdge*)LCMEdge;
6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      LCMEdge_prev->next[(LCMEdge_prev == (CvLCMEdge*)LCMNode->first)] = (CvGraphEdge*)LCMEdge;
6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        LCMEdge_prev->next[(LCMEdge_prev->vtx[0] != (CvGraphVtx*)LCMNode)] = (CvGraphEdge*)LCMEdge;
6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    LCMEdge->next[i] = LCMNode->first;
6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    LCMEdge_prev = LCMEdge;
6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of _cvAttachLCMEdgeToLCMNode
6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint _cvNodeMultyplicity(CvVoronoiSite2D* pSite,
6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvVoronoiEdge2D* pEdge,
6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvVoronoiNode2D* pNode,
6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvVoronoiEdge2D** LinkedEdges,
6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvVoronoiSite2D** LinkedSites)
6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(!pNode->radius)
6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return -1;
6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert(pNode == CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite));
6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int multyplicity = 0;
6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvVoronoiEdge2D* pEdge_cur = pEdge;
6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    do
6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if(pEdge_cur->node[0]->radius && pEdge_cur->node[1]->radius)
6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            LinkedEdges[multyplicity] = pEdge_cur;
6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            LinkedSites[multyplicity] = pSite;
6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            multyplicity++;
6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pEdge_cur = CV_PREV_VORONOIEDGE2D(pEdge_cur,pSite);
6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pSite = CV_TWIN_VORONOISITE2D(pSite,pEdge_cur);
6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }while(pEdge_cur != pEdge);
6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return multyplicity;
6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of _cvNodeMultyplicity
6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_INLINE
6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid _cvPrepareData(CvLCMComplexNodeData* pLCMCCNData,
6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CvLCMData* pLCMData)
6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pLCMCCNData->site_first = pLCMData->psite;
6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pLCMCCNData->site_last = CV_TWIN_VORONOISITE2D(pLCMData->psite,pLCMData->pedge);
6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(pLCMData->pedge == CV_LAST_VORONOIEDGE2D(pLCMData->psite))
6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pLCMCCNData->edge = CV_PREV_VORONOIEDGE2D(pLCMData->pedge,pLCMData->psite);
6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pLCMCCNData->edge_node = *pLCMData->pnode;
6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pLCMCCNData->site_first_pt = pLCMData->psite->node[0]->pt;
6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pLCMCCNData->site_last_pt = pLCMData->psite->node[0]->pt;
6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pLCMCCNData->edge = pLCMData->pedge;
6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pLCMCCNData->edge_node = *pLCMData->pnode;
6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _cvProjectionPointToSegment(&pLCMCCNData->edge_node.pt,
6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  &pLCMCCNData->site_first->node[0]->pt,
6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  &pLCMCCNData->site_first->node[1]->pt,
6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  &pLCMCCNData->site_first_pt,
6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  NULL);
6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _cvProjectionPointToSegment(&pLCMCCNData->edge_node.pt,
6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  &pLCMCCNData->site_last->node[0]->pt,
6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  &pLCMCCNData->site_last->node[1]->pt,
6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  &pLCMCCNData->site_last_pt,
6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  NULL);
6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of _cvPrepareData
6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid _cvProjectionPointToSegment(CvPoint2D32f* PointO,
6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 CvPoint2D32f* PointA,
6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 CvPoint2D32f* PointB,
6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 CvPoint2D32f* PrPoint,
6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 float* dist)
6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float scal_AO_AB, scal_AB_AB;
6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint2D32f VectorAB = {PointB->x - PointA->x, PointB->y - PointA->y};
6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scal_AB_AB = VectorAB.x*VectorAB.x + VectorAB.y*VectorAB.y;
6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(scal_AB_AB < LCM_CONST_ZERO)
7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *PrPoint = *PointA;
7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if(dist)
7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *dist = (float)sqrt( (double)(PointO->x -PointA->x)*(PointO->x -PointA->x) + (PointO->y - PointA->y)*(PointO->y - PointA->y));
7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return;
7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint2D32f VectorAO = {PointO->x - PointA->x, PointO->y - PointA->y};
7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scal_AO_AB = VectorAO.x*VectorAB.x + VectorAO.y*VectorAB.y;
7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(dist)
7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        float vector_AO_AB = (float)fabs(VectorAO.x*VectorAB.y - VectorAO.y*VectorAB.x);
7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *dist = (float)(vector_AO_AB/sqrt((double)scal_AB_AB));
7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float alfa = scal_AO_AB/scal_AB_AB;
7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    PrPoint->x = PointO->x - VectorAO.x + alfa*VectorAB.x;
7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    PrPoint->y = PointO->y - VectorAO.y + alfa*VectorAB.y;
7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return;
7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}//end of _cvProjectionPointToSegment
7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
725