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.
kev/Drawer/GVision/BaseLib/BaseElements.cpp

938 lines
16 KiB
C++

1 month ago
#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();
}