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++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "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;
CLayer *pLayer = pXy.FindLayer(layerName);
pXy.GetElement(pLayer, select, DOUBLEFOX_CURVE, includeSubLayer);
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;
}