天天看點

47、使用c++的tinyxml對svg圖形進行算法處理

基本思想:使用c++的tinyxml實作svg圖形進行算法處理,需要預先編譯boost和opencv

​​ Mingw32編譯boost,并使用Clion測試_sxj731533730-​​

clion目錄

47、使用c++的tinyxml對svg圖形進行算法處理

cmakelists.txt

cmake_minimum_required(VERSION 3.16)
project(untitled)

set(CMAKE_CXX_STANDARD 14)
include_directories(${CMAKE_SOURCE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/include)
set(OpenCV_DIR "D:\\Opencv440\\buildMinGW")#改為mingw-bulid的位置
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_library(libboost STATIC IMPORTED)
set_target_properties(libboost PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/boost.a)


add_executable(untitled main.cpp tinystr.cpp tinyxml.cpp tinyxmlparser.cpp tinyxmlerror.cpp )

target_link_libraries(untitled ${OpenCV_LIBS} libboost)      

代碼

#include <iostream>
#include<string>
#include<vector>
#include <map>

#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "tinyxml.h"
#include <fstream>
#include <iostream>

#include <boost/geometry.hpp> // read_wkt
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry/algorithms/union.hpp>



using namespace cv;
using namespace std;
using PointType = boost::geometry::model::d2::point_xy<int>;
using PolygonType = boost::geometry::model::polygon<PointType>;
using MultiPolygonType = boost::geometry::model::multi_polygon<PolygonType>;

template <typename TPolygon>

void WritePolygonsToSVG(const std::vector<TPolygon>& polygons, const std::string& filename)
{
    std::ofstream svg(filename);

    boost::geometry::svg_mapper<PointType> mapper(svg, 400, 400);

    for(unsigned int i = 0; i < polygons.size(); ++i) {

        mapper.add(polygons[i]);
        mapper.map(polygons[i], "fill:rgb(255,128,0);stroke:rgb(0,0,100);stroke-width:1");
    }

}

void createCircleSVG(TiXmlDocument &xml_doc) {


    // 添加XML聲明
    xml_doc.LinkEndChild(new TiXmlDeclaration("1.0", "GBK", ""));
    // 添加根元素
    TiXmlElement *xml_html = new TiXmlElement("html");
    xml_doc.LinkEndChild(xml_html);


    // 嵌套子元素
    TiXmlElement *xml_body = new TiXmlElement("body");
    xml_html->LinkEndChild(xml_body);

    TiXmlElement *xml_h1 = new TiXmlElement("h1");
    xml_h1->LinkEndChild(new TiXmlText("My first SVG"));
    xml_body->LinkEndChild(xml_h1);


    TiXmlElement *xml_circle = new TiXmlElement("circle");
    xml_circle->SetAttribute("cx", "100");
    xml_circle->SetAttribute("cy", "50");
    xml_circle->SetAttribute("r", "40");
    xml_circle->SetAttribute("stroke", "black");
    xml_circle->SetAttribute("stroke-width", "2");
    xml_circle->SetAttribute("fill", "none");


    TiXmlElement *xml_svg = new TiXmlElement("svg");
    xml_svg->SetAttribute("xmlns", "http://www.w3.org/2000/svg");
    xml_svg->SetAttribute("version", "1.1");


    xml_svg->LinkEndChild(xml_circle);
    xml_body->LinkEndChild(xml_svg);


}

void createEllipseSVG(TiXmlDocument &xml_doc) {


    // 添加XML聲明
    xml_doc.LinkEndChild(new TiXmlDeclaration("1.0", "GBK", ""));
    // 添加根元素
    TiXmlElement *xml_html = new TiXmlElement("html");
    xml_doc.LinkEndChild(xml_html);


    // 嵌套子元素
    TiXmlElement *xml_body = new TiXmlElement("body");
    xml_html->LinkEndChild(xml_body);

    TiXmlElement *xml_h1 = new TiXmlElement("h1");
    xml_h1->LinkEndChild(new TiXmlText("My first SVG"));
    xml_body->LinkEndChild(xml_h1);


    TiXmlElement *xml_ellipse = new TiXmlElement("ellipse");
    xml_ellipse->SetAttribute("cx", "300");
    xml_ellipse->SetAttribute("cy", "80");
    xml_ellipse->SetAttribute("rx", "100");
    xml_ellipse->SetAttribute("ry", "50");
    xml_ellipse->SetAttribute("stroke", "black");
    xml_ellipse->SetAttribute("stroke-width", "2");
    xml_ellipse->SetAttribute("fill", "red");


    TiXmlElement *xml_svg = new TiXmlElement("svg");
    xml_svg->SetAttribute("xmlns", "http://www.w3.org/2000/svg");
    xml_svg->SetAttribute("version", "1.1");
    xml_svg->LinkEndChild(xml_ellipse);
    xml_body->LinkEndChild(xml_svg);


}

void createRectSVG(TiXmlDocument &xml_doc) {


    // 添加XML聲明
    xml_doc.LinkEndChild(new TiXmlDeclaration("1.0", "GBK", ""));
    // 添加根元素
    TiXmlElement *xml_html = new TiXmlElement("html");
    xml_doc.LinkEndChild(xml_html);


    // 嵌套子元素
    TiXmlElement *xml_body = new TiXmlElement("body");
    xml_html->LinkEndChild(xml_body);

    TiXmlElement *xml_h1 = new TiXmlElement("h1");
    xml_h1->LinkEndChild(new TiXmlText("My first SVG"));
    xml_body->LinkEndChild(xml_h1);


    TiXmlElement *xml_rect = new TiXmlElement("rect");
    xml_rect->SetAttribute("x", "300");
    xml_rect->SetAttribute("y", "100");
    xml_rect->SetAttribute("width", "300");
    xml_rect->SetAttribute("height", "100");
    xml_rect->SetAttribute("stroke", "black");
    xml_rect->SetAttribute("stroke-width", "2");
    xml_rect->SetAttribute("fill", "none");


    TiXmlElement *xml_svg = new TiXmlElement("svg");
    xml_svg->SetAttribute("xmlns", "http://www.w3.org/2000/svg");
    xml_svg->SetAttribute("version", "1.1");
    xml_svg->LinkEndChild(xml_rect);
    xml_body->LinkEndChild(xml_svg);


}

void createPolygonSVG(TiXmlDocument &xml_doc) {


    // 添加XML聲明
    xml_doc.LinkEndChild(new TiXmlDeclaration("1.0", "GBK", ""));
    // 添加根元素
    TiXmlElement *xml_html = new TiXmlElement("html");
    xml_doc.LinkEndChild(xml_html);


    // 嵌套子元素
    TiXmlElement *xml_body = new TiXmlElement("body");
    xml_html->LinkEndChild(xml_body);

    TiXmlElement *xml_h1 = new TiXmlElement("h1");
    xml_h1->LinkEndChild(new TiXmlText("My first SVG"));
    xml_body->LinkEndChild(xml_h1);


    TiXmlElement *xml_polygon = new TiXmlElement("polygon");
    xml_polygon->SetAttribute("points", "200,10 250,190 160,210");
    xml_polygon->SetAttribute("stroke", "black");
    xml_polygon->SetAttribute("stroke-width", "2");
    xml_polygon->SetAttribute("fill", "none");


    TiXmlElement *xml_svg = new TiXmlElement("svg");
    xml_svg->SetAttribute("xmlns", "http://www.w3.org/2000/svg");
    xml_svg->SetAttribute("version", "1.1");
    xml_svg->LinkEndChild(xml_polygon);
    xml_body->LinkEndChild(xml_svg);


}

void createLineSVG(TiXmlDocument &xml_doc) {


    // 添加XML聲明
    xml_doc.LinkEndChild(new TiXmlDeclaration("1.0", "GBK", ""));
    // 添加根元素
    TiXmlElement *xml_html = new TiXmlElement("html");
    xml_doc.LinkEndChild(xml_html);


    // 嵌套子元素
    TiXmlElement *xml_body = new TiXmlElement("body");
    xml_html->LinkEndChild(xml_body);

    TiXmlElement *xml_h1 = new TiXmlElement("h1");
    xml_h1->LinkEndChild(new TiXmlText("My first SVG"));
    xml_body->LinkEndChild(xml_h1);


    TiXmlElement *xml_line = new TiXmlElement("line");
    xml_line->SetAttribute("x1", "100");
    xml_line->SetAttribute("y1", "100");
    xml_line->SetAttribute("x2", "400");
    xml_line->SetAttribute("y2", "400");
    xml_line->SetAttribute("stroke", "black");
    xml_line->SetAttribute("stroke-width", "2");
    xml_line->SetAttribute("fill", "none");


    TiXmlElement *xml_svg = new TiXmlElement("svg");
    xml_svg->SetAttribute("xmlns", "http://www.w3.org/2000/svg");
    xml_svg->SetAttribute("version", "1.1");
    xml_svg->LinkEndChild(xml_line);
    xml_body->LinkEndChild(xml_svg);


}

void createPolylineSVG(TiXmlDocument &xml_doc) {


    // 添加XML聲明
    xml_doc.LinkEndChild(new TiXmlDeclaration("1.0", "GBK", ""));
    // 添加根元素
    TiXmlElement *xml_html = new TiXmlElement("html");
    xml_doc.LinkEndChild(xml_html);


    // 嵌套子元素
    TiXmlElement *xml_body = new TiXmlElement("body");
    xml_html->LinkEndChild(xml_body);

    TiXmlElement *xml_h1 = new TiXmlElement("h1");
    xml_h1->LinkEndChild(new TiXmlText("My first SVG"));
    xml_body->LinkEndChild(xml_h1);


    TiXmlElement *xml_polyline = new TiXmlElement("polyline");
    xml_polyline->SetAttribute("points", "20,20 40,25 60,40 80,120 120,140 200,180");
    xml_polyline->SetAttribute("stroke", "black");
    xml_polyline->SetAttribute("stroke-width", "2");
    xml_polyline->SetAttribute("fill", "none");


    TiXmlElement *xml_svg = new TiXmlElement("svg");
    xml_svg->SetAttribute("xmlns", "http://www.w3.org/2000/svg");
    xml_svg->SetAttribute("version", "1.1");
    xml_svg->LinkEndChild(xml_polyline);
    xml_body->LinkEndChild(xml_svg);


}

void createPathSVG(TiXmlDocument &xml_doc) {


    // 添加XML聲明
    xml_doc.LinkEndChild(new TiXmlDeclaration("1.0", "GBK", ""));
    // 添加根元素
    TiXmlElement *xml_html = new TiXmlElement("html");
    xml_doc.LinkEndChild(xml_html);


    // 嵌套子元素
    TiXmlElement *xml_body = new TiXmlElement("body");
    xml_html->LinkEndChild(xml_body);

    TiXmlElement *xml_h1 = new TiXmlElement("h1");
    xml_h1->LinkEndChild(new TiXmlText("My first SVG"));
    xml_body->LinkEndChild(xml_h1);


    TiXmlElement *xml_path = new TiXmlElement("path");
    xml_path->SetAttribute("d", "M150 0 L75 200 L225 200 Z");
    xml_path->SetAttribute("stroke", "black");
    xml_path->SetAttribute("stroke-width", "2");
    xml_path->SetAttribute("fill", "none");


    TiXmlElement *xml_svg = new TiXmlElement("svg");
    xml_svg->SetAttribute("xmlns", "http://www.w3.org/2000/svg");
    xml_svg->SetAttribute("version", "1.1");
    xml_svg->LinkEndChild(xml_path);
    xml_body->LinkEndChild(xml_svg);


}

void parseCircleSVG(TiXmlDocument &xml_doc) {

    TiXmlHandle docHandle(&xml_doc);

    TiXmlElement *child = docHandle.FirstChild("html").FirstChild("body").FirstChild("svg").ToElement();


    for (child; child; child = child->NextSiblingElement()) {

        string xmlnsStr = child->Attribute("xmlns");
        string versionStr = child->Attribute("version");
        std::cout << "xmlns :" << xmlnsStr
                  << " version" << versionStr << std::endl;
        TiXmlElement *circleItem = child->FirstChild()->ToElement();

        string cxStr = circleItem->Attribute("cx");
        string cyStr = circleItem->Attribute("cy");
        string rStr = circleItem->Attribute("r");
        string strokeStr = circleItem->Attribute("stroke");
        string stroke_widthStr = circleItem->Attribute("stroke-width");
        string fillStr = circleItem->Attribute("fill");


        std::cout << "cx :" << cxStr
                  << " cy :" << cyStr
                  << " r :" << rStr
                  << " stroke :" << strokeStr
                  << " stroke-width :" << stroke_widthStr
                  << " fill :" << fillStr << std::endl;


    }


}

void parseRectSVG(TiXmlDocument &xml_doc) {

    TiXmlHandle docHandle(&xml_doc);

    TiXmlElement *child = docHandle.FirstChild("html").FirstChild("body").FirstChild("svg").ToElement();


    for (child; child; child = child->NextSiblingElement()) {

        string xmlnsStr = child->Attribute("xmlns");
        string versionStr = child->Attribute("version");
        std::cout << "xmlns :" << xmlnsStr
                  << " version" << versionStr << std::endl;
        TiXmlElement *circleItem = child->FirstChild()->ToElement();

        string xStr = circleItem->Attribute("x");
        string yStr = circleItem->Attribute("y");
        string widthStr = circleItem->Attribute("width");
        string heightStr = circleItem->Attribute("height");
        string strokeStr = circleItem->Attribute("stroke");
        string stroke_widthStr = circleItem->Attribute("stroke-width");
        string fillStr = circleItem->Attribute("fill");


        std::cout << "x :" << xStr
                  << " y :" << yStr
                  << " width :" << widthStr
                  << " height :" << heightStr
                  << " stroke :" << strokeStr
                  << " stroke-width :" << stroke_widthStr
                  << " fill :" << fillStr << std::endl;


    }


}

void parseEllipseSVG(TiXmlDocument &xml_doc) {

    TiXmlHandle docHandle(&xml_doc);

    TiXmlElement *child = docHandle.FirstChild("html").FirstChild("body").FirstChild("svg").ToElement();


    for (child; child; child = child->NextSiblingElement()) {

        string xmlnsStr = child->Attribute("xmlns");
        string versionStr = child->Attribute("version");
        std::cout << "xmlns :" << xmlnsStr
                  << " version" << versionStr << std::endl;
        TiXmlElement *circleItem = child->FirstChild()->ToElement();

        string cxStr = circleItem->Attribute("cx");
        string cyStr = circleItem->Attribute("cy");
        string rxStr = circleItem->Attribute("rx");
        string ryStr = circleItem->Attribute("ry");
        string strokeStr = circleItem->Attribute("stroke");
        string stroke_widthStr = circleItem->Attribute("stroke-width");
        string fillStr = circleItem->Attribute("fill");


        std::cout << "cx :" << cxStr
                  << " cy :" << cyStr
                  << " rx :" << rxStr
                  << " ry :" << ryStr
                  << " stroke :" << strokeStr
                  << " stroke-width :" << stroke_widthStr
                  << " fill :" << fillStr << std::endl;


    }


}

void parsePolygonSVG(TiXmlDocument &xml_doc) {

    TiXmlHandle docHandle(&xml_doc);

    TiXmlElement *child = docHandle.FirstChild("html").FirstChild("body").FirstChild("svg").ToElement();


    for (child; child; child = child->NextSiblingElement()) {

        string xmlnsStr = child->Attribute("xmlns");
        string versionStr = child->Attribute("version");
        std::cout << "xmlns :" << xmlnsStr
                  << " version" << versionStr << std::endl;
        TiXmlElement *circleItem = child->FirstChild()->ToElement();

        string pointsStr = circleItem->Attribute("points");

        string strokeStr = circleItem->Attribute("stroke");
        string stroke_widthStr = circleItem->Attribute("stroke-width");
        string fillStr = circleItem->Attribute("fill");


        std::cout << "points :" << pointsStr
                  << " stroke :" << strokeStr
                  << " stroke-width :" << stroke_widthStr
                  << " fill :" << fillStr << std::endl;


    }


}

void parseLineSVG(TiXmlDocument &xml_doc) {

    TiXmlHandle docHandle(&xml_doc);

    TiXmlElement *child = docHandle.FirstChild("html").FirstChild("body").FirstChild("svg").ToElement();


    for (child; child; child = child->NextSiblingElement()) {

        string xmlnsStr = child->Attribute("xmlns");
        string versionStr = child->Attribute("version");
        std::cout << "xmlns :" << xmlnsStr
                  << " version" << versionStr << std::endl;
        TiXmlElement *circleItem = child->FirstChild()->ToElement();

        string x1Str = circleItem->Attribute("x1");
        string y1Str = circleItem->Attribute("y1");
        string x2Str = circleItem->Attribute("x2");
        string y2Str = circleItem->Attribute("y2");
        string strokeStr = circleItem->Attribute("stroke");
        string stroke_widthStr = circleItem->Attribute("stroke-width");
        string fillStr = circleItem->Attribute("fill");


        std::cout << "x1 :" << x1Str
                  << " x1 :" << y1Str
                  << " x2 :" << x2Str
                  << " y2 :" << y2Str
                  << " stroke :" << strokeStr
                  << " stroke-width :" << stroke_widthStr
                  << " fill :" << fillStr << std::endl;


    }


}

void parsePolylineSVG(TiXmlDocument &xml_doc) {

    TiXmlHandle docHandle(&xml_doc);

    TiXmlElement *child = docHandle.FirstChild("html").FirstChild("body").FirstChild("svg").ToElement();


    for (child; child; child = child->NextSiblingElement()) {

        string xmlnsStr = child->Attribute("xmlns");
        string versionStr = child->Attribute("version");
        std::cout << "xmlns :" << xmlnsStr
                  << " version" << versionStr << std::endl;
        TiXmlElement *circleItem = child->FirstChild()->ToElement();

        string pointsStr = circleItem->Attribute("points");

        string strokeStr = circleItem->Attribute("stroke");
        string stroke_widthStr = circleItem->Attribute("stroke-width");
        string fillStr = circleItem->Attribute("fill");


        std::cout << "points :" << pointsStr
                  << " stroke :" << strokeStr
                  << " stroke-width :" << stroke_widthStr
                  << " fill :" << fillStr << std::endl;


    }


}

void parsePathSVG(TiXmlDocument &xml_doc) {

    TiXmlHandle docHandle(&xml_doc);

    TiXmlElement *child = docHandle.FirstChild("html").FirstChild("body").FirstChild("svg").ToElement();


    for (child; child; child = child->NextSiblingElement()) {

        string xmlnsStr = child->Attribute("xmlns");
        string versionStr = child->Attribute("version");
        std::cout << "xmlns :" << xmlnsStr
                  << " version" << versionStr << std::endl;
        TiXmlElement *pathItem = child->FirstChild()->ToElement();

        string dStr = pathItem->Attribute("d");

        string strokeStr = pathItem->Attribute("stroke");
        string stroke_widthStr = pathItem->Attribute("stroke-width");
        string fillStr = pathItem->Attribute("fill");


        std::cout << "d :" << dStr
                  << " stroke :" << strokeStr
                  << " stroke-width :" << stroke_widthStr
                  << " fill :" << fillStr << std::endl;


    }


}

void constructCircle() {
    TiXmlDocument xml_doc_Circle;
    std::string exampleCircle = "Circle.svg"; // 可以改成xml字尾
    createCircleSVG(xml_doc_Circle);
    xml_doc_Circle.SaveFile(exampleCircle.c_str());
    parseCircleSVG(xml_doc_Circle);

}

void constructRect() {


    TiXmlDocument xml_doc_Rect;
    std::string exampleRect = "Rect.svg"; // 可以改成xml字尾
    createRectSVG(xml_doc_Rect);
    // 儲存到檔案
    xml_doc_Rect.SaveFile(exampleRect.c_str());
    parseRectSVG(xml_doc_Rect);


}

void constructEllipse() {


    TiXmlDocument xml_doc_Ellipse;
    std::string exampleEllipse = "Ellipse.svg"; // 可以改成xml字尾
    createEllipseSVG(xml_doc_Ellipse);
    xml_doc_Ellipse.SaveFile(exampleEllipse.c_str());
    parseEllipseSVG(xml_doc_Ellipse);


}

void constructPolygon() {


    TiXmlDocument xml_doc_Polygon;
    std::string examplePolygon = "Polygon.svg"; // 可以改成xml字尾
    createPolygonSVG(xml_doc_Polygon);
    xml_doc_Polygon.SaveFile(examplePolygon.c_str());
    parsePolygonSVG(xml_doc_Polygon);


}

void constructLine() {


    TiXmlDocument xml_doc_Line;
    std::string exampleLine = "Line.svg"; // 可以改成xml字尾
    createLineSVG(xml_doc_Line);
    xml_doc_Line.SaveFile(exampleLine.c_str());
    parseLineSVG(xml_doc_Line);


}

void constructPolyline() {


    TiXmlDocument xml_doc_Polyline;
    std::string examplePolyline = "Polyline.svg"; // 可以改成xml字尾
    createPolylineSVG(xml_doc_Polyline);
    xml_doc_Polyline.SaveFile(examplePolyline.c_str());
    parsePolylineSVG(xml_doc_Polyline);


}

void constructPath(){


    TiXmlDocument xml_doc_Path;
    std::string examplePath = "Path.svg"; // 可以改成xml字尾
    createPathSVG(xml_doc_Path);
    xml_doc_Path.SaveFile(examplePath.c_str());
    parsePathSVG(xml_doc_Path);


}

string& replace_all(string& str, const string& old_value, const string& new_value)
{
    while( true ) {
        string::size_type pos(0);
        if( (pos=str.find(old_value))!=string::npos )
            str.replace(pos,old_value.length(),new_value);
        else break ;
    }
    return str;
}

void splitStr(const char *strCh, vector<Point> &vPolygonPoint,bool connectFlag=true) {


        char pathArray[10]= {'M','L','H','V','C','S','Q','T','A','Z'};
        string temp=string(strCh);

        for(int i=0;i<sizeof(pathArray)/sizeof(char);i++)
        {
            string str(1,pathArray[i]);
            temp= replace_all(temp,str,"");
            string lowStr(1,pathArray[i]+32);
            temp= replace_all(temp,   lowStr,"");
        }
        strCh=temp.c_str();

    const char *d = " ,";
    char *p;
    p = strtok((char *) strCh, d);
    char *q = p;
    int firstValue = atoi(p);
    int secondValue = 0;
    int i = 0;
    while (p) {
        firstValue = atoi(p);
        // printf("%s\n",p);
        p = strtok(NULL, d);
        secondValue = atoi(p);
        if (i % 2 == 0) {
            vPolygonPoint.push_back(Point(firstValue, secondValue));//存儲坐标
        }
        i++;
    }
    firstValue = atoi(q);
    if(connectFlag){
    vPolygonPoint.push_back(Point(firstValue, secondValue));//存儲坐标
    }
}

void savePoint(Mat Img, vector<Point> &circlePoint) {// img-gray; 将opencv-circle函數繪制的圓 轉成 opencv-polylines 繪制  并記錄外輪廓的點
    for (int i = 0; i < Img.rows; i++) {
        for (int j = 0; j < Img.cols; j++) {
            if (Img.at<uchar>(i, j) == 255) {
                circlePoint.push_back(Point(j, i));
                break;
            }else if( Img.at<uchar>(Img.rows-i, Img.cols-j) == 255){
                circlePoint.push_back(Point(Img.cols-j, Img.rows-i));
                break;
            }
        }
    }


}

void paraseSVG(string svg1,
        string svg2,
        map<string, int> &m_svgType,
        vector<Point> &circlePoint,
        vector<Point> &rectPoint,
        vector<Point> &ellipsePoint,
        vector<Point> &polygonPoint,
        vector<Point> &linePoint,
        vector<Point> &polygonLine,
        vector<Point> &path,
        int &id0,
        int &id1,
        int width,
        int height
       ) {
    std::cout << "----------------------------------accept two svg file to prase -----------------------------------"
              << std::endl;

    TiXmlDocument xml_doc1;
    if (!xml_doc1.LoadFile(svg1.c_str())) {
        cerr << xml_doc1.ErrorDesc() << endl;
        return;
    }
    TiXmlDocument xml_doc2;
    if (!xml_doc2.LoadFile(svg2.c_str())) {
        cerr << xml_doc2.ErrorDesc() << endl;
        return;
    }



    cv::Mat img(height, width, CV_8UC1, Scalar(0, 0, 0));
    cv::Mat circleImg = img.clone();
    cv::Mat ellipseImg = img.clone();

    std::vector<TiXmlDocument> vec_xml_doc;
    vec_xml_doc.push_back(xml_doc1);
    vec_xml_doc.push_back(xml_doc2);

    for (int i = 0; i < vec_xml_doc.size(); i++) {

        TiXmlHandle docHandle(&vec_xml_doc[i]);

        TiXmlElement *child = docHandle.FirstChild("html").FirstChild("body").FirstChild("svg").ToElement();


        for (child; child; child = child->NextSiblingElement()) {

            string xmlnsStr = child->Attribute("xmlns");
            string versionStr = child->Attribute("version");
            std::cout << "xmlns :" << xmlnsStr
                      << " version" << versionStr << std::endl;
            TiXmlElement *Item = child->FirstChild()->ToElement();
            if (Item != NULL) {
                if(i==0) {
                    id0=m_svgType[child->FirstChild()->Value()];}
                else {
                    id1=m_svgType[child->FirstChild()->Value()];}
                switch (m_svgType[child->FirstChild()->Value()]) {//進行類型判斷進行
                    case 0: {
                        std::cout << " processing   " << child->FirstChild()->Value() << "   number "
                                  << m_svgType[child->FirstChild()->Value()] << std::endl;
                        string cxStr = Item->Attribute("cx");
                        string cyStr = Item->Attribute("cy");
                        string rStr = Item->Attribute("r");
                        string strokeStr = Item->Attribute("stroke");
                        string stroke_widthStr = Item->Attribute("stroke-width");
                        string fillStr = Item->Attribute("fill");


                        circle(circleImg, Point(atoi(cxStr.c_str()), atoi(cyStr.c_str())), atoi(rStr.c_str()),
                               Scalar(255, 255, 255), 1, 8);


                        savePoint(circleImg, circlePoint);
                        // circle(img, Point(atoi(cxStr.c_str()), atoi(cyStr.c_str())), atoi(rStr.c_str()), Scalar(255, 255, 255), 1, 8);

                        polylines(img, circlePoint, false, Scalar(255, 255, 255), 1, 8);

                        std::cout << "cx :" << cxStr
                                  << " cy :" << cyStr
                                  << " r :" << rStr
                                  << " stroke :" << strokeStr
                                  << " stroke-width :" << stroke_widthStr
                                  << " fill :" << fillStr << std::endl;
                        break;
                    }
                    case 1: {
                        std::cout << "processing " << child->FirstChild()->Value() << " number "
                                  << m_svgType[child->FirstChild()->Value()] << std::endl;
                        string xStr = Item->Attribute("x");
                        string yStr = Item->Attribute("y");
                        string widthStr = Item->Attribute("width");
                        string heightStr = Item->Attribute("height");
                        string strokeStr = Item->Attribute("stroke");
                        string stroke_widthStr = Item->Attribute("stroke-width");
                        string fillStr = Item->Attribute("fill");
                        rectPoint.push_back(Point(atoi(xStr.c_str()), atoi(yStr.c_str())));
                        rectPoint.push_back(Point(atoi(xStr.c_str()) + atoi(widthStr.c_str()), atoi(yStr.c_str())));
                        rectPoint.push_back(Point(atoi(xStr.c_str()) + atoi(widthStr.c_str()),
                                                  atoi(yStr.c_str()) + atoi(heightStr.c_str())));
                        rectPoint.push_back(Point(atoi(xStr.c_str()), atoi(yStr.c_str()) + atoi(heightStr.c_str())));
                        rectPoint.push_back(Point(atoi(xStr.c_str()), atoi(yStr.c_str())));


                        //rectangle(img, Point(atoi(xStr.c_str()), atoi(yStr.c_str())),Point(atoi(xStr.c_str()) + atoi(widthStr.c_str()),atoi(yStr.c_str()) + atoi(heightStr.c_str())), Scalar(255, 255, 255), 1, 8);
                        polylines(img, rectPoint, true, Scalar(255, 255, 255), 1, 8);
                        std::cout << "x :" << xStr
                                  << " y :" << yStr
                                  << " width :" << widthStr
                                  << " height :" << heightStr
                                  << " stroke :" << strokeStr
                                  << " stroke-width :" << stroke_widthStr
                                  << " fill :" << fillStr << std::endl;
                        break;
                    }
                    case 2: {
                        std::cout << "processing " << child->FirstChild()->Value() << " number "
                                  << m_svgType[child->FirstChild()->Value()] << std::endl;
                        string cxStr = Item->Attribute("cx");
                        string cyStr = Item->Attribute("cy");
                        string rxStr = Item->Attribute("rx");
                        string ryStr = Item->Attribute("ry");
                        string strokeStr = Item->Attribute("stroke");
                        string stroke_widthStr = Item->Attribute("stroke-width");
                        string fillStr = Item->Attribute("fill");


                        ellipse(ellipseImg, Point(atoi(cxStr.c_str()), atoi(cyStr.c_str())),
                                Size(atoi(rxStr.c_str()), atoi(ryStr.c_str())), 45, 0, 360, Scalar(255, 255, 255), 1,
                                8);
                        savePoint(ellipseImg, ellipsePoint);

                       // ellipse(img, Point(atoi(cxStr.c_str()), atoi(cyStr.c_str())),Size(atoi(rxStr.c_str()), atoi(ryStr.c_str())), 45, 0, 360, Scalar(255, 255, 255), 1,8);
                        polylines(img, ellipsePoint, true, Scalar(255, 255, 255), 1, 8);

                        std::cout << "cx :" << cxStr
                                  << " cy :" << cyStr
                                  << " rx :" << rxStr
                                  << " ry :" << ryStr
                                  << " stroke :" << strokeStr
                                  << " stroke-width :" << stroke_widthStr
                                  << " fill :" << fillStr << std::endl;
                        break;
                    }
                    case 3: {
                        std::cout << "processing " << child->FirstChild()->Value() << " number "
                                  << m_svgType[child->FirstChild()->Value()] << std::endl;
                        string pointsStr = Item->Attribute("points");

                        string strokeStr = Item->Attribute("stroke");
                        string stroke_widthStr = Item->Attribute("stroke-width");
                        string fillStr = Item->Attribute("fill");

                        splitStr(pointsStr.c_str(), polygonPoint,true);

                        polylines(img, polygonPoint, false, Scalar(255, 255, 255), 1, 8);
                        std::cout << "points :" << pointsStr
                                  << " stroke :" << strokeStr
                                  << " stroke-width :" << stroke_widthStr
                                  << " fill :" << fillStr << std::endl;
                        break;
                    }
                    case 4: {
                        std::cout << " processing " << child->FirstChild()->Value() << " number "
                                  << m_svgType[child->FirstChild()->Value()] << std::endl;
                        string x1Str = Item->Attribute("x1");
                        string y1Str = Item->Attribute("y1");
                        string x2Str = Item->Attribute("x2");
                        string y2Str = Item->Attribute("y2");
                        string strokeStr = Item->Attribute("stroke");
                        string stroke_widthStr = Item->Attribute("stroke-width");
                        string fillStr = Item->Attribute("fill");
                       // line(img, Point(atoi(x1Str.c_str()), atoi(y1Str.c_str())),Point(atoi(x2Str.c_str()), atoi(y2Str.c_str())), Scalar(255, 255, 255), 1, 8);
                        linePoint.push_back(Point(atoi(x1Str.c_str()), atoi(y1Str.c_str())));
                        linePoint.push_back(Point(atoi(x2Str.c_str()), atoi(y2Str.c_str())));
                        polylines(img, linePoint, false, Scalar(255, 255, 255), 1, 8);
                        std::cout << "x1 :" << x1Str
                                  << " y1 :" << y1Str
                                  << " x2 :" << x2Str
                                  << " y2 :" << y2Str
                                  << " stroke :" << strokeStr
                                  << " stroke-width :" << stroke_widthStr
                                  << " fill :" << fillStr << std::endl;

                        break;
                    }
                    case 5: {
                        std::cout << "processing " << child->FirstChild()->Value() << " number "
                                  << m_svgType[child->FirstChild()->Value()] << std::endl;
                        string pointsStr = Item->Attribute("points");

                        string strokeStr = Item->Attribute("stroke");
                        string stroke_widthStr = Item->Attribute("stroke-width");
                        string fillStr = Item->Attribute("fill");

                        splitStr(pointsStr.c_str(), polygonLine,false);

                        polylines(img, polygonLine, false, Scalar(255, 255, 255), 1, 8);
                        std::cout << "points :" << pointsStr
                                  << " stroke :" << strokeStr
                                  << " stroke-width :" << stroke_widthStr
                                  << " fill :" << fillStr << std::endl;
                        break;
                    }
                    case 6: {
                        std::cout << "processing " << child->FirstChild()->Value() << " number "
                                  << m_svgType[child->FirstChild()->Value()] << std::endl;
                        string pointsStr = Item->Attribute("d");

                        string strokeStr = Item->Attribute("stroke");
                        string stroke_widthStr = Item->Attribute("stroke-width");
                        string fillStr = Item->Attribute("fill");

                        splitStr(pointsStr.c_str(), path,true);

                        polylines(img, path, false, Scalar(255, 255, 255), 1, 8);
                        std::cout << "d :" << pointsStr
                                  << " stroke :" << strokeStr
                                  << " stroke-width :" << stroke_widthStr
                                  << " fill :" << fillStr << std::endl;
                        break;
                    }
                    default: {
                        std::cout << " the type is not existed   " << child->FirstChild()->Value() << " number "
                                  << m_svgType[child->FirstChild()->Value()] << std::endl;
                        break;
                    }
                }


            }

        }


    }
// ---------------------------------------------------上一步,将所有圖形轉成坐标點------------------------------------------------------------------------------------

    imwrite("allPolygons.jpg", img);

}

string convertIntToString(int valueInt)
{

    stringstream ss;
    ss<<valueInt;
    return ss.str();
}
string  convertStrPolgon(vector<Point> vec ){


    string str="";
    for(int i=0;i<vec.size();i++)
    {

        if(i!=vec.size()-1){

            str+= convertIntToString(vec[i].x)+" "+convertIntToString(400-vec[i].y)+string(",");
        }else {
            str+=convertIntToString( vec[i].x)+" "+convertIntToString(400-vec[i].y);
        }
    }

   return "POLYGON(("+str+"))";
}
void combineGraph(vector<Point> vec1,
                   vector<Point> vec2,
                   int width,
                   int height)
{ /// Create two polygons
    PolygonType singlePolygon1;
    PolygonType singlePolygon2;


   string a=convertStrPolgon(vec1);
   string b=convertStrPolgon(vec2);


    boost::geometry::read_wkt(a, singlePolygon1);
    boost::geometry::read_wkt(b, singlePolygon2);

    boost::geometry::correct(singlePolygon1);
    boost::geometry::correct(singlePolygon2);

    /// Run union and check validity (should fail check)
    MultiPolygonType unionResult;
    boost::geometry::union_(singlePolygon1, singlePolygon2, unionResult);

    boost::geometry::validity_failure_type failure_type;
    if(!boost::geometry::is_valid(unionResult, failure_type)) {
        std::cout << "Result of union operation is not valid! " << failure_type << std::endl; // failure_type is 21 == failure_self_intersections
    }

    // Put these into the same type so that they can be passed to WritePolygonsToSVG
    MultiPolygonType polygon1;
    polygon1.push_back(singlePolygon1);

    MultiPolygonType polygon2;
    polygon2.push_back(singlePolygon2);

    std::vector<MultiPolygonType> polygons = {polygon1, polygon2, unionResult};
    WritePolygonsToSVG(polygons[0],"A.svg");
    WritePolygonsToSVG(polygons[1],"B.svg");
    WritePolygonsToSVG(polygons[2],"C.svg");
    WritePolygonsToSVG(unionResult,"allPolygons.svg");
}

void processSVG(string svg1, string svg2)
{
    vector<Point> circlePoint;
    vector<Point> rectPoint;
    vector<Point> ellipsePoint;
    vector<Point> polygonPoint;
    vector<Point> linePoint;
    vector<Point> polygonLine;
    vector<Point> path;
    int height=1080;
    int width=1920;
    //存儲各個圖形的邊界點
    map<string, int> m_svgType = {
            {"circle",  0},
            {"rect",    1},
            {"ellipse", 2},
            {"polygon", 3},
            {"line",    4},
            {"polyline", 5},
            {"path",    6}
    };
     int id0=0;
     int id1=0;
    //圖形的類型
    paraseSVG( svg1,  svg2,m_svgType,circlePoint,rectPoint,ellipsePoint,polygonPoint,linePoint,polygonLine,path,id0,id1,width,height );
    map<int, vector<Point> > m_vecType = {
            {   0,circlePoint},
            {     1,rectPoint},
            {  2,ellipsePoint},
            {  3,polygonPoint},
            {    4,linePoint},
            {  5,polygonLine},
            {     6,path}
    };

    combineGraph(m_vecType[id0],  m_vecType[id1],width,height);

}

int main() {


    constructCircle();
    constructRect();
    constructEllipse();
    constructPolygon();
    constructLine();
    constructPolyline();
    constructPath();



// 也可以讀取檔案 進行解析

    string svg2 = "Path.svg";
    string svg1 = "Circle.svg";

    processSVG(svg1, svg2);



    std::cout << std::endl << "xml generate accomplished!" << std::endl;
    return 0;
}

       

測試結果

F:\untitled\cmake-build-debug\untitled.exe
xmlns :http://www.w3.org/2000/svg version1.1
cx :100 cy :50 r :40 stroke :black stroke-width :2 fill :none
xmlns :http://www.w3.org/2000/svg version1.1
x :300 y :100 width :300 height :100 stroke :black stroke-width :2 fill :none
xmlns :http://www.w3.org/2000/svg version1.1
cx :300 cy :80 rx :100 ry :50 stroke :black stroke-width :2 fill :red
xmlns :http://www.w3.org/2000/svg version1.1
points :200,10 250,190 160,210 stroke :black stroke-width :2 fill :none
xmlns :http://www.w3.org/2000/svg version1.1
x1 :100 x1 :100 x2 :400 y2 :400 stroke :black stroke-width :2 fill :none
xmlns :http://www.w3.org/2000/svg version1.1
points :20,20 40,25 60,40 80,120 120,140 200,180 stroke :black stroke-width :2 fill :none
xmlns :http://www.w3.org/2000/svg version1.1
d :M150 0 L75 200 L225 200 Z stroke :black stroke-width :2 fill :none
----------------------------------accept two svg file to prase -----------------------------------
xmlns :http://www.w3.org/2000/svg version1.1
 processing   circle   number 0
cx :100 cy :50 r :40 stroke :black stroke-width :2 fill :none
xmlns :http://www.w3.org/2000/svg version1.1
processing path number 6
d :M150 0 L75 200 L225 200 Z stroke :black stroke-width :2 fill :none

xml generate accomplished!

Process finished with exit code 0      

opencv的圖形

47、使用c++的tinyxml對svg圖形進行算法處理

合并結果svg

47、使用c++的tinyxml對svg圖形進行算法處理
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g fill-rule="evenodd"><path d="M 188,68 L 216,0 L 366,400 L 66,400 L 152,170 L 150,172 L 146,174 L 140,176 L 132,178 L 116,180 L 100,178 L 92,176 L 86,174 L 82,172 L 78,170 L 74,168 L 72,166 L 68,164 L 66,162 L 64,160 L 62,158 L 60,156 L 58,154 L 56,152 L 54,150 L 52,148 L 52,146 L 50,144 L 48,142 L 48,140 L 46,138 L 46,136 L 44,134 L 44,132 L 42,130 L 42,128 L 42,126 L 40,124 L 40,122 L 40,120 L 40,118 L 38,116 L 38,114 L 38,112 L 38,110 L 38,108 L 38,106 L 38,104 L 38,102 L 36,100 L 38,98 L 38,96 L 38,94 L 38,92 L 38,90 L 38,88 L 38,86 L 38,84 L 40,82 L 40,80 L 40,78 L 40,76 L 42,74 L 42,72 L 42,70 L 44,68 L 44,66 L 46,64 L 46,62 L 48,60 L 48,58 L 50,56 L 52,54 L 52,52 L 54,50 L 56,48 L 58,46 L 60,44 L 62,42 L 64,40 L 66,38 L 68,36 L 72,34 L 74,32 L 78,30 L 82,28 L 86,26 L 92,24 L 100,22 L 116,20 L 132,22 L 140,24 L 146,26 L 150,28 L 154,30 L 158,32 L 160,34 L 164,36 L 166,38 L 168,40 L 170,42 L 172,44 L 174,46 L 176,48 L 178,50 L 180,52 L 180,54 L 182,56 L 184,58 L 184,60 L 186,62 L 186,64 L 188,66 L 188,68 z " style="fill:rgb(255,128,0);stroke:rgb(0,0,100);stroke-width:1"/></g>
</svg>