基本思想:使用c++的tinyxml實作svg圖形進行算法處理,需要預先編譯boost和opencv
Mingw32編譯boost,并使用Clion測試_sxj731533730-
clion目錄
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SOxMjM3EjNlZzNkZGNiNzMzYzXzEDN0ATM4IzLclDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
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的圖形
合并結果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>