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.

2904 lines
62 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 "MLMicroStructure.h"
#include "MLPline.h"
#include "GMLDimsIter.h"
#include "MLFuncom.h"
#include <QFile>
#include <QThread>
#include <QFuture>
#include <QtConcurrent>
#include <QPolygonF>
#include <QTimer>
#include <QDate>
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 <geos/geom.h>
#include <geos/operation/buffer/BufferParameters.h>
#include <geos/operation/buffer/BufferBuilder.h>
#include <geos/algorithm/MinimumDiameter.h>
#include <geos/operation/distance/IndexedFacetDistance.h>
#include <geos/algorithm/construct/MaximumInscribedCircle.h>
#include <geos/algorithm/MinimumBoundingCircle.h>
// geos
#include <capi/geos_c.h>
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<QPolygonF*>& PolygonList);
// 检测两个多边形是否相交
bool checkPolygonCross(const QPolygonF& polygon1, const QPolygonF& polygon2);
// 检测两个多边形是否相交,并返回相交多边形
bool checkPolygonCross(const QPolygonF& polygon1, const QPolygonF& polygon2, QPolygonF& polygonDes);
// 删除相交的多边形(因为凹多边形与凸多边形有叠合)
void deletePolygon(QList<QPolygonF*>& PolygonList);
// 删除相交的多边形(因为凹多边形与凸多边形有叠合)
void deletePolygon(QList<QPolygonF*>& PolygonList1, QList<QPolygonF*>& 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<MLPlNode> &xy, bool bAddTailPt = false);
int getCurve(double l1, double l2, QVector<MLPlNode> &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<LineString> 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<MLPlineList*> > 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<QPolygonF*> posiPolygonList;
for (int i = 0; i < m_noseObjPosiAry.getCount(); i++)
{
MLPline* nosePline = m_noseObjPosiAry.getPline(i);
posiPolygonList.append(new QPolygonF(nosePline->toQPolygonF()));
}
QList<QPolygonF*> 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<QPolygonF*> posiPolygonList2;
QList<QPolygonF*> 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<Geometry> geom_convexHull = pLineString->convexHull();
geos::geom::Polygon* geom_ = dynamic_cast<geos::geom::Polygon*> (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<Geometry> buf = pPolygon->buffer(zoomin);
if (!buf->isEmpty())
{
templine.removeAll();
// 格式转换
geos::geom::Polygon* pPolygonBuf = dynamic_cast<geos::geom::Polygon*> (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<Geometry> geom_convexHull = pLineString->convexHull();
geos::geom::Polygon* geom_ = dynamic_cast<geos::geom::Polygon*> (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<Geometry> buf = pPolygon->buffer(zoomin);
if (!buf->isEmpty())
{
templine.removeAll();
// 格式转换
geos::geom::Polygon* pPolygonBuf = dynamic_cast<geos::geom::Polygon*> (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 <end_j; ++j)
{
for (i = start_i; i < end_i; ++i)
{
k = i + m * j;
double x = pDimsIter->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 <plineList.getCount(); j++)
{
MLPline* pContour2 = plineList.getPline(j);
if (pContour2 == nullptr)
continue;
pContour2->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<MLPlNode> dPointAry;
//计算交点,并按距离排序
GetCrossPt(*pEllipsePline, *pContour, dPointAry);
if (dPointAry.count() >= 2)
{
QVector <MLPlNode> 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 <MLPlNode> 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<MLPlNode> dPointAry;
//计算交点,并按距离排序
GetCrossPt(*pEllipsePline, *pContour, dPointAry);
if (dPointAry.count() >= 2)
{
QVector <MLPlNode> 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 <MLPlNode> 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<QPolygonF*>& 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<QPolygonF*>& PolygonList1, QList<QPolygonF*>& 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!=p2p3!=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<MLPlNode> &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<MLPlNode> &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<MLPlNode> &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<MLPlNode> &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;
}