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++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "stdafx.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;
// //待修改 wcw
// 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<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);
//}
/** 多边形进行布尔运算结果输入到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 _GDF_QT
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<Polygons*>(pDestPolygons);
if(0 == ppg)
return false;
ppg->clear();
ppg->resize(pSourcePolygons->size());
int scale = (int)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 = (int)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 _GDF_QT
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 _GDF_QT
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