You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kev/Drawer/Module/GeoSigmaDraw/InterfaceLayer.cpp

4745 lines
133 KiB
C++

1 month ago

#include "StdAfx.h"
#include "SigmaView.h"
#include "sigmadoc.h"
#include "ActionSortItem.h"
#include ".\actionembellishitem.h"
#include <afxadv.h>
#include "itemmeshprocess.h"
#include "TinyXml\tinyxml.h"
#include "StringManager.h"
#include "ItemDelete.h"
#include "ItemBreakCurve.h"
#include "ActionDeleteItem.h"
#include "ActionComboItem.h"
#include "ItemExtendCurve.h"
#include "ActionListItem.h"
#include "ActionAddItem.h"
#include "ActionAddLayerItem.h"
#include "../SSBase/VoronoiMap/GObjects/mycurve.h"
#include "../SSBase/DrawModel/Point2D.h"
#include "VoronoiMap/InterfaceElements.h"
#include "VoronoiMap/voronoimap.h"
#include <algorithm>
#include <numeric>
#include "InterfaceLayer.h"
#include "Util.h"
#include "pystring.h"
#include "../VoronoiMap/contourfillmap.h"
#include "clipper2/clipper.core.h"
#include "clipper2/clipper.h"
#include "DrawOperator/RTree.h"
typedef RTree<int, double, 2> RTree2D;
typedef RectTemplate<double> AABBRect;
using namespace Clipper2Lib;
#define STAT_MODE_ELEMENTS 0 //统计元素(缺省)
#define STAT_MODE_TRAPS 1 //统计圈闭
#define STAT_MODE_VOLUME 2 //统计体积
#define STAT_MODE_SURVEY 3 //统计测线
#define STAT_MODE_WELL 4 //统计井位
#define STAT_MODE_LAYER 5 //层位统计
#define STAT_MODE_FAULTS 6 //统计断层
#define STAT_MODE_BLOCK_ELEMENT 7 // 统计区块内元素
#define STAT_MODE_WELL_AZIMUTH 8 // 统计井轨迹的方位角
#define STAT_MODE_POLYGON_RELATION 10 // 统计多边形关系
// 统计采用的最小 z 值
static constexpr double MIN_Z = -1E100;
static int GetLayerElementCurve(CSigmaDoc * pDoc, char * layerName, NBase::CPositionList& select, bool withChild);
static int RgnDelete(CSigmaDoc * pDoc, NBase::CPositionList& rgnList, NBase::CPositionList& delList, int nDeleteIdea);
// CString xmlText;
// 保留多少位小数,先给定默认值,应该从配置中读取
static constexpr int decimal = 6;
BOOL GetCurveAzimuth(CCurveEx* pCurve, double &azimuth)
{
NBase::CRect8 rect(1e100, -1e100, -1e100, 1e100);
pCurve->GetRange(rect);
double k, b;
if (!AfxGetPublicFunction()->GetKB(pCurve->num, pCurve->x, pCurve->y, k, b))
{
azimuth = 0;
return FALSE;
}
rect.bottom = k * rect.left + b;
rect.top = k * rect.right + b;
azimuth = AfxGetPublicFunction()->GetAzimuth(rect.left, rect.bottom, rect.right, rect.top);
return TRUE;
}
static std::string PositionToString(POSITION position)
{
uintptr_t number = (uintptr_t)position;
char buffer[65];
_ui64toa(number, buffer, 10);
return std::string(buffer);
}
// 统计体积
int StatisVolumn(CSigmaView* pView, POSITION pt, TiXmlElement *rootElement, int id, CMesh* pMesh, int volumeMode)
{
COne* pOne = pView->m_pDoc->GetDraw()->GetAt(pt);
if (pOne->GetType() != DOUBLEFOX_CURVE)
{
return 0;
}
CString name, txt;
TiXmlElement *itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
TiXmlElement *idElement = new TiXmlElement("ID");
TiXmlElement *nameElement = new TiXmlElement("Name");
TiXmlElement *layerElement = new TiXmlElement("Layer");
TiXmlElement *areaElement = new TiXmlElement("Area");
TiXmlElement *volumnElement = new TiXmlElement("Volumn");
TiXmlElement *areaVolumnElement = new TiXmlElement("AreaVolumn");
TiXmlElement *positionElement = new TiXmlElement("Position");
itemElement->LinkEndChild(idElement);
itemElement->LinkEndChild(nameElement);
itemElement->LinkEndChild(layerElement);
itemElement->LinkEndChild(areaElement);
itemElement->LinkEndChild(volumnElement);
itemElement->LinkEndChild(areaVolumnElement);
itemElement->LinkEndChild(positionElement);
CCurveEx* pCurve = (CCurveEx*)pOne->GetValue();
name = pOne->GetName();
std::string idStr = std::to_string(id);
TiXmlText* idValue = new TiXmlText(idStr.c_str());
idElement->LinkEndChild(idValue);
TiXmlText *nameValue = new TiXmlText(name);
nameElement->LinkEndChild(nameValue);
TiXmlText *layerValue = new TiXmlText(pOne->GetLayer()->GetName());
layerElement->LinkEndChild(layerValue);
double area = pCurve->Area();
AfxGetPublicFunction()->FloatToString(txt, area, decimal);
TiXmlText *areaValue = new TiXmlText(txt);
areaElement->LinkEndChild(areaValue);
if (pMesh)
{
if (volumeMode == 0) //构造图
{
NBase::CPoint3D point;
if (pMesh->GetHightPoint(pCurve, point) > 0) //计算高点
{
double cz = pMesh->GetClosedZ(*pCurve, point.z0); //计算闭合线
double dHAverage = pMesh->TradeArea(*pCurve, cz);
if (std::isnan(dHAverage))
{
dHAverage = 0;
}
double vol = dHAverage * area; //pMesh->Volume(*pCurve, cz); //计算体积
AfxGetPublicFunction()->FloatToString(txt, vol, decimal);
TiXmlText *volumnValue = new TiXmlText(txt);
volumnElement->LinkEndChild(volumnValue);
if (fabs(area) > 1e-6)//权衡面积
{
AfxGetPublicFunction()->FloatToString(txt, dHAverage, 6); // vol / area
TiXmlText *areaVolumnValue = new TiXmlText(txt);
areaVolumnElement->LinkEndChild(areaVolumnValue);
}
}
}
else if (volumeMode == 1) //等厚图
{
double dHAverage = pMesh->TradeArea(*pCurve, 0);
if (std::isnan(dHAverage))
{
dHAverage = 0;
}
double vol = dHAverage * area; //pMesh->Volume(*pCurve, 0); //计算体积
AfxGetPublicFunction()->FloatToString(txt, vol, decimal);
TiXmlText *volumnValue = new TiXmlText(txt);
volumnElement->LinkEndChild(volumnValue);
if (fabs(area) > 1e-6)//权衡面积
{
AfxGetPublicFunction()->FloatToString(txt, dHAverage, 6); // vol / area
TiXmlText *areaVolumnValue = new TiXmlText(txt);
areaVolumnElement->LinkEndChild(areaVolumnValue);
}
}
}
uintptr_t number = (uintptr_t)pt;
char buffer[65];
_ui64toa(number, buffer, 10);
txt.Format("%s", buffer);
TiXmlText *posValue = new TiXmlText(txt);
positionElement->LinkEndChild(posValue);
return 1;
}
// 统计井
int StatisWells(CSigmaView* pView, POSITION pt, TiXmlElement *rootElement, int id, CMesh* pMesh)
{
COne* pOne = pView->m_pDoc->GetDraw()->GetAt(pt);
if (pOne->GetType() != DOUBLEFOX_POINT && pOne->GetType() != DOUBLEFOX_XYZ)
{
return 0;
}
CString name, txt;
TiXmlElement *itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
TiXmlElement *idElement = new TiXmlElement("ID");
TiXmlElement *nameElement = new TiXmlElement("Name");
TiXmlElement *layerPathElement = new TiXmlElement("LayerPath");
TiXmlElement *layerElement = new TiXmlElement("Layer");
TiXmlElement *xElement = new TiXmlElement("X");
TiXmlElement *yElement = new TiXmlElement("Y");
TiXmlElement *zElement = new TiXmlElement("Z");
TiXmlElement *positionElement = new TiXmlElement("Position");
TiXmlElement *meshZElement = new TiXmlElement("图-Z");
TiXmlElement *mistakeElement = new TiXmlElement("误差");
itemElement->LinkEndChild(idElement);
itemElement->LinkEndChild(nameElement);
itemElement->LinkEndChild(layerElement);
itemElement->LinkEndChild(layerPathElement);
itemElement->LinkEndChild(xElement);
itemElement->LinkEndChild(yElement);
itemElement->LinkEndChild(zElement);
itemElement->LinkEndChild(positionElement);
itemElement->LinkEndChild(meshZElement);
itemElement->LinkEndChild(mistakeElement);
CPointNameEx* pPoint = (CPointNameEx*)pOne->GetValue();
name = pOne->GetName();
std::string idStr = std::to_string(id);
TiXmlText *idValue = new TiXmlText(idStr.c_str());
idElement->LinkEndChild(idValue);
TiXmlText *nameValue = new TiXmlText(name);
nameElement->LinkEndChild(nameValue);
AfxGetPublicFunction()->FloatToString(txt, pPoint->x0, decimal);
TiXmlText *layerValue = new TiXmlText(pOne->GetLayer()->GetName());
layerElement->LinkEndChild(layerValue);
if (pOne->GetLayer()->HowToViewPoint)
{
txt = pOne->GetLayer()->HowToViewPoint->MarkName;
}
else {
txt = "";
}
TiXmlText *layerPathValue = new TiXmlText(txt);
layerPathElement->LinkEndChild(layerPathValue);
AfxGetPublicFunction()->FloatToString(txt, pPoint->x0, decimal);
TiXmlText *xValue = new TiXmlText(txt);
xElement->LinkEndChild(xValue);
AfxGetPublicFunction()->FloatToString(txt, pPoint->y0, decimal);
TiXmlText *yValue = new TiXmlText(txt);
yElement->LinkEndChild(yValue);
uintptr_t number = (uintptr_t)pt;
char buffer[65];
_ui64toa(number, buffer, 10);
txt.Format("%s", buffer);
TiXmlText *posValue = new TiXmlText(txt);
positionElement->LinkEndChild(posValue);
if (pMesh)
{
double z0 = pPoint->z0;
double zmin, zmax;
pMesh->GetM(zmin, zmax);
double z1 = pMesh->GetValue(pPoint->x0, pPoint->y0);
meshZElement->LinkEndChild(new TiXmlText(std::to_string(z1).c_str()));
AfxGetPublicFunction()->FloatToString(txt, z0, decimal);
TiXmlText* zValue = new TiXmlText(txt);
zElement->LinkEndChild(zValue);
double mistake = z0 - z1;
std::string str = std::to_string(mistake);
mistakeElement->LinkEndChild(new TiXmlText(str.c_str()));
}
else
{
double z0 = pPoint->z0;
if (pPoint->z0 < MIN_Z)
{
txt = "";
}
else
{
AfxGetPublicFunction()->FloatToString(txt, z0, decimal);
}
TiXmlText* zValue = new TiXmlText(txt);
zElement->LinkEndChild(zValue);
}
return 1;
}
// 统计层位
void StatisLayer(CSigmaView* pView, TiXmlElement *rootElement, CString id, CLayer* pLayer)
{
CString name, txt;
TiXmlElement *itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
TiXmlElement *idElement = new TiXmlElement("ID");
TiXmlElement *layerElement = new TiXmlElement("Layer");
TiXmlElement *pointElement = new TiXmlElement("Point");
TiXmlElement *curveElement = new TiXmlElement("Curve");
itemElement->LinkEndChild(idElement);
itemElement->LinkEndChild(layerElement);
itemElement->LinkEndChild(pointElement);
itemElement->LinkEndChild(curveElement);
TiXmlText *idValue = new TiXmlText(id);
idElement->LinkEndChild(idValue);
txt = pLayer->GetName();
TiXmlText *layerValue = new TiXmlText(txt);
layerElement->LinkEndChild(layerValue);
txt = "0"; if (pLayer->HowToViewPoint) txt = "1";
TiXmlText *pointValue = new TiXmlText(txt);
pointElement->LinkEndChild(pointValue);
txt = "0"; if (pLayer->HowToViewCurve) txt = "1";
TiXmlText *curveValue = new TiXmlText(txt);
curveElement->LinkEndChild(curveValue);
}
// 统计断层
void StatisFaultCsv(CXy* pXy, POSITION pt, CString id, CMesh* pMesh, CString& lineData)
{
COne* pOne = pXy->GetAt(pt);
if (pOne->GetType() != DOUBLEFOX_CURVE) return;
//TiXmlElement *itemElement = new TiXmlElement("Item");
//rootElement->LinkEndChild(itemElement);
//TiXmlElement *idElement = new TiXmlElement("ID");
//TiXmlElement *nameElement = new TiXmlElement("Name");
//TiXmlElement *layerElement = new TiXmlElement("Layer");
//TiXmlElement *faultNatureElement = new TiXmlElement("FaultNature");
//TiXmlElement *extensionLenElement = new TiXmlElement("ExtensionLength");
//TiXmlElement *faultTrendElement = new TiXmlElement("FaultTrend");
//TiXmlElement *inclinationElement = new TiXmlElement("Inclination");
//TiXmlElement *dipAngleElement = new TiXmlElement("DipAngle");
//TiXmlElement *maxHorizonElement = new TiXmlElement("MaxHorizonDistance");
//TiXmlElement *averageHorizonElement = new TiXmlElement("AverageHorizonDistance");
//TiXmlElement *maxVerticalElement = new TiXmlElement("MaxVerticalDistance");
//TiXmlElement *averageVerticalElement = new TiXmlElement("AverageVerticalDistance");
//TiXmlElement *positionElement = new TiXmlElement("Position");
//itemElement->LinkEndChild(idElement);
//itemElement->LinkEndChild(nameElement);
//itemElement->LinkEndChild(layerElement);
//itemElement->LinkEndChild(faultNatureElement);
//itemElement->LinkEndChild(extensionLenElement);
//itemElement->LinkEndChild(faultTrendElement);
//itemElement->LinkEndChild(inclinationElement);
//itemElement->LinkEndChild(dipAngleElement);
//itemElement->LinkEndChild(maxHorizonElement);
//itemElement->LinkEndChild(averageHorizonElement);
//itemElement->LinkEndChild(maxVerticalElement);
//itemElement->LinkEndChild(averageVerticalElement);
//itemElement->LinkEndChild(positionElement);
CString name, layerName, faultNature, extendLength, direction
, incline, inclineAngle, horDistanceMax, horDistanceAve, verDistanceMax, verDistanceAve;
name = pOne->GetName();
double length = 0, trend = 0, dip = 0, dip_angle = 0;
double ave_xydist = 0, max_xydist = 0, min_xydist = 0; //水平断距
double ave_zdist = 0, max_zdist = 0, min_zdist = 0; //垂直断距
CCurveEx* pCurve = (CCurveEx*)pOne->GetValue();
//计算走向得到0-180的角度
trend = pCurve->GetAverageAngle();
//计算倾向,与走向垂直
dip = trend - 90;
if (dip < 0) dip += 180;
// 计算水平断距
pCurve->GetClosureWidth(max_xydist, min_xydist, ave_xydist);
// 计算延伸长度
length = pCurve->GetClosureLength(ave_xydist);
//计算垂直断距
if (pMesh)
{
NBase::dfPoint fpt;
double zmin = 0, zmax = 0, z = 0;
int i;
for (i = 0; i < pCurve->num; i++)
{
pCurve->GetPoint(i, fpt);
z = pMesh->GetValue(fpt.x0, fpt.y0);
if (z > 1e7 || z < -1e7) continue;
zmin = zmax = z;
break;
}
for (; i < pCurve->num; i++)
{
pCurve->GetPoint(i, fpt);
z = pMesh->GetValue(fpt.x0, fpt.y0);
if (z > 1e7 || z < -1e7) continue;
if (z > zmax) zmax = z;
else if (z < zmin) zmin = z;
}
max_zdist = fabs(zmax - zmin);
ave_zdist = max_zdist / 2;
}
dip_angle = atan2(max_zdist, ave_xydist)*RHO;
faultNature = "正断层";
AfxGetPublicFunction()->FloatToString(extendLength, length, decimal);
AfxGetPublicFunction()->FloatToString(direction, trend, decimal);
AfxGetPublicFunction()->FloatToString(incline, dip, decimal);
AfxGetPublicFunction()->FloatToString(inclineAngle, dip_angle, decimal);
AfxGetPublicFunction()->FloatToString(horDistanceMax, max_xydist, decimal);
AfxGetPublicFunction()->FloatToString(horDistanceAve, ave_xydist, decimal);
AfxGetPublicFunction()->FloatToString(verDistanceMax, max_zdist, decimal);
AfxGetPublicFunction()->FloatToString(verDistanceAve, ave_zdist, decimal);
lineData.Format("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s"
, id, name, layerName, faultNature, extendLength, direction
, incline, inclineAngle, horDistanceMax, horDistanceAve, verDistanceMax, verDistanceAve);
}
int StatisFault(CSigmaView* pView, POSITION pt, TiXmlElement *rootElement, int id, CMesh* pMesh)
{
COne* pOne = pView->m_pDoc->GetDraw()->GetAt(pt);
if (pOne->GetType() != DOUBLEFOX_CURVE) return 0;
CString name, txt;
TiXmlElement *itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
TiXmlElement *idElement = new TiXmlElement("ID");
TiXmlElement *nameElement = new TiXmlElement("Name");
TiXmlElement *layerElement = new TiXmlElement("Layer");
TiXmlElement *faultNatureElement = new TiXmlElement("FaultNature");
TiXmlElement *extensionLenElement = new TiXmlElement("ExtensionLength");
TiXmlElement *faultTrendElement = new TiXmlElement("FaultTrend");
TiXmlElement *inclinationElement = new TiXmlElement("Inclination");
TiXmlElement *dipAngleElement = new TiXmlElement("DipAngle");
TiXmlElement *maxHorizonElement = new TiXmlElement("MaxHorizonDistance");
TiXmlElement *averageHorizonElement = new TiXmlElement("AverageHorizonDistance");
TiXmlElement *maxVerticalElement = new TiXmlElement("MaxVerticalDistance");
TiXmlElement *averageVerticalElement = new TiXmlElement("AverageVerticalDistance");
TiXmlElement *positionElement = new TiXmlElement("Position");
itemElement->LinkEndChild(idElement);
itemElement->LinkEndChild(nameElement);
itemElement->LinkEndChild(layerElement);
itemElement->LinkEndChild(faultNatureElement);
itemElement->LinkEndChild(extensionLenElement);
itemElement->LinkEndChild(faultTrendElement);
itemElement->LinkEndChild(inclinationElement);
itemElement->LinkEndChild(dipAngleElement);
itemElement->LinkEndChild(maxHorizonElement);
itemElement->LinkEndChild(averageHorizonElement);
itemElement->LinkEndChild(maxVerticalElement);
itemElement->LinkEndChild(averageVerticalElement);
itemElement->LinkEndChild(positionElement);
name = pOne->GetName();
std::string idStr = std::to_string(id);
TiXmlText *idValue = new TiXmlText(idStr.c_str());
idElement->LinkEndChild(idValue);
TiXmlText *nameValue = new TiXmlText(name);
nameElement->LinkEndChild(nameValue);
TiXmlText *layerValue = new TiXmlText(pOne->GetLayer()->GetName());
layerElement->LinkEndChild(layerValue);
double length = 0, trend = 0, dip = 0, dip_angle = 0;
double ave_xydist = 0, max_xydist = 0, min_xydist = 0; //水平断距
double ave_zdist = 0, max_zdist = 0, min_zdist = 0; //垂直断距
CCurveEx* pCurve = (CCurveEx*)pOne->GetValue();
//计算走向得到0-180的角度
trend = pCurve->GetAverageAngle();
//计算倾向,与走向垂直
dip = trend - 90;
if (dip < 0) dip += 180;
// 计算水平断距
pCurve->GetClosureWidth(max_xydist, min_xydist, ave_xydist);
// 计算延伸长度
length = pCurve->GetClosureLength(ave_xydist);
//计算垂直断距
if (pMesh)
{
NBase::dfPoint fpt;
double zmin = 0, zmax = 0, z = 0;
int i;
for (i = 0; i < pCurve->num; i++)
{
pCurve->GetPoint(i, fpt);
z = pMesh->GetValue(fpt.x0, fpt.y0);
if (z > 1e7 || z < -1e7) continue;
zmin = zmax = z;
break;
}
for (; i < pCurve->num; i++)
{
pCurve->GetPoint(i, fpt);
z = pMesh->GetValue(fpt.x0, fpt.y0);
if (z > 1e7 || z < -1e7) continue;
if (z > zmax) zmax = z;
else if (z < zmin) zmin = z;
}
max_zdist = fabs(zmax - zmin);
ave_zdist = max_zdist / 2;
}
dip_angle = atan2(max_zdist, ave_xydist)*RHO;
//txt.LoadStringA(IDS_STRING_NORMAL_FAULT); //正断层
CStringManager stringManager;
txt = stringManager.GetStringByIDS("IDS_STRING_NORMAL_FAULT");
TiXmlText *faultNatureValue = new TiXmlText(txt);
faultNatureElement->LinkEndChild(faultNatureValue);
AfxGetPublicFunction()->FloatToString(txt, length, decimal);
TiXmlText *extentsionLenValue = new TiXmlText(txt);
extensionLenElement->LinkEndChild(extentsionLenValue);
AfxGetPublicFunction()->FloatToString(txt, trend, decimal);
TiXmlText *faultTrendValue = new TiXmlText(txt);
faultTrendElement->LinkEndChild(faultTrendValue);
AfxGetPublicFunction()->FloatToString(txt, dip, decimal);
TiXmlText *inclinationValue = new TiXmlText(txt);
inclinationElement->LinkEndChild(inclinationValue);
AfxGetPublicFunction()->FloatToString(txt, dip_angle, decimal);
TiXmlText *dipAngleValue = new TiXmlText(txt);
dipAngleElement->LinkEndChild(dipAngleValue);
AfxGetPublicFunction()->FloatToString(txt, max_xydist, decimal);
TiXmlText *maxHorizonValue = new TiXmlText(txt);
maxHorizonElement->LinkEndChild(maxHorizonValue);
AfxGetPublicFunction()->FloatToString(txt, ave_xydist, decimal);
TiXmlText *averageHorizonValue = new TiXmlText(txt);
averageHorizonElement->LinkEndChild(averageHorizonValue);
AfxGetPublicFunction()->FloatToString(txt, max_zdist, decimal);
TiXmlText *maxVerticalValue = new TiXmlText(txt);
maxVerticalElement->LinkEndChild(maxVerticalValue);
AfxGetPublicFunction()->FloatToString(txt, ave_zdist, decimal);
TiXmlText *averageVerticalValue = new TiXmlText(txt);
averageVerticalElement->LinkEndChild(averageVerticalValue);
uintptr_t number = (uintptr_t)pt;
char buffer[65];
//sprintf(buffer, "%lx", pt);
//sscanf(buffer, "%lx", pt);
_ui64toa(number, buffer, 10);
txt.Format("%s", buffer);
TiXmlText *posValue = new TiXmlText(txt);
positionElement->LinkEndChild(posValue);
return 1;
}
// 统计圈闭
void StatisTrapsCsv(CXy* pXy, POSITION pt, CString id, CMesh* pMesh, CString& lineData)
{
if (pMesh == nullptr)
{
return;
}
COne* pOne = pXy->GetAt(pt);
if (pOne->GetType() != DOUBLEFOX_CURVE) return;
CCurveEx* pCurve = (CCurveEx*)pOne->GetValue();
NBase::CPoint3D hp;
int count = pMesh->GetHightPoint(pCurve, hp);
BOOL bf = TRUE;
double zmin, zmax;
pMesh->GetM(zmin, zmax);
if (zmin < 0 && zmax < 0) bf = FALSE;
CString name, hpHeight, closeZ, closeHeight, area, volume, strAngle, hpX, hpY;
name = pOne->GetName();
AfxGetPublicFunction()->FloatToString(area, pCurve->Area(), decimal);
if (count > 0)
{
AfxGetPublicFunction()->FloatToString(hpHeight, hp.z0, decimal);
double sum = pMesh->GetClosedZ(*pCurve, hp.z0);
AfxGetPublicFunction()->FloatToString(closeZ, sum, decimal);
double vol = pMesh->Volume(*pCurve, sum); //计算体积
AfxGetPublicFunction()->FloatToString(volume, vol, decimal);
if (bf) sum -= hp.z0;
else sum = hp.z0 - sum;
AfxGetPublicFunction()->FloatToString(closeHeight, sum, decimal);
AfxGetPublicFunction()->FloatToString(hpX, hp.x0, decimal);
AfxGetPublicFunction()->FloatToString(hpY, hp.y0, decimal);
// 倾角计算
double dAngle = pMesh->CalculateAngle(*pCurve);
AfxGetPublicFunction()->FloatToString(strAngle, dAngle, decimal);
lineData.AppendFormat("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s"
, id, name
, pOne->GetLayer()->GetPathName().Mid(7)
, hpHeight, closeZ, closeHeight, area, volume, strAngle, hpX, hpY);
}
else
{
lineData.AppendFormat("%s,%s,%s,,,,,,,"
, id, name
, pOne->GetLayer()->GetPathName().Mid(7));
}
}
int StatisTraps(CSigmaView* pView, POSITION pt, TiXmlElement *rootElement, int id, CMesh* pMesh)
{
if (pMesh == nullptr)
{
return 0;
}
COne* pOne = pView->m_pDoc->GetDraw()->GetAt(pt);
if (pOne->GetType() != DOUBLEFOX_CURVE) return 0;
CCurveEx* pCurve = (CCurveEx*)pOne->GetValue();
NBase::CPoint3D hp;
int count = pMesh->GetHightPoint(pCurve, hp);
BOOL bf = TRUE;
double zmin, zmax;
pMesh->GetM(zmin, zmax);
if (zmin < 0 && zmax < 0) bf = FALSE;
CString name, txt;
TiXmlElement *itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
TiXmlElement *idElement = new TiXmlElement("ID");
TiXmlElement *nameElement = new TiXmlElement("Name");
TiXmlElement *layerElement = new TiXmlElement("Layer");
TiXmlElement *heightPointElement = new TiXmlElement("HeightPointDepth");
TiXmlElement *closeLineElement = new TiXmlElement("CloseLine");
TiXmlElement *closeHeightElement = new TiXmlElement("CloseHeight");
TiXmlElement *closeAreaElement = new TiXmlElement("CloseArea");
TiXmlElement *volumeElement = new TiXmlElement("Volume");
TiXmlElement *coordinateXElement = new TiXmlElement("CoordinateX");
TiXmlElement *coordinateYElement = new TiXmlElement("CoordinateY");
TiXmlElement *positionElement = new TiXmlElement("Position");
itemElement->LinkEndChild(idElement);
itemElement->LinkEndChild(nameElement);
itemElement->LinkEndChild(layerElement);
itemElement->LinkEndChild(heightPointElement);
itemElement->LinkEndChild(closeLineElement);
itemElement->LinkEndChild(closeHeightElement);
itemElement->LinkEndChild(closeAreaElement);
itemElement->LinkEndChild(volumeElement);
itemElement->LinkEndChild(coordinateXElement);
itemElement->LinkEndChild(coordinateYElement);
itemElement->LinkEndChild(positionElement);
name = pOne->GetName();
std::string idStr = std::to_string(id);
TiXmlText *idValue = new TiXmlText(idStr.c_str());
idElement->LinkEndChild(idValue);
TiXmlText *nameValue = new TiXmlText(name);
nameElement->LinkEndChild(nameValue);
TiXmlText *layerValue = new TiXmlText(pOne->GetLayer()->GetPathName().Mid(7));
layerElement->LinkEndChild(layerValue);
AfxGetPublicFunction()->FloatToString(txt, pCurve->Area(), decimal);
TiXmlText *closeAreaValue = new TiXmlText(txt);
closeAreaElement->LinkEndChild(closeAreaValue);
if (count > 0)
{
AfxGetPublicFunction()->FloatToString(txt, hp.z0, decimal);
TiXmlText *heightPointValue = new TiXmlText(txt);
heightPointElement->LinkEndChild(heightPointValue);
double sum = pMesh->GetClosedZ(*pCurve, hp.z0);
AfxGetPublicFunction()->FloatToString(txt, sum, decimal);
TiXmlText *closeLineValue = new TiXmlText(txt);
closeLineElement->LinkEndChild(closeLineValue);
double vol = pMesh->Volume(*pCurve, sum); //计算体积
AfxGetPublicFunction()->FloatToString(txt, vol, decimal);
TiXmlText *volumeValue = new TiXmlText(txt);
volumeElement->LinkEndChild(volumeValue);
if (bf) sum -= hp.z0;
else sum = hp.z0 - sum;
AfxGetPublicFunction()->FloatToString(txt, sum, decimal);
TiXmlText *closeHeightValue = new TiXmlText(txt);
closeHeightElement->LinkEndChild(closeHeightValue);
AfxGetPublicFunction()->FloatToString(txt, hp.x0, decimal);
TiXmlText *xValue = new TiXmlText(txt);
coordinateXElement->LinkEndChild(xValue);
AfxGetPublicFunction()->FloatToString(txt, hp.y0, decimal);
TiXmlText *yValue = new TiXmlText(txt);
coordinateYElement->LinkEndChild(yValue);
}
else
{
txt = "";
TiXmlText *heightPointValue = new TiXmlText(txt);
heightPointElement->LinkEndChild(heightPointValue);
TiXmlText *closeLineValue = new TiXmlText(txt);
closeLineElement->LinkEndChild(closeLineValue);
TiXmlText *volumeValue = new TiXmlText(txt);
volumeElement->LinkEndChild(volumeValue);
TiXmlText *closeHeightValue = new TiXmlText(txt);
closeHeightElement->LinkEndChild(closeHeightValue);
TiXmlText *xValue = new TiXmlText(txt);
coordinateXElement->LinkEndChild(xValue);
TiXmlText *yValue = new TiXmlText(txt);
coordinateYElement->LinkEndChild(yValue);
}
uintptr_t number = (uintptr_t)pt;
char buffer[65];
_ui64toa(number, buffer, 10);
txt.Format("%s", buffer);
TiXmlText *posValue = new TiXmlText(txt);
positionElement->LinkEndChild(posValue);
return 1;
}
// 统计测线
int StatisSurvey(CSigmaView* pView, POSITION pt, TiXmlElement *rootElement, int id)
{
COne* pOne = pView->m_pDoc->GetDraw()->GetAt(pt);
if (pOne->GetType() != DOUBLEFOX_CURVE) return 0;
CString name, txt;
TiXmlElement *itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
TiXmlElement *idElement = new TiXmlElement("ID");
TiXmlElement *nameElement = new TiXmlElement("Name");
TiXmlElement *layerElement = new TiXmlElement("Layer");
TiXmlElement *firstElement = new TiXmlElement("FirstStakeNo");
TiXmlElement *lastElement = new TiXmlElement("LastStakeNo");
TiXmlElement *stakeLengthElement = new TiXmlElement("StakeLength");
TiXmlElement *lengthElement = new TiXmlElement("RealLength");
TiXmlElement *azimuthElement = new TiXmlElement("Azimuth");
TiXmlElement * positionElement = new TiXmlElement("Position");
itemElement->LinkEndChild(idElement);
itemElement->LinkEndChild(nameElement);
itemElement->LinkEndChild(layerElement);
itemElement->LinkEndChild(firstElement);
itemElement->LinkEndChild(lastElement);
itemElement->LinkEndChild(stakeLengthElement);
itemElement->LinkEndChild(lengthElement);
itemElement->LinkEndChild(azimuthElement);
itemElement->LinkEndChild(positionElement);
name = pOne->GetName();
std::string idStr = std::to_string(id);
TiXmlText *idValue = new TiXmlText(idStr.c_str());
idElement->LinkEndChild(idValue);
TiXmlText *nameValue = new TiXmlText(name);
nameElement->LinkEndChild(nameValue);
TiXmlText *layerValue = new TiXmlText(pOne->GetLayer()->GetName());
layerElement->LinkEndChild(layerValue);
CCurveEx* pCurve = (CCurveEx*)pOne->GetValue();
AfxGetPublicFunction()->FloatToString(txt, pCurve->Length(), decimal);
TiXmlText *lengthValue = new TiXmlText(txt);
lengthElement->LinkEndChild(lengthValue);
AfxGetPublicFunction()->FloatToString(txt, pCurve->l[0], decimal);
TiXmlText *firstStakeValue = new TiXmlText(txt);
firstElement->LinkEndChild(firstStakeValue);
AfxGetPublicFunction()->FloatToString(txt, pCurve->l[pCurve->num - 1], decimal);
TiXmlText *lastStakeValue = new TiXmlText(txt);
lastElement->LinkEndChild(lastStakeValue);
double len = pCurve->l[pCurve->num - 1] - pCurve->l[0];
if (len < 0) len *= -1;
AfxGetPublicFunction()->FloatToString(txt, len, decimal);
TiXmlText *stakeLenValue = new TiXmlText(txt);
stakeLengthElement->LinkEndChild(stakeLenValue);
double azimuth;
/* if*/(GetCurveAzimuth(pCurve, azimuth));
//{
AfxGetPublicFunction()->FloatToString(txt, azimuth, decimal);
TiXmlText *azimuthValue = new TiXmlText(txt);
azimuthElement->LinkEndChild(azimuthValue);
//}
uintptr_t number = (uintptr_t)pt;
char buffer[65];
_ui64toa(number, buffer, 10);
txt.Format("%s", buffer);
TiXmlText *posValue = new TiXmlText(txt);
positionElement->LinkEndChild(posValue);
return 1;
}
static TiXmlElement* FindXmlNodeByPosition(TiXmlElement *rootElement, const char *position)
{
for (TiXmlElement* itemElement = rootElement->FirstChildElement("Item"); itemElement; itemElement = itemElement->NextSiblingElement("Item"))
{
TiXmlElement* positionElement = itemElement->FirstChildElement("Position");
if (positionElement)
{
const char* posValue = positionElement->GetText();
if (posValue && strcmp(posValue, position) == 0)
{
return itemElement;
}
}
}
return nullptr;
}
/**
*
*
* \param pView
* \param pt
* \param rootElement
* \param id
* \return
*/
int StatisticBlockElements(CSigmaView* pView, POSITION pt, TiXmlElement *rootElement, int& id) {
COne* pOne = pView->m_pDoc->GetDraw()->GetAt(pt);
if (!pOne->IsView()) return 0;
if (pOne->GetLayer()->IsNotViewNotEdit()) return 0;
if (pOne->GetType() != DOUBLEFOX_CURVE) return 0;
CCurveEx* pBlock = (CCurveEx*)(pOne->GetValue());
CXy* pxy = pView->m_pDoc->m_pXy;
CPtrList* pLst = pxy->GetValueList();
POSITION pFind = pLst->GetHeadPosition();
POSITION posFind;
COne *pOneFind;
int nCount = 0;
while (pFind) {
posFind = pFind;
pOneFind = (COne *)(pLst->GetNext(pFind));
if (!pOneFind->IsView()) continue;
if (pOneFind->GetLayer()->IsNotViewNotEdit()) continue;
if (pOneFind->GetType() == DOUBLEFOX_XYZ || pOneFind->GetType() == DOUBLEFOX_POINT)
{
CPointNameBase* pPoint = (CPointNameBase*)pOneFind->GetValue();
if (pBlock->IsInside(pPoint->x0, pPoint->y0))
{
CString name, txt;
// 图元指针
uintptr_t number = (uintptr_t)posFind;
char buffer[65];
_ui64toa(number, buffer, 10);
txt.Format("%s", buffer);
name = pOne->GetName();
TiXmlElement *posElement = FindXmlNodeByPosition(rootElement, buffer);
// 该元素已经被统计过,不再被统计,我们需要把这个区块名称追加上去
if (posElement != nullptr)
{
TiXmlElement *blockElement = posElement->FirstChildElement("BlockName");
const char *blockName = blockElement->GetText();
CString strNewBlock(blockName);
strNewBlock += " | ";
strNewBlock += name;
blockElement->FirstChild()->SetValue(strNewBlock);
continue;
}
TiXmlElement *itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
TiXmlElement *idElement = new TiXmlElement("ID");
TiXmlElement *blockNameElement = new TiXmlElement("BlockName");
TiXmlElement *blockLayerElement = new TiXmlElement("BlockLayer");
TiXmlElement *nameElement = new TiXmlElement("Name");
TiXmlElement *layerElement = new TiXmlElement("Layer");
TiXmlElement *positionElement = new TiXmlElement("Position");
TiXmlElement *xElement = new TiXmlElement("X");
TiXmlElement *yElement = new TiXmlElement("Y");
TiXmlElement *zElement = new TiXmlElement("Z");
itemElement->LinkEndChild(idElement);
itemElement->LinkEndChild(blockNameElement);
itemElement->LinkEndChild(blockLayerElement);
itemElement->LinkEndChild(nameElement);
itemElement->LinkEndChild(layerElement);
itemElement->LinkEndChild(xElement);
itemElement->LinkEndChild(yElement);
itemElement->LinkEndChild(zElement);
itemElement->LinkEndChild(positionElement);
id++;
// 序号
CString strID;
strID.Format(_T("%d"), id);
TiXmlText *idValue = new TiXmlText(strID);
idElement->LinkEndChild(idValue);
// 区域图层
TiXmlText *blockLayerValue = new TiXmlText(pOne->GetLayer()->GetName());
blockLayerElement->LinkEndChild(blockLayerValue);
// 区域名称
TiXmlText *blockNameValue = new TiXmlText(name);
blockNameElement->LinkEndChild(blockNameValue);
// 名称
name = pOneFind->GetName();
TiXmlText *nameValue = new TiXmlText(name);
nameElement->LinkEndChild(nameValue);
// 图层
TiXmlText *layerValue = new TiXmlText(pOneFind->GetLayer()->GetName());
layerElement->LinkEndChild(layerValue);
// 坐标
AfxGetPublicFunction()->FloatToString(txt, pPoint->x0, decimal);
TiXmlText *xValue = new TiXmlText(txt);
xElement->LinkEndChild(xValue);
AfxGetPublicFunction()->FloatToString(txt, pPoint->y0, decimal);
TiXmlText *yValue = new TiXmlText(txt);
yElement->LinkEndChild(yValue);
if (pPoint->z0 < MIN_Z)
{
txt = "";
}
else
{
AfxGetPublicFunction()->FloatToString(txt, pPoint->z0, decimal);
}
TiXmlText *zValue = new TiXmlText(txt);
zElement->LinkEndChild(zValue);
// 图元指针
_ui64toa(number, buffer, 10);
txt.Format("%s", buffer);
TiXmlText *posValue = new TiXmlText(txt);
positionElement->LinkEndChild(posValue);
nCount++;
}
}
}
return nCount;
}
// 统计元素
int StatisElement(CSigmaView* pView, POSITION pt, TiXmlElement *rootElement, int id, CMesh* pMesh)
{
CString name, txt;
TiXmlElement *itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
TiXmlElement *idElement = new TiXmlElement("ID");
TiXmlElement *nameElement = new TiXmlElement("Name");
TiXmlElement *typeElement = new TiXmlElement("Type");
TiXmlElement *layerElement = new TiXmlElement("Layer");
TiXmlElement *symbolElement = new TiXmlElement("Symbol");
TiXmlElement *lengthElement = new TiXmlElement("RealLength");
TiXmlElement *areaElement = new TiXmlElement("Area");
TiXmlElement *azimuthElement = new TiXmlElement("Azimuth");
TiXmlElement *positionElement = new TiXmlElement("Position");
TiXmlElement *xElement = new TiXmlElement("X");
TiXmlElement *yElement = new TiXmlElement("Y");
TiXmlElement *zElement = new TiXmlElement("Z");
itemElement->LinkEndChild(idElement);
//TiXmlElement *zElement = new TiXmlElement("Z");
itemElement->LinkEndChild(idElement);
itemElement->LinkEndChild(nameElement);
itemElement->LinkEndChild(typeElement);
itemElement->LinkEndChild(layerElement);
itemElement->LinkEndChild(symbolElement);
itemElement->LinkEndChild(lengthElement);
itemElement->LinkEndChild(areaElement);
itemElement->LinkEndChild(azimuthElement);
itemElement->LinkEndChild(positionElement);
itemElement->LinkEndChild(xElement);
itemElement->LinkEndChild(yElement);
itemElement->LinkEndChild(zElement);
COne* pOne = pView->m_pDoc->GetDraw()->GetAt(pt);
name = pOne->GetName();
//CPointNameEx* pPoint = (CPointNameEx*)pOne->GetValue();
CString type = pView->m_pDoc->GetElementTypeString(pt);
std::string idStr = std::to_string(id);
TiXmlText *idValue = new TiXmlText(idStr.c_str());
idElement->LinkEndChild(idValue);
TiXmlText *nameValue = new TiXmlText(name);
nameElement->LinkEndChild(nameValue);
TiXmlText *typeValue = new TiXmlText(type);
typeElement->LinkEndChild(typeValue);
TiXmlText *layerValue = new TiXmlText(pOne->GetLayer()->GetName());
layerElement->LinkEndChild(layerValue);
uintptr_t number = (uintptr_t)pt;
char buffer[65];
_ui64toa(number, buffer, 10);
txt.Format("%s", buffer);
TiXmlText *posValue = new TiXmlText(txt);
positionElement->LinkEndChild(posValue);
switch (pOne->GetType())
{
case DOUBLEFOX_XYZ:
case DOUBLEFOX_POINT:
{
CPointNameEx* pPoint = (CPointNameEx*)pOne->GetValue();
if (pOne->GetLayer()->HowToViewPoint)
{
TiXmlText *symbolValue = new TiXmlText(pOne->GetLayer()->HowToViewPoint->MarkName);
symbolElement->LinkEndChild(symbolValue);
}
AfxGetPublicFunction()->FloatToString(txt, pPoint->x0, decimal);
TiXmlText *xValue = new TiXmlText(txt);
xElement->LinkEndChild(xValue);
AfxGetPublicFunction()->FloatToString(txt, pPoint->y0, decimal);
TiXmlText *yValue = new TiXmlText(txt);
yElement->LinkEndChild(yValue);
if (pMesh)
{
double z0 = pMesh->GetValue(pPoint->x0, pPoint->y0);
double zmin, zmax;
pMesh->GetM(zmin, zmax);
if (!(z0<zmin || z0>zmax)) // 当该Z值有效时才显示
{
AfxGetPublicFunction()->FloatToString(txt, z0, decimal);
TiXmlText *zValue = new TiXmlText(txt);
zElement->LinkEndChild(zValue);
}
}
else
{
if (pPoint->z0 < MIN_Z) {
txt = "";
}
else {
AfxGetPublicFunction()->FloatToString(txt, pPoint->z0, decimal);
}
TiXmlText *zValue = new TiXmlText(txt);
zElement->LinkEndChild(zValue);
}
}
break;
case DOUBLEFOX_CURVE:
{
CCurveEx* pCurve = (CCurveEx*)pOne->GetValue();
AfxGetPublicFunction()->FloatToString(txt, pCurve->Length(), decimal);
TiXmlText *lengthValue = new TiXmlText(txt);
lengthElement->LinkEndChild(lengthValue);
AfxGetPublicFunction()->FloatToString(txt, pCurve->Area(), decimal);
TiXmlText *areaValue = new TiXmlText(txt);
areaElement->LinkEndChild(areaValue);
//positionElement->LinkEndChild(posValue);
double azimuth;
/*if */(GetCurveAzimuth(pCurve, azimuth));
//{
AfxGetPublicFunction()->FloatToString(txt, azimuth, decimal);
TiXmlText *azimuthValue = new TiXmlText(txt);
azimuthElement->LinkEndChild(azimuthValue);
//}
}
break;
}
return 1;
}
// 统计井的方位角
int StatisAzimuth(CSigmaView* pView, POSITION pt, TiXmlElement *rootElement, int id)
{
COne* pOne = pView->m_pDoc->GetDraw()->GetAt(pt);
if (pOne->GetType() != DOUBLEFOX_CURVE) return 0;
CString name, txt;
TiXmlElement *itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
TiXmlElement *idElement = new TiXmlElement("ID");
TiXmlElement *nameElement = new TiXmlElement("Name");
TiXmlElement *lengthElement = new TiXmlElement("RealLength");
TiXmlElement *azimuthElement = new TiXmlElement("Azimuth");
TiXmlElement * positionElement = new TiXmlElement("Position");
itemElement->LinkEndChild(idElement);
itemElement->LinkEndChild(nameElement);
itemElement->LinkEndChild(lengthElement);
itemElement->LinkEndChild(azimuthElement);
itemElement->LinkEndChild(positionElement);
// 序号
std::string idStr = std::to_string(id);
TiXmlText *idValue = new TiXmlText(idStr.c_str());
idElement->LinkEndChild(idValue);
// 名称
name = pOne->GetName();
TiXmlText *nameValue = new TiXmlText(name);
nameElement->LinkEndChild(nameValue);
// 长度
CCurveEx* pCurve = (CCurveEx*)pOne->GetValue();
AfxGetPublicFunction()->FloatToString(txt, pCurve->Length(), decimal);
TiXmlText *lengthValue = new TiXmlText(txt);
lengthElement->LinkEndChild(lengthValue);
// 方位角
double azimuth = 0;
CMyCurve myCurve;
myCurve.Create(pCurve->num);
for (int i = 0; i < pCurve->num; i++) {
myCurve.SetPoint(i, pCurve->x[i], pCurve->y[i], pCurve->z[i]);
}
azimuth = myCurve.GetAzimuthDegree2();
AfxGetPublicFunction()->FloatToString(txt, azimuth, decimal);
TiXmlText *azimuthValue = new TiXmlText(txt);
azimuthElement->LinkEndChild(azimuthValue);
// Position
uintptr_t number = (uintptr_t)pt;
char buffer[65];
_ui64toa(number, buffer, 10);
txt.Format("%s", buffer);
TiXmlText *posValue = new TiXmlText(txt);
positionElement->LinkEndChild(posValue);
return 1;
}
void TracePath(const PathD& path)
{
TRACE("Pline\n");
for (auto pt : path) {
TRACE("%f,%f\n", pt.x, pt.y);
}
TRACE("\n");
}
void TracePaths(const PathsD& paths) {
for (auto line : paths)
{
TracePath(line);
}
}
void TraceTree(const PolyTreeD& polytree, int depth = 0) {
// 打印当前深度,用于可视化树的层级
int nCount = polytree.Count();
for (int i=0;i<nCount;i++)
{
PolyPathD* pChild = polytree.Child(i);
PathsD result;
details::PolyPathToPathsD(*pChild, result);
if (result.size() > 0)
{
TracePaths(result);
}
}
}
// 统计多边形关系
void StatisPolygonRelation(CSigmaView* pView, const CList<POSITION, POSITION>& lstPolygons, TiXmlElement *rootElement)
{
vector< PathD> blocks;
vector<POSITION> curves;
CXy* pXy = pView->m_pDoc->GetDraw();
POSITION pos, pt;
pos = lstPolygons.GetHeadPosition();
while (pos) {
pt = lstPolygons.GetNext(pos);
COne* pOne = pXy->GetAt(pt);
if (pOne->GetType() != DOUBLEFOX_CURVE) return;
CCurveEx* pCurve = (CCurveEx*)pOne->GetValue();
PathD block;
for (int i = 0; i < pCurve->num; i++)
{
block.push_back(PointD(pCurve->x[i], pCurve->y[i]));
}
size_t count = block.size();
if (count < 3) {
continue;
}
// 使区域闭合
if (block.at(0).x != block.at(count - 1).x || block.at(0).y != block.at(count - 1).y)
{
block.push_back(PointD(block.at(0).x, block.at(0).y));
}
blocks.push_back(block);
curves.push_back(pt);
}
if (blocks.size() == 0)
{
return;
}
int id = 0;
for (size_t i = 0; i < blocks.size(); ++i)
{
PathsD plyClip;
plyClip.push_back(blocks[i]);
PathsD subs;
vector<CString> subNames;
vector<CString> outSubNames;
// 查找相交曲线
for (size_t j = 0; j < blocks.size(); ++j)
{
if (j == i) {
continue;
}
PathsD plySub;
plySub.push_back(blocks[j]);
// 进行裁剪操作
//PathsD solution = Clipper2Lib::Intersect(plySub, plyClip, FillRule::NonZero, 4);
PathsD solution;
ClipperD clipper(3);
clipper.AddSubject(plySub);
clipper.AddClip(plyClip);
clipper.Execute(ClipType::Intersection, FillRule::NonZero, solution);
if (!solution.empty())
{
subs.push_back(blocks[j]);
subNames.push_back(pXy->GetAt(curves[j])->GetName());
}
else {
outSubNames.push_back(pXy->GetAt(curves[j])->GetName());
}
}
double dAreaBlock = abs(Clipper2Lib::Area(plyClip));
id++;
CString name, txt;
TiXmlElement *itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
TiXmlElement *idElement = new TiXmlElement("ID");
TiXmlElement *nameElement = new TiXmlElement("区块名称");
TiXmlElement *nameIntersectsElement = new TiXmlElement("关联区块");
TiXmlElement *intersectAreaElement = new TiXmlElement("相交面积");
TiXmlElement *diffrenceAreaElement = new TiXmlElement("不相交面积");
TiXmlElement * unionAreaElement = new TiXmlElement("合并面积");
TiXmlElement * blockAreaElement = new TiXmlElement("区块面积");
TiXmlElement *nameOutElement = new TiXmlElement("无关联区块");
TiXmlElement * positionElement = new TiXmlElement("Position");
itemElement->LinkEndChild(idElement);
itemElement->LinkEndChild(nameElement);
itemElement->LinkEndChild(nameIntersectsElement);
itemElement->LinkEndChild(intersectAreaElement);
itemElement->LinkEndChild(diffrenceAreaElement);
itemElement->LinkEndChild(unionAreaElement);
itemElement->LinkEndChild(blockAreaElement);
itemElement->LinkEndChild(nameOutElement);
itemElement->LinkEndChild(positionElement);
// 序号
CString strID;
strID.Format("%d", id);
TiXmlText *idValue = new TiXmlText(strID);
idElement->LinkEndChild(idValue);
// 名称
name = pXy->GetAt(curves[i])->GetName();
TiXmlText *nameValue = new TiXmlText(name);
nameElement->LinkEndChild(nameValue);
CString strNames;
// 相交区块名称
for (auto subName : subNames) {
if (strNames.IsEmpty())
{
strNames.Append(subName);
}
else {
strNames.Append("|");
strNames.Append(subName);
}
}
TiXmlText *nameIntersectsValue = new TiXmlText(strNames);
nameIntersectsElement->LinkEndChild(nameIntersectsValue);
// 区块面积
AfxGetPublicFunction()->FloatToString(txt, dAreaBlock, 2);
TiXmlText *blockAreaValue = new TiXmlText(txt);
blockAreaElement->LinkEndChild(blockAreaValue);
CString strNamesOut;
// 不相交区块名称
for (auto subName : outSubNames) {
if (strNamesOut.IsEmpty())
{
strNamesOut.Append(subName);
}
else {
strNamesOut.Append("|");
strNamesOut.Append(subName);
}
}
TiXmlText *nameOutValue = new TiXmlText(strNamesOut);
nameOutElement->LinkEndChild(nameOutValue);
// Position
uintptr_t number = (uintptr_t)curves[i];
char buffer[65];
_ui64toa(number, buffer, 10);
txt.Format("%s", buffer);
TiXmlText *posValue = new TiXmlText(txt);
positionElement->LinkEndChild(posValue);
if (subs.empty()) {
continue;
}
// 创建一个Clipper对象
ClipperD clipper(decimal);
// 将多边形添加到Clipper对象中
clipper.AddSubject(subs);
clipper.AddClip(plyClip);
// 执行相交操作
//PathsD closedIntersect; // 外轮廓
//PathsD openIntersect; // 内部孔洞
PolyTreeD treeIntersect;
clipper.Execute(ClipType::Intersection, FillRule::NonZero, treeIntersect);
//clipper.Execute(ClipType::Intersection, FillRule::NonZero, closedIntersect, openIntersect);
//TraceTree(treeIntersect);
//TracePaths(treeIntersect.);
//TracePaths(openIntersect);
PathsD pathsIntersect = PolyTreeToPathsD(treeIntersect);
//PathsD closedUnion;
//PathsD openUnion; // 代表孔洞
PolyTreeD treeUnion;
clipper.Execute(ClipType::Union, FillRule::NonZero, treeUnion);
//clipper.Execute(ClipType::Union, FillRule::NonZero, closedUnion, openUnion);
//TraceTree(treeUnion);
//TracePaths(closedUnion);
//TracePaths(openUnion);
PathsD pathsUnion = PolyTreeToPathsD(treeUnion);
PolyTreeD treeDiffrence;
clipper.Clear();// = ClipperD(decimal);
clipper.AddClip(subs);
clipper.AddSubject(plyClip);
clipper.Execute(ClipType::Difference, FillRule::NonZero, treeDiffrence);
PathsD pathsDiffrence = PolyTreeToPathsD(treeDiffrence);
// 获取相交结果
//PathsD solutionUnion = Clipper2Lib::Union(subs, plyClip, FillRule::NonZero, 2);
double dAreaInter = Clipper2Lib::Area(pathsIntersect);
double dAreaUnion = Clipper2Lib::Area(pathsUnion);
double dAreaDiffrence = Clipper2Lib::Area(pathsDiffrence);
// 相交面积
AfxGetPublicFunction()->FloatToString(txt, dAreaInter, 2);
TiXmlText *intersectAreaValue = new TiXmlText(txt);
intersectAreaElement->LinkEndChild(intersectAreaValue);
// 不相交面积
AfxGetPublicFunction()->FloatToString(txt, dAreaDiffrence, 2);
TiXmlText *diffrenceAreaValue = new TiXmlText(txt);
diffrenceAreaElement->LinkEndChild(diffrenceAreaValue);
// 相并面积
AfxGetPublicFunction()->FloatToString(txt, dAreaUnion, 2);
TiXmlText *unionAreaValue = new TiXmlText(txt);
unionAreaElement->LinkEndChild(unionAreaValue);
}
}
static void CopyToClipboard(CLayer* pLayer)
{
if (pLayer == NULL) return;
int count = 0;
short ver = CUR_VERSION;
// Create a shared file and associate a CArchive with it
CSharedFile file;
CArchive ar(&file, CArchive::store);
// Serialize selected objects to the archive
if (pLayer->HowToViewCurve)
{
AfxGetPublicFunction()->WriteElementType(ar, DOUBLEFOX_HOWTOVIEW_CURVE, ver);
pLayer->HowToViewCurve->Serialize(ar, ver);
count++;
}
if (pLayer->HowToViewPoint)
{
AfxGetPublicFunction()->WriteElementType(ar, DOUBLEFOX_HOWTOVIEW_POINT, ver);
pLayer->HowToViewPoint->Serialize(ar, ver);
count++;
}
AfxGetPublicFunction()->WriteElementType(ar, 0, ver); //写文件结束标志
ar.Close();
if (count == 0) return;
COleDataSource* pDataSource = NULL;
TRY
{
pDataSource = new COleDataSource;
// put on local format instead of or in addation to
pDataSource->CacheGlobalData(CSigmaView::m_clipboardDraw, file.Detach());
pDataSource->SetClipboard();
}
CATCH_ALL(e)
{
delete pDataSource;
THROW_LAST();
}
END_CATCH_ALL
}
// 最上显示
extern "C" __declspec(dllexport)
void LayerMovetoTop(CSigmaView* pView, LPCTSTR layerName)
{
if (pView->m_pDoc->GetDraw() == NULL) return;
CList<POSITION, POSITION> list;
pView->m_pDoc->GetDraw()->GetElement(layerName, list);
if (list.GetCount() == 0) return;
if (pView->m_pDoc == NULL)
{
return;
}
pView->m_pDoc->SetActionItem(new CActionSortItem(pView->m_pDoc, IDS_STRING_ACTION_LAYER_MOVETOFRONT, list, 0));
}
// 最下显示
extern "C" __declspec(dllexport)
void LayerMovetoBottom(CSigmaView* pView, LPCTSTR layerName)
{
if (pView->m_pDoc->GetDraw() == NULL) return;
CList<POSITION, POSITION> list;
pView->m_pDoc->GetDraw()->GetElement(layerName, list);
if (list.GetCount() == 0) return;
if (pView->m_pDoc == NULL)
{
return;
}
pView->m_pDoc->SetActionItem(new CActionSortItem(pView->m_pDoc, IDS_STRING_ACTION_LAYER_MOVETOBACK, list, 1));
}
// 删除修饰
extern "C" __declspec(dllexport)
void LayerRemoveEmbellish(CSigmaView* pView, LPCTSTR layerName)
{
CXy* pxy = pView->m_pDoc->m_pXy;
//CLayer* pLayer = pxy->GetCurrentLayer();
CLayer* pLayer = pView->m_pDoc->m_pXy->FindLayer(layerName);
if (pLayer == NULL) return;
//为了修饰的Redo/Undo
CActionEmbellishItem *pAction = new CActionEmbellishItem(pView->m_pDoc, IDS_STRING_EMBELLISH, pLayer);
pAction->SetOldHowToView(pLayer); //备份老修饰
int del = 0;
if (pLayer->HowToViewCurve)
{
delete pLayer->HowToViewCurve;
pLayer->HowToViewCurve = NULL;
del++;
}
if (pLayer->HowToViewPoint)
{
delete pLayer->HowToViewPoint;
pLayer->HowToViewPoint = NULL;
del++;
}
if (del > 0 && pView->m_pDoc)
{
pAction->SetNewHowToView(pLayer);
pView->m_pDoc->SetActionItem(pAction);
pView->m_pDoc->Invalidate();
//pView->m_pDoc->SetModifiedFlag();
}
else
delete pAction;
}
// 选择焦点层元素
extern "C" __declspec(dllexport)
void LayerSelectActiveElement(CSigmaView* pView, LPCSTR layerName)
{
if (pView->m_pDoc == NULL) return;
NBase::CPositionList list;
CLayer* pLayer = pView->m_pDoc->GetDraw()->FindLayer(layerName);
if (pLayer != NULL)
pView->m_pDoc->GetDraw()->GetElement(layerName, list, FALSE);
pView->m_pDoc->SetSelection(list);
}
// 选择子层元素
extern "C" __declspec(dllexport)
void LayerSelectElements(CSigmaView* pView, LPCSTR layerName)
{
if (pView->m_pDoc == NULL) return;
NBase::CPositionList list;
pView->m_pDoc->GetDraw()->GetElement(layerName, list, TRUE, FALSE);
pView->m_pDoc->SetSelection(list);
}
//保存焦点层
extern "C" __declspec(dllexport)
int LayerSaveActiveLayer(CSigmaView* pView, LPCSTR layerName, LPCSTR fileName)
{
if (pView->m_pDoc->GetDraw() == NULL) return 0;
CXy* pxy = pView->m_pDoc->GetDraw();
CList<POSITION, POSITION> list;
pxy->GetElement(layerName, list, true);
if (list.GetCount() == 0)
{
return 0;
}
CFile fw;
if (!fw.Open(fileName, CFile::modeCreate | CFile::modeWrite))
{
// ::AfxMessageBox("Open file to write error!");
return -1;
}
// 写图层及使用的符号和修饰
POSITION p, pos;
CStringList listMarkOther;
CString str;
COne *pOne;
AfxGetGlobalMark()->BackupMark();
AfxGetGlobalMark()->SetMark(&pxy->mark);
CStringList arrLayerUsing;
CPtrList valueLayer;
//写使用到的符号
p = list.GetHeadPosition();
while (p)
{
pos = list.GetNext(p);
pOne = pxy->GetAt(pos);
pOne->GetNewUsing(listMarkOther, TRUE);
if (arrLayerUsing.Find(pOne->GetLayer()->GetPathName())) continue;
arrLayerUsing.AddTail(pOne->GetLayer()->GetPathName());
valueLayer.AddTail(pOne->GetLayer());
}
long total = (long)(listMarkOther.GetCount() + list.GetCount());
long count = 0;
void *v = NULL;
p = listMarkOther.GetHeadPosition();
while (p)
{
count++;
str = listMarkOther.GetNext(p);
str.MakeUpper();
if (!AfxGetGlobalMark()->Lookup(str, v)) continue;
AfxGetGlobalMark()->WriteMark_One(fw, v, CUR_VERSION);
}
//写使用到的类别及类别修饰
CLayer *pLayer = NULL;
pos = valueLayer.GetHeadPosition();
while (pos)
{
pLayer = (CLayer*)valueLayer.GetNext(pos);
pLayer->WriteLegend(fw, CUR_VERSION, 1);
}
CString strTemp("HowToViewCurve\r\n\r\n");
int nLen = strTemp.GetLength();
fw.Write(strTemp.GetBuffer(), strTemp.GetLength());
strTemp = "HowToViewPoint\r\n\r\n";
nLen = strTemp.GetLength();
fw.Write(strTemp.GetBuffer(), strTemp.GetLength());
// 写数据
pxy->DFD_Write(fw, list);
//short ver = CUR_VERSION;
//CLayer* pLayer = pView->m_pDoc->GetDraw()->FindLayer(layerName);
//if (pLayer)
//{
// CString str;
// str.Format("Class %s", pLayer->GetClassName());
// AfxGetPublicFunction()->WriteLine(fw, str);
// pLayer->WriteLayerName(fw, ver);
// pLayer->WriteLegend(fw, ver, 1.0);
//}
//else
//{
// CLayerName ln(layerName);
// CString str;
// str.Format("Class %s", ln.GetClassName());
// AfxGetPublicFunction()->WriteLine(fw, str);
// str.Format("%s M %s", ln.GetClassName(), ln.GetPathName());
// AfxGetPublicFunction()->WriteLine(fw, str);
//}
//POSITION pt;
//POSITION pos = list.GetHeadPosition();
//while (pos)
//{
// pt = list.GetNext(pos);
// pView->m_pDoc->GetDraw()->DFD_Write(fw, pt, ver, FALSE);
//}
fw.Close();
AfxGetGlobalMark()->RestoreMark();
return list.GetCount();
}
//保存层为.xyz文件
extern "C" __declspec(dllexport)
int LayerSaveLayerToXyz(CSigmaView* pView, LPCSTR layerName, LPCSTR fileName)
{
int ret = 0;
if (pView->m_pDoc->GetDraw() == NULL) return 0;
CXy* pxy = pView->m_pDoc->GetDraw();
CList<POSITION, POSITION> list;
pxy->GetElement(layerName, list, true);
if (list.GetCount() == 0)
{
return 0;
}
FILE * pFile = fopen(fileName, "w+");
if (!pFile)
{
::AfxMessageBox("Open file to write error!");
}
// 写图层及使用的符号和修饰
POSITION p, pos;
COne *pOne;
CCurveEx * pc = nullptr;
//写使用到的符号
p = list.GetHeadPosition();
while (p)
{
pos = list.GetNext(p);
pOne = pxy->GetAt(pos);
if (pOne->GetType() == DOUBLEFOX_CURVE) {
CCurveEx * pc = (CCurveEx *)pOne->value;
for (int i = 0; i < pc->num; ++i)
{
double x = pc->x[i];
double y = pc->y[i];
fprintf(pFile, "%f,%f,%s\n", x, y, pc->name);
}
ret++;
}
}
fclose(pFile);
return ret;
}
static bool IsLayerEmbellishNeedCopy(CLayer* pLayer)
{
if (pLayer == nullptr)
{
return false;
}
if (pLayer->HowToViewPoint == nullptr && pLayer->HowToViewCurve == nullptr)
{
return false;
}
return true;
}
static void SerializeCopyPasteHeader(CArchive& ar)
{
// 魔法数字,为了防止读取粘贴板时读到脏数据
const uint32_t copyMagic = 31;
if (ar.IsStoring())
{
uint64_t header = KEVISUALIZATION_BINARY;
ar << header;
uint64_t type = copyMagic;
ar << type;
}
else
{
uint64_t header = 0;
ar >> header;
if (header != KEVISUALIZATION_BINARY)
{
throw std::runtime_error("不是 KEV 二进制格式数据");
}
uint64_t type = 0;
ar >> type;
if (type != copyMagic)
{
throw std::runtime_error("不是复制图层样式的数据");
}
}
}
static void SerializeCopyPasteLayerEmbellish(CArchive& ar, short ver, CLayer* pLayer)
{
if (ar.IsStoring())
{
pLayer->Serialize(ar, ver);
}
else
{
auto pNewLayer = std::make_unique<CLayer>();
pNewLayer->Serialize(ar, ver);
swap(pNewLayer->HowToViewPoint, pLayer->HowToViewPoint);
swap(pNewLayer->HowToViewCurve, pLayer->HowToViewCurve);
// 现在 pNewLayer 里面是旧的修饰,它们还不能释放,因为 redo 的 Action 还持有它,我们必须置空,防止被释放
pNewLayer->HowToViewPoint = nullptr;
pNewLayer->HowToViewCurve = nullptr;
}
}
static void PutFileToClipboard(CSharedFile& file)
{
COleDataSource* pDataSource = nullptr;
try
{
pDataSource = new COleDataSource;
pDataSource->CacheGlobalData(CSigmaView::m_clipboardDraw, file.Detach());
pDataSource->SetClipboard();
}
catch (...)
{
delete pDataSource;
}
}
static std::vector<CString> GetLayerMarkNames(CHowToViewPoint* pHowToViewPoint, CHowToViewCurve* pHowToViewCurve)
{
std::vector<CString> result;
if (pHowToViewPoint != nullptr)
{
result.push_back(pHowToViewPoint->MarkName);
}
if (pHowToViewCurve != nullptr)
{
for (int i = 0; i < pHowToViewCurve->GetCount(); i++)
{
CCurveView* pView = pHowToViewCurve->GetAt(i);
if (auto* pArrow = dynamic_cast<CCurveArrow*>(pView))
{
result.push_back(pArrow->MarkName);
}
else if (auto* pScale = dynamic_cast<CCurveScale*>(pView))
{
result.push_back(pScale->MarkName);
}
else if (auto* pTwoMark = dynamic_cast<CCurveTwoMark*>(pView))
{
result.push_back(pTwoMark->MarkName);
}
else if (auto* pRgn = dynamic_cast<CCurveRgn*>(pView))
{
result.push_back(pRgn->MarkName);
}
}
}
return result;
}
static void GetCXyMark(CXy* pXy, const std::vector<CString>& markNames, CGlobalMark& mark)
{
CMapStringToPtrNoCase* pMarks = pXy->GetMark();
for (const CString& name : markNames)
{
void* pDraw = nullptr;
if (pMarks->Lookup(name, pDraw))
{
mark.SetAt(name, pDraw);
}
}
}
static void SerializeCopyPasteLayerMark(CArchive& ar, short ver, CXy* pXy, CLayer* pLayer)
{
if (ar.IsStoring())
{
std::vector<CString> markNames = GetLayerMarkNames(pLayer->HowToViewPoint, pLayer->HowToViewCurve);
CGlobalMark tempMark;
CMapStringToPtrNoCase mark;
tempMark.SetMark(&mark);
GetCXyMark(pXy, markNames, tempMark);
tempMark.Serialize(ar, ver);
}
else
{
CGlobalMark tempMark;
tempMark.SetMark(&pXy->mark);
tempMark.Serialize(ar, ver);
}
}
/**
*
*
* \param pView
*/
extern "C" __declspec(dllexport)
void LayerCopyEmbellish(CSigmaView* pView, LPCSTR layerName)
{
if (pView == nullptr)
{
return;
}
//CLayer* pLayer = pView->m_pDoc->m_pXy->GetCurrentLayer();
CLayer* pLayer = pView->m_pDoc->m_pXy->FindLayer(layerName);
if (pLayer == nullptr)
{
return;
}
if (!IsLayerEmbellishNeedCopy(pLayer))
{
return;
}
short ver = CUR_VERSION;
CSharedFile file;
CArchive ar(&file, CArchive::store);
SerializeCopyPasteHeader(ar);
SerializeCopyPasteLayerEmbellish(ar, ver, pLayer);
SerializeCopyPasteLayerMark(ar, ver, pView->m_pDoc->m_pXy, pLayer);
ar.Close();
PutFileToClipboard(file);
}
/**
*
*
* \param pView
*/
extern "C" __declspec(dllexport)
void PasteLayerEmbellish(CSigmaView* pView, LPCSTR layerName)
{
if (pView == nullptr)
{
return;
}
//CLayer* pLayer = pView->m_pDoc->m_pXy->GetCurrentLayer();
CLayer* pLayer = pView->m_pDoc->m_pXy->FindLayer(layerName);
if (pLayer == nullptr)
{
return;
}
COleDataObject dataObject;
dataObject.AttachClipboard();
CFile* pFile = dataObject.GetFileData(CSigmaView::m_clipboardDraw);
if (pFile == nullptr)
{
return;
}
short ver = CUR_VERSION;
CArchive ar(pFile, CArchive::load);
try
{
//为了修饰的Redo/Undo
auto pAction = std::make_unique<CActionEmbellishItem>(pView->m_pDoc, IDS_STRING_EMBELLISH, pLayer);
pAction->SetOldHowToView(pLayer); //备份老修饰
SerializeCopyPasteHeader(ar);
SerializeCopyPasteLayerEmbellish(ar, ver, pLayer);
SerializeCopyPasteLayerMark(ar, ver, pView->m_pDoc->m_pXy, pLayer);
pAction->SetNewHowToView(pLayer);
pView->m_pDoc->SetActionItem(pAction.release());
}
catch (...)
{
}
}
// 统计
extern "C" __declspec(dllexport)
BSTR StatisticCsv(CXy* pXy, wchar_t** layers, int layerCount, BOOL bIncludeSublayer, int nStatMode, int surfaceType)
{
if (pXy == NULL) { return 0; }
CList<POSITION, POSITION> select;
CString name;
for (int i = 0; i < layerCount; i++)
{
name = *(layers + i);
pXy->GetElement(name, select, bIncludeSublayer);
}
if (select.IsEmpty())
{
return nullptr;
}
POSITION pos, pt;
CMesh* pMesh = NULL;
pos = pXy->FindFirstElement(DOUBLEFOX_MESH);
if (pos)
{
pMesh = (CMesh*)pXy->GetAtValue(pos);
}
int total = select.GetCount();
pos = select.GetHeadPosition();
CString strContent("");
int i = 1;
CString id;
while (pos)
{
CString strLine("");
id.Format("%d", i);
pt = select.GetNext(pos);
switch (nStatMode)
{
case STAT_MODE_ELEMENTS:
//strContent += StatisElement(pView, pt, rootElement, id, pMesh);
break;
case STAT_MODE_SURVEY:
//StatisSurvey(pView, pt, rootElement, id);
break;
case STAT_MODE_TRAPS:
StatisTrapsCsv(pXy, pt, id, pMesh, strLine);
break;
case STAT_MODE_FAULTS:
StatisFaultCsv(pXy, pt, id, pMesh, strLine);
break;
case STAT_MODE_WELL:
//StatisWells(pView, pt, rootElement, id, pMesh);
break;
case STAT_MODE_VOLUME:
//StatisVolumn(pView, pt, rootElement, id, pMesh, surfaceType);
break;
}
if (strLine.GetLength() > 0) {
strContent.AppendFormat("%s\r\n", strLine);
}
i++;
}
if (strContent.GetLength() > 0) {
switch (nStatMode)
{
case STAT_MODE_TRAPS:
strContent.Insert(0, "序号,名称,层位,高点埋深,闭合线,闭合高度,圈闭面积,体积,倾角,高点坐标X,高点坐标Y\r\n");
break;
case STAT_MODE_FAULTS:
strContent.Insert(0, "序号,名称,层位,断层性质,延伸长度,断层走向,倾向,倾角,最大水平断距,平均水平断距,最大垂直断距,平均垂直断距\r\n");
break;
}
return strContent.AllocSysString();
}
return nullptr;
}
// 统计区域内的区块,所有内部及相交的线
extern "C" __declspec(dllexport)
BSTR StaticBlocksInfo(CSigmaView* pView, LPCTSTR blockLine)
{
if (pView->m_pDoc == NULL) { return 0; }
vector<CString> vecString;
CString strTmp;
int iPos = 0;
while (AfxExtractSubString(strTmp, blockLine, iPos, ' '))
{
iPos++;
vecString.push_back(strTmp);
}
NBase::CPointList pts;
double dX, dY;
for (auto iter = vecString.begin(); iter != vecString.end(); ++iter) {
CString strLine = *iter;
int nCount = sscanf(strLine, "%lf,%lf", &dX, &dY);
if (nCount >= 2) {
NBase::dfPoint dp;
dp.x0 = dX;
dp.y0 = dY;
pts.AddTail(dp);
}
}
if (pts.GetSize() == 0) {
return 0;
}
CString strData("");
CCurveEx* pBlock = new CCurveEx();
pBlock->SetPoints(pts, 2);
// 获取区域内的线
CXy* pxy = pView->m_pDoc->m_pXy;
CPtrList* pLst = pxy->GetValueList();
//POSITION pFind = pLst->GetHeadPosition();
//POSITION posFind;
COne *pOneFind;
CCurveAnd curveAnd;
int id = 0;
POSITION posCur = pLst->GetHeadPosition();
while (true) {
pLst->GetNext(posCur);
if (posCur == 0) {
break;
}
pOneFind = (COne *)(pxy->GetAt(posCur));
if (!pOneFind->IsView()) continue;
if (pOneFind->GetLayer()->IsNotViewNotEdit()) continue;
if (pOneFind->GetType() == DOUBLEFOX_CURVE)
{
CCurveEx* pCurve = (CCurveEx*)(pOneFind->value);
int nRelation = pBlock->IsInside(*pCurve);
if (nRelation == 0) {
continue;
}
//else /*if (nRelation == -1)*/ {
// //int nOut = curveAnd.GetCurveOutside(pCurve, pBlock);
// double dCenterX = 0;
// double dCenterY = 0;
// for (int i = 0; i < pCurve->num; i++) {
// dCenterX += pCurve->x[i];
// dCenterY += pCurve->y[i];
// }
// dCenterX /= pCurve->num;
// dCenterY /= pCurve->num;
// if (pBlock->IsInside(dCenterX, dCenterY) == 0) {
// continue;
// }
//}
if (pBlock->num == pCurve->num) {
bool bEqual = true;
for (int i = 0; i < pBlock->num; i++) {
if (pBlock->x[i] != pCurve->x[i] || pBlock->y[i] != pCurve->y[i])
{
bEqual = false;
break;
}
}
if (bEqual == true) {
continue;
}
}
uintptr_t number = (uintptr_t)posCur;
char buffer[65];
_ui64toa(number, buffer, 10);
CString txt;
txt.Format("%s,", buffer);
strData.Append(txt);
strData.Append(pCurve->name);
strData.Append("\r\n");
}
}
delete pBlock;
pBlock = nullptr;
return strData.AllocSysString();
}
extern "C" __declspec(dllexport)
BSTR CutStaticBlocks(CSigmaView* pView, LPCTSTR posData, LPCTSTR blockLine)
{
NBase::CPositionList lstPos;
int iPos = 0;
CString strTmp;
while (AfxExtractSubString(strTmp, posData, iPos, ' '))
{
iPos++;
std::string strPos = (LPCTSTR)strTmp;
uintptr_t num = std::stoull(strPos);
void* pVoid = reinterpret_cast<void*>(num);
lstPos.AddTail((POSITION)pVoid);
}
if (pView->m_pDoc == NULL) { return 0; }
vector<CString> vecString;
iPos = 0;
while (AfxExtractSubString(strTmp, blockLine, iPos, ' '))
{
iPos++;
vecString.push_back(strTmp);
}
NBase::CPointList pts;
double dX, dY;
for (auto iter = vecString.begin(); iter != vecString.end(); ++iter) {
CString strLine = *iter;
int nCount = sscanf(strLine, "%lf,%lf", &dX, &dY);
if (nCount >= 2) {
NBase::dfPoint dp;
dp.x0 = dX;
dp.y0 = dY;
pts.AddTail(dp);
}
}
if (pts.GetSize() == 0) {
return 0;
}
CCurveEx* pBlock = new CCurveEx();
pBlock->SetPoints(pts, 2);
if (pBlock->IsClosed() == false)
{
pBlock->SetToClose();
pBlock->num += 1;
pBlock->GetLocation();
}
CCutOut co;
co.SetSourceCurveRange(nullptr);
co.SetXY(pView->m_pDoc->m_pXy);
co.m_dMiniCurveSmoothStep = pView->m_pDoc->GetDC().GetMiniSmoothStep();
int rt = co.CutOut(pBlock, &lstPos);
//元素增加操作
int nInfoID = ID_CUT_OUT_MAP_RECTANGLE;
//for undo/redo
CActionListItem *pAction = new CActionListItem(pView->m_pDoc, nInfoID);
CActionAddItem* pItem = new CActionAddItem(pView->m_pDoc, 0, co.m_plAdd);
pAction->AddTailItem(pItem);
pView->m_pDoc->SetActionItem(pAction);
delete pBlock;
pBlock = nullptr;
CString strData("");
COne* pOne = nullptr;
POSITION pos = co.m_plAdd.GetHeadPosition();
while (pos)
{
POSITION pt = co.m_plAdd.GetNext(pos);
pOne = pView->m_pDoc->m_pXy->GetAt(pt);
uintptr_t number = (uintptr_t)pt;
char buffer[65];
_ui64toa(number, buffer, 10);
CString txt;
txt.Format("Position %s", buffer);
strData.Append(txt);
strData.Append("\r\n");
CCurveEx* pCurve = (CCurveEx*)(pOne->value);
strData.Append("Layer M ");
strData.Append(pOne->GetLayer()->GetName());
strData.Append("\r\n");
strData.Append("Pline.");
strData.Append(pCurve->name);
strData.Append("\r\n");
CString strCoord("");
for (int i = 0; i < pCurve->num; i++) {
strCoord.Format("%lf,%lf ", pCurve->x[i], pCurve->y[i]);
strData.Append(strCoord);
}
strData.Append("\r\n");
}
return strData.AllocSysString();
}
extern "C" __declspec(dllexport)
double CaculateBlockArea(CSigmaView* pView, POSITION pos)
{
double dArea = 0;
COne* pOne = pView->m_pDoc->m_pXy->GetAt(pos);
if (pOne->GetType() == DOUBLEFOX_CURVE)
{
CCurveEx* pCurve = (CCurveEx*)(pOne->value);
dArea = pCurve->Area();
}
return dArea;
}
extern "C" __declspec(dllexport)
void ResetLayerByOther(CSigmaView* pView, POSITION pos, POSITION posRefer, LPCTSTR suffix)
{
COne* pOne = pView->m_pDoc->m_pXy->GetAt(pos);
COne* pOneRefer = pView->m_pDoc->m_pXy->GetAt(posRefer);
CString strLayerRef = pOneRefer->GetLayer()->GetName();
strLayerRef += suffix;
bool bNew = true;
CLayer* pLayerNew = pView->m_pDoc->m_pXy->FindAddLayer(strLayerRef, &bNew);
pOne->SetLayer(pLayerNew);
if (bNew&& pOneRefer->GetLayer()->HowToViewCurve!=nullptr)
{
CHowToViewCurve* hvc = new CHowToViewCurve;
*hvc = *(pOneRefer->GetLayer()->HowToViewCurve);
pLayerNew->SetHowToViewCurve(hvc);
}
}
// 统计区域内的区块
extern "C" __declspec(dllexport)
BSTR StaticBlocks(CSigmaView* pView, LPCTSTR blockLine)
{
if (pView->m_pDoc == NULL) { return 0; }
vector<CString> vecString;
CString strTmp;
int iPos = 0;
while (AfxExtractSubString(strTmp, blockLine, iPos, ' '))
{
iPos++;
vecString.push_back(strTmp);
}
NBase::CPointList pts;
double dX, dY;
for (auto iter = vecString.begin(); iter != vecString.end(); ++iter) {
CString strLine = *iter;
int nCount = sscanf(strLine, "%lf,%lf", &dX, &dY);
if (nCount >= 2) {
NBase::dfPoint dp;
dp.x0 = dX;
dp.y0 = dY;
pts.AddTail(dp);
}
}
if (pts.GetSize() == 0) {
return 0;
}
CString strData("");
CCurveEx* pBlock = new CCurveEx();
pBlock->SetPoints(pts, 2);
// 获取区域内的线
CXy* pxy = pView->m_pDoc->m_pXy;
CPtrList* pLst = pxy->GetValueList();
POSITION pFind = pLst->GetHeadPosition();
//POSITION posFind;
COne *pOneFind;
CCurveAnd curveAnd;
int id = 0;
while (pFind) {
//posFind = pFind;
pOneFind = (COne *)(pLst->GetNext(pFind));
if (!pOneFind->IsView()) continue;
if (pOneFind->GetLayer()->IsNotViewNotEdit()) continue;
if (pOneFind->GetType() == DOUBLEFOX_CURVE)
{
CCurveEx* pCurve = (CCurveEx*)(pOneFind->value);
int nRelation = pBlock->IsInside(*pCurve);
if (nRelation == 0) {
continue;
}
else if (nRelation == -1) {
//int nOut = curveAnd.GetCurveOutside(pCurve, pBlock);
double dCenterX = 0;
double dCenterY = 0;
for (int i = 0; i < pCurve->num; i++) {
dCenterX += pCurve->x[i];
dCenterY += pCurve->y[i];
}
dCenterX /= pCurve->num;
dCenterY /= pCurve->num;
if (pBlock->IsInside(dCenterX, dCenterY) == 0) {
continue;
}
}
if (pBlock->num == pCurve->num) {
bool bEqual = true;
for (int i = 0; i < pBlock->num; i++) {
if (pBlock->x[i] != pCurve->x[i] || pBlock->y[i] != pCurve->y[i])
{
bEqual = false;
break;
}
}
if (bEqual == true) {
continue;
}
}
strData.Append("Pline.");
strData.Append(pCurve->name);
strData.Append("\r\n");
CString strCoord("");
for (int i = 0; i < pCurve->num; i++) {
strCoord.Format("%lf,%lf ", pCurve->x[i], pCurve->y[i]);
strData.Append(strCoord);
}
strData.Append("\r\n");
}
}
delete pBlock;
pBlock = nullptr;
return strData.AllocSysString();
}
extern "C" __declspec(dllexport)
BSTR XYFindPoint(CXy *pxy, const LPCTSTR pointName, bool needZ) {
CPtrList* pLst = pxy->GetValueList();
POSITION pFind = pLst->GetHeadPosition();
COne *pOneFind;
int id = 0;
CPointNameBase* pPoint = nullptr;
while (pFind) {
pOneFind = (COne *)(pLst->GetNext(pFind));
if (!pOneFind->IsView()) continue;
if (pOneFind->GetLayer()->IsNotViewNotEdit()) continue;
if (pOneFind->GetType() == DOUBLEFOX_XYZ || pOneFind->GetType() == DOUBLEFOX_POINT)
{
CPointNameBase* pPtCur = (CPointNameBase*)pOneFind->GetValue();
CString strName = pPtCur->GetName();
if (strName == pointName) {
if (needZ) {
if (pPtCur->z0 > -1E100) {
pPoint = pPtCur;
break;
}
}
else {
pPoint = pPtCur;
break;
}
}
}
}
CString strData("");
if (pPoint != nullptr) {
strData.Format("%s,%lf,%lf,%lf", pPoint->GetName(), pPoint->x0, pPoint->y0, pPoint->z0);
}
return strData.AllocSysString();
}
extern "C" __declspec(dllexport)
BSTR XYStaticBlockWells(CXy * pxy, const LPCTSTR blockLines)
{
vector<CString> vecString;
CString strTmp;
int iPos = 0;
while (AfxExtractSubString(strTmp, blockLines, iPos, ' '))
{
iPos++;
vecString.push_back(strTmp);
}
NBase::CPointList pts;
double dX, dY;
for (auto iter = vecString.begin(); iter != vecString.end(); ++iter) {
CString strLine = *iter;
int nCount = sscanf(strLine, "%lf,%lf", &dX, &dY);
if (nCount >= 2) {
NBase::dfPoint dp;
dp.x0 = dX;
dp.y0 = dY;
pts.AddTail(dp);
}
}
CString strReturn("");
if (pts.GetSize() == 0) {
return strReturn.AllocSysString();
}
CCurveEx* pBlock = new CCurveEx();
pBlock->SetPoints(pts, 2);
// 创建一个XML的文档对象。
TiXmlDocument *xmlDocument = new TiXmlDocument();
TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "UTF-8", "");
xmlDocument->LinkEndChild(decl);
// 根元素。
TiXmlElement *rootElement = new TiXmlElement("ROOT");
xmlDocument->LinkEndChild(rootElement);
// 获取区域内的点
CPtrList* pLst = pxy->GetValueList();
POSITION pFind = pLst->GetHeadPosition();
POSITION posFind;
COne *pOneFind;
int id = 0;
while (pFind) {
posFind = pFind;
pOneFind = (COne *)(pLst->GetNext(pFind));
if (!pOneFind->IsView()) continue;
if (pOneFind->GetLayer()->IsNotViewNotEdit()) continue;
if (pOneFind->GetType() == DOUBLEFOX_XYZ || pOneFind->GetType() == DOUBLEFOX_POINT)
{
CPointNameBase* pPoint = (CPointNameBase*)pOneFind->GetValue();
if (pBlock->IsInside(pPoint->x0, pPoint->y0))
{
CString name, txt;
TiXmlElement *itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
TiXmlElement *idElement = new TiXmlElement("ID");
//TiXmlElement *blockNameElement = new TiXmlElement("BlockName");
//TiXmlElement *blockLayerElement = new TiXmlElement("BlockLayer");
TiXmlElement *nameElement = new TiXmlElement("Name");
TiXmlElement *layerElement = new TiXmlElement("Layer");
TiXmlElement *positionElement = new TiXmlElement("Position");
TiXmlElement *xElement = new TiXmlElement("X");
TiXmlElement *yElement = new TiXmlElement("Y");
TiXmlElement *zElement = new TiXmlElement("Z");
TiXmlElement *symbolElement = new TiXmlElement("symbol");
itemElement->LinkEndChild(idElement);
//itemElement->LinkEndChild(blockNameElement);
//itemElement->LinkEndChild(blockLayerElement);
itemElement->LinkEndChild(nameElement);
itemElement->LinkEndChild(layerElement);
itemElement->LinkEndChild(xElement);
itemElement->LinkEndChild(yElement);
itemElement->LinkEndChild(zElement);
itemElement->LinkEndChild(positionElement);
itemElement->LinkEndChild(symbolElement);
id++;
// 序号
CString strID;
strID.Format(_T("%d"), id);
TiXmlText *idValue = new TiXmlText(strID);
idElement->LinkEndChild(idValue);
//// 区域名称
//name = pOne->GetName();
//TiXmlText *blockNameValue = new TiXmlText(name);
//blockNameElement->LinkEndChild(blockNameValue);
// 名称
name = pOneFind->GetName();
TiXmlText *nameValue = new TiXmlText(name);
nameElement->LinkEndChild(nameValue);
// 图层
TiXmlText *layerValue = new TiXmlText(pOneFind->GetLayer()->GetName());
layerElement->LinkEndChild(layerValue);
// 坐标
AfxGetPublicFunction()->FloatToString(txt, pPoint->x0, decimal);
TiXmlText *xValue = new TiXmlText(txt);
xElement->LinkEndChild(xValue);
AfxGetPublicFunction()->FloatToString(txt, pPoint->y0, decimal);
TiXmlText *yValue = new TiXmlText(txt);
yElement->LinkEndChild(yValue);
AfxGetPublicFunction()->FloatToString(txt, pPoint->z0, decimal);
TiXmlText *zValue = new TiXmlText(txt);
zElement->LinkEndChild(zValue);
// 图元指针
uintptr_t number = (uintptr_t)posFind;
char buffer[65];
_ui64toa(number, buffer, 10);
txt.Format("%s", buffer);
TiXmlText *posValue = new TiXmlText(txt);
positionElement->LinkEndChild(posValue);
// 符号
if (pOneFind->GetLayer()->HowToViewPoint)
{
TiXmlText *symbolValue = new TiXmlText(pOneFind->GetLayer()->HowToViewPoint->MarkName);
symbolElement->LinkEndChild(symbolValue);
}
}
}
}
TiXmlPrinter printer;
xmlDocument->Accept(&printer);
strReturn = CString(printer.CStr());
delete xmlDocument;
xmlDocument = nullptr;
delete pBlock;
pBlock = nullptr;
return strReturn.AllocSysString();
}
// 统计井数据
extern "C" __declspec(dllexport)
BSTR StaticBlockWells(CSigmaView* pView, LPCTSTR blockLines) {
if (pView->m_pDoc == NULL) { return 0; }
CXy* pxy = pView->m_pDoc->m_pXy;
return XYStaticBlockWells(pxy, blockLines);
}
extern "C" __declspec(dllexport)
BSTR StaticWellsZ(CXy* pXy, LPCTSTR blockLine) {
if (pXy == NULL) { return 0; }
vector<CString> vecString;
CString strTmp;
int iPos = 0;
while (AfxExtractSubString(strTmp, blockLine, iPos, ' '))
{
iPos++;
vecString.push_back(strTmp);
}
NBase::CPointList pts;
double dX, dY;
for (auto iter = vecString.begin(); iter != vecString.end(); ++iter) {
CString strLine = *iter;
int nCount = sscanf(strLine, "%lf,%lf", &dX, &dY);
if (nCount >= 2) {
NBase::dfPoint dp;
dp.x0 = dX;
dp.y0 = dY;
pts.AddTail(dp);
}
}
if (pts.GetSize() == 0) {
return 0;
}
CCurveEx* pBlock = new CCurveEx();
pBlock->SetPoints(pts, 2);
// 获取区域内的点
CPtrList* pLst = pXy->GetValueList();
POSITION pFind = pLst->GetHeadPosition();
POSITION posFind;
COne *pOneFind;
//int id = 0;
CString strData;
while (pFind) {
posFind = pFind;
pOneFind = (COne *)(pLst->GetNext(pFind));
if (!pOneFind->IsView()) continue;
if (pOneFind->GetLayer()->IsNotViewNotEdit()) continue;
if (pOneFind->GetType() == DOUBLEFOX_XYZ || pOneFind->GetType() == DOUBLEFOX_POINT)
{
CPointNameBase* pPoint = (CPointNameBase*)pOneFind->GetValue();
if (pBlock->IsInside(pPoint->x0, pPoint->y0))
{
CString strName, strLayer, strZ, strX, strY;
// 名称
strName = pOneFind->GetName();
// 图层
strLayer = pOneFind->GetLayer()->GetName();
// 坐标
if (pPoint->z0 < -1E100) {
strZ = "";
}
else {
AfxGetPublicFunction()->FloatToString(strZ, pPoint->z0, decimal);
}
AfxGetPublicFunction()->FloatToString(strX, pPoint->x0, decimal);
AfxGetPublicFunction()->FloatToString(strY, pPoint->y0, decimal);
strData += (strLayer + "," + strName + "," + strZ + "," + strX + "," + strY + "\r\n");
}
}
}
if (pBlock) {
delete pBlock;
}
return strData.AllocSysString();
}
//static CPolyline CurveExToPolyline(CCurveEx * pCurve)
//{
// CPolyline polyline;
// polyline.SetName(pCurve->GetName());
// for (int i = 0; i < pCurve->num; i++) {
// polyline.AddPoint(pCurve->x[i], pCurve->y[i], pCurve->z[i]);
// }
// return polyline;
//}
///**
//* 生成龟背图
//* Points格式 name1,x,y name2,x,y ...
//**/
//extern "C" __declspec(dllexport)
//BSTR CreateVoronoi(CXy* pXy, LPCTSTR borderLine, LPCTSTR points) {
// if (pXy == NULL) { return 0; }
// vector<CString> vecString;
// CString strTmp;
// int iPos = 0;
// while (AfxExtractSubString(strTmp, borderLine, iPos, ' '))
// {
// iPos++;
// vecString.push_back(strTmp);
// }
// NBase::CPointList pts;
// double dX, dY;
// for (auto iter = vecString.begin(); iter != vecString.end(); ++iter) {
// CString strLine = *iter;
// int nCount = sscanf(strLine, "%lf,%lf", &dX, &dY);
// if (nCount >= 2) {
// NBase::dfPoint dp;
// dp.x0 = dX;
// dp.y0 = dY;
// pts.AddTail(dp);
// }
// }
// if (pts.GetSize() == 0) {
// return 0;
// }
// // 生成边界线
// CCurveEx* pBlock = new CCurveEx();
// pBlock->SetPoints(pts, 2);
// // 获取区域内的断层 --目前先不考虑断层
// std::list<CPolyline> flts;// = CollectFlts(pBlock);
//
// // 区域内点
// std::vector<CWellPoint> wells;
// vector<CString> vecPointData;
// iPos = 0;
// while (AfxExtractSubString(strTmp, points, iPos, ' '))
// {
// vecPointData.push_back(strTmp);
// iPos++;
// }
// char s[100]; memset(s, 0, sizeof(char) * 100);
// CString strPointName;
// for (auto iter = vecPointData.begin(); iter != vecPointData.end(); ++iter) {
// CString strLine = *iter;
// int nCount = sscanf(strLine, "%99[^,],%lf,%lf", s, &dX, &dY);
// if (nCount >= 3) {
// CWellPoint dp;
// dp.x0 = dX;
// dp.y0 = dY;
// strPointName = s;
// dp.SetName(strPointName);
// wells.push_back(dp);
// }
// }
// if (wells.size() == 0) {
// return 0;
// }
// CPolyline border = CurveExToPolyline(pBlock);
// std::list<CPolyline> results;
// auto voronoiMap = std::make_unique<CVoronoiMap>();
// voronoiMap->SetFltClosingFraction(0.1);
// voronoiMap->ReadWellData(wells);
// voronoiMap->CreateMap(flts, border);
// int nResult = voronoiMap->OutputResult(results);
// if (pBlock) {
// delete pBlock;
// }
// CString strResultData;
// for (auto polyLine : results) {
// int iCount = polyLine.GetSize();
// // 如果是龟背图的折线,每个折线至少有 3 条边形成一个闭合的多边形结构
// if (iCount <= 2) {
// continue;
// }
// CString strPolyName = polyLine.GetName();
// strResultData.Append("Pline.");
// strResultData.Append(strPolyName);
// strResultData.Append("\r\n");
// CString strCoord("");
// for (int i = 0; i < iCount; i++) {
// CPointXYZ &xyz = polyLine.GetPoint(i);
// strCoord.Format("%lf,%lf ", xyz.x0, xyz.y0);
// strResultData.Append(strCoord);
// }
// strResultData.Append("\r\n");
// }
//
// return strResultData.AllocSysString();
//}
CString Curve2String(CCurve* pCurve)
{
CString strData("Pline");
for (int i = 0; i < pCurve->num; i++) {
CString strLine("");
strLine.Format("%s,%s\r\n", pCurve->x[i], pCurve->y[i]);
strData += strLine;
}
return strData;
}
CString MyCurve2String(CMyCurve* pCurve)
{
CString strData("Pline");
for (int i = 0; i < pCurve->num; i++) {
CString strLine("");
strLine.Format("%s,%s\r\n", pCurve->x[i], pCurve->y[i]);
strData += strLine;
}
return strData;
}
double TakeZFromName(LPCTSTR curveName) {
vector<CString> vecString;
CString strTmp;
int iPos = 0;
double dZ = 0;
int nCount=0;
while (AfxExtractSubString(strTmp, curveName, iPos, ','))
{
iPos++;
dZ += atof(strTmp);
nCount++;
}
return dZ / nCount;
}
extern "C" __declspec(dllexport)
double StaticTradeAreaByContour(CXy* pXy, LPCTSTR blockLine, LPCTSTR contourLayer, LPCTSTR faultLayer)
{
CContourFillMap cfmp;
vector<CMyCurve*> contours, flts;
vector<CString> vecString;
CString strTmp;
int iPos = 0;
while (AfxExtractSubString(strTmp, blockLine, iPos, ' '))
{
iPos++;
vecString.push_back(strTmp);
}
GBase::CPointList pts;
double dX, dY;
for (auto iter = vecString.begin(); iter != vecString.end(); ++iter) {
CString strLine = *iter;
int nCount = sscanf(strLine, "%lf,%lf", &dX, &dY);
if (nCount >= 2) {
GBase::dfPoint dp;
dp.x0 = dX;
dp.y0 = dY;
pts.AddTail(dp);
}
}
CString strReturn("");
if (pts.GetSize() == 0) {
return 0.0;
}
CMyCurve curBorder;
curBorder.SetPoints(pts, 2);
// 设置等值线
CList<POSITION, POSITION> lstContour;
pXy->GetElement(contourLayer, lstContour, TRUE);
if (lstContour.GetCount() == 0) {
return 0;
}
POSITION pos, pt;
pos = lstContour.GetHeadPosition();
while (pos)
{
pt = lstContour.GetNext(pos);
COne* pOne = pXy->GetAt(pt);
if (pOne->GetType() == DOUBLEFOX_CURVE) {
CCurveEx* pCurveCur = (CCurveEx*)pOne->value;
CMyCurve* curve = new CMyCurve();
curve->Create(pCurveCur->num);
for (int i = 0; i < pCurveCur->num; i++) {
curve->SetPoint(i, pCurveCur->x[i], pCurveCur->y[i], atof(pCurveCur->GetName()));
}
curve->SetName(pCurveCur->GetName());
curve->GetLocation();
contours.push_back(curve);
}
}
cfmp.SetContours(contours);
// 设置断层
CList<POSITION, POSITION> lstFault;
pXy->GetElement(faultLayer, lstFault, TRUE);
if (lstFault.GetCount() > 0) {
pos = lstFault.GetHeadPosition();
while (pos)
{
pt = lstFault.GetNext(pos);
COne* pOne = pXy->GetAt(pt);
if (pOne->GetType() == DOUBLEFOX_CURVE) {
CCurveEx* pCurveCur = (CCurveEx*)pOne->value;
CMyCurve* curve = new CMyCurve();
curve->Create(pCurveCur->num);
for (int i = 0; i < pCurveCur->num; i++) {
curve->SetPoint(i, pCurveCur->x[i], pCurveCur->y[i], pCurveCur->z[i]);
}
curve->SetName(pCurveCur->GetName());
curve->GetLocation();
flts.push_back(curve);
}
}
cfmp.SetFlts(flts);
}
// 设置边界
cfmp.SetBorder(curBorder);
cfmp.SetExtensivePara(1.1); //maxExtendLength = Global_GetExtendLength();
int rst = cfmp.CreatePolygons();
for (int i = 0; i < (int)contours.size(); i++)
{
if (NULL != contours[i])
delete contours[i];
}
contours.clear();
for (int i = 0; i < (int)flts.size(); i++)
{
if (NULL != flts[i])
delete flts[i];
}
flts.clear();
double dAreaTotal = 0;
double dVolumTotal = 0;
std::vector<CMyCurve*> areas = cfmp.GetResultPolygons();
//cfmp.WritePurePolygons("C:\\temp\\area.dfd");
for (int i = 0; i < areas.size(); i++)
{
CMyCurve* pCurve = areas[i];
//CString strData = MyCurve2String(pCurve);
//TRACE("%s\r\n", strData);
double dArea = pCurve->Area();
dAreaTotal += dArea;
double dZ = TakeZFromName(pCurve->GetName());
dVolumTotal += dZ* dArea;
}
return dVolumTotal / dAreaTotal;
}
// 面积衡量统计
extern "C" __declspec(dllexport)
double StaticTradeArea(CXy* pXy, LPCTSTR blockLine)
{
POSITION pos;
CMesh* pMesh = NULL;
pos = pXy->FindFirstElement(DOUBLEFOX_MESH);
if (pos)
{
pMesh = (CMesh*)pXy->GetAtValue(pos);
}
else {
return 0.0;
}
vector<CString> vecString;
CString strTmp;
int iPos = 0;
while (AfxExtractSubString(strTmp, blockLine, iPos, ' '))
{
iPos++;
vecString.push_back(strTmp);
}
NBase::CPointList pts;
double dX, dY;
for (auto iter = vecString.begin(); iter != vecString.end(); ++iter) {
CString strLine = *iter;
int nCount = sscanf(strLine, "%lf,%lf", &dX, &dY);
if (nCount >= 2) {
NBase::dfPoint dp;
dp.x0 = dX;
dp.y0 = dY;
pts.AddTail(dp);
}
}
CString strReturn("");
if (pts.GetSize() == 0) {
return 0.0;
}
CCurveEx* pBlock = new CCurveEx();
pBlock->SetPoints(pts, 2);
return pMesh->TradeArea(*pBlock);
}
// 计算区域的体积
extern "C" __declspec(dllexport)
double CaculateVolume(CXy* pXy, LPCTSTR blockLine) {
if (pXy == NULL) { return 0; }
POSITION pos;
CMesh* pMesh = NULL;
pos = pXy->FindFirstElement(DOUBLEFOX_MESH);
if (pos)
{
pMesh = (CMesh*)pXy->GetAtValue(pos);
}
else {
return 0.0;
}
vector<CString> vecString;
CString strTmp;
int iPos = 0;
while (AfxExtractSubString(strTmp, blockLine, iPos, ' '))
{
iPos++;
vecString.push_back(strTmp);
}
NBase::CPointList pts;
double dX, dY;
for (auto iter = vecString.begin(); iter != vecString.end(); ++iter) {
CString strLine = *iter;
int nCount = sscanf(strLine, "%lf,%lf", &dX, &dY);
if (nCount >= 2) {
NBase::dfPoint dp;
dp.x0 = dX;
dp.y0 = dY;
pts.AddTail(dp);
}
}
CString strReturn("");
if (pts.GetSize() == 0) {
return 0.0;
}
CCurveEx* pBlock = new CCurveEx();
pBlock->SetPoints(pts, 2);
return pMesh->Volume(*pBlock, 0);
}
extern "C" __declspec(dllexport)
double Mesh_GetZ(CXy* pXy, double ptX, double ptY) {
POSITION pos;
CMesh* pMesh = NULL;
pos = pXy->FindFirstElement(DOUBLEFOX_MESH);
if (pos)
{
pMesh = (CMesh*)pXy->GetAtValue(pos);
}
else {
return -1e100;
}
double dValue = pMesh->GetValue(ptX, ptY);
return dValue;
}
//返回zmin和zmax区间值 超出返回-1e100
extern "C" __declspec(dllexport)
double Mesh_GetZ1(CXy* pXy, double ptX, double ptY) {
POSITION pos;
CMesh* pMesh = NULL;
pos = pXy->FindFirstElement(DOUBLEFOX_MESH);
if (pos)
{
pMesh = (CMesh*)pXy->GetAtValue(pos);
}
else {
return -1e100;
}
double dValue = pMesh->GetValue(ptX, ptY);
double dZmin = 0;
double dZmax = 0;
pMesh->GetM(dZmin, dZmax);
if ((dValue < dZmin) || (dValue > dZmax))
{
return -1e100;
}
return dValue;
}
// 判断两线段是否真正相交2D
bool IsSegIntersect(const double& x1, const double& y1, const double& x2, const double& y2,
const double& x3, const double& y3, const double& x4, const double& y4) {
auto cross = [](double x1, double y1, double x2, double y2) {
return x1 * y2 - x2 * y1;
};
auto direction = [&](double x1, double y1, double x2, double y2, double x3, double y3) {
return cross(x3 - x1, y3 - y1, x2 - x1, y2 - y1);
};
auto onSegment = [](double xi, double yi, double xj, double yj, double xk, double yk) {
return min(xi, xj) <= xk && xk <= max(xi, xj) && min(yi, yj) <= yk && yk <= max(yi, yj);
};
double d1 = direction(x3, y3, x4, y4, x1, y1);
double d2 = direction(x3, y3, x4, y4, x2, y2);
double d3 = direction(x1, y1, x2, y2, x3, y3);
double d4 = direction(x1, y1, x2, y2, x4, y4);
if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) &&
((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0)))
return true;
//if (std::fabs(d1) < 1e-10 && onSegment(x3, y3, x4, y4, x1, y1)) return true;
//if (std::fabs(d2) < 1e-10 && onSegment(x3, y3, x4, y4, x2, y2)) return true;
//if (std::fabs(d3) < 1e-10 && onSegment(x1, y1, x2, y2, x3, y3)) return true;
//if (std::fabs(d4) < 1e-10 && onSegment(x1, y1, x2, y2, x3, y3)) return true;
return false;
}
// 计算点到线段的平方距离
double point_to_segment_distance_sq(const double& xp, const double& yp, const double& x1, const double& y1, const double& x2, const double& y2) {
double l2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
if (l2 == 0.0f) { // 线段退化为点
double dx = xp - x1;
double dy = yp - y1;
return dx * dx + dy * dy;
}
// 计算投影参数 t
double t = ((xp - x1) * (x2 - x1) + (yp - y1) * (y2 - y1)) / l2;
t = std::clamp(t, 0.0, 1.0); // 截断到线段范围内
// 计算投影点
double projection_x = x1 + t * (x2 - x1);
double projection_y = y1 + t * (y2 - y1);
// 计算平方距离
double dx = xp - projection_x;
double dy = yp - projection_y;
return dx * dx + dy * dy;
}
// 统计井点的倾角
extern "C" __declspec(dllexport)
BSTR StatisticWellInclination(CSigmaView* pView, LPCSTR layerName, BOOL childNode, double searchRadius, LPCTSTR faultLayer, LPCTSTR borderLayer)
{
if (pView->m_pDoc == NULL) { return 0; }
CXy* pXy = pView->m_pDoc->m_pXy;
// 获得网格
CMesh* pMesh = NULL;
POSITION posMesh = pXy->FindFirstElement(DOUBLEFOX_MESH);
if (posMesh)
{
pMesh = (CMesh*)pXy->GetAtValue(posMesh);
}
else {
return 0;
}
CGrid* pGrid = pMesh->GetDfg();
// 按图层获取图元
CList<POSITION, POSITION> selectWells;
if (childNode)
{
pXy->GetElement(layerName, selectWells, TRUE);
}
else
pXy->GetElement(layerName, selectWells, FALSE);
if (selectWells.IsEmpty())
{
return 0;
}
// 获得所有的边界
std::vector<CCurve*> vecBorder;
CList<POSITION, POSITION> lstBorder;
if (borderLayer && borderLayer[0] != _T('\0'))
{
pXy->GetElement(borderLayer, lstBorder, TRUE);
POSITION posBorer, ptOneBorder;
posBorer = lstBorder.GetHeadPosition();
while (posBorer)
{
ptOneBorder = lstBorder.GetNext(posBorer);
COne* pOneCurve= pXy->GetAt(ptOneBorder);
if (pOneCurve->GetType() != DOUBLEFOX_CURVE)
{
continue;
}
CCurve* pCurve = (CCurve*)pOneCurve->GetValue();
vecBorder.push_back(pCurve);
}
}
std::vector<std::tuple<CPointNameBase*, NBase::CRect8, POSITION>> pairContainer;
POSITION pos, ptOne;
pos = selectWells.GetHeadPosition();
// 生成每个井点的计算范围
while (pos)
{
ptOne = selectWells.GetNext(pos);
COne* pOne = pXy->GetAt(ptOne);
if (pOne->GetType() != DOUBLEFOX_XYZ && pOne->GetType() != DOUBLEFOX_POINT)
{
continue;
}
CPointNameBase* pPoint = (CPointNameBase*)pOne->GetValue();
// 边界条件
if (vecBorder.size() > 0)
{
bool isInside = false;
for (auto& pCurve : vecBorder)
{
int nIn = pCurve->IsInside(pPoint->x0, pPoint->y0);
if (nIn == 1)
{
isInside = true;
break;
}
}
if (isInside == false)
{
continue;
}
}
NBase::CRect8 rectWell;
rectWell.left = pPoint->x0 - searchRadius;
rectWell.right = pPoint->x0 + searchRadius;
rectWell.bottom = pPoint->y0 - searchRadius;
rectWell.top = pPoint->y0 + searchRadius;
pairContainer.emplace_back(pPoint, rectWell, ptOne);
}
// 构造断层的计算树
vector<tuple<double,double, double,double, CString>> faultSegments;
RTree2D faultTree;
if (faultLayer && faultLayer[0] != _T('\0'))
{
CList<POSITION, POSITION> selectFaults;
pXy->GetElement(faultLayer, selectFaults, TRUE);
POSITION posFault, ptOneFault;
posFault = selectFaults.GetHeadPosition();
while (posFault)
{
ptOneFault = selectFaults.GetNext(posFault);
COne* pOneFault = pXy->GetAt(ptOneFault);
if (pOneFault->GetType() != DOUBLEFOX_CURVE)
{
continue;
}
CCurve* pFault = (CCurve*)pOneFault->GetValue();
for (int i = 1; i < pFault->num; i++)
{
// 直接在容器中构造对象
faultSegments.emplace_back(pFault->x[i - 1], pFault->y[i - 1], pFault->x[i], pFault->y[i], pFault->GetName());
}
}
size_t segCount = faultSegments.size();
for (int i = 0; i < segCount;i++)
{
tuple<double, double, double, double, CString>&pSeg = faultSegments[i];
AABBRect abRect(std::get<0>(pSeg), std::get<1>(pSeg), std::get<2>(pSeg), std::get<3>(pSeg));
faultTree.Insert(abRect.min, abRect.max, i);
}
}
//faultTree.Search(, , searchCallback);
double dDistMinX = pGrid->dx()*0.75;
double dDistMinY = pGrid->dy()*0.75;
std::vector<std::tuple<CPointNameBase*, NBase::CPoint3D, POSITION, CString, double>> vecResult;
// 计算每口井有效范围内的倾角
for (auto&[well, searchRange, wellPos] : pairContainer)
{
int nLeft = int(pGrid->xGrid(searchRange.left) + 0.5);
int nRight = int(pGrid->xGrid(searchRange.right));
if (nLeft < 0)
nLeft = 1;
if (nRight > pGrid->xnum())
nRight = pGrid->xnum();
int nBottom = int(pGrid->yGrid(searchRange.bottom) + 0.5);
int nTop = int(pGrid->yGrid(searchRange.top));
if (nBottom < 0)
nBottom = 1;
if (nTop > pGrid->ynum())
nTop = pGrid->ynum();
double dZSource = pGrid->Value(well->x0, well->y0);
double dAngle = 0;
double dFindX = 0;
double dFindY = 0;
double dFindZ = 0;
for (int i = nLeft; i <= nRight; i++)
{
for (int j = nBottom; j <= nTop; j++)
{
double dDesZ = pGrid->Value(i, j);
// z值不在有效范围内
if (!pGrid->IsValueInRange(dDesZ)) {
continue;
}
double dDesX = pGrid->x(i);
double dDesY = pGrid->y(j);
double dX = dDesX - well->x0;
// 与井点距离太近
if (abs(dX) < dDistMinX)
{
continue;
}
double dY = dDesY - well->y0;
if (abs(dY) < dDistMinY)
{
continue;
}
// 判断是否与断层相交
bool foundIntersection = false;
AABBRect rectSearch(well->x0, well->y0, dDesX, dDesY);
int nHits = faultTree.Search(rectSearch.min, rectSearch.max, [&faultSegments, &foundIntersection
, &well, &dDesX, &dDesY](int find) {
tuple<double, double, double, double, CString>& seg = faultSegments[find];
if (IsSegIntersect(std::get<0>(seg), std::get<1>(seg), std::get<2>(seg), std::get<3>(seg)
, well->x0, well->y0, dDesX, dDesY)) {
foundIntersection = true;
return false; // ❗️终止搜索
}
return true;
});
if (foundIntersection == true)
{
continue;
}
double dZ = dDesZ - dZSource;
double dL = dX*dX + dY*dY;
// 梯度平方
double dGradientSq = (dZ * dZ) / dL;
if (dGradientSq > std::abs(dAngle))
{
dAngle = dGradientSq;
//if (dZ < 0)
//{
// dAngle = -dGradientSq;
//}
dFindX = dDesX;
dFindY = dDesY;
dFindZ = dDesZ;
}
}
}
// 查找最近的断层线
double dFaultDist = -1;
CString strFaultName("");
if (faultSegments.size() > 0)
{
size_t maxHits = 5;
std::vector<int> order;
double p_min[2] = { well->x0, well->y0 };
double p_max[2] = { well->x0, well->y0 };
auto count = faultTree.NNSearch(p_min, p_max, [maxHits, &order](int segID, double distMBR) {
order.push_back(segID);
return order.size() < maxHits;
});
if (order.size() > 0)
{
double dDistMin = std::numeric_limits<double>::max();
int resultSeg = -1;
for (auto segID : order)
{
tuple<double, double, double, double, CString>& seg = faultSegments[segID];
double dDist = point_to_segment_distance_sq(well->x0, well->y0, std::get<0>(seg), std::get<1>(seg), std::get<2>(seg), std::get<3>(seg));
if (dDist < dDistMin)
{
dDistMin = dDist;
resultSeg = segID;
}
}
dFaultDist = std::sqrt(dDistMin);
tuple<double, double, double, double, CString>& segResult = faultSegments[resultSeg];
strFaultName = std::get<4>(segResult);
}
/* TODO: 以下才是近乎完美的NNSearch方案
// 调用NNSearch并传入一个Lambda表达式作为回调函数
tree.NNSearch(query_min, query_max,
// --- 核心回调函数逻辑 ---
// [&] 表示以引用的方式捕获外部作用域的所有变量(如 min_true_dist_sq 和 best_segment_id
// segment_id 是R-Tree返回的候选线段ID
// box_dist_sq 是查询点到该候选线段“包围盒”的距离的平方
[&](const int& segment_id, double box_dist_sq) -> bool {
std::cout << " 发现候选: 线段 " << segment_id
<< "。到其【包围盒】的平方距离为: " << box_dist_sq << std::endl;
// --- ** 核心剪枝优化 ** ---
// NNSearch会按“到包围盒距离”的升序来访问候选项。
// 如果当前候选的“包围盒”距离就已经比我们已经找到的“真实”最短距离还要远,
// 那么这个包围盒内部的任何线段都不可能成为新的最近者。
// 因此,我们可以安全地终止对这个分支以及更远分支的搜索。
if (box_dist_sq > min_true_dist_sq) {
std::cout << " -> 【剪枝】。包围盒距离(" << box_dist_sq
<< ") > 当前最小真实距离(" << min_true_dist_sq << "),停止搜索。" << std::endl;
return false; // 返回 false 会提前终止 NNSearch
}
// 如果候选项有潜力,我们就进行精确计算
// 1. 根据ID从我们的主数据库中获取线段的完整几何信息
const LineSegment& candidate_seg = segments[segment_id];
// 2. 计算点到线段的精确距离(的平方)
double true_dist_sq = distancePointToSegmentSq(query_point, candidate_seg);
std::cout << " -> 计算其【真实】平方距离为: " << true_dist_sq << std::endl;
// 3. 如果找到了一个更近的线段,则更新我们的记录
if (true_dist_sq < min_true_dist_sq) {
min_true_dist_sq = true_dist_sq;
best_segment_id = segment_id;
std::cout << " -> ★发现新的最近者ID: " << best_segment_id
<< ", 新的最小真实平方距离: " << min_true_dist_sq << std::endl;
}
return true; // 返回 true 以继续搜索其他可能的候选项 }
*/
}
CPointNameBase ptFind;
ptFind.x0 = dFindX;
ptFind.y0 = dFindY;
ptFind.z0 = dFindZ;
vecResult.emplace_back(well, std::move(ptFind), wellPos, strFaultName, dFaultDist);
}
// 输出结果
// 创建一个XML的文档对象。
TiXmlDocument *xmlDocument = new TiXmlDocument();
TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "UTF-8", "");
xmlDocument->LinkEndChild(decl);
// 根元素。
TiXmlElement *rootElement = new TiXmlElement("ROOT");
xmlDocument->LinkEndChild(rootElement);
CString name, txt;
int nId = 0;
for (auto&[sourceWell, destPoint, wellPos, faultName, faultDist] : vecResult)
{
TiXmlElement *itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
TiXmlElement *idElement = new TiXmlElement("序号");
TiXmlElement *nameElement = new TiXmlElement("井名");
//TiXmlElement *layerElement = new TiXmlElement("Layer");
TiXmlElement *xElement = new TiXmlElement("井点X");
TiXmlElement *yElement = new TiXmlElement("井点Y");
TiXmlElement *zElement = new TiXmlElement("井点Z");
TiXmlElement *xDest = new TiXmlElement("目标X");
TiXmlElement *yDest = new TiXmlElement("目标Y");
TiXmlElement *zDest = new TiXmlElement("目标Z");
TiXmlElement *angleElement = new TiXmlElement("倾角");
TiXmlElement *positionElement = new TiXmlElement("Position");
TiXmlElement *faultNameEle = new TiXmlElement("最近断层");
TiXmlElement *faultDistEle = new TiXmlElement("断层距离");
itemElement->LinkEndChild(idElement);
itemElement->LinkEndChild(nameElement);
//itemElement->LinkEndChild(layerElement);
itemElement->LinkEndChild(xElement);
itemElement->LinkEndChild(yElement);
itemElement->LinkEndChild(zElement);
itemElement->LinkEndChild(xDest);
itemElement->LinkEndChild(yDest);
itemElement->LinkEndChild(zDest);
itemElement->LinkEndChild(angleElement);
itemElement->LinkEndChild(positionElement);
itemElement->LinkEndChild(faultNameEle);
itemElement->LinkEndChild(faultDistEle);
// 序号
CString strID;
strID.Format(_T("%d"), nId);
TiXmlText *idValue = new TiXmlText(strID);
idElement->LinkEndChild(idValue);
// 名称
name = sourceWell->GetName();
TiXmlText *nameValue = new TiXmlText(name);
nameElement->LinkEndChild(nameValue);
//// 图层
//TiXmlText *layerValue = new TiXmlText(sourceWell->GetLayer()->GetName());
//layerElement->LinkEndChild(layerValue);
// 井点坐标
AfxGetPublicFunction()->FloatToString(txt, sourceWell->x0, decimal);
TiXmlText *xValue = new TiXmlText(txt);
xElement->LinkEndChild(xValue);
AfxGetPublicFunction()->FloatToString(txt, sourceWell->y0, decimal);
TiXmlText *yValue = new TiXmlText(txt);
yElement->LinkEndChild(yValue);
AfxGetPublicFunction()->FloatToString(txt, pGrid->Value(sourceWell->x0, sourceWell->y0), decimal);
TiXmlText *zValue = new TiXmlText(txt);
zElement->LinkEndChild(zValue);
// 目的坐标
AfxGetPublicFunction()->FloatToString(txt, destPoint.x0, decimal);
TiXmlText *xValueDest = new TiXmlText(txt);
xDest->LinkEndChild(xValueDest);
AfxGetPublicFunction()->FloatToString(txt, destPoint.y0, decimal);
TiXmlText *yValueDest = new TiXmlText(txt);
yDest->LinkEndChild(yValueDest);
AfxGetPublicFunction()->FloatToString(txt, destPoint.z0, decimal);
TiXmlText *zValueDest = new TiXmlText(txt);
zDest->LinkEndChild(zValueDest);
// 角度
double distH = ((NBase::CPoint2D*)sourceWell)->Distance(static_cast<NBase::CPoint2D>(destPoint));
double dInclineZ = destPoint.z0 - pGrid->Value(sourceWell->x0, sourceWell->y0);
double dAngle = std::atan2(dInclineZ, distH);
dAngle = dAngle * 180.0 / M_PI;
//if (dInclineZ < 0) {
// dAngle *= -1;
//}
AfxGetPublicFunction()->FloatToString(txt, dAngle, decimal);
TiXmlText *tiAngle = new TiXmlText(txt);
angleElement->LinkEndChild(tiAngle);
// 图元指针
uintptr_t number = (uintptr_t)wellPos;
char buffer[65];
_ui64toa(number, buffer, 10);
txt.Format("%s", buffer);
TiXmlText *posValue = new TiXmlText(txt);
positionElement->LinkEndChild(posValue);
// 断层
TiXmlText *txFaultName = new TiXmlText(faultName);
faultNameEle->LinkEndChild(txFaultName);
// 断层距离
txt = "";
if (faultDist >= 0)
{
AfxGetPublicFunction()->FloatToString(txt, faultDist, decimal);
}
TiXmlText *txFaultDist = new TiXmlText(txt);
faultDistEle->LinkEndChild(txFaultDist);
nId++;
}
TiXmlPrinter printer;
xmlDocument->Accept(&printer);
CString strReturn("");
strReturn = CString(printer.CStr());
delete xmlDocument;
xmlDocument = nullptr;
return strReturn.AllocSysString();
}
// 统计
extern "C" __declspec(dllexport)
BSTR Statisc(CSigmaView* pView, LPCSTR layerName, BOOL childNode, int nStatMode, int surfaceType)
{
if (pView->m_pDoc == NULL) { return 0; }
// 按图层获取图元
CList<POSITION, POSITION> select;
if (layerName == NULL)
{
CXyElementFilter filter;
pView->m_pDoc->GetDraw()->GetElement(filter, select);
}
else
{
pView->m_pDoc->GetDraw()->GetElement(layerName, select, childNode);
}
if (select.IsEmpty())
{
//::AfxMessageBox("No data");
return 0;
}
//string xmlstr;
// 创建一个XML的文档对象。
TiXmlDocument *xmlDocument = new TiXmlDocument();
TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "UTF-8", "");
xmlDocument->LinkEndChild(decl);
// 根元素。
TiXmlElement *rootElement = new TiXmlElement("ROOT");
xmlDocument->LinkEndChild(rootElement);
if (nStatMode == STAT_MODE_POLYGON_RELATION)
{
StatisPolygonRelation(pView, select, rootElement);
}
else {
POSITION pos, pt;
CMesh* pMesh = NULL;
pos = pView->m_pDoc->GetDraw()->FindFirstElement(DOUBLEFOX_MESH);
if (pos)
{
pMesh = (CMesh*)pView->m_pDoc->GetDraw()->GetAtValue(pos);
}
int total = 0;
total = select.GetCount();
pos = select.GetHeadPosition();
int id = 1;
//CLayer* pLayer;
while (pos)
{
pt = select.GetNext(pos);
switch (nStatMode)
{
case STAT_MODE_ELEMENTS:
id += StatisElement(pView, pt, rootElement, id, nullptr);//pMesh
break;
case STAT_MODE_SURVEY:
id += StatisSurvey(pView, pt, rootElement, id);
break;
case STAT_MODE_TRAPS:
id += StatisTraps(pView, pt, rootElement, id, pMesh);
break;
case STAT_MODE_FAULTS:
id += StatisFault(pView, pt, rootElement, id, pMesh);
break;
case STAT_MODE_WELL:
id += StatisWells(pView, pt, rootElement, id, pMesh);
break;
case STAT_MODE_VOLUME:
id += StatisVolumn(pView, pt, rootElement, id, pMesh, surfaceType);
break;
case STAT_MODE_BLOCK_ELEMENT:
id += StatisticBlockElements(pView, pt, rootElement, id);
break;
case STAT_MODE_WELL_AZIMUTH:
id += StatisAzimuth(pView, pt, rootElement, id);
}
}
}
TiXmlPrinter printer;
xmlDocument->Accept(&printer);
// xmlstr = printer.CStr();
CString strText = CString(printer.CStr());
// int len = strText.GetLength();
delete xmlDocument;
xmlDocument = nullptr;
return strText.AllocSysString();
//return ::SysAllocString(strText);
}
// 统计分层
extern "C" __declspec(dllexport)
BSTR StatiscLayer(CSigmaView* pView, LPCSTR layerName)
{
if (pView->m_pDoc == NULL) { ::AfxMessageBox("The doc pointer is null", MB_ICONSTOP); return 0; }
CPtrList select;
pView->m_pDoc->GetDraw()->GetLayer(select, layerName, TRUE);
if (select.IsEmpty()) { ::AfxMessageBox("No Layers"); return 0; }
POSITION pos;
pos = select.GetHeadPosition();
TiXmlPrinter printer;
// string xmlstr;
// 创建一个XML的文档对象。
TiXmlDocument *xmlDocument = new TiXmlDocument();
TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "UTF-8", "");
xmlDocument->LinkEndChild(decl);
// 根元素。
TiXmlElement *rootElement = new TiXmlElement("ROOT");
xmlDocument->LinkEndChild(rootElement);
int i = 1;
CString id;
CLayer* pLayer;
while (pos)
{
id.Format("%d", i);
pLayer = (CLayer*)select.GetNext(pos);
StatisLayer(pView, rootElement, id, pLayer);
i++;
}
xmlDocument->Accept(&printer);
CString strData = printer.CStr();
delete xmlDocument;
xmlDocument = nullptr;
return strData.AllocSysString();
}
static CString ProjectionConfigPath()
{
char lpReturnedString[256];
int nSize=256;
GetModuleFileName(NULL, lpReturnedString, nSize);
CString exePath(lpReturnedString);
int pos = exePath.ReverseFind('\\');
if (pos != -1)
{
exePath = exePath.Left(pos);
}
exePath += "Projection.ini";
return exePath;
}
static void InitProjection(CProjection& xyz, CXy* pXy, CString strProjection)
{
xyz.SetOutArgv(strProjection);
xyz.SetInArgv(pXy->GetProjection());
xyz.SetEarch(pXy->m_ExchangeXYZ.m_longitude, pXy->m_ExchangeXYZ.m_latitude);
xyz.Initial(ProjectionConfigPath());
CString strCurProjection = xyz.GetInArgv();
}
static CString ResourceCommentToXml(const std::vector<map<std::string, std::string>>& data)
{
TiXmlDocument *xmlDocument = new TiXmlDocument();
TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "UTF-8", "");
xmlDocument->LinkEndChild(decl);
TiXmlElement *rootElement = new TiXmlElement("ROOT");
xmlDocument->LinkEndChild(rootElement);
for (const auto& map : data)
{
TiXmlElement* itemElement = new TiXmlElement("Item");
rootElement->LinkEndChild(itemElement);
for (const auto& pair : map)
{
TiXmlElement* element = new TiXmlElement(pair.first.c_str());
itemElement->LinkEndChild(element);
TiXmlText* value = new TiXmlText(pair.second.c_str());
element->LinkEndChild(value);
}
}
TiXmlPrinter printer;
xmlDocument->Accept(&printer);
CString str = printer.CStr();
return str;
}
static std::pair<std::string, std::string> GetNameAndFid(const std::string& str)
{
std::pair<std::string, std::string > pair;
std::vector<std::string> nameAndFid;
pystring::split(str, nameAndFid, "|");
if (nameAndFid.size() > 0)
{
pair.first = nameAndFid[0];
}
if (nameAndFid.size() > 1)
{
pair.second = nameAndFid[1];
}
return pair;
}
struct DMS
{
int degrees;
int minutes;
double seconds;
bool is_negative;
};
// 函数定义:将小数形式的经度转换为 DMS 结构体
static DMS DecimalToDMS(double decimal_degrees)
{
DMS dms;
dms.is_negative = decimal_degrees < 0;
decimal_degrees = std::abs(decimal_degrees);
dms.degrees = static_cast<int>(decimal_degrees);
double fractional = (decimal_degrees - dms.degrees) * 60;
dms.minutes = static_cast<int>(fractional);
dms.seconds = (fractional - dms.minutes) * 60;
return dms;
}
// 函数定义:格式化 DMS 结构体为字符串表示
// 注意客户习惯和一般书面表示不一样他们习惯前面不带度、分、秒这样的符号分和秒不足两位前面补0并且最后的小数只保存三位
// 比如 112°654″.1324 要表示成 1120654.132
static std::string FormatDMS(const DMS& dms)
{
std::string sign = dms.is_negative ? "-" : "";
// C++20 以前没有 format
char buf[64]{ 0 };
double integer = 0.0;
double fract = modf(dms.seconds, &integer); // 将小数拆分为整数部分和小数部分
sprintf_s(buf, sizeof(buf),
"%s%d%02d%02d.%03d", // 注意最后一个不能用 %.3f 然后接小数,这样会多输出一个 0
sign.c_str(),
dms.degrees,
dms.minutes,
(int)integer,
(int)(fract * 1000));
return std::string(buf);
}
// 将经纬度转换为度分秒字符串
static std::string DecimalToDMSString(double x)
{
return FormatDMS(DecimalToDMS(x));
}
// 资源评价统计
extern "C" __declspec(dllexport)
BSTR StatiscResourceComment(CSigmaView* pView, wchar_t* layerName)
{
if (pView->m_pDoc == NULL)
{
return CString().AllocSysString();
}
NBase::CPositionList select;
CXyElementFilter filter;
filter.addLayer(CString(layerName), true)
.addType(DOUBLEFOX_CURVE);
pView->m_pDoc->GetDraw()->GetElement(filter, select);
CProjection xyz;
// FIXME: 转换成经纬度,单位度,直接写这种字符串很不好,但是接口是这样设计的,先这么用了,后面再一起讨论要不要进行二次封装
InitProjection(xyz, pView->m_pDoc->m_pXy, "China - 1954 Gauss 6, 21, 0, 2 0, 2 0, 0");
std::vector<std::map<std::string, std::string>> data;
for (POSITION pos = select.GetHeadPosition(); pos != nullptr; select.GetNext(pos))
{
POSITION pt = select.GetAt(pos);
COne *pOne = (COne *)select.GetAt(pt);
if (pOne->GetType() != DOUBLEFOX_CURVE)
{
continue;
}
CCurveEx *pCurve = (CCurveEx *)pOne->GetValue();
CCurveEx* pNewCurve = new CCurveEx();
*pNewCurve = *pCurve;
pNewCurve->ExchangeXY(&xyz);
// 矿权统计,不需要最前面叫矿权的图层名,这里选择直接去掉最上面一层图层名
CString layerName = pOne->GetLayer()->GetName();
int index = layerName.Find("\\");
if (index != -1)
{
layerName = layerName.Mid(index + 1);
}
else
{
layerName.Empty();
}
// 转换坐标
std::vector<std::string> curve;
for (int i = 0; i < pNewCurve->num; i++)
{
std::string x = DecimalToDMSString(pNewCurve->x[i]);
std::string y = DecimalToDMSString(pNewCurve->y[i]);
curve.push_back(x + " " + y);
}
std::string name;
std::string fid;
std::tie(name, fid) = GetNameAndFid(pOne->GetName().GetString());
// WKT 格式,一种通用的标准格式
std::string wkt = "POLYGON((" + pystring::join(",", curve) + "))";
std::map<std::string, std::string> map;
map["FID"] = fid;
map["图元名称"] = name;
map["AU_评价单元"] = name;
map["资源类型"] = layerName.GetString();
map["评价层位"] = "";
map["盆地"] = "";
map["评价单位"] = "";
map["WKT"] = wkt;
map["Position"] = PositionToString(pt);
data.push_back(map);
}
return ResourceCommentToXml(data).AllocSysString();
}
//extern "C" __declspec(dllexport)
//void MemoCopyXml(BYTE* xml)
//{
// int len = xmlText.GetLength();
// memcpy(xml, xmlText.GetBuffer(0), len);
//}
/**
*
*
* \param pView
* \param positions position
* \param length
*/
extern "C" __declspec(dllexport)
void ActiveElements(CSigmaView* pView, POSITION positions[], int length)
{
if (length <= 0)
{
return;
}
pView->m_pDoc->ClearSelection();
std::vector<COne*> ones;
std::vector<POSITION> validPositions = GetValidPositions(pView->m_pDoc->m_pXy, positions, length);
for (auto pos : validPositions)
{
COne* pOne = (COne*)pView->m_pDoc->GetDraw()->GetAt(pos);
if (pOne != nullptr)
{
ones.push_back(pOne);
}
}
if (ones.empty())
{
return;
}
pView->m_pDoc->PushActionDC(ID_VIEW_WINDOW);
CRect rt;
rt = pView->GetClientRect();
NBase::CRect8 rect = ones[0]->GetRect();
for (COne* pOne : ones)
{
NBase::CRect8 oneRect = pOne->GetRect();
if (oneRect.left < rect.left)
{
rect.left = oneRect.left;
}
if (oneRect.top > rect.top)
{
rect.top = oneRect.top;
}
if (oneRect.right > rect.right)
{
rect.right = oneRect.right;
}
if (oneRect.bottom < rect.bottom)
{
rect.bottom = oneRect.bottom;
}
}
rect.InflateRect(rect.Width() / 4, rect.Height() / 4);
pView->m_pDoc->GetDC().Extend(rect, rt, EXTEND_MODE_DEFAULT);
NBase::CPositionList list;
for (COne* pOne : ones)
{
POSITION pos2 = pView->m_pDoc->m_pXy->Find(pOne);
if (pos2 && pOne->IsCanEdit() && pOne->IsView())
{
list.AddTail(pos2);
}
}
pView->m_pDoc->SetSelection(list);
pView->m_pDoc->Invalidate();
}
void ActiveElement(CSigmaView* pView, POSITION pos)
{
pView->m_pDoc->ClearSelection();
COne* pOne = (COne*)pView->m_pDoc->GetDraw()->GetAt(pos);
if (pOne == NULL)
{
return;
}
pView->m_pDoc->PushActionDC(ID_VIEW_WINDOW);
CRect rt;
rt = pView->GetClientRect();
NBase::CRect8 rect = pOne->GetRect();
rect.InflateRect(rect.Width() / 4, rect.Height() / 4);
pView->m_pDoc->GetDC().Extend(rect, rt, EXTEND_MODE_DEFAULT);
NBase::CPositionList list;
POSITION pos2 = pView->m_pDoc->m_pXy->Find(pOne);
if (pos2 && pOne->IsCanEdit() && pOne->IsView())
{
list.AddTail(pos2);
pView->m_pDoc->SetSelection(list);
}
pView->m_pDoc->Invalidate();
}
extern "C" __declspec(dllexport)
void ActiveEelement(CSigmaView* pView, POSITION pos)
{
if (IsValidPosition(pView->m_pDoc->m_pXy, pos))
{
ActiveElement(pView, pos);
}
}
/**
* 线
*
* \param pView
* \param layerNameSeprated
* \param textSubLayerName
* \param curveSubLayerName 线
* \return
*/
extern "C" __declspec(dllexport)
int Layer_SeparateTextAndCurve(CSigmaView * pView, char * layerNameSeprated, char * textSubLayerName, char * curveSubLayerName)
{
if (pView->m_pDoc->m_pXy == NULL)
return -1;
CXy * pXy = pView->m_pDoc->m_pXy;
CList<POSITION, POSITION> list;
pXy->GetElement(layerNameSeprated, list);
if (list.GetCount() == 0)
return -1;
CLayer * textFind = pXy->FindLayer(textSubLayerName);
if (textFind != 0)
return -1;
textFind = pXy->FindAddLayer(textSubLayerName);
if (textFind == 0)
return -1;
CLayer * curveFind = pXy->FindLayer(curveSubLayerName);
if (curveFind != 0)
return -1;
curveFind = pXy->FindAddLayer(curveSubLayerName);
if (curveFind == 0)
return -1;
POSITION pos, text;
pos = list.GetHeadPosition();
while (pos)
{
text = list.GetNext(pos);
switch (pXy->GetElementType(text))
{
case DOUBLEFOX_TEXT:
case DOUBLEFOX_XYZ:
case DOUBLEFOX_POINT:
pXy->SetElementLayer(text, textFind);
break;
case DOUBLEFOX_CURVE:
case DOUBLEFOX_CIRCLE:
case DOUBLEFOX_ELLIPSE:
case DOUBLEFOX_ARC:
pXy->SetElementLayer(text, curveFind);
break;
}
}
if (pView->m_pDoc)
pView->m_pDoc->Modified();
return 1;
}
//函数功能:删除曲线内元素
//返回值:-1--失败 0--指定图层内无曲线 1--删除成功
extern "C" __declspec(dllexport)
int Layer_DeleteInCurve(CSigmaView * pView, char * layerName)
{
if (pView == 0)
return -1;
NBase::CPositionList rgnList;
int ret = GetLayerElementCurve(pView->m_pDoc, layerName, rgnList, false);
if (ret == 0 || ret == -1)
{
return ret;
}
NBase::CPositionList delList;
if (RgnDelete(pView->m_pDoc, rgnList, delList, 0) > 0)
{
//pDoc->InvalidateDelete(delList);
pView->m_pDoc->SetActionItem(new CActionDeleteItem(pView->m_pDoc, IDS_STRING_ACTION_DELETE, delList));
return 1;
}
return -1;
}
//函数功能:删除曲线内元素
//返回值:-1--失败 0--指定图层内无曲线 1--删除成功
extern "C" __declspec(dllexport)
int Layer_DeleteOutCurve(CSigmaView * pView, char * layerName)
{
if (pView == 0)
return -1;
NBase::CPositionList rgnList;
int ret = GetLayerElementCurve(pView->m_pDoc, layerName, rgnList, false);
if (ret == 0 || ret == -1)
{
return ret;
}
NBase::CPositionList delList;
if (RgnDelete(pView->m_pDoc, rgnList, delList, 1) > 0)
{
CItemDelete item(pView->m_pDoc);
COne* pOne;
//CCurveEx* pCurve;
POSITION pos, pt, pb;
pos = delList.GetHeadPosition();
while (pos)
{
pb = pos;
pt = delList.GetNext(pos);
pOne = pView->m_pDoc->GetDraw()->GetAt(pt);
if (pOne->GetType() == DOUBLEFOX_CURVE)
{
//pCurve=(CCurveEx*)pDoc->GetDraw()->GetAtValue(pt);
if (item.ElementInRegion(pOne, rgnList))
delList.RemoveAt(pb);
}
else
delList.RemoveAt(pb);
}
pView->m_pDoc->SetActionItem(new CActionDeleteItem(pView->m_pDoc, IDS_STRING_ACTION_DELETE, delList));
return 1;
}
return -1;
}
extern "C" __declspec(dllexport)
int Layer_BreakCurve(CSigmaView * pView, char * layerName)
{
if (pView == 0)
return -1;
NBase::CPositionList rgnList;
int ret = GetLayerElementCurve(pView->m_pDoc, layerName, rgnList, false);
if (ret == 0 || ret == -1)
{
return ret;
}
CItemBreakCurve bc(pView->m_pDoc);
bc.BreakAllEditableCurve(rgnList);
return 1;
}
extern "C" __declspec(dllexport)
int Layer_ExtendCurve(CSigmaView * pView, char * layerName)
{
if (pView == 0)
return -1;
NBase::CPositionList rgnList;
int ret = GetLayerElementCurve(pView->m_pDoc, layerName, rgnList, false);
if (ret == 0 || ret == -1)
{
return ret;
}
CItemExtendCurve bc(pView->m_pDoc);
bc.ExtendCurve(rgnList);
return 1;
}
extern "C" __declspec(dllexport)
int Layer_ChangeLayer(CSigmaView * pView, char * layerNameOld, char * layerNameNew)
{
if (pView == 0)
return -1;
NBase::CPositionList* ppl = pView->GetSelection();
if (ppl == NULL || ppl->IsEmpty())
return -1;
POSITION pt = NULL;
//CString layer = pView->m_pDoc->GetSelectedElementLayer(*ppl);
COne* pOne;
POSITION pos;
CLayer* pl = pView->m_pDoc->GetDraw()->FindLayer(layerNameNew);
//将与page.have类别相同的元素去掉,为了防止在UNDO时出问题
NBase::CPositionList list;
pos = ppl->GetHeadPosition();
while (pos)
{
pt = ppl->GetNext(pos);
pOne = pView->m_pDoc->GetDraw()->GetAt(pt);
//if (pOne->GetLayer() == pl)
// continue;
list.AddTail(pt);
}
if (list.IsEmpty())
return -1;
CActionListItem* pAction = new CActionListItem(pView->m_pDoc, IDS_STRING_CHANGE_LAYER);
//如果该类别没有时
CLayer* pAddedLayer = NULL;
if (pl == NULL)
pAddedLayer = pView->m_pDoc->GetDraw()->FindAddLayer(layerNameNew);
pos = list.GetHeadPosition();
while (pos)
{
pt = list.GetNext(pos);
pView->m_pDoc->GetDraw()->SetElementLayer(pt, layerNameNew);
}
//for redo undo
pAction->AddChangeLayerItem(list, layerNameOld, layerNameNew);
if (pl == NULL)
{
//for redo undo
CLayer* pCurLayer = pView->m_pDoc->GetDraw()->GetCurrentLayer();
pAction->AddLayerAddItem(pAddedLayer, pCurLayer->GetPathName());
}
pView->m_pDoc->SetActionItem(pAction);
return 1;
}
/**
** 线
**/
extern "C" __declspec(dllexport)
int Layer_GetCurves(CSigmaView * pView, char* layerName, BYTE*& buffElement, int& buffLen)
{
NBase::CPositionList lstCurve;
int nCount = GetLayerElementCurve(pView->m_pDoc, layerName, lstCurve, true);
CXy* pxy = pView->m_pDoc->m_pXy;
BOOL bReturn = pxy->WriteMemory(buffElement, buffLen, lstCurve, 3, 0);
if (bReturn == false) {
nCount = 0;
}
return nCount;
}
static int XyGetLayerElementCurve(CXy * pxy, char * layerName, NBase::CPositionList& curveSelect, bool withChild)
{
if (pxy == NULL)
return -1;
//HTREEITEM hItem = m_wndTreeCtrl.GetSelectedItem();
//if (hItem == NULL) return 0;
//CString layer = m_wndTreeCtrl.GetPathName(hItem);
pxy->GetElement(layerName, curveSelect, withChild);
if (curveSelect.GetCount() == 0)
return 0;
POSITION pt, bp;
POSITION pos = curveSelect.GetHeadPosition();
while (pos)
{
bp = pos;
pt = curveSelect.GetNext(pos);
if (pxy->GetElementType(pt) == DOUBLEFOX_CURVE)
continue;
curveSelect.RemoveAt(bp);
}
return curveSelect.GetCount();
}
static int GetLayerElementCurve(CSigmaDoc * pDoc, char * layerName, NBase::CPositionList& curveSelect, bool withChild)
{
if (pDoc == NULL)
return -1;
return XyGetLayerElementCurve(pDoc->m_pXy, layerName, curveSelect, withChild);
}
extern "C" __declspec(dllexport)
int XyLayer_GetCurves(CXy* pxy, char* layerName, BYTE*& buffElement, int& buffLen, bool withChilds=true)
{
NBase::CPositionList lstCurve;
int nCount = XyGetLayerElementCurve(pxy, layerName, lstCurve, withChilds);
BOOL bReturn = pxy->WriteMemory(buffElement, buffLen, lstCurve, 3, 0);
if (bReturn == false) {
nCount = 0;
}
return nCount;
}
// 导出文件中的线类数据和点类数据
extern "C" __declspec(dllexport)
const char* XyExportFileData(CXy* pxy, bool withLine, bool withPoint) {
if (pxy == NULL)
return nullptr;
std::stringstream ss;
CPtrList* plist = pxy->GetValueList();
POSITION pos = plist->GetHeadPosition();
COne* pOne;
while (pos)
{
pOne = (COne*)plist->GetNext(pos);
if (pOne->GetViewState() == LAYER_NotViewNotEdit) {
continue;
}
if (withLine && pOne->GetType() == DOUBLEFOX_CURVE)
{
CString strLayerName = pOne->GetLayer()->GetName();
if (strLayerName.IsEmpty()) {
strLayerName = "0";
}
CCurveEx* pCurve = (CCurveEx*)pOne->value;
CString strLineName = pCurve->GetName();
for (int i = 0; i < pCurve->num; i++)
{
ss << pCurve->x[i];
ss << ",";
ss << pCurve->y[i];
ss << ",";
ss << pCurve->z[i];
ss << ",";
ss << strLineName;
ss << ",";
ss << strLayerName;
ss << "\r\n";
}
}
if (withPoint && (pOne->GetType() == DOUBLEFOX_POINT || pOne->GetType() == DOUBLEFOX_XYZ))
{
CString strLayerName = pOne->GetLayerName();
CPointNameEx* pPoint = (CPointNameEx*)pOne->GetValue();
CString strPointName = pPoint->GetName();
ss << pPoint->x0;
ss << ",";
ss << pPoint->y0;
ss << ",";
ss << pPoint->z0;
ss << ",";
ss << strPointName;
ss << ",";
ss << strLayerName;
ss << "\r\n";
}
}
std::string resultStr = ss.str();
char* result = new char[resultStr.length() + 1];
strcpy_s(result, resultStr.length() + 1, resultStr.c_str());
return result;
}
static int RgnDelete(CSigmaDoc * pDoc, NBase::CPositionList& rgnList, NBase::CPositionList& delList, int nDeleteIdea)
{
if (pDoc == NULL)
return 0;
if (pDoc->m_pXy == NULL)
return 0;
CItemDelete item(pDoc);
POSITION pt, bp;
POSITION pos = rgnList.GetHeadPosition();
while (pos)
{
bp = pos;
pt = rgnList.GetNext(pos);
item.GetSelectWidthRegion(delList, pt, nDeleteIdea);
}
//去除范围线本身
POSITION ps, pb, pg;
pos = rgnList.GetHeadPosition();
while (pos)
{
pt = rgnList.GetNext(pos);
ps = delList.GetHeadPosition();
while (ps)
{
pg = ps;
pb = delList.GetNext(ps);
if (pb != pt) continue;
delList.RemoveAt(pg);
}
}
//去除重复线
pos = delList.GetHeadPosition();
while (pos)
{
pt = delList.GetAt(pos);
ps = pos;
if (ps) delList.GetNext(ps);
while (ps)
{
pg = ps;
pb = delList.GetNext(ps);
if (pb != pt) continue;
delList.RemoveAt(pg);
}
delList.GetNext(pos);
}
return (int)delList.GetCount();
}
/**
* 线
*
* \param curve1
* \param curve2
* \return
*/
static std::vector<NBase::dfPoint> GetCrossPoint(CCurveEx& curve1, CCurveEx& curve2)
{
// 求交点,返回的交点里面存储的是桩号
CCrossList crossList;
curve1.Cross(curve2, crossList);
if (crossList.IsEmpty())
{
return {};
}
std::vector<NBase::dfPoint> result;
result.reserve(crossList.GetCount());
// 将桩号转换为交点
for (POSITION pos = crossList.GetHeadPosition(); pos != nullptr; crossList.GetNext(pos))
{
CCrossPoint crossPoint = crossList.GetAt(pos);
double l1 = crossPoint.x[0];
double* l = curve1.l;
NBase::dfPoint t;
int i = AfxGetPublicFunction()->BinarySearch(crossPoint.x[0], curve1.num, curve1.l);
if (i <= 0) i = 0;
else if (i > curve1.num - 2) i = curve1.num - 2;
t.x0 = AfxGetPublicFunction()->LineValue(l1, l + i, curve1.x + i);
t.y0 = AfxGetPublicFunction()->LineValue(l1, l + i, curve1.y + i);
t.z0 = AfxGetPublicFunction()->LineValue(l1, l + i, curve1.z + i);
result.push_back(t);
}
return result;
}
struct CurveRangeDetail
{
POSITION pos = nullptr;
CCurveEx* pCurve = nullptr;
NBase::CRect8 range;
};
// 提取曲线和范围
static std::vector<CurveRangeDetail> FetchCurves(CXy& pXy, const CString& layerName, bool includeSubLayer)
{
NBase::CPositionList select;
1 month ago
CLayer *pLayer = pXy.FindLayer(layerName);
pXy.GetElement(pLayer, select, DOUBLEFOX_CURVE, includeSubLayer);
1 month ago
std::vector<CurveRangeDetail> curves;
curves.reserve(select.GetCount());
for (POSITION pos = select.GetHeadPosition(); pos != nullptr; select.GetNext(pos))
{
POSITION pt = select.GetAt(pos);
COne* pOne = pXy.GetAt(pt);
CCurveEx* pCurve = pOne->GetValueSafe<CCurveEx>();
NBase::CRect8 range(1e100, -1e100, -1e100, 1e100);
pCurve->GetRange(range);
curves.push_back({ pt, pCurve, range });
}
return curves;
}
// 计算交点
static std::vector<std::map<std::string, std::string>> FindIntersections(const std::vector<CurveRangeDetail>& curves)
{
std::vector<std::map<std::string, std::string>> result;
// 这里取裸指针以及下面的 count 都是性能优化不要轻易修改当图元非常多时vector 的 size() 和 operator[] 是瓶颈
const CurveRangeDetail* pCurves = curves.data();
size_t count = curves.size();
for (size_t i = 0; i < count; i++)
{
CCurveEx* pCurve1 = pCurves[i].pCurve;
const NBase::CRect8& range1 = pCurves[i].range;
for (size_t j = i + 1; j < count; j++)
{
CCurveEx* pCurve2 = pCurves[j].pCurve;
const NBase::CRect8& range2 = pCurves[j].range;
// 先判断包围盒是否相交
if (!IsIntersecting(range1, range2))
{
continue;
}
std::vector<NBase::dfPoint> crossPoints = GetCrossPoint(*pCurve1, *pCurve2);
for (const auto& crossPoint : crossPoints)
{
std::map<std::string, std::string> map;
CString text;
text.Format("%s|%s", pCurve1->GetName(), pCurve2->GetName());
map["名称"] = text.GetBuffer();
map["X"] = std::to_string(crossPoint.x0);
map["Y"] = std::to_string(crossPoint.y0);
result.push_back(map);
}
}
}
return result;
}
struct IntersectionsDetail
{
NBase::dfPoint point{}; // 交点
POSITION pos1 = nullptr; // 第一条曲线 POSITION
CCurveEx *pCurve1 = nullptr; // 第一条曲线
POSITION pos2 = nullptr; // 第二条曲线 POSITION
CCurveEx *pCurve2 = nullptr; // 第二条曲线
};
// 计算交点,包括曲线自己和自己的交点
static std::vector<IntersectionsDetail> FindIntersections2(const std::vector<CurveRangeDetail>& curvesDetails)
{
std::vector<IntersectionsDetail> result;
// 这里取裸指针以及下面的 count 都是性能优化不要轻易修改当图元非常多时vector 的 size() 和 operator[] 是瓶颈
const CurveRangeDetail* pData = curvesDetails.data();
size_t count = curvesDetails.size();
#pragma omp parallel for
for (int32_t i = 0; i < count; i++)
{
std::vector<IntersectionsDetail> localResult;
for (int32_t j = i + 1; j < count; j++)
{
// 先判断包围盒是否相交
if (!IsIntersecting(pData[i].range, pData[j].range))
{
continue;
}
std::vector<NBase::dfPoint> crossPoints = GetCrossPoint(*(pData[i].pCurve), *(pData[j].pCurve));
for (const auto& crossPoint : crossPoints)
{
IntersectionsDetail detail { crossPoint, pData[i].pos, pData[i].pCurve, pData[j].pos, pData[j].pCurve};
localResult.push_back(detail);
}
}
#pragma omp critical
{
result.insert(result.end(), localResult.begin(), localResult.end());
}
}
return result;
}
/**
* 线
*
* \param pXy
* \param layerName
* \param includeSubLayer
* \return
*/
static std::vector<IntersectionsDetail> FindIntersectionsSelf(const std::vector<CurveRangeDetail>& curvesDetails)
{
std::vector<IntersectionsDetail> result;
#pragma omp parallel for
for (int32_t i = 0; i < curvesDetails.size(); i++)
{
POSITION pos = curvesDetails[i].pos;
CCurveEx* pCurve = curvesDetails[i].pCurve;
std::unique_ptr<CCurveEx> pNewCurve = DeduplicateCurvePoints(*curvesDetails[i].pCurve);
std::vector<IntersectionsDetail> localResult;
for (int32_t j = 0; j < pNewCurve->num - 1; j++)
{
// j + 2 是为了跳过相邻线段
for (int32_t k = j + 2; k < pNewCurve->num - 1; k++)
{
double p0_x = pNewCurve->x[j];
double p0_y = pNewCurve->y[j];
double p1_x = pNewCurve->x[j + 1];
double p1_y = pNewCurve->y[j + 1];
double p2_x = pNewCurve->x[k];
double p2_y = pNewCurve->y[k];
double p3_x = pNewCurve->x[k + 1];
double p3_y = pNewCurve->y[k + 1];
// 曲线是否相交,我们通过线段一段段比较判断,这样会导致闭合曲线的闭合点也认为是相交的,忽略掉这个闭合点
if (pNewCurve->IsClosed() && IsFirstIndex(*pNewCurve, j) && IsLastIndex(*pNewCurve, k + 1))
{
continue;
}
double x = 0.0;
double y = 0.0;
if (GetLineIntersection(p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y, x, y) > 0)
{
NBase::dfPoint point;
point.x0 = x;
point.y0 = y;
IntersectionsDetail detail{ point, pos, pCurve, pos, pCurve };
localResult.push_back(detail);
}
}
}
#pragma omp critical
{
result.insert(result.end(), localResult.begin(), localResult.end());
}
}
return result;
}
/**
*
* \param pXy CXy
* \param layerName
* \param includeSubLayer
*/
extern "C" __declspec(dllexport)
BSTR XyStatiscCurveCrossPoints(CXy* pXy, LPCTSTR layerName, bool includeSubLayer)
{
if (pXy == nullptr || layerName == nullptr)
{
TRACE("pXy 和 layerName 不能为 nullptr\n");
return CString().AllocSysString();
}
auto curves = FetchCurves(*pXy, CString(layerName), includeSubLayer);
auto data = FindIntersections(curves);
return ResourceCommentToXml(data).AllocSysString();
}
/**
* 线
*
* \param name 线
* \param x x
* \param y y
* \param width
* \return 线
*/
static std::unique_ptr<CCurveEx> CreateCenterSquareCurve(const CString &name, double centerX, double centerY, double width)
{
auto pCurve = std::make_unique<CCurveEx>();
pCurve->Create(5);
double halfWidth = width / 2.0;
const std::array<std::pair<double, double>, 5> points = { {
{centerX - halfWidth, centerY + halfWidth}, // 左上
{centerX + halfWidth, centerY + halfWidth}, // 右上
{centerX + halfWidth, centerY - halfWidth}, // 右下
{centerX - halfWidth, centerY - halfWidth}, // 左下
{centerX - halfWidth, centerY + halfWidth}, // 闭合到左上
} };
for (size_t i = 0; i < points.size(); i++)
{
pCurve->x[i] = points[i].first;
pCurve->y[i] = points[i].second;
}
pCurve->SetName(name);
return pCurve;
}
/**
* 线
*
* \param name
* \param rect
* \return
*/
inline std::unique_ptr<CCurveEx> CreateRectCurve(const CString& name, const NBase::CRect8& rect)
{
auto pCurve = std::make_unique<CCurveEx>();
pCurve->Create(5);
const std::array<std::pair<double, double>, 5> points = { {
{rect.left, rect.top}, // 左上
{rect.right, rect.top}, // 右上
{rect.right, rect.bottom}, // 右下
{rect.left, rect.bottom}, // 左下
{rect.left, rect.top}, // 闭合到左上
} };
for (size_t i = 0; i < points.size(); i++)
{
pCurve->x[i] = points[i].first;
pCurve->y[i] = points[i].second;
}
pCurve->SetName(name);
return pCurve;
}
/**
* 线
*
* \param pXy
* \param layerName
* \param includeSubLayer
* \return
*/
std::vector<NBase::CRect8> CreateRects(std::vector<IntersectionsDetail>& data, double width)
{
std::vector<NBase::CRect8> rects;
for (size_t i = 0; i < data.size(); i++)
{
IntersectionsDetail& detail = data[i];
double x = detail.point.x0;
double y = detail.point.y0;
double halfWidth = width / 2.0;
NBase::CRect8 rect(
x - halfWidth,
y + halfWidth,
x + halfWidth,
y - halfWidth
);
rects.push_back(rect);
}
return rects;
}
extern "C" __declspec(dllexport)
void MarkCurveIntersectionsWithSquares(CSigmaView* pView, LPCTSTR layerName, bool includeSubLayer)
{
const CString crossLayerName = "交点";
if (pView == nullptr)
{
TRACE("pView 不能为 nullptr\n");
return;
}
CXy* pXy = pView->m_pDoc->m_pXy;
NBase::CRect8 range(1e100, -1e100, -1e100, 1e100);
pXy->GetRange(range);
// TODO: 交点框宽度,这里要换成一个更加合适的值
double width = range.Width() / 100.0;
if (width < 1)
{
width = 1;
}
// 计算交点
std::vector<CurveRangeDetail> curves = FetchCurves(*pXy, CString(layerName), includeSubLayer);
std::vector<IntersectionsDetail> data = FindIntersections2(curves);
std::vector<IntersectionsDetail> data2 = FindIntersectionsSelf(curves);
data.insert(data.end(), data2.begin(), data2.end());
// 使用 ActionTypeLayerAdd确保上层在撤消的时候会重新加载图层
auto pAction = std::make_unique<CActionListItem>(pView->m_pDoc, ActionType::ActionTypeLayerAdd);
// 这么做是为了用户再次点击交点检测时,直接清理掉前一次的结果
pXy->RemoveLayer(crossLayerName);
// 添加图层
CString curLayerName = pXy->GetCurrentLayer()->GetPathName();
CLayer *pCrossLayer = pXy->FindLayer(crossLayerName);
if (pCrossLayer == nullptr)
{
pCrossLayer = pXy->FindAddLayer(crossLayerName);
if (pCrossLayer == nullptr)
{
TRACE("创建交点图层失败\n");
return;
}
pAction->AddLayerAddItem(pCrossLayer, curLayerName);
}
std::vector<NBase::CRect8> rects = CreateRects(data, width);
std::vector<NBase::CRect8> mergedRects = MergeRects(rects);
// 创建交点标记
NBase::CPositionList insertedPositions;
// 创建圈出交点的正方形
for (size_t i = 0; i < mergedRects.size(); i++)
{
const NBase::CRect8& rect = mergedRects[i];
CString name;
name.Format("%lu", i + 1);
auto pCurve = CreateRectCurve(name, rect);
// 创建 COne
auto pOne = std::make_unique<COne>();
pOne->SetColor(0);
pOne->SetValueSafe(pCurve.release());
pOne->SetLayer(pCrossLayer);
POSITION pos = pXy->AddTailOne(pOne.release());
insertedPositions.AddTail(pos);
}
pAction->AddAddItem(insertedPositions);
pView->m_pDoc->SetActionItem(pAction.release());
}
/**
*
* \param pXy CXy
* \param layerName
* \param includeSubLayer
*/
extern "C" __declspec(dllexport)
BSTR StatiscCurveCrossPoints(CSigmaView* pView, LPCTSTR layerName, bool includeSubLayer)
{
return XyStatiscCurveCrossPoints(pView->m_pDoc->GetDraw(), layerName, includeSubLayer);
}
extern std::unique_ptr<CCurveEx> CreateCurveFromXyMesh(CXy& xy, double x1, double y1, double x2, double y2);
/**
* 线使 z 线 z
*
* \param pView
* \param layerName
* \param x1 x
* \param y1 y
* \param x2 x
* \param y2 y
* \return
*/
extern "C" __declspec(dllexport)
bool CreateCurveFillZ(CSigmaView* pView, LPCTSTR layerName, double x1, double y1, double x2, double y2)
{
if (pView == nullptr || pView->m_pDoc == nullptr || pView->m_pDoc->m_pXy == nullptr)
{
TRACE("pView pView->m_pDoc pView->m_pDoc->m_Xy 都不能为 null\n");
return false;
}
if (layerName == nullptr)
{
TRACE("layerName 不能为 nullptr\n");
return false;
}
CXy& xy = *(pView->m_pDoc->m_pXy);
std::unique_ptr<CCurveEx> pCurve = CreateCurveFromXyMesh(xy, x1, y1, x2, y2);
if (!pCurve)
{
TRACE("未找到空间位置匹配的网格\n");
return false;
}
auto pAction = std::make_unique<CActionComboItem>();
bool bCreateNew = false;
CLayer* pLayer = xy.FindAddLayer(CString(layerName), &bCreateNew);
if (bCreateNew)
{
CString strCurrentLayerName = xy.GetCurrentLayer()->GetPathName();
auto pActionAddLayer = std::make_unique<CActionLayerAddItem>(pView->m_pDoc, pLayer, strCurrentLayerName);
pAction->AddAction(pActionAddLayer.release());
}
auto pOne = std::make_unique<COne>();
auto* pRawOne = pOne.get();
pOne->SetLayer(pLayer);
pOne->SetValueSafe(pCurve.release());
xy.AddTailOne(pRawOne);
auto pActionAdd = std::make_unique<CActionAddItem>(pView->m_pDoc, IDS_STRING_ACTION_ADD, pRawOne);
pOne.release();
pAction->AddAction(pActionAdd.release());
pView->m_pDoc->SetActionItem(pAction.release());
return true;
}