#include "StdAfx.h" #include "SigmaView.h" #include "sigmadoc.h" #include "ActionSortItem.h" #include ".\actionembellishitem.h" #include #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 #include #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 RTree2D; typedef RectTemplate 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 (!(z0zmax)) // 当该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 0) { TracePaths(result); } } } // 统计多边形关系 void StatisPolygonRelation(CSigmaView* pView, const CList& lstPolygons, TiXmlElement *rootElement) { vector< PathD> blocks; vector 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 subNames; vector 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 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 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 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 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(); 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 GetLayerMarkNames(CHowToViewPoint* pHowToViewPoint, CHowToViewCurve* pHowToViewCurve) { std::vector 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(pView)) { result.push_back(pArrow->MarkName); } else if (auto* pScale = dynamic_cast(pView)) { result.push_back(pScale->MarkName); } else if (auto* pTwoMark = dynamic_cast(pView)) { result.push_back(pTwoMark->MarkName); } else if (auto* pRgn = dynamic_cast(pView)) { result.push_back(pRgn->MarkName); } } } return result; } static void GetCXyMark(CXy* pXy, const std::vector& 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 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(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 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 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(num); lstPos.AddTail((POSITION)pVoid); } if (pView->m_pDoc == NULL) { return 0; } vector 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 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 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 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 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 flts;// = CollectFlts(pBlock); // // // 区域内点 // std::vector wells; // vector 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 results; // auto voronoiMap = std::make_unique(); // 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 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 contours, flts; vector 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 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 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 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 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 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 selectWells; if (childNode) { pXy->GetElement(layerName, selectWells, TRUE); } else pXy->GetElement(layerName, selectWells, FALSE); if (selectWells.IsEmpty()) { return 0; } // 获得所有的边界 std::vector vecBorder; CList 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> 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> faultSegments; RTree2D faultTree; if (faultLayer && faultLayer[0] != _T('\0')) { CList 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&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> 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& 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 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::max(); int resultSeg = -1; for (auto segID : order) { tuple& 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& 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(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 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>& 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 GetNameAndFid(const std::string& str) { std::pair pair; std::vector 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(decimal_degrees); double fractional = (decimal_degrees - dms.degrees) * 60; dms.minutes = static_cast(fractional); dms.seconds = (fractional - dms.minutes) * 60; return dms; } // 函数定义:格式化 DMS 结构体为字符串表示 // 注意:客户习惯和一般书面表示不一样,他们习惯前面不带度、分、秒这样的符号,分和秒不足两位前面补0,并且最后的小数只保存三位 // 比如 112°6′54″.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> 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 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 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 ones; std::vector 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 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 GetCrossPoint(CCurveEx& curve1, CCurveEx& curve2) { // 求交点,返回的交点里面存储的是桩号 CCrossList crossList; curve1.Cross(curve2, crossList); if (crossList.IsEmpty()) { return {}; } std::vector 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 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 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(); NBase::CRect8 range(1e100, -1e100, -1e100, 1e100); pCurve->GetRange(range); curves.push_back({ pt, pCurve, range }); } return curves; } // 计算交点 static std::vector> FindIntersections(const std::vector& curves) { std::vector> 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 crossPoints = GetCrossPoint(*pCurve1, *pCurve2); for (const auto& crossPoint : crossPoints) { std::map 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 FindIntersections2(const std::vector& curvesDetails) { std::vector 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 localResult; for (int32_t j = i + 1; j < count; j++) { // 先判断包围盒是否相交 if (!IsIntersecting(pData[i].range, pData[j].range)) { continue; } std::vector 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 FindIntersectionsSelf(const std::vector& curvesDetails) { std::vector 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 pNewCurve = DeduplicateCurvePoints(*curvesDetails[i].pCurve); std::vector 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 CreateCenterSquareCurve(const CString &name, double centerX, double centerY, double width) { auto pCurve = std::make_unique(); pCurve->Create(5); double halfWidth = width / 2.0; const std::array, 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 CreateRectCurve(const CString& name, const NBase::CRect8& rect) { auto pCurve = std::make_unique(); pCurve->Create(5); const std::array, 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 CreateRects(std::vector& data, double width) { std::vector 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 curves = FetchCurves(*pXy, CString(layerName), includeSubLayer); std::vector data = FindIntersections2(curves); std::vector data2 = FindIntersectionsSelf(curves); data.insert(data.end(), data2.begin(), data2.end()); // 使用 ActionTypeLayerAdd,确保上层在撤消的时候会重新加载图层 auto pAction = std::make_unique(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 rects = CreateRects(data, width); std::vector 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(); 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 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 pCurve = CreateCurveFromXyMesh(xy, x1, y1, x2, y2); if (!pCurve) { TRACE("未找到空间位置匹配的网格\n"); return false; } auto pAction = std::make_unique(); bool bCreateNew = false; CLayer* pLayer = xy.FindAddLayer(CString(layerName), &bCreateNew); if (bCreateNew) { CString strCurrentLayerName = xy.GetCurrentLayer()->GetPathName(); auto pActionAddLayer = std::make_unique(pView->m_pDoc, pLayer, strCurrentLayerName); pAction->AddAction(pActionAddLayer.release()); } auto pOne = std::make_unique(); auto* pRawOne = pOne.get(); pOne->SetLayer(pLayer); pOne->SetValueSafe(pCurve.release()); xy.AddTailOne(pRawOne); auto pActionAdd = std::make_unique(pView->m_pDoc, IDS_STRING_ACTION_ADD, pRawOne); pOne.release(); pAction->AddAction(pActionAdd.release()); pView->m_pDoc->SetActionItem(pAction.release()); return true; }