You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

367 lines
8.1 KiB
C++

1 month ago
#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