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.

938 lines
16 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 "BaseElements.h"
#include <fstream>
#include <sstream>
#include "Clipper/clipperhandler.h"
#include "PublicFunctions.h"
using namespace std;
using namespace NClipperLib;
#ifndef ZERO6
#define ZERO6 1e-6
#endif
GBaseObj::GBaseObj()
:m_strName(_T(""))
,m_strLayer(_T(""))
,m_color(RGB(0,0,0))
,m_type(eNull)
{
}
GBaseObj::~GBaseObj()
{
}
GBaseObj& GBaseObj::operator=(const GBaseObj& other)
{
m_strName = other.m_strName;
m_strLayer = other.m_strLayer;
m_color = other.m_color;
m_type = other.m_type;
return *this;
}
void GBaseObj::SetName(string strName)
{
m_strName = strName;
}
void GBaseObj::SetName(char* strname)
{
m_strName.assign(strname);
}
void GBaseObj::SetName(const char* strname)
{
m_strName.assign(strname);
}
void GBaseObj::SetPosition(const char* strname) {
m_strPosition.assign(strname);
}
string GBaseObj::GetPosition(void)
{
return m_strPosition;
}
void GBaseObj::SetLayer(string strLayer)
{
m_strLayer = strLayer;
}
void GBaseObj::SetLayer(const char* strLayer)
{
m_strLayer.assign(strLayer);
}
void GBaseObj::SetColor(COLORREF clr)
{
m_color = clr;
}
string GBaseObj::GetName(void)
{
return m_strName;
}
string GBaseObj::GetLayer(void)
{
return m_strLayer;
}
COLORREF GBaseObj::GetColor(void)
{
return m_color;
}
ElementType GBaseObj::GetType(void)
{
return m_type;
}
void GBaseObj::SetType(ElementType type)
{
m_type = type;
}
///////////////////////////////////////////
GPoint3D::GPoint3D(void)
:x0(0)
, y0(0)
, z0(0)
{
SetName("Point");
SetType(ePoint);
}
GPoint3D::GPoint3D(double x, double y, double z)
:x0(x)
, y0(y)
, z0(z)
{
SetName("Point");
SetType(ePoint);
}
bool GPoint3D::operator==(const GPoint3D& other) const
{
if (fabs(x0 - other.x0) < ZERO6 && fabs(y0 - other.y0) < ZERO6)
return true;
return false;
}
bool GPoint3D::operator<(const GPoint3D& other) const
{
if (*this == other)
return false;
if (fabs(x0 - other.x0) < 1e-6)
return y0 < other.y0;
return x0 < other.x0;
}
GPoint3D & GPoint3D::operator=(const GPoint3D & other)
{
// TODO: <20>ڴ˴<DAB4><CBB4><EFBFBD><EFBFBD><EFBFBD> return <20><><EFBFBD><EFBFBD>
this->GBaseObj::operator=(other);
x0 = other.x0;
y0 = other.y0;
z0 = other.z0;
return *this;
}
void GPoint3D::Write(FILE* fw)
{
fprintf(fw, "3dPoint %.12g,%.12g,%.12g 0 %s\n", x0, y0, z0, m_strName.c_str());
}
double GPoint3D::Distance2D(const GPoint3D& other) const
{
return sqrt((x0 - other.x0)*(x0 - other.x0) + (y0 - other.y0)*(y0 - other.y0));
}
void GPoint3D::Rotate(double xs, double ys, double radian)
{
CPublicFunctions::Rotate(x0, y0, xs, ys, radian);
}
void GPoint3D::Rotate(double xs, double ys, double cosa, double sina)
{
CPublicFunctions::Rotate(x0, y0, xs, ys, cosa, sina);
}
GPoint3D::~GPoint3D(void)
{
}
GPline::GPline(void)
:GBaseObj()
{
SetName("");
SetType(eLine);
}
GPline::~GPline(void)
{
Clear();
}
void GPline::Clear(void)
{
m_points.clear();
}
void Trim(string& line)
{
if (line.empty())
return;
size_t istart = line.find_first_not_of(' ');
size_t iend = line.find_last_not_of(' ');
line = line.substr(istart, iend - istart + 1);
}
int GPline::ReadFile(ifstream & ifs)
{
Clear();
string line;
stringstream sstr;
char ch;
int num = -1;
GPoint3D pt;
size_t idx;
while (getline(ifs, line))
{
Trim(line);
if (line.size() < 1)
break;
if (line.size() < 3)
continue;
idx = line.find(',');
if (idx == std::string::npos)
continue;
sstr.clear();
sstr.str(line);
if (num < 0)
count(line.begin(), line.end(), ',');
if (num < 3)
sstr >> pt.x0 >> ch >> pt.y0;
else
sstr >> pt.x0 >> ch >> pt.y0 >> ch >> pt.z0;
AddPoint(pt);
}
return (int)m_points.size();
}
void GPline::AddPoint(const GPoint3D& pt)
{
m_points.push_back(pt);
}
int GPline::GetCount(void)const
{
return (int)m_points.size();
}
GRect8 GPline::GetRect(void) const
{
if (this->GetCount() < 1)
return GRect8();
GRect8 rt(X(0), X(0), Y(0), Y(0));
for (int i = 1; i < GetCount(); i++)
{
rt.left = min(rt.left, X(i));
rt.right = max(rt.right, X(i));
rt.bottom = min(rt.bottom, Y(i));
rt.top = max(rt.top, Y(i));
}
return rt;
}
double GPline::X(int i) const
{
return m_points[i].x0;
}
double GPline::Y(int i) const
{
return m_points[i].y0;
}
double GPline::Z(int i) const
{
return m_points[i].z0;
}
void GPline::SetPoint(int idx, double xx, double yy, double zz)
{
m_points[idx] = GPoint3D(xx, yy, zz);
}
void GPline::SetPoint(int idx, const GPoint3D& pt)
{
m_points[idx] = pt;
}
void GPline::SetPoints(const list<GPoint3D>& ptlst) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD>
{
m_points.clear();
m_points.assign(ptlst.begin(),ptlst.end());
}
void GPline::operator+=(double t)
{
/*int i, j;
CLine2D line1, line2;
double tx, ty;
i = 0;
for (i = 1; i<num; ++i)
{
if (line1.Create(x[0], y[0], x[i], y[i]))
break;
}
if (line1.One() == 0)
return;
line1 += t;
for (j = 0; j<i; ++j)
{
x[j] = line1.x0;
y[j] = line1.y0;
}
while (i < num - 1)
{
j = i;
while (++i<num)
{
if (line2.Create(x[j], y[j], x[i], y[i]))
break;
}
if (i >= num)
{
while (j<i)
{
x[j] += -line1.b*t;
y[j] += line1.a*t;
++j;
}
break;
}
line2.One();
line2 += t;
line1.Cross(line2, tx, ty);
while (j < i)
{
x[j] = tx;
y[j] = ty;
++j;
}
line1 = line2;
}
if (i == num - 1)
{
x[num - 1] += -line1.b*t;
y[num - 1] += line1.a*t;
}
GetLocation();*/
}
double GPline::L(int i) const
{
double totaldist = 0;
double dist = 0;
GPoint3D pt1, pt2;
for (int k = 0; k < i; k++)
{
pt1 = m_points[k];
pt2 = m_points[k + 1];
dist = pt1.Distance2D(pt2);
totaldist += dist;
}
return totaldist;
}
void GPline::Write(FILE* fw)
{
if (m_strName.empty())
fprintf(fw, "Pline\n");
else
fprintf(fw, "Pline.%s\n", m_strName.c_str());
for (int i = 0; i < GetCount(); i++)
fprintf(fw, "%.12g,%.12g,%.12g\n", X(i), Y(i), Z(i));
fprintf(fw, "\n");
}
GPoint3D GPline::GetPoint(int idx) const
{
return m_points[idx];
}
double GPline::GetLength(void)
{
double total = 0;
double len = 0;
if (GetCount() < 2)
return total;
for (int i = 0; i < m_points.size() - 1; i++)
{
len = m_points[i].Distance2D(m_points[i + 1]);
total += len;
}
return total;
}
double GPline::GetAverageDirection(void)
{
double rst = 0.0;
int N = GetCount();
if (N < 1)
return rst;
double totaldist = this->GetLength();
if (fabs(totaldist) < ZERO6)
return rst;
double dist = 0;
double angle = 0;
bool bStanding = false;
GRect8 rt = this->GetRect();
if (rt.Width() < rt.Height())
bStanding = true;
int i = 0;
for ( i = 0; i < N-1; i++)
{
dist = CPublicFunctions::Distance(X(i), Y(i), X(i + 1), Y(i + 1));
//angle = CPublicFunctions::GetAngle180(X(i), Y(i), X(i + 1), Y(i + 1));
if(bStanding)
{
angle = CPublicFunctions::GetAngle180(X(i), Y(i), X(i + 1), Y(i + 1));
if (fabs(angle) < ZERO6)
angle = 0;
else if (angle < 0)
angle += PI;
}
else
{
if (fabs(X(i + 1) - X(i)) < ZERO6)
angle = PI / 2.0;
else
angle = atan((Y(i + 1) - Y(i))/(X(i + 1) - X(i)) );
}
//if (fabs(angle) < ZERO6)
// angle = 0;
//else if (angle < 0)
// angle += PI;
rst += angle* dist / totaldist;
}
if (rst > PI / 2.0)
rst -= PI;
//if (this->IsClosed(ZERO6) )
//{
// dist = CPublicFunctions::Distance(X(i), Y(i), X(0), Y(0));
// angle = CPublicFunctions::GetAngle180(X(i), Y(i), X(0), Y(0));
// rst += angle* dist / totaldist;
//}
return rst;
}
double GPline::Area(void) const
{
double s = 0.0;
int i;
int num = GetCount();
if (num < 1)
return 0.0;
s = (Y(0) + Y(num - 1)) * (X(0) - X(num - 1));
for (i = 0; i < num - 1; ++i)
s += (Y(i + 1) + Y(i)) * (X(i + 1) - X(i));
return fabs(s * 0.5);
}
void GPline::GetGravityCenter(double& x0, double& y0)
{
x0 = X(0);
y0 = Y(0);
int num = GetCount();
if (num < 2)
return;
double *x = new double[num];
double *y = new double[num];
for (int i = 0; i < num; i++)
{
x[i] = X(i);
y[i] = Y(i);
}
CPublicFunctions::GetGravityCenter(x, y, num, x0, y0);
delete[]x;
delete[]y;
}
//<2F>жϵ<D0B6>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>other<65>Ƿ<EFBFBD><C7B7>
bool GPline::IsIntersected(const GPline& other) const
{
int N1 = GetCount();
int N2 = other.GetCount();
if (N1 < 2 || N2 < 2)
return 0;
double x1, y1, x2, y2, x3, y3, x4, y4;
for (int i = 0; i < N1 - 1; i++)
{
x1 = X(i); y1 = Y(i);
x2 = X(i + 1); y2 = Y(i + 1);
for (int j = 0; j < N2 - 1; j++)
{
x3 = other.X(j); y3 = other.Y(j);
x4 = other.X(j + 1); y4 = other.Y(j + 1);
if (CPublicFunctions::IsSegmentCross(x1, y1, x2, y2, x3, y3, x4, y4))
return true;
}
}
return false;
}
void GPline::GetLocation(void) //<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>׮<EFBFBD><D7AE>
{
m_locations.clear();
m_locations.resize(this->GetCount(), 0.0);
double totaldist = 0;
double dist = 0;
GPoint3D pt1, pt2;
for (int k = 1; k < this->GetCount(); k++)
{
pt1 = m_points[k-1 ];
pt2 = m_points[k ];
dist = pt1.Distance2D(pt2);
totaldist += dist;
m_locations[k] = totaldist;
}
}
bool GPline::GetCoordinate(double l0, double & x, double& y, double& z, int& locationIndex)
{
if (l0 < 0.0)
return false;
int iStart = -1;
double lstart = 0.0;
double lend = 0.0;
this->GetLocation();
int N = this->GetCount();
if (l0 > m_locations[N - 1] + 1e-6)
return false;
iStart = CPublicFunctions::BinarySearch(l0, m_locations);
if (iStart == N - 1)
{
GPoint3D ptEnd = GetPoint(N - 1);
x = ptEnd.x0;
y = ptEnd.y0;
z = ptEnd.z0;
locationIndex = N - 1;
return m_locations[N - 1];
}
lstart = m_locations[iStart];
lend = m_locations[iStart + 1];
GPoint3D pt1= GetPoint(iStart);
if (fabs(lend - lstart) < 1e-5)
{
x = pt1.x0;
y = pt1.y0;
z = pt1.z0;
locationIndex = iStart + 1;
return true;
}
double factor = (l0 - lstart) / (lend - lstart);
GPoint3D pt2 = GetPoint(iStart + 1);
x = pt1.x0 + (pt2.x0 - pt1.x0)*factor;
y = pt1.y0 + (pt2.y0 - pt1.y0)*factor;
z = pt1.z0 + (pt2.z0 - pt1.z0)*factor;
locationIndex = iStart;
return true;
}
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB> istartΪ<74><CEAA>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>factorΪ<72><CEAA><EFBFBD><EFBFBD><EFBFBD>߶α<DFB6><CEB1><EFBFBD>
int GPline::GetLocation(double x0, double y0, double& factor)
{
int i = 0;
GPoint3D pt1, pt2;
bool bfound = false;
for (i = 0; i < this->GetCount() - 1; i++)
{
pt1 = this->GetPoint(i);
pt2 = this->GetPoint(i + 1);
if (CPublicFunctions::IsPointOnsegment(x0, y0, pt1.x0, pt1.y0, pt2.x0, pt2.y0))
{
bfound = true;
break;
}
}
if (!bfound)
return -1;
if (fabs(pt1.x0 - pt2.x0) < ZERO6)
factor = (y0 - pt1.y0) / (pt2.y0 - pt1.y0);
else
factor = (x0 - pt1.x0) / (pt2.x0 - pt1.x0);
return i;
}
//<2F><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>other<65>Ľ<EFBFBD><C4BD><EFBFBD><E3A3AC><EFBFBD><EFBFBD>list<CPoint3D>
int GPline::GetCrossPoints(const GPline& other, list<GPoint3D>& cxpts, std::list<int>& cxpIndexs)
{
int N1 = this->GetCount();
int N2 = other.GetCount();
if (N1 < 2 || N2 < 2)
return 0;
double x1, y1, x2, y2, x3, y3, x4, y4;
GPoint3D cxpt;
for(int i = 0; i < N1 - 1; i ++ )
{
x1 = X(i); y1 = Y(i);
x2 = X(i + 1); y2 = Y(i + 1);
for(int j =0; j < N2-1; j ++)
{
x3 = other.X(j); y3 = other.Y(j);
x4 = other.X(j + 1); y4 = other.Y(j + 1);
if (0 == CPublicFunctions::IsSegmentCross(x1, y1, x2, y2, x3, y3, x4, y4))
continue;
CPublicFunctions::LineCrossPoint(x1, y1, x2, y2, x3, y3, x4, y4, cxpt.x0, cxpt.y0);
cxpts.push_back(cxpt);
cxpIndexs.push_back(i);
}
}
cxpts.unique();
cxpIndexs.unique();
return (int)cxpts.size();
}
//<2F>жϵ<D0B6><CFB5>Ƿ<EFBFBD><C7B7>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>1<EFBFBD><31><EFBFBD>񷵻<EFBFBD>0 <20><><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD>2
int GPline::IsInside(double x0, double y0) const
{
int N = GetCount();
double* x = new double[N];
double* y = new double[N];
int rst = 0;
for (int i = 0; i < N; i++)
{
x[i] = X(i);
y[i] = Y(i);
}
rst = CPublicFunctions::IsInsidePolygon(x0, y0, x, y, N);
delete[]x;
delete[]y;
return rst;
}
//<2F>ж<EFBFBD>other<65>Ƿ<EFBFBD><C7B7>ڵ<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>߶<EFBFBD><DFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>1<EFBFBD><31><EFBFBD>񷵻<EFBFBD>0<EFBFBD><30> <20><><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD>ֲ<EFBFBD><D6B2>ڷ<EFBFBD><DAB7><EFBFBD>2
int GPline::IsInside(const GPline& other) const
{
if (IsIntersected(other))
return 2;
//<2F><><EFBFBD><EFBFBD><E0BDBB>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>other<65>Ƿ<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD>ڵ<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (1 == IsInside(other.X(1), other.Y(1)))
return 1;
return 0;
}
//<2F>жϵ<D0B6><CFB5>Ƿ<EFBFBD><C7B7>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>1<EFBFBD><31><EFBFBD>񷵻<EFBFBD>0 <20><><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD>2
int GPline::IsInside(const GRect8& rect) const
{
GPline other;
other.FromRect(rect);
return IsInside(other);
}
void GPline::FromRect(const GRect8& rect)
{
this->Clear();
double x[4] = { rect.left,rect.right,rect.right,rect.left };
double y[4] = { rect.bottom,rect.bottom,rect.top,rect.top };
for (int i = 0; i < 4; i++)
this->AddPoint(GPoint3D(x[i], y[i], 0));
this->AddPoint(m_points.front());
}
bool GPline::IsClosed(double esp)
{
if (fabs(m_points.front().x0 - m_points.back().x0) < esp &&
fabs(m_points.front().y0 - m_points.back().y0) < esp)
return true;
return false;
}
void GetPolygon(const GPline& pc, ClipperPolygon& dstpgn)
{
ClipperPoint pt;
dstpgn.reserve(pc.GetCount());
for (int i = 0; i < pc.GetCount(); i++)
{
pt.x = pc.X(i);
pt.y = pc.Y(i);
dstpgn.push_back(pt);
}
}
void CreatePline(ClipperPolygon& pgn, GPline& pc)
{
pc.Clear();
if (pgn.size() < 2)
return;
GPoint3D pt;
for (int i = 0; i < pgn.size(); i++)
{
pt.x0 = pgn[i].x;
pt.y0 = pgn[i].y;
pc.AddPoint(pt);
}
if (!pc.IsClosed(ZERO6))
pc.AddPoint(pc.GetPoint(0));
}
bool GPline::GetIntersectedPolygon(const GPline& other, GPline& solution)
{
ClipperPolygon pgn1, pgn2;
ClipperPolygons ps1, ps2;
ClipperPolygons dstps;
ps1.push_back(pgn1);
ps2.push_back(pgn2);
GetPolygon(*this, ps1[0]);
GetPolygon(other, ps2[0]);
CClipperHandler hd;
hd.SetPrecison(8);
hd.Execute(ps1, ps2, dstps, ectIntersection);
if (dstps.empty())
return false;
if (1 == dstps.size() || dstps[0].size() > dstps[1].size())
CreatePline(dstps[0], solution);
else
CreatePline(dstps[1], solution);
return true;
}
void GPline::Rotate(double xs, double ys, double radian)
{
for (int i = 0; i < GetCount(); i++)
m_points[i].Rotate(xs, ys, radian);
}
void GPline::Rotate(double xs, double ys, double cosa, double sina)
{
for (int i = 0; i < GetCount(); i++)
m_points[i].Rotate(xs, ys, cosa,sina);
}
void GPline::Reverse()
{
std::reverse(m_points.begin(), m_points.end());
}
GRect8::GRect8(void)
{
}
GRect8::GRect8(double l, double r, double b, double t)
:left(l)
, right(r)
, bottom(b)
, top(t)
{
}
bool GRect8::IsIntersected(const GRect8 & other) const
{
if (left > other.right + ZERO6)
return false;
if (bottom > other.top + ZERO6)
return false;
if (right < other.left - ZERO6)
return false;
if (top < other.bottom - ZERO6)
return false;
return true;
}
void GRect8::GetCenter(double & x, double & y)
{
x = (left + right) / 2.0;
y = (top + bottom) / 2.0;
}
double GRect8::Width(void)
{
return right - left;
}
double GRect8::Height(void)
{
return top - bottom;
}
void GRect8::Create(double x0, double y0, double width, double height)
{
left = x0;
bottom = y0;
right = left + width;
top = bottom + height;
}
//x0,y0Ϊ<30><CEAA><EFBFBD>ĵ㣬б<E3A3AC><D0B1>k <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ߣ<EFBFBD><DFA3><EFBFBD><EFBFBD><EFBFBD>Ϊlen
GPline* CreateLine(double x0, double y0, double sina, double cosa, double len)
{
double x1 = x0, y1 = y0, x2 = x0, y2 = y0;
if (fabs(sina - 1.0) < 1e-6)
{
y1 = y0 + len;
y2 = y0 - len;
}
else
{
x1 = x0 - len*cosa;
y1 = y0 - len*sina;
x2 = x0 + len*cosa;
y2 = y0 + len*sina;
}
GPline* pln = new GPline();
pln->AddPoint(GPoint3D(x1, y1, 0));
pln->AddPoint(GPoint3D(x2, y2, 0));
return pln;
}
//<2F><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> xs ,ys<79><73><EFBFBD>㣬 xe ye <20>յ<EFBFBD> <20>Ƕ<EFBFBD>lndirect, lenΪ<6E><CEAA>1/2<><32><EFBFBD><EFBFBD>
int CreateLines(vector<GPline*>& dstLines, double xs, double ys, double xe, double ye,
double dx, double dy, double lndirect, double len)
{
double x = xs;
double y = ys;
double tts = sqrt(dx*dx + dy*dy);
int N = (int)(len / tts);
int i = -1;
double sina = sin(lndirect);
double cosa = cos(lndirect);
GPline* pln = nullptr;
while (i < N)
{
i++;
if (x > xe && (ye > ys && y > ys))
break;
if (x > xe && ye < ys && y < ye)
break;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pln = CreateLine(x, y, sina, cosa, len);
dstLines.push_back(pln);
x += dx;
y += dy;
}
return (int)dstLines.size();
}