|
|
|
|
|
#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 <20><><EFBFBD>þ<EFBFBD><C3BE>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ */
|
|
|
|
|
|
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;
|
|
|
|
|
|
// //<2F><><EFBFBD><EFBFBD> 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;
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>ڴ<EFBFBD><DAB4>ж<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,DOUBLEVEC <20>д<EFBFBD><D0B4><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
//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<double> 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);
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
/** <20><><EFBFBD><EFBFBD><EFBFBD>ν<EFBFBD><CEBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㣬<EFBFBD><E3A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뵽solution<6F><6E>,eTypeΪ<65><CEAA><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD>ཻ<EFBFBD><E0BDBB><EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>(exclusive or)*/
|
|
|
|
|
|
|
|
|
|
|
|
/** <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>μ<EFBFBD><CEBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|
|
|
|
|
bool CClipperHandler::Execute(ClipperPolygons& polySubject, ClipperPolygons& polyClip, ClipperPolygons& polySolution, EClipType eType)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
m_pSubject = & polySubject;
|
|
|
|
|
|
m_pClip = &polyClip;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> <20><> <20>Ŵ<EFBFBD><C5B4><EFBFBD><EFBFBD>ӣ<EFBFBD>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
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()
|
|
|
|
|
|
{
|
|
|
|
|
|
//<2F><>ȡ<EFBFBD><C8A1>ֵ
|
|
|
|
|
|
int nScale = m_nPrec + 1; //<2F>Ŵ<EFBFBD><C5B4><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
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;
|
|
|
|
|
|
//<2F>õ<EFBFBD><C3B5><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Сֵ
|
|
|
|
|
|
#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); //<2F><><EFBFBD>β<EFBFBD><CEB2><EFBFBD><EFBFBD><EFBFBD>Сֵ
|
|
|
|
|
|
//m_nYInitOffset = floor(ymin);
|
|
|
|
|
|
|
|
|
|
|
|
//xmin -= m_nXInitOffset; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>غ<EFBFBD>
|
|
|
|
|
|
//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<Polygons*>(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<ClipperPolygons*>(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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @<40><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>μ<EFBFBD><CEBC><EFBFBD>С<EFBFBD><D0A1><EFBFBD>꣬ʧ<EAA3AC>ܷ<EFBFBD><DCB7><EFBFBD>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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** @<40><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>μ<EFBFBD><CEBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>꣬ʧ<EAA3AC>ܷ<EFBFBD><DCB7><EFBFBD>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
|