agg_conv_gpc.h

来自「这是VCF框架的代码」· C头文件 代码 · 共 438 行

H
438
字号
//----------------------------------------------------------------------------// Anti-Grain Geometry - Version 2.4// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)//// Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied// warranty, and with no claim as to its suitability for any purpose.////----------------------------------------------------------------------------// Contact: mcseem@antigrain.com//          mcseemagg@yahoo.com//          http://www.antigrain.com//----------------------------------------------------------------------------//// General Polygon Clipper based on the GPC library by Alan Murta // Union, Intersection, XOR, A-B, B-A// Contact the author if you intend to use it in commercial applications!// http://www.cs.man.ac.uk/aig/staff/alan/software/// Alan Murta (email: gpc@cs.man.ac.uk)////----------------------------------------------------------------------------#ifndef AGG_CONV_GPC_INCLUDED#define AGG_CONV_GPC_INCLUDED#include <math.h>#include "agg_basics.h"#include "agg_array.h"extern "C" { #include "gpc.h" }namespace agg{    enum gpc_op_e    {        gpc_or,        gpc_and,        gpc_xor,        gpc_a_minus_b,        gpc_b_minus_a    };    //================================================================conv_gpc    template<class VSA, class VSB> class conv_gpc    {        enum status        {            status_move_to,            status_line_to,            status_stop        };        struct contour_header_type        {            int num_vertices;            int hole_flag;            gpc_vertex* vertices;        };        typedef pod_bvector<gpc_vertex, 8>          vertex_array_type;        typedef pod_bvector<contour_header_type, 6> contour_header_array_type;    public:        typedef VSA source_a_type;        typedef VSB source_b_type;        typedef conv_gpc<source_a_type, source_b_type> self_type;        ~conv_gpc()        {            free_gpc_data();        }        conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) :            m_src_a(&a),            m_src_b(&b),            m_status(status_move_to),            m_vertex(-1),            m_contour(-1),            m_operation(op)        {            memset(&m_poly_a, 0, sizeof(m_poly_a));            memset(&m_poly_b, 0, sizeof(m_poly_b));            memset(&m_result, 0, sizeof(m_result));        }        void attach1(VSA& source) { m_src_a = &source; }        void attach2(VSB& source) { m_src_b = &source; }        void operation(gpc_op_e v) { m_operation = v; }        // Vertex Source Interface        void     rewind(unsigned path_id);        unsigned vertex(double* x, double* y);    private:        conv_gpc(const conv_gpc<VSA, VSB>&);        const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&);        //--------------------------------------------------------------------        void free_polygon(gpc_polygon& p);        void free_result();        void free_gpc_data();        void start_contour();        void add_vertex(double x, double y);        void end_contour(unsigned orientation);        void make_polygon(gpc_polygon& p);        void start_extracting();        bool next_contour();        bool next_vertex(double* x, double* y);        //--------------------------------------------------------------------        template<class VS> void add(VS& src, gpc_polygon& p)        {            unsigned cmd;            double x, y;            double start_x = 0.0;            double start_y = 0.0;            bool line_to = false;            unsigned orientation = 0;            m_contour_accumulator.remove_all();            while(!is_stop(cmd = src.vertex(&x, &y)))            {                if(is_vertex(cmd))                {                    if(is_move_to(cmd))                    {                        if(line_to)                        {                            end_contour(orientation);                            orientation = 0;                        }                        start_contour();                        start_x = x;                        start_y = y;                    }                    add_vertex(x, y);                    line_to = true;                }                else                {                    if(is_end_poly(cmd))                    {                        orientation = get_orientation(cmd);                        if(line_to && is_closed(cmd))                        {                            add_vertex(start_x, start_y);                        }                    }                }            }            if(line_to)            {                end_contour(orientation);            }            make_polygon(p);        }    private:        //--------------------------------------------------------------------        source_a_type*             m_src_a;        source_b_type*             m_src_b;        status                     m_status;        int                        m_vertex;        int                        m_contour;        gpc_op_e                   m_operation;        vertex_array_type          m_vertex_accumulator;        contour_header_array_type  m_contour_accumulator;        gpc_polygon                m_poly_a;        gpc_polygon                m_poly_b;        gpc_polygon                m_result;    };    //------------------------------------------------------------------------    template<class VSA, class VSB>     void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p)    {        int i;        for(i = 0; i < p.num_contours; i++)        {            delete [] p.contour[i].vertex;        }        delete [] p.hole;        delete [] p.contour;        memset(&p, 0, sizeof(gpc_polygon));    }    //------------------------------------------------------------------------    template<class VSA, class VSB>     void conv_gpc<VSA, VSB>::free_result()    {        if(m_result.contour)        {            gpc_free_polygon(&m_result);        }        memset(&m_result, 0, sizeof(m_result));    }    //------------------------------------------------------------------------    template<class VSA, class VSB>     void conv_gpc<VSA, VSB>::free_gpc_data()    {        free_polygon(m_poly_a);        free_polygon(m_poly_b);        free_result();    }    //------------------------------------------------------------------------    template<class VSA, class VSB>     void conv_gpc<VSA, VSB>::start_contour()    {        contour_header_type h;        memset(&h, 0, sizeof(h));        m_contour_accumulator.add(h);        m_vertex_accumulator.remove_all();    }    //------------------------------------------------------------------------    template<class VSA, class VSB>     inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y)    {        gpc_vertex v;        v.x = x;        v.y = y;        m_vertex_accumulator.add(v);    }    //------------------------------------------------------------------------    template<class VSA, class VSB>     void conv_gpc<VSA, VSB>::end_contour(unsigned orientation)    {        if(m_contour_accumulator.size())        {            if(m_vertex_accumulator.size() > 2)            {                contour_header_type& h =                     m_contour_accumulator[m_contour_accumulator.size() - 1];                h.num_vertices = m_vertex_accumulator.size();                h.hole_flag = 0;                // TO DO: Clarify the "holes"                //if(is_cw(orientation)) h.hole_flag = 1;                h.vertices = new gpc_vertex [h.num_vertices];                gpc_vertex* d = h.vertices;                int i;                for(i = 0; i < h.num_vertices; i++)                {                    const gpc_vertex& s = m_vertex_accumulator[i];                    d->x = s.x;                    d->y = s.y;                    ++d;                }            }            else            {                m_vertex_accumulator.remove_last();            }        }    }    //------------------------------------------------------------------------    template<class VSA, class VSB>     void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p)    {        free_polygon(p);        if(m_contour_accumulator.size())        {            p.num_contours = m_contour_accumulator.size();            // TO DO: Clarify the "holes"            //p.hole = new int[p.num_contours];            p.hole = 0;            p.contour = new gpc_vertex_list[p.num_contours];            int i;            //int* ph = p.hole;            gpc_vertex_list* pv = p.contour;            for(i = 0; i < p.num_contours; i++)            {                const contour_header_type& h = m_contour_accumulator[i];                // *ph++ = h.hole_flag;                pv->num_vertices = h.num_vertices;                pv->vertex = h.vertices;                ++pv;            }        }    }    //------------------------------------------------------------------------    template<class VSA, class VSB>     void conv_gpc<VSA, VSB>::start_extracting()    {        m_status = status_move_to;        m_contour = -1;        m_vertex = -1;    }    //------------------------------------------------------------------------    template<class VSA, class VSB>     bool conv_gpc<VSA, VSB>::next_contour()    {        if(++m_contour < m_result.num_contours)        {            m_vertex = -1;            return true;        }        return false;    }    //------------------------------------------------------------------------    template<class VSA, class VSB>     inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y)    {        const gpc_vertex_list& vlist = m_result.contour[m_contour];        if(++m_vertex < vlist.num_vertices)        {            const gpc_vertex& v = vlist.vertex[m_vertex];            *x = v.x;            *y = v.y;            return true;        }        return false;    }    //------------------------------------------------------------------------    template<class VSA, class VSB>     void conv_gpc<VSA, VSB>::rewind(unsigned path_id)    {        free_result();        m_src_a->rewind(path_id);        m_src_b->rewind(path_id);        add(*m_src_a, m_poly_a);        add(*m_src_b, m_poly_b);        switch(m_operation)        {           case gpc_or:                gpc_polygon_clip(GPC_UNION,                                 &m_poly_a,                                 &m_poly_b,                                 &m_result);               break;           case gpc_and:                gpc_polygon_clip(GPC_INT,                                 &m_poly_a,                                 &m_poly_b,                                 &m_result);               break;           case gpc_xor:                gpc_polygon_clip(GPC_XOR,                                 &m_poly_a,                                 &m_poly_b,                                 &m_result);               break;           case gpc_a_minus_b:                gpc_polygon_clip(GPC_DIFF,                                 &m_poly_a,                                 &m_poly_b,                                 &m_result);               break;           case gpc_b_minus_a:                gpc_polygon_clip(GPC_DIFF,                                 &m_poly_b,                                 &m_poly_a,                                 &m_result);               break;        }        start_extracting();    }    //------------------------------------------------------------------------    template<class VSA, class VSB>     unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y)    {        if(m_status == status_move_to)        {            if(next_contour())             {                if(next_vertex(x, y))                {                    m_status = status_line_to;                    return path_cmd_move_to;                }                m_status = status_stop;                return path_cmd_end_poly | path_flags_close;            }        }        else        {            if(next_vertex(x, y))            {                return path_cmd_line_to;            }            else            {                m_status = status_move_to;            }            return path_cmd_end_poly | path_flags_close;        }        return path_cmd_stop;    }   }#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?