#include "MLMicroStructure.h" #include "MLPline.h" #include "GMLDimsIter.h" #include "MLFuncom.h" #include #include #include #include #include #include #include namespace geos { namespace geom { class GeometryFactory; class Geometry; class CoordinateSequence; namespace prep { class PreparedGeometry; }; } }; class QwtDotsCommand { public: const MLPlineList* series; int from; int to; double offsetDis; double redundant; double closeDis; double minAngle; double minRadius; bool outCircle; }; #include #include #include #include #include #include #include // geos #include using namespace geos::geom; using namespace geos::io; // 得到曲内网格平均值 double getGridPolygonValue(MLPline* polyline, GMLDimsIter* pDimsIter, double* minValue = nullptr, double* maxValue = nullptr); double getGridPolylineValue(MLPline* polyline, GMLDimsIter* grid, double* minValue = nullptr, double* maxValue = nullptr); // 删除圈闭内的线 void deleteInsidePline(MLPlineList* pPlineList); // 删除圈闭内的线 void deleteInsidePline(MLPlineList& plineList); // 删除圈闭内的线,使用曲线面积法, void deleteInsidePlineArea(MLPlineList& plineList); void deleteInsideSubPline(MLPlineList& plineList); void sortContourPlineArea(MLPlineList& plineList); //排列判断 bool compareDataArea(MLPline* pPline1, MLPline* pPline2) { double value1 = pPline1->getArea(); double value2 = pPline2->getArea(); if (value1 > value2) { return true; } return false; } void deleteInsidePlineArea(MLPlineList& plineList) { // 大在前,小在后 sortContourPlineArea(plineList); int num = plineList.getCount(); for (int i = 0; i < plineList.getCount(); i++) { MLPline* pContour1 = plineList.getPline(i); if (pContour1 == nullptr) continue; pContour1->resetBox(); pContour1->calculateBox(); } deleteInsideSubPline(plineList); } int LinePolyline(MLPlNode& data1, MLPlNode& data2, MLPline* curve, MLPlNode& data, bool bExtend); // 取折线两个节点之间的线 MLPline getPolyline(const MLPoint& pt1, const MLPoint& pt2, const MLPline& polyline); MLPlineList* getOffsetPline(QwtDotsCommand command); // 合并多边形 void combinaPolygon(QList& PolygonList); // 检测两个多边形是否相交 bool checkPolygonCross(const QPolygonF& polygon1, const QPolygonF& polygon2); // 检测两个多边形是否相交,并返回相交多边形 bool checkPolygonCross(const QPolygonF& polygon1, const QPolygonF& polygon2, QPolygonF& polygonDes); // 删除相交的多边形(因为凹多边形与凸多边形有叠合) void deletePolygon(QList& PolygonList); // 删除相交的多边形(因为凹多边形与凸多边形有叠合) void deletePolygon(QList& PolygonList1, QList& PolygonList2, double unitSacle); QPointF getCentroid(const QPolygonF& polygon); // 计算QT多边形面积 double calculateArea(const QPolygonF& polygon); MLPline* getOffsetPl(MLPline* pPolyline, double dDistance); void GetBezierData(int bIsClose, double sd, MLPline& OrgPline, MLPline& NewPline); //得到第一条折线切第二条折线,得到距离点保存在xy中 int GetCrossPt(MLPline &c1, MLPline &c2, QVector &xy, bool bAddTailPt = false); int getCurve(double l1, double l2, QVector &dp, MLPline& dPline, int bDoubleHeadTail = 1, bool bNoLineValue = false); // 非过点光滑 // 1、bClose为真,封闭式光滑 // 2、起止点重合,封闭式光滑 // 3、否则,开放式光滑 void smoothPoints(MLPline& destPline, const MLPline& srcPline, int nInsertPts, bool bClose) { destPline.removeAll(); int ii, nCnt = srcPline.getCount(); if (nCnt <= 2) { for (ii = 0; ii < nCnt; ii++) destPline.addTailPt(srcPline.getAtPt(ii)); return; } MLPlNode dptSta(srcPline.getHeadPt()); MLPlNode dptEnd(srcPline.getTailPt()); MLPointAry arrSourPt; arrSourPt.clear(); bool bEqual = (dptSta == dptEnd); if (bClose || bEqual) // 封闭式光滑 { arrSourPt.append(dptSta); for (ii = 1; ii < nCnt - 1; ii++) arrSourPt.append(srcPline.getAtPt(ii)); if (!bEqual) arrSourPt.append(dptEnd); arrSourPt.append(dptSta); for (ii = 1; ii < 4; ii++) { int jj = ii % nCnt; arrSourPt.append(srcPline.getAtPt(ii)); } } else // 开放式光滑 { arrSourPt.append(dptSta); arrSourPt.append(dptSta); arrSourPt.append(dptSta); for (ii = 1; ii < nCnt - 1; ii++) arrSourPt.append(srcPline.getAtPt(ii)); arrSourPt.append(dptEnd); arrSourPt.append(dptEnd); arrSourPt.append(dptEnd); } MLPoint dptTmp, dpt[4]; double A[4], B[4], t1, t2, t3; nCnt = (int)arrSourPt.count(); for (int ii = 0; ii < nCnt - 3; ii++) { for (int jj = 0; jj < 4; jj++) dpt[jj] = arrSourPt.at(ii + jj); A[0] = (dpt[0].x + 4.0 * dpt[1].x + dpt[2].x) / 6.0; A[1] = -(dpt[0].x - dpt[2].x) / 2.0; A[2] = (dpt[0].x - 2.0 * dpt[1].x + dpt[2].x) / 2.0; A[3] = -(dpt[0].x - 3.0 * dpt[1].x + 3.0 * dpt[2].x - dpt[3].x) / 6.0; B[0] = (dpt[0].y + 4.0 * dpt[1].y + dpt[2].y) / 6.0; B[1] = -(dpt[0].y - dpt[2].y) / 2.0; B[2] = (dpt[0].y - 2.0 * dpt[1].y + dpt[2].y) / 2.0; B[3] = -(dpt[0].y - 3.0 * dpt[1].y + 3.0 * dpt[2].y - dpt[3].y) / 6.0; for (int kk = 0; kk <= nInsertPts; kk++) { t1 = (double)kk / (double)(nInsertPts + 1); t2 = t1 * t1; t3 = t2 * t1; dptTmp.x = A[0] + A[1] * t1 + A[2] * t2 + A[3] * t3; dptTmp.y = B[0] + B[1] * t1 + B[2] * t2 + B[3] * t3; destPline.addTailPt(dptTmp); if (ii == nCnt - 4 && (bClose || bEqual)) break; } } } bool PtAtPolyline(const MLPoint& point, const MLPline& polyline) { for (int i = 0; i < polyline.getCount(); i++) { if (fabs(point.x - polyline[i].x) < 0.01 && fabs(point.y - polyline[i].y) < 0.01) { return true; } if (i > 0) { MLPoint pt1 = polyline.getAtPt(i - 1); MLPoint pt2 = polyline.getAtPt(i); double dis = GetDistance(pt1, pt2); double dis1 = GetDistance(pt1, point); double dis2 = GetDistance(point, pt2); // if (fabs(dis - (dis1 + dis2)) <= 0.01) { return true; } } } return false; } // 重新计算面积、幅度差、长轴,短轴; void calPolygonInfo(MLPlineList& plineList, GMLDimsIter* grid, const QString& name, double dRadiusScale,double minDepth, double maxDepth) { MLPlineList plineListTmp; // 临时存储线 for (int i = 0; i < plineList.getCount(); i++) { MLPline* pPline = plineList.getPline(i); MLPline* pNewPline = pPline->clone(); pNewPline->calculateLength(); plineListTmp.addPline(pNewPline); } plineList.clearPline(); geos::geom::PrecisionModel pm(1e+10); geos::geom::GeometryFactory::Ptr geometryFactory = geos::geom::GeometryFactory::create(&pm); // 凸闭合圈闭 for (int i = 0; i < plineListTmp.getCount(); i++) { MLPline* pPline = plineListTmp.getPline(i); // 两个点不进行计算 if (pPline->getCount() <= 2) continue; // 计算面积 pPline->calculateArea(); double area = pPline->getArea(); // 面积太小,过滤 if (area <= 1) continue; // 面积除 area /= 1000; // 幅度差 double minValue = 0; double maxValue = 0; getGridPolygonValue(pPline, grid, &minValue, &maxValue); double deltValue = (maxValue - minValue); // 过滤幅度差 if (deltValue < minDepth || deltValue > maxDepth) continue; // 长轴 geos::geom::CoordinateArraySequence sequence; for (int j = 0; j < pPline->getCount(); j++) { sequence.add(Coordinate(pPline->getAtPt(j).x, pPline->getAtPt(j).y)); } if (pPline->getHeadPt() != pPline->getTailPt()) { sequence.add(Coordinate(pPline->getAtPt(0).x, pPline->getAtPt(0).y)); } geos::geom::LinearRing* pLineString = geometryFactory->createLinearRing(sequence); // 半径 geos::algorithm::MinimumBoundingCircle mbc(pLineString); double actualRadius1 = mbc.getRadius() * 2; geos::geom::Coordinate actualCentre = mbc.getCentre(); // 短轴 geos::geom::Polygon* pPolygon = geometryFactory->createPolygon(pLineString, nullptr); double tolerance = 0.01; geos::algorithm::construct::MaximumInscribedCircle mic(pPolygon, tolerance); // 半径 std::unique_ptr radiusLine = mic.getRadiusLine(); double actualRadius2 = radiusLine->getLength() * 2; // 过滤比较细长的圈闭 if (actualRadius2 > 0.000001) { // 长短轴的比大于10,进行删除 double scale = actualRadius1 / actualRadius2; if (scale > dRadiusScale) { continue; } } QString sName = QString("%1=%2,%3,%4,%5,%6") .arg(name) .arg(i) .arg(area, 0, 'f', 6) .arg(deltValue, 0, 'f', 2) .arg(actualRadius1, 0, 'f', 2) .arg(actualRadius2, 0, 'f', 2); pPline->setName(sName.toLocal8Bit().data()); MLPline* pNewPline = pPline->clone(); plineList.addPline(pNewPline); geometryFactory->destroyGeometry(pLineString); } } MLMicroStructure::MLMicroStructure() { m_dimsIter = new GMLDimsIter; m_minArea = 1000; m_limitNum = 4; m_bFaultFilter = true; m_faultCloseDis = 100; m_bCloseShape = true; m_closeDis = 50; m_bFaultShape = true; m_extendDis = 200; m_bNoseShape = true; m_offsetDis = 250; m_minAngle = 140; m_redundant = 0.6; m_radius = 800; m_smooth = false; m_zoomin = 10; m_unitSacle = 0.7; m_minDepth = 0; m_maxDepth = 100; } void MLMicroStructure::setContourList(const MLPlineList& contourList) { m_contourList.clearPline(); for (int i = 0; i < contourList.getCount(); i++) { MLPline* pPline = contourList.getPline(i); m_contourList.addPline(pPline->clone()); } } void MLMicroStructure::setFaultList(const MLPlineList& faultList) { m_faultList.clearPline(); for (int i = 0; i < faultList.getCount(); i++) { MLPline* pPline = faultList.getPline(i); m_faultList.addPline(pPline->clone()); } } void MLMicroStructure::setGridInfo(double* xyRange, int* nxny, double* inc, double*zRange) { m_dimsIter->setGridInfo(xyRange, nxny, inc, zRange); } void MLMicroStructure::setZData(long num, float* data) { m_dimsIter->setZData(num, data); } bool MLMicroStructure::run() { // 过滤最小面积 double minArea = m_minArea; int limitNum = m_limitNum; // 删除断层内部 bool bFaultFilter = m_bFaultFilter; double faultCloseDis = m_faultCloseDis; // 闭合圈闭 bool bCloseShape = m_bCloseShape; double closeDis = m_closeDis; // 断层圈闭 bool bFaultShape = m_bFaultShape; double extendDis = m_extendDis; // 鼻状 bool bNoseShape = m_bNoseShape; double offsetDis = m_offsetDis; double minAngle = m_minAngle; double redundant = m_redundant; double minRadius = m_radius; bool smooth = m_smooth; double zoomin = m_zoomin; // 放大系数 double unitSacle = m_unitSacle; bool outCircle = m_bOutCircle; double dRadiusScale = m_dRadiusScale; double minDepth = m_minDepth; double maxDepth = m_maxDepth; // 判断文件是否存在 if (m_faultList.getCount() <=0) { //QMessageBox::warning(this, "error", "open fault polygon file failed"); //return false; } if (m_contourList.getCount() <=0) { //QMessageBox::warning(this, "error", "open contour file failed"); return false; } bool bReadGrid = true; if (m_dimsIter->getXnYnTotal() <=0) { //QMessageBox::warning(this, "error", "open grid file failed"); bReadGrid = false; } // 使用面积和节点过滤等值线 int num = m_contourList.getCount(); for (int i = m_contourList.getCount() - 1; i >= 0; i--) { MLPline* pPline = m_contourList.getPline(i); double area = pPline->getArea(); if (area < minArea) { m_contourList.removePline(pPline); delete pPline; pPline = nullptr; continue; } // 小于4个点 if (pPline->getCount() < limitNum) { m_contourList.removePline(pPline); delete pPline; pPline = nullptr; continue; } pPline->redundant(); } // 删除断层多边形内部等值线 if (bFaultFilter) { num = m_faultList.getCount(); for (int i = 0; i < m_faultList.getCount(); i++) { MLPline* pFault = (MLPline*)m_faultList.getPline(i); pFault->calculateBox(); if (pFault->getHeadTailDistance() > faultCloseDis) { continue; } for (int j = m_contourList.getCount() - 1; j >= 0; j--) { MLPline* pPline = m_contourList.getPline(j); pPline->calculateBox(); // 不相交 if (!CrossRtRt(pPline->getBox(), pFault->getBox())) { continue; } int notes = pPline->getCount(); int cenpt = int(notes / 2); if (pFault->contains(pPline->getAtPt(cenpt))) { m_contourList.removePline(pPline); delete pPline; pPline = nullptr; } } } } // 闭合圈闭 *********************************************************************** MLPlineList closeObjAry; if (bCloseShape && m_contourList.getCount() > 0) { for (int i = m_contourList.getCount() - 1; i >= 0; i--) { MLPline* pPline = m_contourList.getPline(i); // 首尾距离判断闭合圈闭 double dis = pPline->getHeadTailDistance(); if (dis <= closeDis) { closeObjAry.addPline(pPline); m_contourList.removePline(pPline); } } // 清空闭合圈闭内部线 //deleteInsidePline(closeObjAry); deleteInsidePlineArea(closeObjAry); m_closeObjPosiAry.clearPline(); m_closeObjNegaAry.clearPline(); // 根据网格判断是否高还是低 if (bReadGrid) { for (int i = 0; i < closeObjAry.getCount(); i++) { MLPline* closePline = closeObjAry.getPline(i); double dPlValue = atof(closePline->getName()); double dAveValue = getGridPolygonValue(closePline, m_dimsIter); if (dPlValue > 0) { if (dAveValue <= dPlValue) m_closeObjPosiAry.addPline(closePline->clone()); else m_closeObjNegaAry.addPline(closePline->clone()); } else { if (dAveValue <= dPlValue) m_closeObjNegaAry.addPline(closePline->clone()); else m_closeObjPosiAry.addPline(closePline->clone()); } } } } num = m_contourList.getCount(); // 断层圈闭************************************************************* MLPlineList faultObjAry; if (bFaultShape && m_faultList.getCount() > 0) { for (int i = num - 1; i >= 0; i--) { MLPline* pContour = m_contourList.getPline(i); pContour->calculateBox(); int index1 = -1; int index2 = -1; bool bFirst1 = true; bool bFirst2 = true; double distan1 = 0.0; double distan2 = 0.0; MLPlNode CrossPt1, CrossPt2; // 等值线开头两个点 MLPlNode pt11 = pContour->getAtPt(0); MLPlNode pt12 = pContour->getAtPt(1); // 等值线结尾两个点 MLPlNode pt21 = pContour->getAtPt(pContour->getCount() - 1); MLPlNode pt22 = pContour->getAtPt(pContour->getCount() - 2); for (int j = 0; j < m_faultList.getCount(); j++) { MLPline* pFault = (MLPline*)m_faultList.getPline(j); pFault->calculateBox(); // 不相交 if (!CrossRtRt(pContour->getBox(), pFault->getBox())) { continue; } MLPlNode crossPt; // 记录等值线头与断层相交 if (LinePolyline(pt12, pt11, pFault, crossPt, true)) { double dis1 = GetDistance(pt11.x, pt11.y, crossPt.x, crossPt.y); double dis2 = GetDistance(pt12.x, pt12.y, crossPt.x, crossPt.y); double dis = dis1; if (dis > dis2) dis = dis2; if (dis < extendDis) { if (bFirst1) { distan1 = dis; CrossPt1 = crossPt; index1 = j; bFirst1 = false; } else if (dis < distan1) { distan1 = dis1; CrossPt1 = crossPt; index1 = j; } } } // 记录等值线尾与断层相交 if (LinePolyline(pt22, pt21, pFault, crossPt, true)) { double dis1 = GetDistance(pt22.x, pt22.y, crossPt.x, crossPt.y); double dis2 = GetDistance(pt21.x, pt21.y, crossPt.x, crossPt.y); double dis = dis1; if (dis > dis2) dis = dis2; if (dis < extendDis) { if (bFirst2) { distan2 = dis; CrossPt2 = crossPt; index2 = j; bFirst2 = false; } else if (dis < distan2) { distan2 = dis; CrossPt2 = crossPt; index2 = j; } } } } // 判断为同一条断层 if (index1 == index2 && index1 != -1) { MLPline* pFaultPline = (MLPline*)m_faultList.getPline(index1); // 取断层线两个节点之间的线 MLPline faultPolyline = getPolyline(CrossPt1, CrossPt2, *pFaultPline); // 向等值线添加断层线 if (!faultPolyline.isEmpty()) { for (int k = faultPolyline.getCount() - 1; k >= 0; k--) { pContour->addTailPt(faultPolyline[k]); } // 面积过滤 pContour->calculateArea(); if (pContour->getArea() < minArea) { continue; } faultObjAry.addPline(pContour); m_contourList.removePline(pContour); } } } // 清空内部线 //deleteInsidePline(faultObjAry); deleteInsidePlineArea(faultObjAry); m_faultObjPosiAry.clearPline(); m_faultObjNegaAry.clearPline(); if (bReadGrid) { for (int i = 0; i < faultObjAry.getCount(); i++) { MLPline* faultPline = faultObjAry.getPline(i); double dPlValue = atof(faultPline->getName()); double dAveValue = getGridPolygonValue(faultPline, m_dimsIter); if (dPlValue > 0) { if (dAveValue <= dPlValue) m_faultObjPosiAry.addPline(faultPline->clone()); else m_faultObjNegaAry.addPline(faultPline->clone()); } else { if (dAveValue <= dPlValue) m_faultObjNegaAry.addPline(faultPline->clone()); else m_faultObjPosiAry.addPline(faultPline->clone()); } } } } // 鼻状圈闭*********************************************************************** MLPlineList noseObjAry; m_noseObjPosiAry.clearPline(); m_noseObjNegaAry.clearPline(); int mothed = 1; if (bNoseShape) { uint numThreads = QThread::idealThreadCount(); int to = m_contourList.getCount() - 1; int from = 0; const int numPoints = (to - from + 1) / numThreads; QwtDotsCommand command; command.series = &m_contourList; command.offsetDis = offsetDis; command.closeDis = closeDis; command.minAngle = minAngle; command.redundant = redundant; command.minRadius = minRadius; command.outCircle = outCircle; initGEOS(0, 0); QList< QFuture > futures; //// 测试 //command.from = 0; //command.to = 10; //getOffsetPline(command); for (uint i = 0; i < numThreads; i++) { const int index0 = from + i * numPoints; if (i == numThreads - 1) { command.from = index0; command.to = to; futures += QtConcurrent::run(&getOffsetPline, command); } else { command.from = index0; command.to = index0 + numPoints - 1; futures += QtConcurrent::run(&getOffsetPline, command); } } for (int i = 0; i < futures.size(); i++) futures[i].waitForFinished(); // 并行结果 for (int i = 0; i < futures.size(); i++) { MLPlineList* pPlineList = futures[i].result(); for (int j = 0; j < pPlineList->getCount(); j++) { noseObjAry.addPline(pPlineList->getPline(j)); } } if (bReadGrid) { // 利用均值判断,是鼻是沟; for (int i = 0; i < noseObjAry.getCount(); i++) { MLPline* nosePline = noseObjAry.getPline(i); double dPlValue = getGridPolylineValue(nosePline, m_dimsIter); double dAveValue = getGridPolygonValue(nosePline, m_dimsIter); if (dPlValue > 0) { if (dAveValue <= dPlValue) m_noseObjPosiAry.addPline(nosePline->clone()); else m_noseObjNegaAry.addPline(nosePline->clone()); } else { if (dAveValue <= dPlValue) m_noseObjNegaAry.addPline(nosePline->clone()); else m_noseObjPosiAry.addPline(nosePline->clone()); } } // 创建QT多边形 QList posiPolygonList; for (int i = 0; i < m_noseObjPosiAry.getCount(); i++) { MLPline* nosePline = m_noseObjPosiAry.getPline(i); posiPolygonList.append(new QPolygonF(nosePline->toQPolygonF())); } QList negaPolygonList; for (int i = 0; i < m_noseObjNegaAry.getCount(); i++) { MLPline* nosePline = m_noseObjNegaAry.getPline(i); negaPolygonList.append(new QPolygonF(nosePline->toQPolygonF())); } // 合并多边形 combinaPolygon(posiPolygonList); // 合并多边形 combinaPolygon(negaPolygonList); m_noseObjPosiAry.clearPline(); m_noseObjNegaAry.clearPline(); // 用做删除处理 QList posiPolygonList2; QList negaPolygonList2; geos::geom::PrecisionModel pm(1e+10); geos::geom::GeometryFactory::Ptr geometryFactory = geos::geom::GeometryFactory::create(&pm); // 求取最大多凸多边形 for (int i = 0; i < posiPolygonList.count(); i++) { geos::geom::CoordinateArraySequence sequence; QPolygonF* pPolygonF = posiPolygonList[i]; for (int j = 0; j < pPolygonF->count(); j++) sequence.add(Coordinate(pPolygonF->at(j).x(), pPolygonF->at(j).y())); LineString* pLineString = geometryFactory->createLineString(sequence); std::unique_ptr geom_convexHull = pLineString->convexHull(); geos::geom::Polygon* geom_ = dynamic_cast (geom_convexHull.get()); if (geom_ && !geom_->isEmpty()) { MLPline templine; for (int k = 0; k < geom_->getNumPoints(); k++) { templine.addTailPt(geom_->getCoordinates()->getX(k), geom_->getCoordinates()->getY(k)); } // 光滑 MLPline smoothPline; if (smooth) { smoothPoints(smoothPline, templine, templine.getCount() / 2, true); templine.copyPt(smoothPline); } // 偏移 if (zoomin > 0) { // 格式转换 geos::geom::CoordinateArraySequence sequence; for (int k = 0; k < templine.getCount(); k++) { MLPlNode node = templine.getAtPt(k); sequence.add(geos::geom::Coordinate(node.x, node.y)); } sequence.add(geos::geom::Coordinate(templine.getHeadPt().x, templine.getHeadPt().y)); // 创建多边形 geos::geom::LinearRing* pLinearRing = geometryFactory->createLinearRing(sequence); geos::geom::Polygon* pPolygon = geometryFactory->createPolygon(pLinearRing, nullptr); std::unique_ptr buf = pPolygon->buffer(zoomin); if (!buf->isEmpty()) { templine.removeAll(); // 格式转换 geos::geom::Polygon* pPolygonBuf = dynamic_cast (buf.get()); const geos::geom::LineString* pLineaBuf = pPolygonBuf->getExteriorRing(); for (int i = 0; i < pLineaBuf->getNumPoints(); i++) { MLPoint dpt(pLineaBuf->getCoordinates()->getX(i), pLineaBuf->getCoordinates()->getY(i)); templine.addTailPt(dpt); } } geometryFactory->destroyGeometry(pPolygon); } m_noseObjPosiAry.addPline(templine.clone()); // 创建新的QPolygon QPolygonF* pNewPolygon = new QPolygonF; templine.toQPolygonF(*pNewPolygon); posiPolygonList2.push_back(pNewPolygon); } geometryFactory->destroyGeometry(pLineString); } // 求取最大多凹多边形 for (int i = 0; i < negaPolygonList.count(); i++) { geos::geom::CoordinateArraySequence sequence; QPolygonF* pPolygonF = negaPolygonList[i]; for (int j = 0; j < pPolygonF->count(); j++) { sequence.add(Coordinate(pPolygonF->at(j).x(), pPolygonF->at(j).y())); } LineString* pLineString = geometryFactory->createLineString(sequence); std::unique_ptr geom_convexHull = pLineString->convexHull(); geos::geom::Polygon* geom_ = dynamic_cast (geom_convexHull.get()); if (geom_ && !geom_->isEmpty()) { MLPline templine; for (int k = 0; k < geom_->getNumPoints(); k++) { templine.addTailPt(geom_->getCoordinates()->getX(k), geom_->getCoordinates()->getY(k)); } // 光滑 MLPline smoothPline; if (smooth) { smoothPoints(smoothPline, templine, templine.getCount() / 2, true); templine.copyPt(smoothPline); } // 偏移 if (zoomin > 0) { // 格式转换 geos::geom::CoordinateArraySequence sequence; for (int k = 0; k < templine.getCount(); k++) { MLPlNode node = templine.getAtPt(k); sequence.add(geos::geom::Coordinate(node.x, node.y)); } sequence.add(geos::geom::Coordinate(templine.getHeadPt().x, templine.getHeadPt().y)); // 创建多边形 geos::geom::LinearRing* pLinearRing = geometryFactory->createLinearRing(sequence); geos::geom::Polygon* pPolygon = geometryFactory->createPolygon(pLinearRing, nullptr); std::unique_ptr buf = pPolygon->buffer(zoomin); if (!buf->isEmpty()) { templine.removeAll(); // 格式转换 geos::geom::Polygon* pPolygonBuf = dynamic_cast (buf.get()); const geos::geom::LineString* pLineaBuf = pPolygonBuf->getExteriorRing(); for (int i = 0; i < pLineaBuf->getNumPoints(); i++) { MLPoint dpt(pLineaBuf->getCoordinates()->getX(i), pLineaBuf->getCoordinates()->getY(i)); templine.addTailPt(dpt); } } geometryFactory->destroyGeometry(pPolygon); } m_noseObjNegaAry.addPline(templine.clone()); // 创建新的QPolygon QPolygonF* pNewPolygon = new QPolygonF; templine.toQPolygonF(*pNewPolygon); negaPolygonList2.push_back(pNewPolygon); } geometryFactory->destroyGeometry(pLineString); //noseObjNegaAry.addPline(new MLPline(*negaPolygonList[i])); } // 删除凸起和凹陷相交的多边形 deletePolygon(posiPolygonList2, negaPolygonList2, unitSacle); // 删除原有的 m_noseObjPosiAry.clearPline(); m_noseObjNegaAry.clearPline(); if (!posiPolygonList2.isEmpty()) { for (int i = 0; i < posiPolygonList2.count(); i++) { QPolygonF* pPolygon = posiPolygonList2.at(i); MLPline* pPline = new MLPline(*pPolygon); pPline->calculateArea(); m_noseObjPosiAry.addPline(pPline); } } if (!negaPolygonList2.isEmpty()) { for (int i = 0; i < negaPolygonList2.count(); i++) { QPolygonF* pPolygon = negaPolygonList2.at(i); MLPline* pPline = new MLPline(*pPolygon); pPline->calculateArea(); m_noseObjNegaAry.addPline(pPline); } } // delete Qt 多边形 for (int i = 0; i < posiPolygonList.count(); i++) delete posiPolygonList[i]; for (int i = 0; i < negaPolygonList.count(); i++) delete negaPolygonList[i]; // delete for (int i = 0; i < posiPolygonList2.count(); i++) delete posiPolygonList2[i]; for (int i = 0; i < negaPolygonList2.count(); i++) delete negaPolygonList2[i]; } } // 重新计算面积、幅度差、长轴,短轴; if (bCloseShape) { // 凸闭合圈闭 calPolygonInfo(m_closeObjPosiAry, m_dimsIter, "cp", dRadiusScale, minDepth, maxDepth); // 凹闭合圈闭 calPolygonInfo(m_closeObjNegaAry, m_dimsIter, "cn", dRadiusScale, minDepth, maxDepth); } if (bFaultShape) { // 凸断层圈闭 calPolygonInfo(m_faultObjPosiAry, m_dimsIter, "fp", dRadiusScale, minDepth, maxDepth); // 凹断层圈闭 calPolygonInfo(m_faultObjNegaAry, m_dimsIter, "fn", dRadiusScale, minDepth, maxDepth); } if (bNoseShape) { // 凸鼻状圈闭 calPolygonInfo(m_noseObjPosiAry, m_dimsIter, "np", dRadiusScale, minDepth, maxDepth); // 凹鼻状圈闭 calPolygonInfo(m_noseObjNegaAry, m_dimsIter, "nn", dRadiusScale, minDepth, maxDepth); } // clear m_dimsIter->clearMemory(); m_faultList.clearPline(); m_contourList.clearPline(); noseObjAry.clearPline(); return true; } void MLMicroStructure::clearMemory() { m_closeObjPosiAry.clearPline(); m_closeObjNegaAry.clearPline(); m_faultObjPosiAry.clearPline(); m_faultObjNegaAry.clearPline(); m_noseObjPosiAry.clearPline(); m_noseObjNegaAry.clearPline(); delete m_dimsIter; } /**/ int MLMicroStructure::readDfgBinary(const char* file) { if (m_dimsIter) { m_dimsIter->readDfgBinary(file); } return 0; } //排列判断 bool compareBarData(MLPline* pPline1, MLPline* pPline2) { double value1 = atof(pPline1->getName()); double value2 = atof(pPline2->getName()); value1 = fabs(value1); value2 = fabs(value2); if (value1 > value2) { return true; } return false; } //排列判断 bool compareBarData2(MLPline* pPline1, MLPline* pPline2) { double value1 = atof(pPline1->getName()); double value2 = atof(pPline2->getName()); value1 = fabs(value1); value2 = fabs(value2); if (value1 < value2) { return true; } return false; } void sortContourPline(MLPlineList* pPlineList) { // 对等值线排序列 qSort(pPlineList->m_PlineList.begin(), pPlineList->m_PlineList.end(), compareBarData); } void sortContourPline2(MLPlineList* pPlineList) { // 对等值线排序列 qSort(pPlineList->m_PlineList.begin(), pPlineList->m_PlineList.end(), compareBarData2); } void sortContourPlineArea(MLPlineList& plineList) { // 对等值线排序列 qSort(plineList.m_PlineList.begin(), plineList.m_PlineList.end(), compareDataArea); } // 检查是否在线上 bool onPolyline(const MLPoint& point, const MLPline& polyline) { for (int i = 0; i < polyline.getCount(); i++) { if (fabs(point.x - polyline[i].x) < 0.01 && fabs(point.y - polyline[i].y) < 0.01) { return true; } if (i > 0) { MLPoint pt1 = polyline.getAtPt(i - 1); MLPoint pt2 = polyline.getAtPt(i); double dis = GetDistance(pt1, pt2); double dis1 = GetDistance(pt1, point); double dis2 = GetDistance(point, pt2); // if (fabs(dis - (dis1 + dis2)) <= 0.01) { return true; } } } return false; } // 检查是否包含子线,点在线上不算 bool containsPts(const MLPline& polyline, const MLPline& subPolyline) { MLPline newPolyline = polyline; for (int i = 0; i < subPolyline.getCount(); i++) { MLPlNode node = subPolyline.getAtPt(i); if (onPolyline(node, newPolyline)) continue; if (newPolyline.contains(node)) { return true; } } return false; } // 得到曲内网格平均值 double getGridPolygonValue(MLPline* polyline, GMLDimsIter* pDimsIter, double* minValue, double* maxValue) { double x1 = pDimsIter->getXYRange()[0]; double x2 = pDimsIter->getXYRange()[1]; double y1 = pDimsIter->getXYRange()[2]; double y2 = pDimsIter->getXYRange()[3]; int i, j, k; int num = 0; double zz = 0.0; double average = 0.0; int n = pDimsIter->getGridY(); int m = pDimsIter->getGridX(); double minV = 0; double maxV = 0; double firstV = true; MLRect dRt = polyline->calculateBox(); int start_j = pDimsIter->getIndexFrY(dRt.bottom)-1; int end_j = pDimsIter->getIndexFrY(dRt.top)+1; if (start_j < 0) start_j = 0; if (end_j > pDimsIter->getGridY()) end_j = pDimsIter->getGridY(); int start_i = pDimsIter->getIndexFrX(dRt.left)-1; int end_i = pDimsIter->getIndexFrX(dRt.right)+1; if (start_i < 0) start_i = 0; if (end_i > pDimsIter->getGridX()) end_i = pDimsIter->getGridX(); for (j = start_j; j getX(i); double y = pDimsIter->getY(j); double z = pDimsIter->getZValue(i, j); if (z < -99999999.0 || z > 99999999.0) continue; //if (!dRect.contains(x, y)) // continue; if (polyline->contains(x, y)) { zz += z; num++; if (firstV) { minV = z; maxV = z; firstV = false; } else { if (minV > z) minV = z; if (maxV < z) maxV = z; } } } } if (num > 0) average = zz / num; if (minValue) { *minValue = minV; } if (maxValue) { *maxValue = maxV; } return average; } double getGridPolylineValue(MLPline* polyline, GMLDimsIter* pDimsIter, double* minValue, double* maxValue) { MLRect dRt = polyline->calculateBox(); double minV = 0; double maxV = 0; double firstV = true; double plAverage = 0; double inAverage = 0; int num = 0; for (int i = 0; i < polyline->getCount(); i++) { MLPlNode node = polyline->getAtPt(i); double z = pDimsIter->getZValue(node.x, node.y); if (z < -99999999.0 || z > 99999999.0) continue; plAverage += z; num++; if (firstV) { minV = z; maxV = z; firstV = false; } else { if (minV > z) minV = z; if (maxV < z) maxV = z; } } if (num > 0) plAverage = plAverage / num; if (minValue) { *minValue = minV; } if (maxValue) { *maxValue = maxV; } return plAverage; } // 删除圈闭内的线 void deleteInsidePline(MLPlineList* pPlineList) { // 按等值线值排序, 小在前,大在后 sortContourPline2(pPlineList); MLPlineList delPlineList; int num = pPlineList->getCount(); // 闭合圈闭正 for (int i = pPlineList->getCount() - 1; i >= 0; i--) { MLPline* pContour1 = pPlineList->getPline(i); if (pContour1 == nullptr) continue; double value1 = atof(pContour1->getName()); value1 = fabs(value1); for (int j = i - 1; j >= 0; j--) { MLPline* pContour2 = pPlineList->getPline(j); if (pContour2 == nullptr) continue; double value2 = atof(pContour2->getName()); value2 = fabs(value2); if (value2 > value1) continue; if (Equ(value1, value2)) continue; if (containsPts(*pContour1, *pContour2)) { pPlineList->removePline(pContour2); delPlineList.addPline(pContour2); } } } // 大在前,小在后 sortContourPline(pPlineList); num = pPlineList->getCount(); // 闭合圈闭反 for (int i = pPlineList->getCount() - 1; i >= 0; i--) { MLPline* pContour1 = pPlineList->getPline(i); if (pContour1 == nullptr) continue; double value1 = atof(pContour1->getName()); value1 = fabs(value1); for (int j = i - 1; j >= 0; j--) { MLPline* pContour2 = pPlineList->getPline(j); if (pContour2 == nullptr) continue; double value2 = atof(pContour2->getName()); value2 = fabs(value2); if (value2 < value1) continue; if (Equ(value1, value2)) continue; if (containsPts(*pContour1, *pContour2)) { pPlineList->removePline(pContour2); delPlineList.addPline(pContour2); } } } delPlineList.clearPline(); } void deleteInsideSubPline(MLPlineList& plineList) { for (int i = 0;i< plineList.getCount();i++) { MLPline* pContour1 = plineList.getPline(i); if (pContour1 == nullptr) continue; pContour1->calculateBox(); bool isContaines = false; for (int j = i + 1; j calculateBox(); // 不相交 if (!CrossRtRt(pContour1->getBox(), pContour2->getBox())) { continue; } // 曲线1包含曲线2 if (containsPts(*pContour1, *pContour2)) { plineList.removePline(pContour2); delete pContour2; isContaines = true; } } if (isContaines) { deleteInsideSubPline(plineList); goto exitt; } } exitt: return; } void deleteInsidePline(MLPlineList& plineList) { // 大在前,小在后 sortContourPlineArea(plineList); int num = plineList.getCount(); deleteInsideSubPline(plineList); } int LinePolyline(MLPlNode& data1, MLPlNode& data2, MLPline* curve, MLPlNode& data, bool bExtend) { /* * data2 为最近相交点 **/ int nCount = 0; int num = curve->getCount(); MLPlNode* pPtDest = new MLPlNode[num]; int* pIdx = new int[num]; double minx, maxx; double miny, maxy; bool first = true; for (int i = 0; i < num; i++) { if (first) { minx = curve->getAtPt(i).x; maxx = curve->getAtPt(i).x; miny = curve->getAtPt(i).y; maxy = curve->getAtPt(i).y; first = false; } else { if (minx > curve->getAtPt(i).x) minx = curve->getAtPt(i).x; if (maxx < curve->getAtPt(i).x) maxx = curve->getAtPt(i).x; if (miny > curve->getAtPt(i).y) miny = curve->getAtPt(i).y; if (maxy < curve->getAtPt(i).y) maxy = curve->getAtPt(i).y; } } int j = 0; for (int i = 1; i < num; i++) { double L2x1, L2y1, L2x2, L2y2; L2x1 = curve->getAtPt(i - 1).x; L2y1 = curve->getAtPt(i - 1).y; L2x2 = curve->getAtPt(i).x; L2y2 = curve->getAtPt(i).y; double dis1 = GetDistance(data2, curve->getAtPt(i - 1)); double dis2 = GetDistance(data2, curve->getAtPt(i)); double dis3 = GetDistance(curve->getAtPt(i - 1), curve->getAtPt(i)); // 在线上 if (fabs(dis3 - (dis1 + dis2)) < 0.01) { pPtDest[j].x = data2.x; pPtDest[j].y = data2.y; pIdx[j] = i; j++; } // 相交 else if (LineLine(data1.x, data1.y, data2.x, data2.y, &L2x1, &L2y1, &L2x2, &L2y2)) { pPtDest[j].x = L2x1; pPtDest[j].y = L2y1; pIdx[j] = i; j++; } else if (LineLine(data1.x, data1.y, data2.x, data2.y, &L2x1, &L2y1, &L2x2, &L2y2, bExtend)) { double dis11 = GetDistance(data2, MLPlNode(L2x1, L2y1)); double dis12 = GetDistance(data1, MLPlNode(L2x1, L2y1)); // 如果离线近的点,离交点的距离反而远了。 if (dis11 > dis12) { continue; } if (L2x1 >= minx && L2x1 <= maxx && L2y1 >= miny && L2y1 <= maxy) { pPtDest[j].x = L2x1; pPtDest[j].y = L2y1; pIdx[j] = i; j++; } } } if (j == 1) { data = pPtDest[0]; int idx = pIdx[0]; delete[] pPtDest; delete[] pIdx; double L2x1 = curve->getAtPt(idx - 1).x; double L2y1 = curve->getAtPt(idx - 1).y; double L2x2 = curve->getAtPt(idx).x; double L2y2 = curve->getAtPt(idx).y; if ((L2x1 < L2x2) && (L2x1 <= data.x && data.x <= L2x2)) return 1; if ((L2x1 > L2x2) && (L2x2 <= data.x && data.x <= L2x1)) return 1; if ((L2y1 < L2y2) && (L2y1 <= data.y && data.y <= L2y2)) return 1; if ((L2y1 > L2y2) && (L2y2 <= data.y && data.y <= L2y1)) return 1; return 0; } if (j > 1) { double dis = GetDistance(data2, pPtDest[0]); data = pPtDest[0]; int idx = pIdx[0]; for (int i = 1; i < j; i++) { double leng = GetDistance(data2, pPtDest[i]); if (leng < dis) { dis = leng; data = pPtDest[i]; idx = pIdx[i]; } } delete[] pPtDest; delete[] pIdx; double L2x1 = curve->getAtPt(idx - 1).x; double L2y1 = curve->getAtPt(idx - 1).y; double L2x2 = curve->getAtPt(idx).x; double L2y2 = curve->getAtPt(idx).y; if ((L2x1 < L2x2) && (L2x1 <= data.x && data.x <= L2x2)) return 1; if ((L2x1 > L2x2) && (L2x2 <= data.x && data.x <= L2x1)) return 1; if ((L2y1 < L2y2) && (L2y1 <= data.y && data.y <= L2y2)) return 1; if ((L2y1 > L2y2) && (L2y2 <= data.y && data.y <= L2y1)) return 1; return 0; } delete[] pPtDest; return 0; } int findIndex(const MLPoint& point, const MLPline& polyline) { int idx = -1; for (int i = 1; i < polyline.getCount(); i++) { MLPoint pt1 = polyline.getAtPt(i - 1); MLPoint pt2 = polyline.getAtPt(i); double dis = GetDistance(pt1, pt2); double dis1 = GetDistance(pt1, point); double dis2 = GetDistance(point, pt2); // if (fabs(dis - (dis1 + dis2)) <= 0.01) { return i; } } return idx; } MLPline getPolyline(const MLPoint& pt1, const MLPoint& pt2, const MLPline& polyline) { MLPline newPolyline; MLPline newPolyline1, newPolyline2; int idx1 = findIndex(pt1, polyline); int idx2 = findIndex(pt2, polyline); int count = polyline.getCount(); if (idx1 <= 0 || idx2 <= 0) return newPolyline; if (idx1 == idx2) return newPolyline; // 线首尾点距离 double plDis = polyline.getHeadTailDistance(); if (idx1 < idx2) { // 为单线 if (GetDistance(pt1, pt2) < plDis) { // 1 newPolyline1.addTailPt(pt1); for (int i = idx1; i < idx2 - 1; i++) { newPolyline1.addTailPt(polyline[i]); } newPolyline1.addTailPt(pt2); return newPolyline1; } else { // 1 newPolyline1.addTailPt(pt1); for (int i = idx1; i < idx2 - 1; i++) { newPolyline1.addTailPt(polyline[i]); } newPolyline1.addTailPt(pt2); newPolyline1.calculateLength(); double length1 = newPolyline1.getLength(); // 2 newPolyline2.addTailPt(pt1); for (int i = idx1; i >= 0; i--) { newPolyline2.addTailPt(polyline[i]); } for (int i = polyline.getCount() - 1; i >= idx2; i--) { newPolyline2.addTailPt(polyline[i]); } newPolyline2.addTailPt(pt2); newPolyline2.calculateLength(); double length2 = newPolyline2.getLength(); // 取两节点最短的线段 if (length1 > length2) { return newPolyline2; } else { return newPolyline1; } } } if (idx1 > idx2) { // 为单线 if (GetDistance(pt1, pt2) < plDis) { // 1 newPolyline1.addTailPt(pt1); for (int i = idx1; i >= idx2; i--) { newPolyline1.addTailPt(polyline[i]); } newPolyline1.addTailPt(pt2); return newPolyline1; } else { // 1 newPolyline1.addTailPt(pt1); for (int i = idx1 - 1; i >= idx2; i--) { newPolyline1.addTailPt(polyline[i]); } newPolyline1.addTailPt(pt2); newPolyline1.calculateLength(); double length1 = newPolyline1.getLength(); //2 newPolyline2.addTailPt(pt1); for (int i = idx1; i < count; i++) { newPolyline2.addTailPt(polyline[i]); } for (int i = 0; i < idx2; i++) { newPolyline2.addTailPt(polyline[i]); } newPolyline2.addTailPt(pt2); newPolyline2.calculateLength(); double length2 = newPolyline2.getLength(); if (length1 > length2) { return newPolyline2; } else { return newPolyline1; } } } return newPolyline; } void Switch(double &dVal1, double &dVal2) { double v = dVal1; dVal1 = dVal2; dVal2 = v; } MLPlineList* getOffsetPline(QwtDotsCommand command) { MLPlineList* pPlineLise = new MLPlineList; geos::geom::PrecisionModel pm(1e+10); geos::geom::GeometryFactory::Ptr factory = geos::geom::GeometryFactory::create(&pm); for (int i = command.from; i < command.to; i++) { MLPline* pContour = command.series->getPline(i); pContour->redundant(3.0); if (pContour->getHeadPt().y > pContour->getTailPt().y) { pContour->reversePt(); pContour->calculateLength(); } GEOSGeometry* geom_ = nullptr; GEOSGeometry* geomLeft_ = nullptr; GEOSGeometry* geomRight_ = nullptr; const size_t size = pContour->getCount(); geos::geom::CoordinateArraySequence sequence(size); for (int j = 0; j < size; j++) { MLPlNode node = pContour->getAtPt(j); sequence.setAt(geos::geom::Coordinate(node.x, node.y), j); } // 原等值线 geom_ = factory->createLineString(sequence); geomLeft_ = GEOSOffsetCurve(geom_, command.offsetDis, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_BEVEL, 0); geomRight_ = GEOSOffsetCurve(geom_, -command.offsetDis, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_BEVEL, 0); int numGeo1 = 0; if (geomLeft_) numGeo1 = geomLeft_->getNumGeometries(); int numGeo2 = 0; if (geomRight_) numGeo2 = geomRight_->getNumGeometries(); // 判断左偏移等值线 if (numGeo1 >= 1) { for (int ig = 0; ig < numGeo1; ig++) { const Geometry *geom_sub = geomLeft_->getGeometryN(ig); int count = geom_sub->getNumPoints(); if (count < 3) continue; MLPline* temPl = new MLPline; for (int k = 0; k < count; k++) { temPl->addTailPt(geom_sub->getCoordinates()->getX(k), geom_sub->getCoordinates()->getY(k)); } temPl->redundant(command.redundant); temPl->calculateAngle(); // 生成圆多边形 MLPlineList ellipsePlineList; for (int k = 0; k < temPl->getCount(); k++) { // 角度 double angle = temPl->getAtPt(k).a * RHO; MLPlNode node = temPl->getAtPt(k); // 如果角度小于规定角度 if (angle < command.minAngle) { MLPline* pPline = new MLPline; pPline->createEllipse(node, command.minRadius); pPline->calculateLength(); ellipsePlineList.addPline(pPline); } } // 计算圆与原等值线相关,并取原等值 MLPlineList newPlineList; for (int k = 0; k < ellipsePlineList.getCount(); k++) { MLPline* pEllipsePline = ellipsePlineList.getPline(k); QVector dPointAry; //计算交点,并按距离排序 GetCrossPt(*pEllipsePline, *pContour, dPointAry); if (dPointAry.count() >= 2) { QVector dp; double dbx1 = dPointAry.first().l; double dbx2 = dPointAry.last().l; // 如果线头被包含 if (pEllipsePline->contains(pContour->getHeadPt())) dbx1 = 0; // 如果线尾被包含 else if (pEllipsePline->contains(pContour->getTailPt())) dbx2 = pContour->getLength() - 1; else if (PtAtPolyline(pContour->getHeadPt(), *pEllipsePline)) dbx1 = 0; else if (PtAtPolyline(pContour->getTailPt(), *pEllipsePline)) dbx2 = 0; // 取线 getCurve(dbx1, dbx2, dp, *pContour, 0, 0); // 赋值 if (dp.size() > 1) { MLPline* pNewPline = new MLPline; newPlineList.addPline(pNewPline); for (int m = 0; m < dp.size(); m++) pNewPline->addTailPt(dp.at(m)); } } else if (dPointAry.count() == 1) { double dbx1 = dPointAry.first().l; bool headContains = pEllipsePline->contains(pContour->getHeadPt()); bool tailContains = pEllipsePline->contains(pContour->getTailPt()); QVector dp; if (headContains && tailContains) { } else if (headContains) { // 取线 getCurve(0, dbx1, dp, *pContour, 0, 0); } else if (tailContains) { // 取线 double length = pContour->getLength(); getCurve(dbx1, length, dp, *pContour, 0, 0); } // 赋值 if (dp.size() > 1) { MLPline* pNewPline = new MLPline; newPlineList.addPline(pNewPline); for (int m = 0; m < dp.size(); m++) pNewPline->addTailPt(dp.at(m)); } } else { // 20220605 删除掉,大庆不需要圆圈 // if (command.outCircle) // { // newPlineList.addPline(pEllipsePline->clone()); // } } } for (int k = 0; k < newPlineList.getCount(); k++) { pPlineLise->addPline(newPlineList.getPline(k)->clone()); } newPlineList.clearPline(); ellipsePlineList.clearPline(); delete temPl; } } // 判断右偏移等值线 if (numGeo2 >= 1) { for (int ig = 0; ig < numGeo2; ig++) { const Geometry *geom_sub = geomRight_->getGeometryN(ig); int count = geom_sub->getNumPoints(); if (count < 3) continue; MLPline* temPl = new MLPline; for (int k = 0; k < count; k++) { temPl->addTailPt(geom_sub->getCoordinates()->getX(k), geom_sub->getCoordinates()->getY(k)); } temPl->redundant(command.redundant); temPl->calculateAngle(); // 生成圆多边形 MLPlineList ellipsePlineList; for (int k = 0; k < temPl->getCount(); k++) { double angle = temPl->getAtPt(k).a*RHO; MLPlNode node = temPl->getAtPt(k); // 如果角度小于规定角度 if (angle < command.minAngle) { MLPline* pPline = new MLPline; pPline->createEllipse(node, command.minRadius); pPline->calculateLength(); ellipsePlineList.addPline(pPline); //pPlineLise->addPline(pPline); } } // 计算圆与原等值线相关,并取原等值 MLPlineList newPlineList; for (int k = 0; k < ellipsePlineList.getCount(); k++) { MLPline* pEllipsePline = ellipsePlineList.getPline(k); QVector dPointAry; //计算交点,并按距离排序 GetCrossPt(*pEllipsePline, *pContour, dPointAry); if (dPointAry.count() >= 2) { QVector dp; double dbx1 = dPointAry.first().l; double dbx2 = dPointAry.last().l; // 如果线头被包含 if (pEllipsePline->contains(pContour->getHeadPt())) dbx1 = 0; // 如果线尾被包含 else if (pEllipsePline->contains(pContour->getTailPt())) dbx2 = pContour->getLength() - 1; else if (PtAtPolyline(pContour->getHeadPt(), *pEllipsePline)) dbx1 = 0; else if (PtAtPolyline(pContour->getTailPt(), *pEllipsePline)) dbx2 = 0; // 取线 getCurve(dbx1, dbx2, dp, *pContour, 0, 0); // 赋值 if (dp.size() > 1) { MLPline* pNewPline = new MLPline; newPlineList.addPline(pNewPline); for (int m = 0; m < dp.size(); m++) pNewPline->addTailPt(dp.at(m)); } } else if (dPointAry.count() == 1) { double dbx1 = dPointAry.first().l; bool headContains = pEllipsePline->contains(pContour->getHeadPt()); bool tailContains = pEllipsePline->contains(pContour->getTailPt()); QVector dp; if (headContains && tailContains) { } else if (headContains) { // 取线 getCurve(0, dbx1, dp, *pContour, 0, 0); } else if (tailContains) { // 取线 double length = pContour->getLength(); getCurve(dbx1, length, dp, *pContour, 0, 0); } // 赋值 if (dp.size() > 1) { MLPline* pNewPline = new MLPline; newPlineList.addPline(pNewPline); for (int m = 0; m < dp.size(); m++) pNewPline->addTailPt(dp.at(m)); } } else { // 20220605 删除掉,大庆不需要圆圈 // if (command.outCircle) // { // newPlineList.addPline(pEllipsePline->clone()); // } } } for (int k = 0; k < newPlineList.getCount(); k++) { pPlineLise->addPline(newPlineList.getPline(k)->clone()); } newPlineList.clearPline(); ellipsePlineList.clearPline(); delete temPl; } } if (geom_) { factory->destroyGeometry(geom_); } if (geomLeft_) { factory->destroyGeometry(geomLeft_); } if (geomRight_) { factory->destroyGeometry(geomRight_); } } return pPlineLise; } void combinaPolygon(QList& PolygonList) { for (int i = 0; i < PolygonList.count(); i++) { QPolygonF* circlePolygon1 = PolygonList[i]; for (int j = i + 1; j < PolygonList.count(); j++) { QPolygonF* circlePolygon2 = PolygonList[j]; // 检测两个多边形是否相交 if (!checkPolygonCross(*circlePolygon1, *circlePolygon2)) { continue; } QPolygonF resPolygon = circlePolygon1->united(*circlePolygon2); if (!resPolygon.isEmpty()) { QPolygonF* newPolygon = new QPolygonF(resPolygon); PolygonList.removeOne(circlePolygon1); PolygonList.removeOne(circlePolygon2); delete circlePolygon1; delete circlePolygon2; PolygonList.push_back(newPolygon); combinaPolygon(PolygonList); goto goto_pos; } } } goto_pos: return; } // 删除相交的多边形(因为凹多边形与凸多边形有叠合) void deletePolygon(QList& PolygonList1, QList& PolygonList2, double unitSacle) { for (int i = 0; i < PolygonList1.count(); i++) { QPolygonF* polygon1 = PolygonList1[i]; for (int j = 0; j < PolygonList2.count(); j++) { QPolygonF* polygon2 = PolygonList2[j]; // 检测两个多边形是否相交 QPolygonF desPolygon; if (!checkPolygonCross(*polygon1, *polygon2, desPolygon)) { continue; } double dArea1 = calculateArea(*polygon1); double dArea2 = calculateArea(*polygon2); double dAreaDes = calculateArea(desPolygon); if (dArea1 > dArea2) { // 相交面积大于0.7,删除小面积的 double scale1 = dAreaDes / dArea2; if (scale1 >= unitSacle) { PolygonList2.removeOne(polygon2); delete polygon2; deletePolygon(PolygonList1, PolygonList2, unitSacle); goto goto_pos; } } else if (dArea1 < dArea2) { // 相交面积大于0.7,删除小面积的 double scale2 = dAreaDes / dArea1; if (scale2 >= unitSacle) { PolygonList1.removeOne(polygon1); delete polygon1; deletePolygon(PolygonList1, PolygonList2, unitSacle); goto goto_pos; } } else { } } } goto_pos: return; } // 检测两个多边形是否相交,并返回相交多边形 bool checkPolygonCross(const QPolygonF& polygon1, const QPolygonF& polygon2) { if (polygon1.isEmpty() || polygon2.isEmpty()) { return false; } if (polygon1.count() == polygon2.count()) { if (polygon1.first().toPoint() == polygon2.first().toPoint() && polygon1.last().toPoint() == polygon2.last().toPoint() && polygon1[polygon1.count() / 2].toPoint() == polygon2[polygon2.count() / 2].toPoint()) { return false; } } QPolygonF polygon = polygon1.intersected(polygon2); if (!polygon.isEmpty()) { return true; } return false; } bool checkPolygonCross(const QPolygonF& polygon1, const QPolygonF& polygon2, QPolygonF& polygonDes) { if (polygon1.isEmpty() || polygon2.isEmpty()) { return false; } if (polygon1.count() == polygon2.count()) { if (polygon1.first().toPoint() == polygon2.first().toPoint() && polygon1.last().toPoint() == polygon2.last().toPoint() && polygon1[polygon1.count() / 2].toPoint() == polygon2[polygon2.count() / 2].toPoint()) { return false; } } polygonDes = polygon1.intersected(polygon2); if (!polygonDes.isEmpty()) { return true; } return false; } QPointF getCentroid(const QPolygonF& polygon) { /* Compute polygon centroid location */ int i, last; double A, d, xold, yold; A = calculateArea(polygon); last = polygon.count(); double Cx = 0.0, Cy = 0.0; xold = polygon[last - 1].x(); yold = polygon[last - 1].y(); for (i = 0; i < last; i++) { d = (xold * polygon[i].y() - polygon[i].x() * yold); Cx += (polygon[i].x() + xold) * d; Cy += (polygon[i].y() + yold) * d; xold = polygon[i].x(); yold = polygon[i].y(); } Cx /= (6.0 * A); Cy /= (6.0 * A); return QPointF(Cx, Cy); //return ((A < 0.0) ? -1 : +1); /* -1 means CCW, +1 means CW */ } double calculateArea(const QPolygonF& polygon) { double area = 0.; int i, j; int n = polygon.count(); QPointF dPt1, dPt2; double ai = 0.; for (i = n - 1, j = 0; j < n; i = j, j++) { dPt1 = polygon[i]; dPt2 = polygon[j]; ai = dPt1.x() * dPt2.y() - dPt2.x() * dPt1.y(); area += ai; } return area = fabs(area / 2.0); } MLPline* getOffsetPl(MLPline* pPolyline, double dDistance) { MLPline* pNewPolyline = new MLPline; int count = pPolyline->getCount(); for (int i = 1; i < count; i++) { MLPoint dPt1 = pPolyline->getAtPt(i - 1); MLPoint dPt2 = pPolyline->getAtPt(i); double dscale = 1.0;// (dDepth - dPt1.cz) / (dPt2.cz - dPt1.cz); double dxa = dPt2.x - dPt1.x; double dya = dPt2.y - dPt1.y; double drr = sqrt(dxa * dxa + dya * dya); double dis = dDistance; double dsize = drr * dscale; double dSin = dya / drr; double dCos = dxa / drr; MLPoint dPt; dPt.x = dPt1.x + dsize * dCos + dis * dSin; dPt.y = dPt1.y + dsize * dSin - dis * dCos; dPt.l = dPt2.l; pNewPolyline->addHeadPt(dPt); } return pNewPolyline; } int GetBXY(double *X, double *Y, int isClose, MLPline& dPline) { int i, n; int num = dPline.getCount(); n = num + 4; for (i = 2; i < n - 2; ++i) { X[i] = dPline[i - 2].x; Y[i] = dPline[i - 2].y; } if (!isClose) { X[0] = X[2]; X[1] = X[2]; Y[0] = Y[2]; Y[1] = Y[2]; X[n - 2] = X[n - 3]; X[n - 1] = X[n - 3]; Y[n - 2] = Y[n - 3]; Y[n - 1] = Y[n - 3]; } else { X[0] = X[n - 4]; X[1] = X[n - 3]; Y[0] = Y[n - 4]; Y[1] = Y[n - 3]; X[n - 2] = X[2]; X[n - 1] = X[3]; Y[n - 2] = Y[2]; Y[n - 1] = Y[3]; return 1; } return 0; } void GetB(double t, double *B) { double t2; t2 = 1.0 - t; B[2] = t2; B[0] = t2 * t2*t2*OS; t2 = t * t; B[1] = t2 * (0.5*t - 1.0) + TT_; B[2] = 0.5*t2*B[2] + 0.5*t + OS; B[3] = OS * t*t2; } double VectorM(int n, double *v1, double *v2) { double s; s = 0.0; while (--n >= 0) { s += v1[n] * v2[n]; } return s; } void GetBezierData(int bIsClose, double sd, MLPline& OrgPline, MLPline& NewPline) { int i, j, k; int IsDraw; double B[4]; double xx, yy, s, xp, yp; int nn, n; double *X, *Y; int num = OrgPline.getCount(); n = num + 4; X = new double[n + n + 4]; Y = X + n + 2; GetBXY(X, Y, bIsClose, OrgPline); GetB(0.0, B); xp = VectorM(4, X, B); yp = VectorM(4, Y, B); IsDraw = 1; s = 0.0; k = 0; if (sd < 1.0) sd = 1.0; MLPlNode dPoint; dPoint.x = xp; dPoint.y = yp; //NewPline.addTailPt(dPoint); for (i = 0; i < n - 4; ++i) { nn = (int)(sqrt((X[i + 2] - X[i + 1])*(X[i + 2] - X[i + 1]) + (Y[i + 2] - Y[i + 1])*(Y[i + 2] - Y[i + 1])) / sd); if (nn < 0) nn = -nn; if (nn < 2) nn = 2; for (j = 0; j < nn; ++j) { GetB((double)j / (double)nn, B); xx = VectorM(4, X + i, B); yy = VectorM(4, Y + i, B); if (IsDraw) { MLPlNode dPoint; dPoint.x = xx; dPoint.y = yy; NewPline.addTailPt(dPoint); } s += sqrt((xx - xp)*(xx - xp) + (yy - yp)*(yy - yp)); xp = xx; yp = yy; } } if (!bIsClose) { dPoint = OrgPline.getTailPt(); NewPline.addTailPt(dPoint); } else { NewPline.addTailPt(NewPline.getHeadPt()); } delete[] X; X = NULL; } int Intersection(MLPlNode p1, MLPlNode p2, MLPlNode p3, MLPlNode p4, MLPlNode &Int) { //保证参数p1!=p2,p3!=p4 if (p1 == p2 || p3 == p4) { return -1; //返回-1代表至少有一条线段首尾重合,不能构成线段 } //为方便运算,保证各线段的起点在前,终点在后。 if (p1 > p2) { std::swap(p1, p2); } if (p3 > p4) { std::swap(p3, p4); } //判定两线段是否完全重合 if (p1 == p3 && p2 == p4) { return 6; } //求出两线段构成的向量 MLPlNode v1, v2;// = {p2.x - p1.x, p2.y - p1.y}, v2 = {p4.x - p3.x, p4.y - p3.y}; v1.x = p2.x - p1.x; v1.y = p2.y - p1.y; v2.x = p4.x - p3.x; v2.y = p4.y - p3.y; //求两向量外积,平行时外积为0 float Corss = v1 ^ v2; //如果起点重合 if (p1 == p3) { Int = p1; //起点重合且共线(平行)返回5;不平行则交于端点,返回3 return (Equ(Corss, 0) ? 5 : 3); } //如果终点重合 if (p2 == p4) { Int = p2; //终点重合且共线(平行)返回5;不平行则交于端点,返回3 return (Equ(Corss, 0) ? 5 : 3); } //如果两线端首尾相连 if (p1 == p4) { Int = p1; return 3; } if (p2 == p3) { Int = p2; return 3; }//经过以上判断,首尾点相重的情况都被排除了 //将线段按起点坐标排序。若线段1的起点较大,则将两线段交换 if (p1 > p3) { std::swap(p1, p3); std::swap(p2, p4); //更新原先计算的向量及其外积 std::swap(v1, v2); Corss = v1 ^ v2; } //处理两线段平行的情况 if (Equ(Corss, 0)) { //做向量v1(p1, p2)和vs(p1,p3)的外积,判定是否共线 MLPlNode vs;// = {p3.x - p1.x, p3.y - p1.y}; vs.x = p3.x - p1.x; vs.y = p3.y - p1.y; //外积为0则两平行线段共线,下面判定是否有重合部分 if (Equ(v1 ^ vs, 0)) { //前一条线的终点大于后一条线的起点,则判定存在重合 if (p2 > p3) { Int = p3; return 4; //返回值4代表线段部分重合 } }//若三点不共线,则这两条平行线段必不共线。 //不共线或共线但无重合的平行线均无交点 return 0; } //以下为不平行的情况,先进行快速排斥试验 //x坐标已有序,可直接比较。y坐标要先求两线段的最大和最小值 float ymax1 = p1.y, ymin1 = p2.y, ymax2 = p3.y, ymin2 = p4.y; if (ymax1 < ymin1) { std::swap(ymax1, ymin1); } if (ymax2 < ymin2) { std::swap(ymax2, ymin2); } //如果以两线段为对角线的矩形不相交,则无交点 if (p1.x > p4.x || p2.x < p3.x || ymax1 < ymin2 || ymin1 > ymax2) { return 0; }//下面进行跨立试验 MLPlNode vs1, vs2;//= {p1.x - p3.x, p1.y - p3.y}, vs2 = {p2.x - p3.x, p2.y - p3.y}; vs1.x = p1.x - p3.x; vs1.y = p1.y - p3.y; vs2.x = p2.x - p3.x; vs2.y = p2.y - p3.y; MLPlNode vt1, vt2;// = {p3.x - p1.x, p3.y - p1.y}, vt2 = {p4.x - p1.x, p4.y - p1.y}; vt1.x = p3.x - p1.x; vt1.y = p3.y - p1.y; vt2.x = p4.x - p1.x; vt2.y = p4.y - p1.y; float s1v2, s2v2, t1v1, t2v1; //根据外积结果判定否交于线上 if (Equ(s1v2 = vs1 ^ v2, 0) && p4 > p1 && p1 > p3) { Int = p1; return 2; } if (Equ(s2v2 = vs2 ^ v2, 0) && p4 > p2 && p2 > p3) { Int = p2; return 2; } if (Equ(t1v1 = vt1 ^ v1, 0) && p2 > p3 && p3 > p1) { Int = p3; return 2; } if (Equ(t2v1 = vt2 ^ v1, 0) && p2 > p4 && p4 > p1) { Int = p4; return 2; } //未交于线上,则判定是否相交 if (s1v2 * s2v2 > 0 || t1v1 * t2v1 > 0) { return 0; } //以下为相交的情况,算法详见文档 //计算二阶行列式的两个常数项 float ConA = p1.x * v1.y - p1.y * v1.x; float ConB = p3.x * v2.y - p3.y * v2.x; //计算行列式D1和D2的值,除以系数行列式的值,得到交点坐标 Int.x = (ConB * v1.x - ConA * v2.x) / Corss; Int.y = (ConB * v1.y - ConA * v2.y) / Corss; //正交返回1 return 1; } //按点长度插入 void insertPt(QVector &xy, MLPlNode &Pt) { int i, num; MLPlNode t; num = (int)xy.count(); if (num < 1) { xy.append(Pt); return; } t = xy.at(0); if (Pt.l < t.l) { xy.insert(0, Pt); return; } if (num == 1) { xy.append(Pt); return; } for (i = 0; i < num; ++i) { t = xy.at(i); if (Pt.l < t.l) { xy.insert(i, Pt); return; } } xy.append(Pt); } int GetCrossPt(MLPlNode& P1, MLPlNode& P2, MLPlNode& P3, MLPlNode& P4, QVector &xy) { MLPlNode pt; double x, y, l, l2; double dbL1x1, dbL1y1, dbL1x2, dbL1y2; double dbL2x1, dbL2y1, dbL2x2, dbL2y2; dbL1x1 = P1.x; dbL1y1 = P1.y; dbL1x2 = P2.x; dbL1y2 = P2.y; dbL2x1 = P3.x; dbL2y1 = P3.y; dbL2x2 = P4.x; dbL2y2 = P4.y; x = dbL2x1; y = dbL2y1; l = P3.l; l2 = P1.l; int nRes = Intersection(P1, P2, P3, P4, pt); if (nRes == 1 || nRes == 2) { double dd = GetDistance(pt.x, pt.y, dbL2x1, dbL2y1); double dd2 = GetDistance(pt.x, pt.y, dbL1x1, dbL1y1); pt.l = l + dd; pt.z = l2 + dd2; insertPt(xy, pt); return 1; } return 0; } //得到第一条折线切第二条折线,得到距离点保存在xy中 int GetCrossPt(MLPline &c1, MLPline &c2, QVector &xy, bool bAddTailPt) { int i, j; bool bCross = false; //设置曲线是否有交点 if (c2.getCount() < 2) return 0; if (c1.getCount() == c2.getCount() && c1[0].x == c2[0].x && c1[1].x == c2[1].x && c1[c1.getCount() - 1].x == c2[c2.getCount() - 1].x) return 0; for (i = 1; i < c1.getCount(); i++) { MLPlNode P1, P2; P1 = c1[i - 1]; P2 = c1[i]; if (P1 == P2) continue; for (j = 1; j < c2.getCount(); j++) { MLPlNode P3, P4; P3 = c2[j - 1]; P4 = c2[j]; if (P3 == P4) continue; int nRes = GetCrossPt(P1, P2, P3, P4, xy); if (nRes == 1) bCross = true; } } if (bCross && bAddTailPt) { c2[0].z = 0.0; xy.insert(0, c2[0]); c2[c2.getCount() - 1].z = c2[c2.getCount() - 1].l; xy.append(c2[c2.getCount() - 1]); } return 1; } int getCurve(double l1, double l2, QVector &dp, MLPline& dPline, int bDoubleHeadTail/*=1*/, bool bNoLineValue/*=false*/) { int num = dPline.getCount(); int n = (int)dp.count(); if (n > 0) dp.clear(); int i; MLPlNode t; if (dPline.getHeadPt().l < dPline.getTailPt().l) { if (l1 < dPline.getHeadPt().l) { l1 = dPline.getHeadPt().l; //return 1; } if (l1 > dPline.getTailPt().l) { l1 = dPline.getTailPt().l; //return 1; } if (l2 < dPline.getHeadPt().l) { l2 = dPline.getHeadPt().l; //return 1; } if (l2 > dPline.getTailPt().l) { l2 = dPline.getTailPt().l; //return 1; } } else { if (l1 > dPline.getHeadPt().l || l1 < dPline.getTailPt().l) return 1; if (l2 > dPline.getHeadPt().l || l2 < dPline.getTailPt().l) return 1; } i = bs(l1, dPline); t.x = cz(l1, i, dPline, 3, 0); t.y = cz(l1, i, dPline, 3, 1); t.z = dPline[i].z; t.l = l1; if (!bNoLineValue) { dp.append(t); if (bDoubleHeadTail) dp.append(t); } else { t.x = dPline[i].x; t.y = dPline[i].y; t.z = dPline[i].z; t.l = dPline[i].l; if (fabs(l1 - dPline[i].l) < fabs(dPline[i + 1].l - l1)) dp.append(t); } double a = dPline[0].l; double b = dPline[num - 1].l; //if(dPline[0].l < dPline[num-1].l) if (a < b) { if (l1 < l2) { while (++i <= num) { if (dPline[i].l >= l2) break; t.x = dPline[i].x; t.y = dPline[i].y; t.z = dPline[i].z; t.l = dPline[i].l; dp.append(t); } } else { ++i; while (--i >= 0) { if (dPline[i].l <= l2) break; t.x = dPline[i].x; t.y = dPline[i].y; t.z = dPline[i].z; t.l = dPline[i].l; dp.append(t); } } } else { //double aa = dPline[0].l; //double bb = dPline[num-1].l; if (l1 > l2) { while (++i <= num) { if (dPline[i].l <= l2) break; t.x = dPline[i].x; t.y = dPline[i].y; t.z = dPline[i].z; t.l = dPline[i].l; dp.append(t); } } else { ++i; while (--i >= 0) { if (dPline[i].l >= l2) break; t.x = dPline[i].x; t.y = dPline[i].y; t.z = dPline[i].z; t.l = dPline[i].l; dp.append(t); } } } i = bs(l2, dPline); t.x = cz(l2, i, dPline, 3, 0); t.y = cz(l2, i, dPline, 3, 1); t.z = dPline[i].z; t.l = l2; if (!bNoLineValue) { dp.append(t); if (bDoubleHeadTail) dp.append(t); } else { t.x = dPline[i + 1].x; t.y = dPline[i + 1].y; t.z = dPline[i + 1].z; t.l = dPline[i + 1].l; if (fabs(l2 - dPline[i].l) > fabs(dPline[i + 1].l - l2)) dp.append(t); } return 0; }