#include "pch.h" #include "clipper.h" #include "clipperhandler.h" namespace NClipperLib { const double ZERO10 = 1e-10; CClipperHandler::CClipperHandler(void) : m_nPrec(8) , m_pSubject(0) , m_pClip(0) //, m_dXOffset(0) //, m_dYOffset(0) { } CClipperHandler::CClipperHandler(unsigned int nPrec) : m_nPrec(nPrec) , m_pSubject(0) , m_pClip(0) { } CClipperHandler::~CClipperHandler(void) { } /** @brief 设置精度,即精确到小数点后多少位 */ void CClipperHandler::SetPrecison(unsigned int nPrec) { m_nPrec = nPrec; } //inline long64 Round(double val) //{ // if ((val < 0)) return (long64)(val - 0.5); else return (long64)(val + 0.5); //} //bool CClipperHandler::LoadFromFile(Polygons *pp, char * filename, double scale, // int xOffset , int yOffset ) //{ // if(0 == pp) // return false; // // Polygons& ppg = *pp; // ppg.clear(); // // FILE *f = fopen(filename, "r"); // if (!f) return false; // int polyCnt, vertCnt; // char junk [80]; // double X, Y; // if (fscanf(f, "%d", &polyCnt) == 1 && polyCnt > 0) // { // ppg.resize(polyCnt); // for (int i = 0; i < polyCnt; i++) { // if (fscanf(f, "%d", &vertCnt) != 1 || vertCnt <= 0) break; // ppg[i].resize(vertCnt); // for (int j = 0; j < vertCnt; j++) { // if (fscanf(f, "%lf%*[, ]%lf", &X, &Y) != 2) break; // //待修改 ww // ppg[i][j].X = Round((X + xOffset) * scale); // ppg[i][j].Y = Round((Y + yOffset) * scale); // fgets(junk, 80, f); // } // } // } // m_dScale = scale; // m_dXOffset = xOffset; // m_dYOffset = yOffset; // // // fclose(f); // return true; //} // 从内存中读取多边形,DOUBLEVEC 中存有一个多边形的所有坐标 //bool CClipperHandler::LoadFromMemory(Polygons *pp,const vector< DOUBLEVEC >& polyData, double scale, // int xOffset , int yOffset ) //{ // if(0 == pp) // return false; // // Polygons& ppg = *pp; // ppg.clear(); // double X, Y; // int polyCnt = polyData.size(); // int vertCnt; // ppg.resize(polyCnt); // for(int j = 0; j < polyData.size(); j ++ ) // { // vertCnt = polyData[j].size()/2; // ppg[j].resize(vertCnt); // // for(int i = 0; i < vertCnt; i ++ ) // { // X = polyData[j][2*i]; // Y = polyData[j][2*i+1]; // ppg[j][i].X = (X + xOffset) * scale; // ppg[j][i].Y = (Y + yOffset) * scale; // } // } // m_dScale = scale; // m_dXOffset = xOffset; // m_dYOffset = yOffset; // // return true; //} // //void CClipperHandler::SaveToMemeory(Polygons *ppg, vector< DOUBLEVEC >& polyData) //{ // if(0 == ppg) // return; // Polygons& pp = *ppg; // // polyData.reserve(pp.size()); // vector vec; // for(int i = 0; i < pp.size(); i ++ ) // { // DOUBLEVEC vec; // int vertCnt = pp[i].size(); // vec.resize(vertCnt*2 ); // for(int j = 0; j < vertCnt; j ++ ) // { // vec[2*j] = pp[i][j].X /m_dScale - m_dXOffset; // vec[2*j+1] = pp[i][j].Y /m_dScale - m_dXOffset; // } // polyData.push_back(vec); // } // // //} //void CClipperHandler::SaveToFile(char *filename, Polygons *ppg) //{ // if(0 == ppg) // return; // FILE *f = fopen(filename, "w"); // if (!f) return; // double X ; // double Y; // Polygons& pp = *ppg; // fprintf(f, "%d\n", pp.size()); // for (unsigned i = 0; i < pp.size(); ++i) // { // fprintf(f, "%d\n", pp[i].size()); // //if (scale > 1.01 || scale < 0.99) { // // for (unsigned j = 0; j < pp[i].size(); ++j) // // fprintf(f, "%.6lf, %.6lf,\n", // // (double)pp[i][j].X /scale, (double)pp[i][j].Y /scale); // //} // //else // //{ // for (unsigned j = 0; j < pp[i].size(); ++j) // fprintf(f, "%g, %g,\n", pp[i][j].X, pp[i][j].Y ); // //} // } // fclose(f); //} /** 多边形进行布尔运算,结果输入到solution中,eType为运算模式,相交,合并,相减,抑或(exclusive or)*/ /** 将一个多边形集拷贝到目标多边形中 */ bool CClipperHandler::Execute(ClipperPolygons& polySubject, ClipperPolygons& polyClip, ClipperPolygons& polySolution, EClipType eType) { m_pSubject = & polySubject; m_pClip = &polyClip; //获取参数 , 放大因子,偏移量等 if(!GetOperationParas()) return false; Clipper clpr; ClipType ctType = (ClipType)eType; Polygons subject,clip,solution; ClipPolysToPolygons(&polySubject,&subject); ClipPolysToPolygons(&polyClip,&clip); clpr.AddPolygons(subject, ptSubject); clpr.AddPolygons(clip, ptClip); if (!clpr.Execute(ctType, solution, pftEvenOdd, pftEvenOdd)) return false; PolygonToClipPolys(&solution, &polySolution); return true; } bool CClipperHandler::GetOperationParas() { //获取极值 int nScale = m_nPrec + 1; //放大比例 if(m_pSubject == NULL || m_pClip == NULL) return false; double xmin,ymin; double xmin2,ymin2; if(!GetMinimumValue(*m_pSubject,xmin,ymin)) return false; if(!GetMinimumValue(*m_pClip,xmin2,ymin2)) return false; //得到所有多边形坐标最小值 #ifndef _QT_VERSION xmin = min(xmin,xmin2); ymin = min(ymin,ymin2); #else xmin = std::min(xmin,xmin2); ymin = std::min(ymin,ymin2); #endif m_dXOffset = xmin/* - ZERO10*/; m_dYOffset = ymin/* - ZERO10*/; //m_nXInitOffset = floor(xmin); //整形部分最小值 //m_nYInitOffset = floor(ymin); //xmin -= m_nXInitOffset; //将整形重合 //ymin -= m_nYInitOffset; //xmin *= nScale; //ymin *= nScale; //m_nXScaleOffset //xmin2 = xmin - m_nXOffset; //ymin2 = ymin - m_nYOffset; return true; } inline long64 Round(double val) { if ((val < 0)) return (long64)(val - 0.5); else return (long64)(val + 0.5); } bool CClipperHandler::ClipPolysToPolygons(ClipperPolygons* pSourcePolygons, Polygons* pDestPolygons) { if(0 == pSourcePolygons || 0 == pDestPolygons) return false; Polygons* ppg = static_cast(pDestPolygons); if(0 == ppg) return false; ppg->clear(); ppg->resize(pSourcePolygons->size()); int scale = pow(float(10),int(m_nPrec) ); for(int i = 0; i < pSourcePolygons->size(); i ++ ) { (*ppg)[i].resize((*pSourcePolygons)[i].size()); for(int j = 0; j < (*pSourcePolygons)[i].size(); j ++ ) { (*ppg)[i][j].X = Round ( ((*pSourcePolygons)[i][j].x - m_dXOffset) * scale ); (*ppg)[i][j].Y = Round ( ((*pSourcePolygons)[i][j].y - m_dYOffset) * scale ) ; } } return true; } bool CClipperHandler::PolygonToClipPolys(Polygons* pSourcePolygons, ClipperPolygons* pDestPolygons) { if(0 == pSourcePolygons || 0 == pDestPolygons) return false; ClipperPolygons* ppg = static_cast(pDestPolygons); if(0 == ppg) return false; ppg->clear(); ppg->resize(pSourcePolygons->size()); int scale = pow( float(10),int(m_nPrec) ); for(int i = 0; i < pSourcePolygons->size(); i ++ ) { (*ppg)[i].resize((*pSourcePolygons)[i].size()); for(int j = 0; j < (*pSourcePolygons)[i].size(); j ++ ) { (*ppg)[i][j].x = double( (*pSourcePolygons)[i][j].X ) / scale + m_dXOffset; (*ppg)[i][j].y = double( (*pSourcePolygons)[i][j].Y )/ scale + m_dYOffset; } } return true; } /** @获取多边形集最小坐标,失败返回false*/ bool CClipperHandler::GetMinimumValue(ClipperPolygons& sourcePolygons, double& xmin, double& ymin ) { if(sourcePolygons.empty()) return false; int nCount = 0; for(int i = 0; i < sourcePolygons.size(); i ++ ) { for(int j = 0; j < sourcePolygons[i].size(); j ++ ) { if(nCount == 0) { xmin = sourcePolygons[i][j].x; ymin = sourcePolygons[i][j].y; } else { #ifndef _QT_VERSION xmin = min(xmin,sourcePolygons[i][j].x); ymin = min(ymin,sourcePolygons[i][j].y); #else xmin = std::min(xmin,sourcePolygons[i][j].x); ymin = std::min(ymin,sourcePolygons[i][j].y); #endif } nCount ++ ; } } if(nCount == 0) return false; return true; } /** @获取多边形集最大坐标,失败返回false*/ bool CClipperHandler::GetMaximumValue(ClipperPolygons& sourcePolygons, double& xmax, double& ymax ) { if(sourcePolygons.empty()) return false; int nCount = 0; for(int i = 0; i < sourcePolygons.size(); i ++ ) { for(int j = 0; j < sourcePolygons[i].size(); j ++ ) { if(nCount == 0) { xmax = sourcePolygons[i][j].x; ymax = sourcePolygons[i][j].y; } else { #ifndef _QT_VERSION xmax = max(xmax,sourcePolygons[i][j].x); ymax = max(ymax,sourcePolygons[i][j].y); #else xmax = std::max(xmax,sourcePolygons[i][j].x); ymax = std::max(ymax,sourcePolygons[i][j].y); #endif } nCount ++ ; } } if(nCount == 0) return false; return true; } }//namespace