#include "stdafx.h" #include "BaseElements.h" #include #include #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: 在此处插入 return 语句 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& ptlst) //设置整条曲线点 { 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) { while (jGetLength(); 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; } //判断当前线与other是否相交 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) //获取所有桩号 { 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; } //获取点所在位置 istart为起始点序号,factor为所处线段比例 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; } //获取当前线与other的交点,存入list int GPline::GetCrossPoints(const GPline& other, list& cxpts, std::list& 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(); } //判断点是否在多边形内部,是返回1,否返回0 在线上返回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; } //判断other是否在当前曲线多边形内部,若是返回1,否返回0, 部分在,部分不在返回2 int GPline::IsInside(const GPline& other) const { if (IsIntersected(other)) return 2; //不相交,取任意一个结点判断other是否全部在当前多边形内 if (1 == IsInside(other.X(1), other.Y(1))) return 1; return 0; } //判断点是否在多边形内部,是返回1,否返回0 在线上返回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为中心点,斜率k 生成一条线,长度为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; } //生成一组测线 xs ,ys起点, xe ye 终点 角度lndirect, len为线1/2长度 int CreateLines(vector& 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; //生成新线 pln = CreateLine(x, y, sina, cosa, len); dstLines.push_back(pln); x += dx; y += dy; } return (int)dstLines.size(); }