|
|
#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!=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<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;
|
|
|
} |