|
|
#include "stdafx.h"
|
|
|
#include <stack>
|
|
|
#include <random>
|
|
|
#include "DrawOperator/XyIO.h"
|
|
|
#include "TinyXml/tinyxml.h"
|
|
|
#include "ActionDeleteItem.h"
|
|
|
#include "DrawOperator/Net.h"
|
|
|
#include "DrawOperator/LibraryManager.h"
|
|
|
#include "DrawOperator\FileUtility.h"
|
|
|
#include "DrawOperator/unordered_dense.h"
|
|
|
#include "DrawOperator\MergePDFFile.h"
|
|
|
#include "Util.h"
|
|
|
#include "Legend.h"
|
|
|
#include "UndecidedZone.h"
|
|
|
|
|
|
void XyDeSerialize(CXy* pXy, CArchive& ar);
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void* XyCreate() {
|
|
|
CXy* pXy = new CXy;
|
|
|
AfxGetPublicFunction()->EnableJudgeRange(TRUE);
|
|
|
return pXy;
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool DestroyXy(CXy* pXy)
|
|
|
{
|
|
|
if (pXy != nullptr)
|
|
|
{
|
|
|
delete pXy;
|
|
|
pXy = nullptr;
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyOpenFile(CXy* pXy, LPCTSTR lpszFileName, bool realTimeDraw)
|
|
|
{
|
|
|
if (pXy != NULL) {
|
|
|
pXy->Clear();
|
|
|
}
|
|
|
else {
|
|
|
pXy = new CXy;
|
|
|
}
|
|
|
return pXy->OpenFile(lpszFileName, realTimeDraw);
|
|
|
//pXy->m_bRealTimeDraw = realTimeDraw;
|
|
|
//if (pXy->ReadOtherWithExtension(lpszFileName))
|
|
|
//{
|
|
|
// return TRUE;
|
|
|
//}
|
|
|
//CString path(lpszFileName);
|
|
|
//CString tempFileName = PreprocessFile(path);
|
|
|
//if (tempFileName.IsEmpty())
|
|
|
//{
|
|
|
// return FALSE;
|
|
|
//}
|
|
|
|
|
|
//CFile file;
|
|
|
//if (file.Open(tempFileName, CFile::modeRead))
|
|
|
//{
|
|
|
// CArchive ar(&file, CArchive::load);
|
|
|
// XyDeSerialize(pXy, ar);
|
|
|
// ar.Close();
|
|
|
// file.Close();
|
|
|
//}
|
|
|
//CFileStatus status;
|
|
|
//// 注意:如果 tempFileName 和 path 相同,说明原文件没有加密,这时的 tempFileName 就是原文件的路径,不能删除
|
|
|
//if (CFile::GetStatus(tempFileName, status) && tempFileName != path)
|
|
|
//{
|
|
|
// CFile::Remove(tempFileName);
|
|
|
//}
|
|
|
//return TRUE;
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyDrawFile(CXy* pXy, HDC hdcMem, int left, int top, int width, int height)
|
|
|
{
|
|
|
CRect client;
|
|
|
client.left = left;
|
|
|
client.bottom = top;
|
|
|
client.top = height + top;
|
|
|
client.right = width + left;
|
|
|
|
|
|
CRect8 rect(1e100, -1e100, -1e100, 1e100);
|
|
|
if (pXy->GetCount() > 0)
|
|
|
{
|
|
|
pXy->GetRange(rect);
|
|
|
pXy->m_range = rect;
|
|
|
}
|
|
|
else {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
CDC* pDC = CDC::FromHandle(hdcMem);
|
|
|
CXyDC m_xyDC;
|
|
|
m_xyDC.Create(pDC);
|
|
|
|
|
|
// m_xyDC.SetViewRect(client); 629612432
|
|
|
m_xyDC.Extend(rect, client, EXTEND_MODE_CENTER);
|
|
|
pXy->Draw(m_xyDC, false);
|
|
|
return true;
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyEnableMeshPackage(CXy* pXy, bool enable) {
|
|
|
pXy->EnableMeshPackage(enable);
|
|
|
}
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
// 从内存块读取数据生成图片
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
extern "C" __declspec(dllexport)
|
|
|
HBITMAP GetBitmap(CXy* pXy, int width, int height, int inflate)
|
|
|
{
|
|
|
if (pXy == NULL)
|
|
|
return FALSE;
|
|
|
|
|
|
CDC dc; dc.CreateCompatibleDC(NULL);
|
|
|
CXyDC pDC;
|
|
|
pDC.Create(&dc, false);
|
|
|
//pDC.SetAntiAlias(true);
|
|
|
|
|
|
CSize sz(width, height);
|
|
|
CRect rt(0, 0, width, height);
|
|
|
|
|
|
int planes = dc.GetDeviceCaps(PLANES);
|
|
|
int bpp = dc.GetDeviceCaps(BITSPIXEL);
|
|
|
|
|
|
CBitmap* pBitmap, * pOldBitmap;
|
|
|
pBitmap = new CBitmap();
|
|
|
pBitmap->CreateBitmap(sz.cx, sz.cy, planes, bpp, NULL);
|
|
|
pOldBitmap = dc.SelectObject(pBitmap);
|
|
|
|
|
|
dc.FillSolidRect(0, 0, sz.cx, sz.cy, RGB(255, 255, 255));
|
|
|
|
|
|
CRect8 rect(1e100, -1e100, -1e100, 1e100);
|
|
|
if (pXy->GetCount() > 0)
|
|
|
{
|
|
|
pXy->GetRange(rect);
|
|
|
pXy->m_range = rect;
|
|
|
rt.InflateRect(-inflate, -inflate, -inflate, -inflate);
|
|
|
pDC.Extend(rect, rt, EXTEND_MODE_CENTER);
|
|
|
pDC.SetViewRect(rt);
|
|
|
pXy->Draw(pDC);
|
|
|
}
|
|
|
dc.SelectObject(pOldBitmap);
|
|
|
|
|
|
HBITMAP hBit = (HBITMAP)pBitmap->Detach();
|
|
|
|
|
|
pBitmap->DeleteObject();
|
|
|
dc.DeleteDC();
|
|
|
delete pBitmap;
|
|
|
|
|
|
return hBit;
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool GetMapSize(CXy* pXy, double& xMin, double& yMin, double& xMax, double& yMax)
|
|
|
{
|
|
|
CRect8 rect(1e100, -1e100, -1e100, 1e100);
|
|
|
pXy->GetRange(rect, false);
|
|
|
xMin = rect.left;
|
|
|
yMin = rect.bottom;
|
|
|
xMax = rect.right;
|
|
|
yMax = rect.top;
|
|
|
return true;
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void DeleteHBITMAP(HBITMAP hBmp)
|
|
|
{
|
|
|
DeleteObject(hBmp);
|
|
|
}
|
|
|
|
|
|
void XyDeSerialize(CXy* pXy, CArchive& ar)
|
|
|
{
|
|
|
//CPublicFunction& pf = *AfxGetPublicFunction();
|
|
|
|
|
|
if (pXy == NULL) pXy = new CXy;
|
|
|
//BeginProgress(IDS_STRING_OpenFile);
|
|
|
|
|
|
CString name = ar.GetFile()->GetFileName();
|
|
|
name.MakeLower();
|
|
|
CSplitPath sp(name);
|
|
|
|
|
|
CString ext = sp.GetExtension();
|
|
|
//ar.m_pDocument = this; // set back-pointer in archive
|
|
|
if (ext == _T(".dfb") ||
|
|
|
ext == _T(".dft"))
|
|
|
{
|
|
|
pXy->m_version = pXy->DFB_ReadVersion(ar);
|
|
|
pXy->DFB_ReadEncrypt(ar, pXy->m_version);
|
|
|
if (pXy->IsEncrypted())
|
|
|
{
|
|
|
//if (!VerifyPassword(GetDraw()))
|
|
|
//{
|
|
|
// m_bCancelRead = TRUE;
|
|
|
// EndProgress();
|
|
|
// return;
|
|
|
//}
|
|
|
}
|
|
|
pXy->DFB_Serialize(ar, pXy->m_version);
|
|
|
}
|
|
|
else if (ext == ".dml" || ext == ".xml")
|
|
|
pXy->DML_Read2(*(ar.GetFile()));
|
|
|
else if (ext == ".pcg")
|
|
|
pXy->PCG_Read2(*(ar.GetFile()));
|
|
|
else
|
|
|
pXy->DFD_Read2(*(ar.GetFile()));
|
|
|
//// 断层边缘补丁
|
|
|
//m_pXy->CreateMeshPackage();
|
|
|
|
|
|
//EndProgress();
|
|
|
}
|
|
|
|
|
|
bool XySerialize(CXy* pXy, CArchive& ar, int docTypeID,int version=-1)
|
|
|
{
|
|
|
short ver = version;
|
|
|
switch (docTypeID)
|
|
|
{
|
|
|
default: //当前缺省版本
|
|
|
pXy->DFD_Write2(*(ar.GetFile()), ver, TRUE);
|
|
|
break;
|
|
|
case DF_FORMAT_DFT: //双狐模板格式
|
|
|
case DF_FORMAT_BINARY: //双狐二进制格式
|
|
|
pXy->DFB_SerializeWrite(ar, ver, TRUE);
|
|
|
break;
|
|
|
case DF_FORMAT_DML:
|
|
|
pXy->DML_WriteAll(*(ar.GetFile()), ver, TRUE);
|
|
|
break;
|
|
|
case DF_FORMAT_PCG:
|
|
|
pXy->PCG_WriteAll(*(ar.GetFile()), 2, TRUE);
|
|
|
break;
|
|
|
case DF_FORMAT_OLD_ASCII: //老版本-不再写老版本
|
|
|
//pXy->DFD_Write2(*(ar.GetFile()), 2004, TRUE);
|
|
|
pXy->DFD_Write2(*(ar.GetFile()), ver, TRUE);
|
|
|
break;
|
|
|
case DF_FORMAT_DXF:
|
|
|
//pxy->ToDxf(&GetDC(), *(ar.GetFile()));
|
|
|
//xy.ToDxf(&GetDC(), *(ar.GetFile()));
|
|
|
break;
|
|
|
case DF_FORMAT_CGM:
|
|
|
//pf.SetExportDPI(::GetPreferences().WorkaroundSave.m_nExportModeDPI, ::GetPreferences().WorkaroundSave.m_dExportDPI);
|
|
|
//pxy->ToCgm(&GetDC(), *(ar.GetFile()));
|
|
|
//xy.ToCgm(&GetDC(), *(ar.GetFile()));
|
|
|
break;
|
|
|
case DF_FORMAT_EPS:
|
|
|
//pf.SetExportDPI(::GetPreferences().WorkaroundSave.m_nExportModeDPI, ::GetPreferences().WorkaroundSave.m_dExportDPI);
|
|
|
//pxy->ToEps(&GetDC(), *(ar.GetFile()));
|
|
|
//xy.ToEps(&GetDC(), *(ar.GetFile()));
|
|
|
break;
|
|
|
case DF_FORMAT_PDF:
|
|
|
//pf.SetExportDPI(::GetPreferences().WorkaroundSave.m_nExportModeDPI, ::GetPreferences().WorkaroundSave.m_dExportDPI);
|
|
|
//pxy->ToPdf(&GetDC(), *(ar.GetFile()));
|
|
|
//xy.ToPdf(&GetDC(), *(ar.GetFile()));
|
|
|
break;
|
|
|
case DF_FORMAT_UMAP_ASC:
|
|
|
//pxy->ToUmap(&GetDC(), *(ar.GetFile()));
|
|
|
//xy.ToUmap(&GetDC(), *(ar.GetFile()));
|
|
|
break;
|
|
|
case DF_FORMAT_MAPGIS_W:
|
|
|
//pxy->ToMapGisAsc(&GetDC(), *(ar.GetFile()), FALSE);
|
|
|
//xy.ToMapGisAsc(&GetDC(), *(ar.GetFile()), FALSE);
|
|
|
break;
|
|
|
case DF_FORMAT_KML:
|
|
|
//pxy->ToKML(*(ar.GetFile()));
|
|
|
//xy.ToKML(*(ar.GetFile()));
|
|
|
break;
|
|
|
case DF_FORMAT_GEOMAP:
|
|
|
//pxy->ToGeoMap(&GetDC(), *(ar.GetFile()));
|
|
|
//xy.ToGeoMap(&GetDC(), *(ar.GetFile()));
|
|
|
break;
|
|
|
}
|
|
|
return TRUE;
|
|
|
}
|
|
|
// 将图形数据插入到最下层
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyInsertDataBottom(CXy* pXy, BYTE* data, int dataLen, LPCTSTR newLayer) {
|
|
|
CXy* pxyMerge = new CXy;
|
|
|
bool bOpen = pxyMerge->ReadMemory(data, dataLen, 1);
|
|
|
if (bOpen == false) {
|
|
|
delete pxyMerge;
|
|
|
return FALSE;
|
|
|
}
|
|
|
// 全部装入一个新图层
|
|
|
if (strlen(newLayer) != 0)
|
|
|
{
|
|
|
CString strNamePre = newLayer;
|
|
|
strNamePre += "\\";
|
|
|
CClassList* pClassList = pxyMerge->GetClassList();
|
|
|
for (POSITION posClass = pClassList->GetHeadPosition(); posClass != nullptr; pClassList->GetNext(posClass))
|
|
|
{
|
|
|
CLayerList* pLayerList = pClassList->GetAt(posClass);
|
|
|
for (POSITION posLayer = pLayerList->GetHeadPosition(); posLayer != nullptr; pLayerList->GetNext(posLayer))
|
|
|
{
|
|
|
CLayer* pLayer = pLayerList->GetAt(posLayer);
|
|
|
CString strNameOld = pLayer->GetName();
|
|
|
CString strNewName = strNamePre + strNameOld;
|
|
|
pLayer->SetName(strNewName);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!pxyMerge->GetProjection().IsEmpty() && !pXy->GetProjection().IsEmpty())
|
|
|
pxyMerge->ChangeToProjection(pXy->GetProjection());
|
|
|
CPositionList select;
|
|
|
pXy->MoveInBottom(pxyMerge, select);
|
|
|
delete pxyMerge;
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyInsertFileAfter(CXy* pXy, LPCTSTR mergeFile, POSITION pos) {
|
|
|
CXy* pxyMerge = new CXy;
|
|
|
//pxyMerge->m_bRealTimeDraw = FALSE;
|
|
|
bool bOpen = XyOpenFile(pxyMerge, mergeFile, FALSE);
|
|
|
if (bOpen == false) {
|
|
|
delete pxyMerge;
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
if (!pxyMerge->GetProjection().IsEmpty() && !pXy->GetProjection().IsEmpty())
|
|
|
pxyMerge->ChangeToProjection(pXy->GetProjection());
|
|
|
CPositionList select;
|
|
|
pXy->MoveIn(pxyMerge, select, pos, 0, 0, true, true);
|
|
|
delete pxyMerge;
|
|
|
return TRUE;
|
|
|
}
|
|
|
///合并另一个文件
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyMerge(CXy* pXy, LPCTSTR mergeFile)
|
|
|
{
|
|
|
return XyInsertFileAfter(pXy, mergeFile, 0);
|
|
|
//CString name, strExt;
|
|
|
//CSplitPath sp(mergeFile);
|
|
|
//strExt = sp.GetExtension();
|
|
|
//strExt.MakeLower();
|
|
|
//
|
|
|
//CXy* pxyMerge = new CXy;
|
|
|
////pxyMerge->m_bRealTimeDraw = FALSE;
|
|
|
//bool bOpen = XyOpenFile(pxyMerge, mergeFile, FALSE);
|
|
|
//if (bOpen == false) {
|
|
|
// delete mergeFile;
|
|
|
// return FALSE;
|
|
|
//}
|
|
|
|
|
|
//if (!pxyMerge->GetProjection().IsEmpty() && !pXy->GetProjection().IsEmpty())
|
|
|
// pxyMerge->ChangeToProjection(pXy->GetProjection());
|
|
|
//CPositionList select;
|
|
|
//pXy->MoveIn(pxyMerge, select, 0, 0, 0, true, true);
|
|
|
//delete pxyMerge;
|
|
|
//return TRUE;
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XySaveAs(CXy* pxy, LPCTSTR saveFile,int version=-1)
|
|
|
{
|
|
|
CString newName = saveFile;
|
|
|
if (newName.IsEmpty())
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
int docTypeID = 0;
|
|
|
CString ext = AfxGetPublicFunction()->GetSplitPath(newName, "ext");
|
|
|
if (ext.MakeLower() == _T(".xyz")) {
|
|
|
docTypeID = NFormatType::DF_FORMAT_XYZ;
|
|
|
}
|
|
|
else {
|
|
|
CDocType DocType;
|
|
|
docTypeID = DocType.GetIndexFromExt(AfxGetPublicFunction()->GetSplitPath(newName, "ext"));
|
|
|
docTypeID = DocType.GetIDFromIndex(docTypeID);
|
|
|
}
|
|
|
|
|
|
CFile file;
|
|
|
CFileException fileException;
|
|
|
if (file.Open(newName, CFile::modeCreate | CFile::modeWrite, &fileException))
|
|
|
{
|
|
|
if (version < 0) {
|
|
|
version = pxy->m_version;
|
|
|
}
|
|
|
CArchive ar(&file, CArchive::store);
|
|
|
XySerialize(pxy, ar, docTypeID, version);
|
|
|
ar.Close();
|
|
|
file.Close();
|
|
|
PostProcessFile(newName);
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyFindPointByName(CXy* pxy, LPCTSTR eleName, BYTE*& buffElement, int& buffLen)
|
|
|
{
|
|
|
CString strNameFind(eleName);
|
|
|
CPositionList posList;
|
|
|
POSITION posCur = pxy->GetValueList()->GetHeadPosition();
|
|
|
CString name;
|
|
|
COne* pOne;
|
|
|
while (true)
|
|
|
{
|
|
|
pxy->GetValueList()->GetNext(posCur);
|
|
|
if (posCur == 0) {
|
|
|
break;
|
|
|
}
|
|
|
pOne = pxy->GetAt(posCur);
|
|
|
if (pOne->GetType() == DOUBLEFOX_POINT) {
|
|
|
// if(pOne->IsCanEdit())
|
|
|
CPointNameEx* pPoint = (CPointNameEx*)pOne->GetValue();
|
|
|
if (pPoint->GetName() == strNameFind)
|
|
|
{
|
|
|
posList.AddTail(posCur);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
if (posList.GetCount() == 0)
|
|
|
{
|
|
|
buffLen = 0;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
return pxy->WriteMemory(buffElement, buffLen, posList, 3, 0);
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyFindPointByInfo(CXy* pxy, POSITION& posFind
|
|
|
, LPCTSTR elementName, double x, double y, LPCTSTR layerName)
|
|
|
{
|
|
|
posFind = 0;
|
|
|
if (pxy == 0)
|
|
|
{
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
CString strLayerFind(layerName);
|
|
|
POSITION posCur = pxy->GetValueList()->GetHeadPosition();
|
|
|
|
|
|
COne* pOne;
|
|
|
CString name;
|
|
|
CString strlayer;
|
|
|
while (true)
|
|
|
{
|
|
|
pxy->GetValueList()->GetNext(posCur);
|
|
|
if (posCur == 0) {
|
|
|
break;
|
|
|
}
|
|
|
pOne = pxy->GetAt(posCur);
|
|
|
|
|
|
name = pOne->GetName();
|
|
|
if (elementName != name) {
|
|
|
continue;
|
|
|
}
|
|
|
strlayer = pOne->GetLayer()->GetName();
|
|
|
if (strLayerFind.GetLength() > 0 && strLayerFind != strlayer)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
int eleType = pOne->GetType();
|
|
|
if (eleType == DOUBLEFOX_POINT
|
|
|
|| eleType == DOUBLEFOX_XYZ)
|
|
|
{
|
|
|
CPointNameEx* pPoint = (CPointNameEx*)pOne->GetValue();
|
|
|
if (abs(pPoint->x0 - x) > 1E-10 || abs(pPoint->y0 - y) > 1E-10) {
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
|
else if (eleType == DOUBLEFOX_TEXT)
|
|
|
{
|
|
|
CText* pPoint = (CText*)pOne->GetValue();
|
|
|
if (abs(pPoint->x0 - x) > 1E10 && abs(pPoint->y0 - y) > 1E10) {
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
|
posFind = posCur;
|
|
|
break;
|
|
|
}
|
|
|
if (posFind > 0) {
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
BOOL XyGetElementByPosition(CXy* pxy, BYTE*& buffElement, int& buffLen, POSITION elementPtr)
|
|
|
{
|
|
|
if (pxy == 0)
|
|
|
return FALSE;
|
|
|
|
|
|
COne* pOne = (COne*)(pxy->GetAt(elementPtr));
|
|
|
if (pOne == 0)
|
|
|
return FALSE;
|
|
|
|
|
|
if (pOne->GetType() == DOUBLEFOX_MESH) {
|
|
|
((CMesh*)(pOne->value))->WriteElementDML(buffElement, buffLen);
|
|
|
return TRUE;
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_TEXT) {
|
|
|
((CText*)(pOne->value))->color = pOne->color;
|
|
|
return pOne->WriteMemory(buffElement, 0, buffLen, 3);
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_ELLIPSE)
|
|
|
{
|
|
|
((CEllipse*)(pOne->value))->color = pOne->color;
|
|
|
return pOne->WriteMemory(buffElement, 0, buffLen, 3);
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_CIRCLE)
|
|
|
{
|
|
|
((CCircle*)(pOne->value))->color = pOne->color;
|
|
|
return pOne->WriteMemory(buffElement, 0, buffLen, 3);
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_ARC)
|
|
|
{
|
|
|
((CArc*)(pOne->value))->color = pOne->color;
|
|
|
return pOne->WriteMemory(buffElement, 0, buffLen, 3);
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_SCALERULER)
|
|
|
{
|
|
|
((CScaleRuler*)(pOne->value))->color = pOne->color;
|
|
|
return pOne->WriteMemory(buffElement, 0, buffLen, 3);
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_PROPORTION)
|
|
|
{
|
|
|
((CProportion*)(pOne->value))->color = pOne->color;
|
|
|
return pOne->WriteMemory(buffElement, 0, buffLen, 3);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return pOne->WriteMemory(buffElement, 0, buffLen, 3);
|
|
|
}
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
BOOL XySetElement(CXy* pxy, BYTE* buffElement, int buffLen, POSITION elementPtr)
|
|
|
{
|
|
|
BOOL bEdited = FALSE;
|
|
|
POSITION pos;
|
|
|
pos = (POSITION)elementPtr;
|
|
|
COne* pOne = (COne*)(pxy->GetAt(pos));
|
|
|
|
|
|
if (pOne->GetType() == DOUBLEFOX_SECTION) {
|
|
|
((CSection*)(pOne->value))->ReadElementDML(buffElement, -1, buffLen);
|
|
|
bEdited = true;
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_MESH) {
|
|
|
CMesh* pMesh = (CMesh*)(pOne->value);
|
|
|
pMesh->m_bRealTimeDraw = false;
|
|
|
pMesh->ReadElementDML(buffElement, -1, buffLen);
|
|
|
|
|
|
pMesh->SetM(pMesh->m_pRuler->zmin, pMesh->m_pRuler->zmax);
|
|
|
pMesh->GetBitmap();
|
|
|
bEdited = true;
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_TEXT) {
|
|
|
pOne->ReadMemory(buffElement, -1, buffLen, 3);
|
|
|
CText* pText = (CText*)(pOne->value);
|
|
|
pText->color = pOne->color;
|
|
|
bEdited = true;
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_ELLIPSE)
|
|
|
{
|
|
|
pOne->ReadMemory(buffElement, 0, buffLen, 3);
|
|
|
((CEllipse*)(pOne->value))->color = pOne->color;
|
|
|
bEdited = true;
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_CIRCLE)
|
|
|
{
|
|
|
pOne->ReadMemory(buffElement, 0, buffLen, 3);
|
|
|
((CCircle*)(pOne->value))->color = pOne->color;
|
|
|
bEdited = true;
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_ARC)
|
|
|
{
|
|
|
pOne->ReadMemory(buffElement, 0, buffLen, 3);
|
|
|
((CArc*)(pOne->value))->color = pOne->color;
|
|
|
TRACE(_T("CArc Width:"), ((CArc*)(pOne->value))->m_dCurveWidth);
|
|
|
bEdited = true;
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_PROPORTION)
|
|
|
{
|
|
|
pOne->ReadMemory(buffElement, 0, buffLen, 3);
|
|
|
((CProportion*)(pOne->value))->color = pOne->color;
|
|
|
bEdited = true;
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_SCALERULER)
|
|
|
{
|
|
|
pOne->ReadMemory(buffElement, 0, buffLen, 3);
|
|
|
((CScaleRuler*)(pOne->value))->color = pOne->color;
|
|
|
bEdited = true;
|
|
|
}
|
|
|
else if (pOne->GetType() == DOUBLEFOX_CURVE)
|
|
|
{
|
|
|
CHowToViewCurve* pHWCOld = pOne->HowToViewCurve;
|
|
|
if (pHWCOld != NULL)
|
|
|
{
|
|
|
pHWCOld->Empty();
|
|
|
}
|
|
|
pOne->ReadMemory(buffElement, 0, buffLen, 3);
|
|
|
|
|
|
bEdited = true;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (pOne->HowToViewCurve != NULL)
|
|
|
{
|
|
|
pOne->HowToViewCurve->Empty();
|
|
|
}
|
|
|
pOne->ReadMemory(buffElement, -1, buffLen, 3);
|
|
|
bEdited = true;
|
|
|
}
|
|
|
|
|
|
return bEdited;
|
|
|
}
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
int XyDeleteLayerElement(CXy* pxy, LPCTSTR layerName, BOOL childNode) {
|
|
|
CList<POSITION, POSITION> select;
|
|
|
if (childNode)
|
|
|
{
|
|
|
pxy->GetElement(layerName, select, TRUE);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pxy->GetElement(layerName, select, FALSE);
|
|
|
}
|
|
|
if (select.IsEmpty())
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
POSITION pos = select.GetHeadPosition();
|
|
|
POSITION pt;
|
|
|
while (pos)
|
|
|
{
|
|
|
pt = select.GetNext(pos);
|
|
|
pxy->RemoveAt(pt);
|
|
|
}
|
|
|
|
|
|
return select.GetCount();
|
|
|
}
|
|
|
/**
|
|
|
* 添加图层
|
|
|
*
|
|
|
* \param pXy 图件对象
|
|
|
* \param layerName 图层名
|
|
|
* \return 成功、失败,如果相同层名已经存在,将不会创建新的图层,并返回成功
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyAddLayer(CXy* pXy, LPCTSTR layerName)
|
|
|
{
|
|
|
return pXy->FindAddLayer(layerName) != nullptr;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 统计边框数量
|
|
|
*
|
|
|
* \param pXy 图件对象
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
int XyBorderCount(CXy* pXy)
|
|
|
{
|
|
|
CPositionList select;
|
|
|
return pXy->GetElement(DOUBLEFOX_GRID, select);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取图元范围
|
|
|
*
|
|
|
* \param pXy 图件
|
|
|
* \param pos 图元的 position
|
|
|
* \param left
|
|
|
* \param top
|
|
|
* \param right
|
|
|
* \param bottom
|
|
|
* \return 成功,失败
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyGetRange(CXy* pXy, POSITION pos, double* left, double* top, double* right, double* bottom)
|
|
|
{
|
|
|
if (pXy == nullptr || pos == nullptr)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
COne* pOne = pXy->GetAt(pos);
|
|
|
if (pOne == nullptr)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
CRect8 range = pOne->GetRect();
|
|
|
*left = range.left;
|
|
|
*right = range.right;
|
|
|
*top = range.top;
|
|
|
*bottom = range.bottom;
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyGetElementsRange(CXy* pXy, POSITION* posArray, int elementCount, double* minX, double* minY, double* maxX, double* maxY)
|
|
|
{
|
|
|
CRect8 range(1e100, -1e100, -1e100, 1e100);
|
|
|
for (int i = 0; i < elementCount; i++)
|
|
|
{
|
|
|
COne* pOne = pXy->GetAt(posArray[i]);
|
|
|
pOne->GetRange(range);
|
|
|
}
|
|
|
*minX = range.left;
|
|
|
*minY = range.bottom;
|
|
|
*maxX = range.right;
|
|
|
*maxY = range.top;
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 给图件添加默认边框
|
|
|
*
|
|
|
* \param pXy 图件对象
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyCreateDefaultBorder(CXy* pXy)
|
|
|
{
|
|
|
CLayer* pLayer = pXy->FindAddLayer("坐标框");
|
|
|
|
|
|
double nan = std::numeric_limits<double>::quiet_NaN();
|
|
|
double minX = nan;
|
|
|
double minY = nan;
|
|
|
double maxX = nan;
|
|
|
double maxY = nan;
|
|
|
|
|
|
CPtrList* value = pXy->GetValueList();
|
|
|
for (POSITION pos = value->GetHeadPosition(); pos != nullptr; value->GetNext(pos))
|
|
|
{
|
|
|
COne* pOne = (COne*)value->GetAt(pos);
|
|
|
|
|
|
if (!pOne->GetLayer()->IsViewAndEdit())
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
CRect8 range = pOne->GetRect();
|
|
|
|
|
|
if (std::isnan(minX))
|
|
|
{
|
|
|
minX = range.left;
|
|
|
maxX = range.right;
|
|
|
minY = range.bottom;
|
|
|
maxY = range.top;
|
|
|
}
|
|
|
|
|
|
if (range.left < minX)
|
|
|
{
|
|
|
minX = range.left;
|
|
|
}
|
|
|
|
|
|
if (range.right > maxX)
|
|
|
{
|
|
|
maxX = range.right;
|
|
|
}
|
|
|
|
|
|
if (range.top > maxY)
|
|
|
{
|
|
|
maxY = range.top;
|
|
|
}
|
|
|
|
|
|
if (range.bottom < minY)
|
|
|
{
|
|
|
minY = range.bottom;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
TRACE("minX = %lf, maxX = %lf, minY = %lf, maxY = %lf\n", minX, maxX, minY, maxY);
|
|
|
|
|
|
CGridding* pGrid = new CGridding;
|
|
|
pGrid->m_step.SetSize(1000, 10);
|
|
|
//自动根据单位设置文字大小
|
|
|
//step=GetDoc()->GetCurrentUnitScale();
|
|
|
pGrid->ScaleProperty(1000, 1000);
|
|
|
pGrid->SetRect(minX, minY, maxX, maxY);
|
|
|
pGrid->SetProjection(&(pXy->m_ExchangeXYZ));
|
|
|
pGrid->SetDisplayMode(CNet::showNull);
|
|
|
|
|
|
POSITION pos = pXy->AddElement(pGrid, DOUBLEFOX_GRID);
|
|
|
//pXy->SetElementColor(pos, color);
|
|
|
|
|
|
COne* pOne = pXy->GetAt(pos);
|
|
|
pOne->SetLayer(pLayer);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据条件筛选获取图元
|
|
|
*
|
|
|
* \param pXy
|
|
|
* \param filter 筛选条件
|
|
|
* \return 以 "," 分割的 position 字符串
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
BSTR XyGetElementByFilter(CXy* pXy, string filter)
|
|
|
{
|
|
|
return CString("").AllocSysString();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 修改网格 z 有效范围
|
|
|
* \param pXy
|
|
|
* \param minZValue 范围最小 z 值
|
|
|
* \param maxZValue 范围最大 z 值
|
|
|
* \param mode 1 无效化,2 抹平
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyMapMeshValueRange(CXy* pXy, double minZValue, double maxZValue, int mode)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 将网格 z 值小于 0 的设置为 0
|
|
|
POSITION meshPos = pXy->FindFirstElement(DOUBLEFOX_MESH);
|
|
|
if (meshPos == nullptr)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
COne* pOne = pXy->GetAt(meshPos);
|
|
|
CMesh* pMesh = (CMesh*)(pOne->GetValue());
|
|
|
|
|
|
pMesh->SetM(minZValue, maxZValue);
|
|
|
|
|
|
CDimension3D* pDfg = pMesh->GetDfg();
|
|
|
|
|
|
long numx = 0;
|
|
|
long numy = 0;
|
|
|
pMesh->GetNumber(numx, numy);
|
|
|
|
|
|
int nIndexZ = 0;
|
|
|
if (pMesh->GetMeshType() == MESH_FXY && pDfg->n >= 3)
|
|
|
{
|
|
|
nIndexZ = pMesh->m_nFxyIndexZ;
|
|
|
}
|
|
|
|
|
|
const double invalidZ = -1E300;
|
|
|
|
|
|
#pragma omp parallel for
|
|
|
for (long x = 0; x < numx; x++)
|
|
|
{
|
|
|
for (long y = 0; y < numy; y++)
|
|
|
{
|
|
|
double z = pDfg->Value(x, y, nIndexZ);
|
|
|
|
|
|
if (IsUnvalidValue(z))
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
if (OutOfRange(z, minZValue, maxZValue))
|
|
|
{
|
|
|
if (mode == 1) // 无效性
|
|
|
{
|
|
|
pDfg->SetValue(x, y, invalidZ);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pDfg->SetValue(x, y, Flatten(z, minZValue, maxZValue));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 过滤网格和等值线,将等值线 z 值超出范围的剔除
|
|
|
* \param pXy
|
|
|
* \param outputName 输出的文件名
|
|
|
* \param layerName 等值线所在的图层名,(会包含子层)
|
|
|
* \param minValue 等值线最小 z 值
|
|
|
* \param maxValue 等值线最大 z 值
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyFilterContourLines(CXy* pXy, wchar_t* layerName, double minZValue, double maxZValue)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 将 z 轴小于 minValue 或 小于 maxValue 的等值线剔除掉
|
|
|
NBase::CPositionList selected;
|
|
|
std::vector<COne*> needRemoveCones;
|
|
|
|
|
|
CXyElementFilter filter;
|
|
|
filter.addLayer(CString(layerName), true)
|
|
|
.addType(DOUBLEFOX_CURVE);
|
|
|
|
|
|
pXy->GetElement(filter, selected);
|
|
|
for (POSITION pos = selected.GetHeadPosition(); pos != nullptr; selected.GetNext(pos))
|
|
|
{
|
|
|
POSITION pt = selected.GetAt(pos);
|
|
|
COne* pOne = pXy->GetAt(pt);
|
|
|
|
|
|
CCurveEx* pCurve = (CCurveEx*)pOne->GetValue();
|
|
|
if (pCurve->name == nullptr)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
try
|
|
|
{
|
|
|
double z = std::stod(pCurve->name); // 对于等值线来说,它的名字就是 z 值
|
|
|
|
|
|
if (z < minZValue || z > maxZValue)
|
|
|
{
|
|
|
needRemoveCones.push_back(pOne);
|
|
|
}
|
|
|
}
|
|
|
catch (std::invalid_argument&)
|
|
|
{
|
|
|
// FIXME: 如果它的名字不是数字,暂不处理
|
|
|
}
|
|
|
}
|
|
|
|
|
|
for (COne* pOne : needRemoveCones)
|
|
|
{
|
|
|
pXy->RemoveAt(pOne);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取图件存储的当前显示范围,暂时不提供设置的接口,即使设置了它,用户在画布上操作之后再保存,这个会重新获取
|
|
|
*
|
|
|
* \param pXy
|
|
|
* \param left
|
|
|
* \param top
|
|
|
* \param right
|
|
|
* \param bottom
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyGetDisplay(CXy* pXy, double& left, double& top, double& right, double& bottom)
|
|
|
{
|
|
|
left = pXy->m_display.left;
|
|
|
top = pXy->m_display.top;
|
|
|
right = pXy->m_display.right;
|
|
|
bottom = pXy->m_display.bottom;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取版本号
|
|
|
*
|
|
|
* \param pXy
|
|
|
* \return 版本号
|
|
|
*/
|
|
|
short XyGetVersion(CXy* pXy)
|
|
|
{
|
|
|
return pXy->m_version;
|
|
|
}
|
|
|
|
|
|
static TiXmlElement* CreateSimpleElement(const std::string_view& key, double value)
|
|
|
{
|
|
|
TiXmlElement* childElement = new TiXmlElement(key.data());
|
|
|
std::string str = std::to_string(value);
|
|
|
childElement->LinkEndChild(new TiXmlText(str.data()));
|
|
|
return childElement;
|
|
|
}
|
|
|
|
|
|
static TiXmlElement* CreateSimpleElement(const std::string_view& key, const std::string_view& value)
|
|
|
{
|
|
|
TiXmlElement* childElement = new TiXmlElement(key.data());
|
|
|
childElement->LinkEndChild(new TiXmlText(value.data()));
|
|
|
return childElement;
|
|
|
}
|
|
|
|
|
|
struct MeshMetadata
|
|
|
{
|
|
|
int rows = 0;
|
|
|
int columns = 0;
|
|
|
double minX = 0.0f;
|
|
|
double maxX = 0.0f;
|
|
|
double minY = 0.0f;
|
|
|
double maxY = 0.0f;
|
|
|
double dx = 0.0f;
|
|
|
double dy = 0.0f;
|
|
|
double minZ = 0.0f;
|
|
|
double maxZ = 0.0f;
|
|
|
};
|
|
|
|
|
|
struct MeshPoint
|
|
|
{
|
|
|
double x = 0.0f;
|
|
|
double y = 0.0f;
|
|
|
double z = 0.0f;
|
|
|
};
|
|
|
|
|
|
static TiXmlElement* MetadataToXml(const MeshMetadata& metadata)
|
|
|
{
|
|
|
TiXmlElement* metadataElement = new TiXmlElement("Metadata");
|
|
|
|
|
|
metadataElement->LinkEndChild(CreateSimpleElement("Rows", metadata.rows));
|
|
|
metadataElement->LinkEndChild(CreateSimpleElement("Columns", metadata.columns));
|
|
|
metadataElement->LinkEndChild(CreateSimpleElement("MinX", metadata.minX));
|
|
|
metadataElement->LinkEndChild(CreateSimpleElement("MaxX", metadata.maxX));
|
|
|
metadataElement->LinkEndChild(CreateSimpleElement("MinY", metadata.minY));
|
|
|
metadataElement->LinkEndChild(CreateSimpleElement("MaxY", metadata.maxY));
|
|
|
metadataElement->LinkEndChild(CreateSimpleElement("DX", metadata.dx));
|
|
|
metadataElement->LinkEndChild(CreateSimpleElement("DY", metadata.dy));
|
|
|
|
|
|
return metadataElement;
|
|
|
}
|
|
|
|
|
|
static std::string GridToXml(const MeshMetadata& metadata, const std::vector<std::vector<MeshPoint>>& dataGrid)
|
|
|
{
|
|
|
TiXmlDocument doc;
|
|
|
|
|
|
TiXmlElement* rootElement = new TiXmlElement("Grid");
|
|
|
doc.LinkEndChild(rootElement);
|
|
|
|
|
|
// 创建子元素 <metadata>
|
|
|
TiXmlElement* metadataElement = MetadataToXml(metadata);
|
|
|
rootElement->LinkEndChild(metadataElement);
|
|
|
|
|
|
// 创建坐标元素
|
|
|
TiXmlElement* coordinatesElement = new TiXmlElement("Coordinates");
|
|
|
rootElement->LinkEndChild(coordinatesElement);
|
|
|
|
|
|
std::vector<std::vector<TiXmlElement*>> dataElementGrid(metadata.rows, std::vector<TiXmlElement*>(metadata.columns));
|
|
|
|
|
|
#pragma omp parallel for
|
|
|
for (int i = 0; i < metadata.rows; i++)
|
|
|
{
|
|
|
for (int j = 0; j < metadata.columns; j++)
|
|
|
{
|
|
|
TiXmlElement* dataElement = new TiXmlElement("Data");
|
|
|
dataElement->SetAttribute("Row", i);
|
|
|
dataElement->SetAttribute("Col", j);
|
|
|
const auto& point = dataGrid[i][j];
|
|
|
dataElement->SetAttribute("X", point.x);
|
|
|
dataElement->SetAttribute("Y", point.y);
|
|
|
std::string value = std::to_string(point.z);
|
|
|
|
|
|
dataElement->LinkEndChild(new TiXmlText(value.c_str()));
|
|
|
|
|
|
dataElementGrid[i][j] = dataElement;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < metadata.rows; i++)
|
|
|
{
|
|
|
for (int j = 0; j < metadata.columns; j++)
|
|
|
{
|
|
|
coordinatesElement->LinkEndChild(dataElementGrid[i][j]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
TiXmlPrinter printer;
|
|
|
doc.Accept(&printer);
|
|
|
std::string result = printer.CStr();
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
static CMesh* GetMesh(CXy* pXy)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
CPositionList select;
|
|
|
int nCount = pXy->GetElement(DOUBLEFOX_MESH, select);
|
|
|
if (nCount <= 0)
|
|
|
{
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
return (CMesh*)pXy->GetAtValue(select.GetHead());
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据坐标获取 z 值
|
|
|
* \param pXy
|
|
|
* \param x x坐标
|
|
|
* \param y y坐标
|
|
|
* \param z 出参,z 值
|
|
|
* \param size x y z 两个数组的长度,这两个数组长度必须一致
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyGetMeshZValue(CXy* pXy, double* x, double* y, double* z, int size)
|
|
|
{
|
|
|
CMesh* pMesh = GetMesh(pXy);
|
|
|
if (pMesh == nullptr)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
#pragma omp parallel for
|
|
|
for (int i = 0; i < size; i++)
|
|
|
{
|
|
|
z[i] = pMesh->GetValue(x[i], y[i]);
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 失败时返回的数据,由于是传递的引用过来,所以要用这个设置一下,防止 C# 那边写入脏数据
|
|
|
/// </summary>
|
|
|
/// <param name="metadata">网格元数据</param>
|
|
|
/// <param name="x">x 数组指针</param>
|
|
|
/// <param name="y">y 数组指针</param>
|
|
|
/// <param name="z">z 数组指针</param>
|
|
|
static void SetMetadataToDefault(MeshMetadata& metadata, double** x, double** y, double** z)
|
|
|
{
|
|
|
metadata.rows = 0;
|
|
|
metadata.columns = 0;
|
|
|
*x = nullptr;
|
|
|
*y = nullptr;
|
|
|
*z = nullptr;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 设置网格元数据
|
|
|
*
|
|
|
* \param metadata
|
|
|
* \param pDfg
|
|
|
*/
|
|
|
static void SetMeshMetadata(MeshMetadata& metadata, CDimension2D* pDfg)
|
|
|
{
|
|
|
metadata.rows = pDfg->num[0];
|
|
|
metadata.columns = pDfg->num[1];
|
|
|
metadata.dx = pDfg->delt[0];
|
|
|
metadata.dy = pDfg->delt[1];
|
|
|
metadata.minX = pDfg->xmin();
|
|
|
metadata.maxX = pDfg->xmax();
|
|
|
metadata.minY = pDfg->ymin();
|
|
|
metadata.maxY = pDfg->ymax();
|
|
|
metadata.minZ = pDfg->range[0];
|
|
|
metadata.maxZ = pDfg->range[1];
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取网格数据
|
|
|
* \param pXy
|
|
|
* \return 网格数据的 xml 格式
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyGetMesh(CXy* pXy, MeshMetadata& metadata, double** x, double** y, double** z)
|
|
|
{
|
|
|
CMesh* pMesh = GetMesh(pXy);
|
|
|
if (pMesh == nullptr)
|
|
|
{
|
|
|
SetMetadataToDefault(metadata, x, y, z);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
CDimension2D* pDfg = (CDimension3D*)(pMesh->GetMesh());
|
|
|
SetMeshMetadata(metadata, pDfg);
|
|
|
|
|
|
if (metadata.rows <= 0 || metadata.columns <= 0)
|
|
|
{
|
|
|
SetMetadataToDefault(metadata, x, y, z);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
*x = new double[metadata.rows];
|
|
|
*y = new double[metadata.columns];
|
|
|
*z = new double[metadata.rows * metadata.columns];
|
|
|
|
|
|
for (int i = 0; i < metadata.rows; i++)
|
|
|
{
|
|
|
(*x)[i] = pDfg->x(i);
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < metadata.columns; i++)
|
|
|
{
|
|
|
(*y)[i] = pDfg->y(i);
|
|
|
}
|
|
|
|
|
|
#pragma omp parallel for
|
|
|
for (int i = 0; i < metadata.rows; i++)
|
|
|
{
|
|
|
for (int j = 0; j < metadata.columns; j++)
|
|
|
{
|
|
|
int index = i * metadata.columns + j;
|
|
|
(*z)[index] = pDfg->Value(i, j);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
static std::unique_ptr<CMesh> CreateMesh(const MeshMetadata& metadata, const double* x, const double* y, const double* z)
|
|
|
{
|
|
|
auto pMesh = std::make_unique<CMesh>();
|
|
|
auto pDfg = std::make_unique<CDimension2D>();
|
|
|
|
|
|
int numx = metadata.rows;
|
|
|
int numy = metadata.columns;
|
|
|
double dx = metadata.dx;
|
|
|
double dy = metadata.dy;
|
|
|
double xmin = metadata.minX;
|
|
|
double ymin = metadata.minY;
|
|
|
double zmin = metadata.minZ;
|
|
|
double zmax = metadata.maxZ;
|
|
|
|
|
|
pDfg->Create(numx, numy, xmin, ymin, dx, dy);
|
|
|
|
|
|
pDfg->range[0] = zmin;
|
|
|
pDfg->range[1] = zmax;
|
|
|
|
|
|
for (int i = 0; i < numx; i++)
|
|
|
{
|
|
|
for (int j = 0; j < numy; j++)
|
|
|
{
|
|
|
pDfg->SetValue(i, j, z[i * numy + j]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
pMesh->SetMesh(pDfg.release(), MESH_DFG, FALSE);
|
|
|
pMesh->EnableUpdateRuler(TRUE);
|
|
|
pMesh->UpdateColorRuler();
|
|
|
|
|
|
return pMesh;
|
|
|
}
|
|
|
static void AddContourCurve(CXy* pXy, vector<CCurve*>* curves, vector<CString*>* layer)
|
|
|
{
|
|
|
for (size_t i = 0; i < curves->size(); i++)
|
|
|
{
|
|
|
CCurve* pCurve = curves->at(i);
|
|
|
if (pCurve == NULL) continue;
|
|
|
|
|
|
CCurveEx *ce = new CCurveEx(pCurve->num);
|
|
|
for (int i = 0; i < ce->num; i++)
|
|
|
{
|
|
|
ce->x[i] = pCurve->x[i];
|
|
|
ce->y[i] = pCurve->y[i];
|
|
|
ce->z[i] = pCurve->z[i];
|
|
|
}
|
|
|
ce->nPoint = pCurve->nPoint;
|
|
|
ce->GetLocation();
|
|
|
POSITION pos = NULL;
|
|
|
if (pCurve->name)
|
|
|
ce->SetName(pCurve->name);
|
|
|
|
|
|
pos = pXy->AddElement(ce, DOUBLEFOX_CURVE);
|
|
|
|
|
|
CString* pName = layer->at(i);
|
|
|
pXy->SetElementLayer(pos, *pName);
|
|
|
}
|
|
|
}
|
|
|
template <typename T>
|
|
|
void DeleteVectorData(std::vector<T *> &vec)
|
|
|
{
|
|
|
for (auto* p : vec) {
|
|
|
delete p;
|
|
|
}
|
|
|
vec.clear();
|
|
|
}
|
|
|
///
|
|
|
/// 曲线平滑
|
|
|
///
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyMeshSmooth(CXy* pXy, POSITION posMesh, double smoothFactor, int smoothTimes = 2)
|
|
|
{
|
|
|
if (smoothFactor < 1e-10) {
|
|
|
return;
|
|
|
}
|
|
|
CMesh* pMeshNew = (CMesh*)(pXy->GetAt(posMesh)->value);
|
|
|
CGrid* pGrid = pMeshNew->GetMesh();
|
|
|
int numx = pGrid->xnum();
|
|
|
int numy = pGrid->ynum();
|
|
|
double dZMin = pGrid->range[0] - 0.001;
|
|
|
double dZMax = pGrid->range[1] + 0.001;
|
|
|
|
|
|
for (int i = 1; i < numx - 1; i++)
|
|
|
{
|
|
|
double dSigma = 0;
|
|
|
double dPtX = 0, dPtY = 0, dOtherX = 0, dOtherY = 0;
|
|
|
for (int j = 1; j < numy - 1; j++) {
|
|
|
double dValueCur = pGrid->Value(i, j);
|
|
|
if (dValueCur< dZMin || dValueCur>dZMax) {
|
|
|
continue;
|
|
|
}
|
|
|
//dPtX = ConvertX2Int(pGrid->x(i), ptOO);
|
|
|
//dPtY = ConvertY2Int(pGrid->y(j), ptOO);
|
|
|
dSigma = 0;
|
|
|
int nCount = 0;
|
|
|
double dValueTmp = pGrid->Value(i - 1, j - 1);
|
|
|
if (dValueTmp >= dZMin && dValueTmp <= dZMax) {
|
|
|
//if (!intersectHelp->Intersects(LineSegment(Point64(dPtX, dPtY)
|
|
|
// , Point64(ConvertX2Int(pGrid->x(i - 1), ptOO), ConvertY2Int(pGrid->y(j - 1), ptOO)))))
|
|
|
//{
|
|
|
dSigma += dValueTmp;
|
|
|
nCount++;
|
|
|
//}
|
|
|
}
|
|
|
dValueTmp = pGrid->Value(i, j - 1);
|
|
|
if (dValueTmp >= dZMin && dValueTmp <= dZMax) {
|
|
|
//if (!intersectHelp->Intersects(LineSegment(Point64(dPtX, dPtY)
|
|
|
// , Point64(ConvertX2Int(pGrid->x(i), ptOO), ConvertY2Int(pGrid->y(j - 1), ptOO)))))
|
|
|
//{
|
|
|
dSigma += dValueTmp;
|
|
|
nCount++;
|
|
|
//}
|
|
|
}
|
|
|
dValueTmp = pGrid->Value(i + 1, j - 1);
|
|
|
if (dValueTmp >= dZMin && dValueTmp <= dZMax) {
|
|
|
//if (!intersectHelp->Intersects(LineSegment(Point64(dPtX, dPtY)
|
|
|
// , Point64(ConvertX2Int(pGrid->x(i + 1), ptOO), ConvertY2Int(pGrid->y(j - 1), ptOO)))))
|
|
|
//{
|
|
|
dSigma += dValueTmp;
|
|
|
nCount++;
|
|
|
//}
|
|
|
}
|
|
|
dValueTmp = pGrid->Value(i - 1, j);
|
|
|
if (dValueTmp >= dZMin && dValueTmp <= dZMax) {
|
|
|
//if (!intersectHelp->Intersects(LineSegment(Point64(dPtX, dPtY)
|
|
|
// , Point64(ConvertX2Int(pGrid->x(i - 1), ptOO), ConvertY2Int(pGrid->y(j), ptOO)))))
|
|
|
//{
|
|
|
dSigma += dValueTmp;
|
|
|
nCount++;
|
|
|
//}
|
|
|
}
|
|
|
dValueTmp = pGrid->Value(i + 1, j);
|
|
|
if (dValueTmp >= dZMin && dValueTmp <= dZMax) {
|
|
|
//if (!intersectHelp->Intersects(LineSegment(Point64(dPtX, dPtY)
|
|
|
// , Point64(ConvertX2Int(pGrid->x(i + 1), ptOO), ConvertY2Int(pGrid->y(j), ptOO)))))
|
|
|
//{
|
|
|
dSigma += dValueTmp;
|
|
|
nCount++;
|
|
|
//}
|
|
|
}
|
|
|
dValueTmp = pGrid->Value(i - 1, j + 1);
|
|
|
if (dValueTmp >= dZMin && dValueTmp <= dZMax) {
|
|
|
//if (!intersectHelp->Intersects(LineSegment(Point64(dPtX, dPtY)
|
|
|
// , Point64(ConvertX2Int(pGrid->x(i - 1), ptOO), ConvertY2Int(pGrid->y(j + 1), ptOO)))))
|
|
|
//{
|
|
|
dSigma += dValueTmp;
|
|
|
nCount++;
|
|
|
//}
|
|
|
}
|
|
|
dValueTmp = pGrid->Value(i, j + 1);
|
|
|
if (dValueTmp >= dZMin && dValueTmp <= dZMax) {
|
|
|
//if (!intersectHelp->Intersects(LineSegment(Point64(dPtX, dPtY)
|
|
|
// , Point64(ConvertX2Int(pGrid->x(i), ptOO), ConvertY2Int(pGrid->y(j + 1), ptOO)))))
|
|
|
//{
|
|
|
dSigma += dValueTmp;
|
|
|
nCount++;
|
|
|
//}
|
|
|
}
|
|
|
dValueTmp = pGrid->Value(i + 1, j + 1);
|
|
|
if (dValueTmp >= dZMin && dValueTmp <= dZMax) {
|
|
|
//if (!intersectHelp->Intersects(LineSegment(Point64(dPtX, dPtY)
|
|
|
// , Point64(ConvertX2Int(pGrid->x(i + 1), ptOO), ConvertY2Int(pGrid->y(j + 1), ptOO)))))
|
|
|
//{
|
|
|
dSigma += dValueTmp;
|
|
|
nCount++;
|
|
|
//}
|
|
|
}
|
|
|
if (nCount == 0) {
|
|
|
return;
|
|
|
}
|
|
|
double dAverage = dSigma / nCount;
|
|
|
double dValueNew = (dValueCur + dAverage * smoothFactor) / (1.0 + smoothFactor);
|
|
|
pGrid->SetValue(i, j, dValueNew);
|
|
|
//TRACE("i:%d, j:%d, %lf\r\n", i, j, dValueNew);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyCreateContour(CXy* pXy, POSITION posMesh, double contourStep, int contourMarkStep)
|
|
|
{
|
|
|
CMesh* pMeshNew = (CMesh*)(pXy->GetAt(posMesh)->value);
|
|
|
|
|
|
CString strLayerMark = _T("Layer:\\等值线\\标注");
|
|
|
CString strLayerOther = _T("Layer:\\等值线\\无标注");
|
|
|
|
|
|
CString curLayerName = pXy->GetCurrentLayer()->GetPathName();
|
|
|
CLayer* pMarkLayer = pXy->FindLayer(strLayerMark);
|
|
|
CLayer* pOtherLayer = pXy->FindLayer(strLayerOther);
|
|
|
|
|
|
if (pMarkLayer == nullptr)
|
|
|
{
|
|
|
pMarkLayer = pXy->FindAddLayer(strLayerMark);
|
|
|
|
|
|
pMarkLayer->HowToViewCurve = new CHowToViewCurve();
|
|
|
pMarkLayer->HowToViewCurve->EnableDrawSourceCurve(FALSE);
|
|
|
CCurveInName* pInName = new CCurveInName();
|
|
|
CRect8 rect = pMeshNew->GetRect();
|
|
|
pInName->text_h = rect.Width() / 300;
|
|
|
pInName->m_size.cx = pInName->text_h*0.06;
|
|
|
pInName->color = RGB(0, 0, 0);
|
|
|
pMarkLayer->HowToViewCurve->Add(pInName);
|
|
|
}
|
|
|
|
|
|
if (pOtherLayer == nullptr)
|
|
|
{
|
|
|
pOtherLayer = pXy->FindAddLayer(strLayerOther);
|
|
|
|
|
|
pOtherLayer->HowToViewCurve = new CHowToViewCurve();
|
|
|
pOtherLayer->HowToViewCurve->EnableDrawSourceCurve(FALSE);
|
|
|
CCurveProperties* pview = new CCurveProperties();
|
|
|
pview->color = RGB(0, 0, 0);
|
|
|
pOtherLayer->HowToViewCurve->Add(pview);
|
|
|
}
|
|
|
|
|
|
std::vector<CCurve*> pCurves;
|
|
|
std::vector<CString*> pLayers;
|
|
|
CGrid* pDfg = pMeshNew->GetMesh();
|
|
|
pMeshNew->ContourCreate(&pCurves, &pLayers, contourStep, contourMarkStep,
|
|
|
strLayerMark, strLayerOther, pDfg->range[0], pDfg->range[1]);
|
|
|
|
|
|
AddContourCurve(pXy, &pCurves, &pLayers);
|
|
|
DeleteVectorData(pCurves);
|
|
|
DeleteVectorData(pLayers);
|
|
|
}
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
POSITION XyCreateMesh(CXy* pXy, LPCTSTR layerName, const float* values,
|
|
|
double xMin, double yMin, int xCount, int yCount, double stepX, double stepY,
|
|
|
double zMin, double zMax)
|
|
|
{
|
|
|
auto *pDfg = new CDimension2D();
|
|
|
pDfg->Create(xCount, yCount, xMin, yMin, stepX, stepY);
|
|
|
for (int i = 0; i < xCount; i++)
|
|
|
{
|
|
|
for (int j = 0; j < yCount; j++)
|
|
|
{
|
|
|
pDfg->SetValue(i, j, values[yCount*i + j]);
|
|
|
}
|
|
|
}
|
|
|
pDfg->range[0] = zMin;
|
|
|
pDfg->range[1] = zMax;
|
|
|
|
|
|
// 添加网格
|
|
|
CMesh* pMeshNew = new CMesh(); // 网格类
|
|
|
CLayer* pLayer = pXy->FindAddLayer("背景");
|
|
|
POSITION posNew = pXy->AddElement(pMeshNew, DOUBLEFOX_MESH);
|
|
|
pXy->SetElementLayer(posNew, pLayer);
|
|
|
pMeshNew->SetMesh(pDfg, MESH_DFG, FALSE);
|
|
|
//pMeshNew->GetMesh();
|
|
|
//// 生成等值线
|
|
|
//CreateContourLines(pXy, pMeshNew, pDfg, contourStep, contourMarkStep);
|
|
|
|
|
|
pMeshNew->EnableUpdateRuler(TRUE);
|
|
|
pMeshNew->UpdateColorRuler();
|
|
|
|
|
|
return posNew;
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* 通过数据添加网格
|
|
|
*
|
|
|
* \param pXy 图件
|
|
|
* \param layerName 要添加到的目标图层名称
|
|
|
* \param metadata 网格元数据
|
|
|
* \param x x 坐标集合
|
|
|
* \param y y 坐标集合
|
|
|
* \param z 所有点的 z 值
|
|
|
* \return 成功返回 true,失败返回 false
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyAddMesh(CXy* pXy, const LPCTSTR layerName, const MeshMetadata* metadata, const double* x, const double* y, const double* z)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
TRACE("pXy 不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if (layerName == nullptr)
|
|
|
{
|
|
|
TRACE("layerName 不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if (metadata == nullptr)
|
|
|
{
|
|
|
TRACE("metadata 不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
auto pMesh = CreateMesh(*metadata, x, y, z);
|
|
|
|
|
|
CLayer* pLayer = pXy->FindAddLayer(layerName);
|
|
|
auto pOne = std::make_unique<COne>();
|
|
|
pOne->SetLayer(pLayer);
|
|
|
pOne->SetValueSafe(pMesh.release());
|
|
|
|
|
|
pXy->AddTailOne(pOne.release());
|
|
|
|
|
|
//pXy->SaveAsWithExtension("E:\\output.dfd");
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyGetMeshInfo(CXy* pXy, BYTE*& buffElement, int& buffLen)
|
|
|
{
|
|
|
CMesh* pMesh = GetMesh(pXy);
|
|
|
if (pMesh == nullptr)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
pMesh->WriteElementDML(buffElement, buffLen);
|
|
|
return true;
|
|
|
}
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XySetMeshInfo(CXy* pXy, LPCTSTR infoData)
|
|
|
{
|
|
|
CMesh* pMesh = GetMesh(pXy);
|
|
|
if (pMesh == nullptr)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
pMesh->m_bRealTimeDraw = false;
|
|
|
CString strInforData(infoData);
|
|
|
CMemFile memFile((BYTE*)strInforData.GetString(), strInforData.GetLength());
|
|
|
pMesh->ReadElementDML(memFile, -1);
|
|
|
|
|
|
pMesh->SetM(pMesh->m_pRuler->zmin, pMesh->m_pRuler->zmax);
|
|
|
//pMesh->GetBitmap();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyGetMeshData(CXy* pXy, double& xMin, double& yMin, int& xNum, int& yNum, double& xStep, double& yStep, double*& pValue, double &zMin, double& zMax)
|
|
|
{
|
|
|
CMesh* pMesh = GetMesh(pXy);
|
|
|
if (pMesh == nullptr)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
CDimension2D* pDfg = (CDimension3D*)(pMesh->GetMesh());
|
|
|
xNum = pDfg->num[0];
|
|
|
yNum = pDfg->num[1];
|
|
|
xStep = pDfg->delt[0];
|
|
|
yStep = pDfg->delt[1];
|
|
|
xMin = pDfg->xmin();
|
|
|
yMin = pDfg->ymin();
|
|
|
pValue = pDfg->u;
|
|
|
|
|
|
zMin = pDfg->range[0];
|
|
|
zMax = pDfg->range[1];
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 图层元素置顶 (让它的图元显示在最上层),由于默认排序规则是后加入的元素显示在上面,所以我们将这些元素放到末尾即可
|
|
|
*
|
|
|
* \param pXy CXy 指针
|
|
|
* \param layer 图层名
|
|
|
* \param bWithSubLayer 是否连带子层图元一起置顶
|
|
|
*
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyLayerElementOrderTop(CXy* pXy, const wchar_t* layer, bool bWithSubLayer)
|
|
|
{
|
|
|
assert(pXy != nullptr);
|
|
|
|
|
|
CPositionList list;
|
|
|
pXy->GetElement(CString(layer), list, bWithSubLayer, true);
|
|
|
|
|
|
for (POSITION p = list.GetHeadPosition(); p != nullptr; list.GetNext(p))
|
|
|
{
|
|
|
POSITION pos = list.GetAt(p);
|
|
|
if (pos != nullptr)
|
|
|
{
|
|
|
pos = pXy->MoveToFront(pos); // 直接将结果赋给pos
|
|
|
if (pos != nullptr)
|
|
|
{
|
|
|
list.SetAt(p, pos);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 图层元素置底 (让它的图元显示在最下层)
|
|
|
*
|
|
|
* \param pXy CXy 指针
|
|
|
* \param layer 图层名
|
|
|
* \param bWithSubLayer 是否连带子层图元一起置顶
|
|
|
*
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyLayerElementOrderBottom(CXy* pXy, const wchar_t* layer, bool bWithSubLayer)
|
|
|
{
|
|
|
assert(pXy != nullptr);
|
|
|
|
|
|
CPositionList list;
|
|
|
pXy->GetElement(CString(layer), list, bWithSubLayer, true);
|
|
|
|
|
|
for (POSITION p = list.GetTailPosition(); p != nullptr; list.GetPrev(p))
|
|
|
{
|
|
|
POSITION pos = list.GetAt(p);
|
|
|
if (pos != nullptr)
|
|
|
{
|
|
|
pos = pXy->MoveToBack(pos);
|
|
|
if (pos != nullptr)
|
|
|
{
|
|
|
list.SetAt(p, pos);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 图层元素上移一层
|
|
|
*
|
|
|
* \param pXy CXy 指针
|
|
|
* \param layer 图层名
|
|
|
* \param bWithSubLayer 是否连带子层图元一起置顶
|
|
|
*
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyLayerElementOrderUp(CXy* pXy, const wchar_t* layer, bool bWithSubLayer)
|
|
|
{
|
|
|
assert(pXy != nullptr);
|
|
|
|
|
|
CPositionList list;
|
|
|
pXy->GetElement(CString(layer), list, bWithSubLayer, true);
|
|
|
|
|
|
for (POSITION p = list.GetTailPosition(); p != nullptr; list.GetPrev(p))
|
|
|
{
|
|
|
POSITION pos = list.GetAt(p);
|
|
|
if (pos != nullptr)
|
|
|
{
|
|
|
pos = pXy->MoveForward(pos);
|
|
|
if (pos != nullptr)
|
|
|
{
|
|
|
list.SetAt(p, pos);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 图层元素下移一层
|
|
|
*
|
|
|
* \param pXy CXy 指针
|
|
|
* \param layer 图层名
|
|
|
* \param bWithSubLayer 是否连带子层图元一起置顶
|
|
|
*
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyLayerElementOrderDown(CXy* pXy, const wchar_t* layer, bool bWithSubLayer)
|
|
|
{
|
|
|
assert(pXy != nullptr);
|
|
|
|
|
|
CPositionList list;
|
|
|
pXy->GetElement(CString(layer), list, bWithSubLayer, true);
|
|
|
|
|
|
for (POSITION p = list.GetHeadPosition(); p != nullptr; list.GetNext(p))
|
|
|
{
|
|
|
POSITION pos = list.GetAt(p);
|
|
|
if (pos != nullptr)
|
|
|
{
|
|
|
pos = pXy->MoveBackward(pos);
|
|
|
if (pos != nullptr)
|
|
|
{
|
|
|
list.SetAt(p, pos);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 列出图层所有 position
|
|
|
*
|
|
|
* \param pXy
|
|
|
* \return
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
BSTR XyListAllElements(CXy* pXy)
|
|
|
{
|
|
|
assert(pXy != nullptr);
|
|
|
|
|
|
std::vector<CString> positions;
|
|
|
|
|
|
CPtrList* pValueList = pXy->GetValueList();
|
|
|
for (POSITION pos = pValueList->GetHeadPosition(); pos != nullptr; pValueList->GetNext(pos))
|
|
|
{
|
|
|
CString str;
|
|
|
str.Format("%I64d", pos);
|
|
|
positions.push_back(str);
|
|
|
}
|
|
|
|
|
|
return JoinStrings(positions, ",").AllocSysString();
|
|
|
}
|
|
|
|
|
|
static std::vector<CLayer*> GetAllLayers(const CXy& xy)
|
|
|
{
|
|
|
CXy& mutXy = const_cast<CXy&>(xy);
|
|
|
std::vector<CLayer*> result;
|
|
|
|
|
|
CClassList* pClassList = mutXy.GetClassList();
|
|
|
for (POSITION classPos = pClassList->GetHeadPosition(); classPos != nullptr; pClassList->GetNext(classPos))
|
|
|
{
|
|
|
CLayerList* pLayerList = pClassList->GetAt(classPos);
|
|
|
for (POSITION layerPos = pLayerList->GetHeadPosition(); layerPos != nullptr; pLayerList->GetNext((layerPos)))
|
|
|
{
|
|
|
result.push_back(pLayerList->GetAt(layerPos));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
static void CopyHowtoViewCurve(const CLayer* pSourceLayer, CLayer* pTargetLayer)
|
|
|
{
|
|
|
if (pTargetLayer->HowToViewCurve != nullptr)
|
|
|
{
|
|
|
delete pTargetLayer->HowToViewCurve;
|
|
|
pTargetLayer->HowToViewCurve = nullptr;
|
|
|
}
|
|
|
|
|
|
if (pSourceLayer->HowToViewCurve != nullptr)
|
|
|
{
|
|
|
pTargetLayer->HowToViewCurve = new CHowToViewCurve();
|
|
|
*pTargetLayer->HowToViewCurve = *pSourceLayer->HowToViewCurve;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void CopyHowtoViewPoint(const CLayer* pSourceLayer, CLayer* pTargetLayer)
|
|
|
{
|
|
|
if (pTargetLayer->HowToViewPoint != nullptr)
|
|
|
{
|
|
|
delete pTargetLayer->HowToViewPoint;
|
|
|
pTargetLayer->HowToViewPoint = nullptr;
|
|
|
}
|
|
|
|
|
|
if (pSourceLayer->HowToViewPoint != nullptr)
|
|
|
{
|
|
|
pTargetLayer->HowToViewPoint = new CHowToViewPoint();
|
|
|
*pTargetLayer->HowToViewPoint = *pSourceLayer->HowToViewPoint;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void CopyMarkTo(CXy* pSourceXy, CXy* pTargetXy, const CString& symbolName)
|
|
|
{
|
|
|
assert(pSourceXy != nullptr);
|
|
|
assert(pTargetXy != nullptr);
|
|
|
|
|
|
if (symbolName.IsEmpty())
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
CMapStringToPtrNoCase* pMarks = pSourceXy->GetMark();
|
|
|
void* pDraw;
|
|
|
if (pMarks->Lookup(symbolName, pDraw))
|
|
|
{
|
|
|
CXy* pOldSymbol = (CXy*)pDraw;
|
|
|
std::unique_ptr<CXy> pNewSymbol = std::make_unique<CXy>();
|
|
|
*pNewSymbol = *pOldSymbol;
|
|
|
pNewSymbol->m_strName = symbolName;
|
|
|
pTargetXy->AddMark(pNewSymbol.release(), true);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void CopyHowtoViewMarkTo(CXy* pSourceXy, CHowToViewCurve* pHowToViewCurve, CHowToViewPoint* pHowToViewPoint, CXy* pTargetXy)
|
|
|
{
|
|
|
if (pHowToViewPoint != nullptr)
|
|
|
{
|
|
|
CopyMarkTo(pSourceXy, pTargetXy, pHowToViewPoint->MarkName);
|
|
|
}
|
|
|
|
|
|
if (pHowToViewCurve != nullptr)
|
|
|
{
|
|
|
for (int i = 0; i < pHowToViewCurve->GetCount(); i++)
|
|
|
{
|
|
|
CCurveView* pView = pHowToViewCurve->GetAt(i);
|
|
|
|
|
|
if (auto* pArrow = dynamic_cast<CCurveArrow*>(pView))
|
|
|
{
|
|
|
CopyMarkTo(pSourceXy, pTargetXy, pArrow->MarkName);
|
|
|
}
|
|
|
else if (auto* pScale = dynamic_cast<CCurveScale*>(pView))
|
|
|
{
|
|
|
CopyMarkTo(pSourceXy, pTargetXy, pScale->MarkName);
|
|
|
}
|
|
|
else if (auto* pTwoMark = dynamic_cast<CCurveTwoMark*>(pView))
|
|
|
{
|
|
|
CopyMarkTo(pSourceXy, pTargetXy, pTwoMark->MarkName);
|
|
|
}
|
|
|
else if (auto* pRgn = dynamic_cast<CCurveRgn*>(pView))
|
|
|
{
|
|
|
CopyMarkTo(pSourceXy, pTargetXy, pRgn->MarkName);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 复制样式到其它图件中
|
|
|
*
|
|
|
* \param pXy
|
|
|
* \param targetFilePath 目标图件
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyApplyStyleToFile(CXy* pXy, LPCTSTR targetFilePath)
|
|
|
{
|
|
|
assert(pXy != nullptr);
|
|
|
|
|
|
std::unique_ptr<CXy> targetXy = std::make_unique<CXy>();
|
|
|
if (!XyOpenFile(targetXy.get(), targetFilePath, false))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
std::vector<CLayer*> layers = GetAllLayers(*pXy);
|
|
|
|
|
|
for (CLayer* pLayer : layers)
|
|
|
{
|
|
|
CString pathName = pLayer->GetPathName();
|
|
|
|
|
|
CLayer* pTargetLayer = targetXy->FindLayer(pathName, FALSE);
|
|
|
if (pTargetLayer == nullptr)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
CopyHowtoViewCurve(pLayer, pTargetLayer);
|
|
|
CopyHowtoViewPoint(pLayer, pTargetLayer);
|
|
|
CopyHowtoViewMarkTo(pXy, pLayer->HowToViewCurve, pLayer->HowToViewPoint, targetXy.get());
|
|
|
}
|
|
|
|
|
|
targetXy->SaveAsWithExtension(targetFilePath);
|
|
|
}
|
|
|
|
|
|
static std::vector<CString> CollectValidLayerNames(CXy& xy, const std::vector<CString>& layerNames)
|
|
|
{
|
|
|
std::vector<CString> validNames;
|
|
|
|
|
|
for (const CString& name: layerNames)
|
|
|
{
|
|
|
CString layerPath = CLayerName(name).GetFullPathNameA();
|
|
|
|
|
|
for (CLayer* pLayer : CollectAllLayers(xy))
|
|
|
{
|
|
|
if (pLayer->GetPathName() == layerPath)
|
|
|
{
|
|
|
validNames.push_back(name);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return validNames;
|
|
|
}
|
|
|
|
|
|
std::unique_ptr<COne> XyLegendCreate(CXy& xy, double x, double y, double width, int rows, LPCTSTR layerNames)
|
|
|
{
|
|
|
std::vector<CString> validNames = CollectValidLayerNames(xy, SplitString(layerNames, _T(",")));
|
|
|
if (validNames.size() == 0)
|
|
|
{
|
|
|
TRACE("没有合法的图层,无法生成图例\n");
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
// 计算列数,向上取整
|
|
|
size_t columns = (validNames.size() + rows - 1) / rows;
|
|
|
|
|
|
Legend legend(xy, x, y, width, _T("图例"), static_cast<int>(columns), validNames);
|
|
|
std::unique_ptr<CInsertBlock> pBlock = legend.Build();
|
|
|
|
|
|
std::unique_ptr<COne> pOne = std::make_unique<COne>();
|
|
|
CLayer* pLayer = xy.FindAddLayer(_T("图例"));
|
|
|
|
|
|
pOne->SetValueSafe(pBlock.release());
|
|
|
pOne->SetLayer(pLayer);
|
|
|
|
|
|
return pOne;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 添加图例
|
|
|
*
|
|
|
* \param pXy 要添加图例的图件
|
|
|
* \param x 要添加的图例 x 坐标
|
|
|
* \param y 要添加的图例 y 坐标
|
|
|
* \param width 图例宽度
|
|
|
* \param rows 设置成多少行
|
|
|
* \param layerNames 哪些图层要生成图例
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyLegendAdd(CXy* pXy, double x, double y, double width, int rows, LPCTSTR layerNames)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
TRACE("pXy: 图件是空指针\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (rows <= 0)
|
|
|
{
|
|
|
TRACE("rows: 行数必须大小0\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (layerNames == nullptr)
|
|
|
{
|
|
|
TRACE("layerNames: 图层名不能是空指针\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
std::unique_ptr<COne> pOne = XyLegendCreate(*pXy, x, y, width, rows, layerNames);
|
|
|
if (pOne)
|
|
|
{
|
|
|
pXy->AddTailOne(pOne.release());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* 测量图例空间占用
|
|
|
*
|
|
|
* \param pXy 要添加图例的图件
|
|
|
* \param x 要添加的图例 x 坐标
|
|
|
* \param y 要添加的图例 y 坐标
|
|
|
* \param rows 设置成多少行
|
|
|
* \param layerNames 哪些图层要生成图例
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
BSTR XyLegendMeasure(CXy* pXy, double width, int rows, LPCTSTR layerNames)
|
|
|
{
|
|
|
CString error;
|
|
|
error.Format("%lf,%lf", 0.0, 0.0);
|
|
|
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
TRACE("pXy: 图件是空指针\n");
|
|
|
return error.AllocSysString();
|
|
|
}
|
|
|
|
|
|
if (rows <= 0)
|
|
|
{
|
|
|
TRACE("rows: 行数必须大小0\n");
|
|
|
return error.AllocSysString();
|
|
|
}
|
|
|
|
|
|
if (layerNames == nullptr)
|
|
|
{
|
|
|
TRACE("layerNames: 图层名不能是空指针\n");
|
|
|
return error.AllocSysString();
|
|
|
}
|
|
|
|
|
|
std::vector<CString> validNames = CollectValidLayerNames(*pXy, SplitString(layerNames, _T(",")));
|
|
|
if (validNames.size() == 0)
|
|
|
{
|
|
|
TRACE("没有任何合法图层\n");
|
|
|
return error.AllocSysString();
|
|
|
}
|
|
|
|
|
|
// 计算列数,向上取整
|
|
|
size_t columns = (validNames.size() + rows - 1) / rows;
|
|
|
|
|
|
Legend legend(*pXy, 0, 0, width, _T("图例"), static_cast<int>(columns), validNames);
|
|
|
std::unique_ptr<CInsertBlock> pBlock = legend.Build();
|
|
|
|
|
|
CString str;
|
|
|
str.Format("%lf,%lf", legend.GetWidth(), legend.GetHeight());
|
|
|
return str.AllocSysString();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 给图件添加边框
|
|
|
*
|
|
|
* \param pXy 要添加边框的图件
|
|
|
* \param layerName 要将边框添加到的图件名
|
|
|
* \param clip 边框向内收多少
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyBorderAdd(CXy* pXy, LPCTSTR layerName, double clip)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
TRACE("pXy 不能为 nullptr");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (layerName == nullptr)
|
|
|
{
|
|
|
TRACE("layerName 不能为 nullptr");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
CRect8 range(1e100, -1e100, -1e100, 1e100);
|
|
|
pXy->GetRange(range);
|
|
|
|
|
|
double left = range.left - clip;
|
|
|
double top = range.top + clip;
|
|
|
double right = range.right + clip;
|
|
|
double bottom = range.bottom - clip;
|
|
|
|
|
|
std::unique_ptr<CGridding> pGridding = std::make_unique<CGridding>();
|
|
|
|
|
|
// 设置范围
|
|
|
pGridding->SetRect(left, top, right, bottom);
|
|
|
pGridding->m_step.cx = std::trunc(abs(right - left) * (1.0 / 4.0)); // 先把宽高步长固定死为图件内容的 1/4
|
|
|
pGridding->m_step.cy = std::trunc(abs(top - bottom) * (1.0 / 4.0));
|
|
|
pGridding->m_szText.cx = 12;
|
|
|
pGridding->m_szText.cy = 30;
|
|
|
pGridding->m_nFlags = 29263;
|
|
|
|
|
|
pGridding->m_ptBase.x0 = 0.0;
|
|
|
pGridding->m_ptBase.y0 = 0.0;
|
|
|
pGridding->m_szCoefficient.cx = 1.0;
|
|
|
pGridding->m_szCoefficient.cy = 1.0;
|
|
|
|
|
|
// 获取外边框
|
|
|
CFrame* pm = pGridding->GetOutFrame();
|
|
|
pm->thickness = 10;
|
|
|
pm->m_nFlags = 2309;
|
|
|
|
|
|
CLayer* pLayer = pXy->FindAddLayer(CString(layerName));
|
|
|
COne* pOne = new COne();
|
|
|
pOne->SetValueSafe(pGridding.release());
|
|
|
pOne->SetLayer(pLayer);
|
|
|
pOne->SetColor(RGB(0, 0, 0));
|
|
|
|
|
|
pXy->AddTailOne(pOne);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 生成 x1, y1 到 x2, y2 的中间点
|
|
|
*
|
|
|
* \param x1 第一个点的 x 坐标
|
|
|
* \param y1 第一个点的 y 坐标
|
|
|
* \param x2 第二个点的 x 坐标
|
|
|
* \param y2 第二个点的 y 坐标
|
|
|
* \param step 步长,则一步在这个方向上移动多远距离
|
|
|
* \return
|
|
|
*/
|
|
|
static std::vector<CPoint3D> GeneratePoints(double x1, double y1, double x2, double y2, double step)
|
|
|
{
|
|
|
double distance = CalcDistance(x1, y1, x2, y2);
|
|
|
int num_steps = static_cast<int>(distance / step);
|
|
|
|
|
|
double xIncrement = (x2 - x1) / distance * step;
|
|
|
double yIncrement = (y2 - y1) / distance * step;
|
|
|
|
|
|
std::vector<CPoint3D> result;
|
|
|
|
|
|
for (int i = 0; i < num_steps + 1; i++)
|
|
|
{
|
|
|
double x = x1 + i * xIncrement;
|
|
|
double y = y1 + i * yIncrement;
|
|
|
|
|
|
result.push_back({ x, y, -1e300 });
|
|
|
}
|
|
|
|
|
|
CPoint2D lastPoint = result[result.size() - 1];
|
|
|
if (lastPoint.x0 != x2 || lastPoint.y0 != y2)
|
|
|
{
|
|
|
result.push_back({ x2, y2, -1e300 });
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据网格为两点的连线生成 z 值
|
|
|
*
|
|
|
* \param mesh 背景网格
|
|
|
* \param x1 第一个点 x 坐标
|
|
|
* \param y1 第一个点 y 坐标
|
|
|
* \param x2 第二个点 x 坐标
|
|
|
* \param y2 第二个点 y 坐标
|
|
|
*/
|
|
|
static std::unique_ptr<CCurveEx> CreateCurveFromMesh(const CMesh &mesh, double x1, double y1, double x2, double y2)
|
|
|
{
|
|
|
CMesh& mutMesh = const_cast<CMesh&>(mesh);
|
|
|
double dx = 0.0;
|
|
|
double dy = 0.0;
|
|
|
|
|
|
mutMesh.GetDelt(dx, dy);
|
|
|
|
|
|
// 一步走网格横宽最短的长度,我们暂时设置为网格最短的边长
|
|
|
double step = min(dx, dy);
|
|
|
|
|
|
CRect8 range(1e300, -1e300, -1e300, 1e300);
|
|
|
mutMesh.GetRange(range);
|
|
|
|
|
|
std::vector<CPoint3D> points = GeneratePoints(x1, y1, x2, y2, step);
|
|
|
|
|
|
for (CPoint3D& point : points)
|
|
|
{
|
|
|
if (point.x0 >= range.left && point.x0 <= range.right &&
|
|
|
point.y0 >= range.bottom && point.y0 <= range.top)
|
|
|
{
|
|
|
point.z0 = mutMesh.GetValue(point.x0, point.y0);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
auto pCurve = std::make_unique<CCurveEx>();
|
|
|
pCurve->Create(static_cast<int>(points.size()));
|
|
|
pCurve->nPoint = 3;
|
|
|
for (size_t i = 0; i < points.size(); i++)
|
|
|
{
|
|
|
pCurve->x[i] = points[i].x0;
|
|
|
pCurve->y[i] = points[i].y0;
|
|
|
pCurve->z[i] = points[i].z0;
|
|
|
}
|
|
|
|
|
|
return pCurve;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据网格创建曲线,其实就是填充线段经过网格点 z 值
|
|
|
*
|
|
|
* \param xy 图件对象
|
|
|
* \param x1 第一个点 x 坐标
|
|
|
* \param y1 第一个点 y 坐标
|
|
|
* \param x2 第二个点 x 坐标
|
|
|
* \param y2 第二个点 y 坐标
|
|
|
* \return 成功返回生成的曲线,失败返回 nullptr
|
|
|
*/
|
|
|
std::unique_ptr<CCurveEx> CreateCurveFromXyMesh(CXy& xy, double x1, double y1, double x2, double y2)
|
|
|
{
|
|
|
CPositionList select;
|
|
|
xy.GetElement(DOUBLEFOX_MESH, select);
|
|
|
|
|
|
CRect8 range1(min(x1, x2), max(y1, y2), max(x1, x2), min(y1, y2));
|
|
|
|
|
|
for (POSITION pos = select.GetHeadPosition(); pos != nullptr; select.GetNext(pos))
|
|
|
{
|
|
|
POSITION pt = select.GetAt(pos);
|
|
|
COne* pOne = xy.GetAt(pt);
|
|
|
CMesh* pMesh = pOne->GetValueSafe<CMesh>();
|
|
|
|
|
|
CRect8 range2(1e300, -1e300, -1e300, 1e300);
|
|
|
pMesh->GetRange(range2);
|
|
|
if (IsIntersecting(range1, range2))
|
|
|
{
|
|
|
return CreateCurveFromMesh(*pMesh, x1, y1, x2, y2);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 创建曲线,使用网格的 z 值填充曲线的 z 值
|
|
|
*
|
|
|
* \param pXy 图件对象指针
|
|
|
* \param layerName 图层名称
|
|
|
* \param x1 第一个点 x 坐标
|
|
|
* \param y1 第一个点 y 坐标
|
|
|
* \param x2 第二个点 x 坐标
|
|
|
* \param y2 第二个点 y 坐标
|
|
|
* \return
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyCreateCurveFillZ(CXy* pXy, LPCTSTR layerName, double x1, double y1, double x2, double y2)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
TRACE("pXy 不能为 null\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if (layerName == nullptr)
|
|
|
{
|
|
|
TRACE("layerName 不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
std::unique_ptr<CCurveEx> pCurve = CreateCurveFromXyMesh(*pXy, x1, y1, x2, y2);
|
|
|
if (!pCurve)
|
|
|
{
|
|
|
TRACE("未找到空间位置匹配的网格\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
CLayer* pLayer = pXy->FindAddLayer(CString(layerName));
|
|
|
auto pOne = std::make_unique<COne>();
|
|
|
pOne->SetLayer(pLayer);
|
|
|
pOne->SetValueSafe(pCurve.release());
|
|
|
pXy->AddTailOne(pOne.release());
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
static bool ExistLayerOrSubLayer(CXy& xy, const CString& layerName)
|
|
|
{
|
|
|
CString layerPath = CLayerName(layerName).GetFullPathNameA();
|
|
|
|
|
|
CClassList* pClassList = xy.GetClassList();
|
|
|
for (POSITION classListPos = pClassList->GetHeadPosition(); classListPos != nullptr; pClassList->GetNext(classListPos))
|
|
|
{
|
|
|
CLayerList* pLayerList = pClassList->GetAt(classListPos);
|
|
|
for (POSITION layerPos = pLayerList->GetHeadPosition(); layerPos != nullptr; pLayerList->GetNext(layerPos))
|
|
|
{
|
|
|
CLayer* pLayer = pLayerList->GetAt(layerPos);
|
|
|
CString currentPath = pLayer->GetPathName();
|
|
|
if (StartsWith(currentPath, layerPath))
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
static void MergeLayerElements(CXy& xy, CLayer& pSourceLayer, CLayer& pTargetLayer)
|
|
|
{
|
|
|
CPtrList* pValueList = xy.GetValueList();
|
|
|
for (POSITION pos = pValueList->GetHeadPosition(); pos != nullptr; pValueList->GetNext(pos))
|
|
|
{
|
|
|
COne* pOne = reinterpret_cast<COne*>(pValueList->GetAt(pos));
|
|
|
if (pOne != nullptr && pOne->GetLayer() == &pSourceLayer)
|
|
|
{
|
|
|
pOne->SetLayer(&pTargetLayer);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 判断是否为子图层 (如果是同一图层也返回 true)
|
|
|
static bool IsSubLayerOf(const CString& layerPath, const CString& parentPath)
|
|
|
{
|
|
|
return StartsWith(layerPath, parentPath) &&
|
|
|
(layerPath.GetLength() == parentPath.GetLength() || layerPath[parentPath.GetLength()] == _T('\\'));
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 将图层移动到目标图层之下
|
|
|
*
|
|
|
* \param pXy 图件对象
|
|
|
* \param currentLayer 当前图层名
|
|
|
* \param targetLayer 目标图层名
|
|
|
* \return
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyMoveLayerUnderTargetLayer(CXy* pXy, LPCTSTR layer , LPCTSTR parentLayer)
|
|
|
{
|
|
|
if (pXy == nullptr || layer == nullptr || parentLayer == nullptr)
|
|
|
{
|
|
|
TRACE("pXy layer parentLayer 都不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 情况1、被移动的图层及子图层都不存在
|
|
|
if (!ExistLayerOrSubLayer(*pXy, layer))
|
|
|
{
|
|
|
TRACE("要移动的图层 %s 不存在\n", layer);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 情况2、要移动到的目标层及子层都不存在
|
|
|
if (!ExistLayerOrSubLayer(*pXy, parentLayer))
|
|
|
{
|
|
|
TRACE("要移动到的图层 %s 不存在\n", parentLayer);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
CString sourceFullPath = CLayerName(layer).GetFullPathNameA();
|
|
|
CString parentFullPath = CLayerName(parentLayer).GetFullPathNameA();
|
|
|
int pos = CString(_T("Layer:")).GetLength();
|
|
|
|
|
|
std::vector<CString> layersToRemove;
|
|
|
|
|
|
CClassList* pClassList = pXy->GetClassList();
|
|
|
for (POSITION classListPos = pClassList->GetHeadPosition(); classListPos != nullptr; pClassList->GetNext(classListPos))
|
|
|
{
|
|
|
CLayerList* pLayerList = pClassList->GetAt(classListPos);
|
|
|
for (POSITION layerPos = pLayerList->GetHeadPosition(); layerPos != nullptr; pLayerList->GetNext(layerPos))
|
|
|
{
|
|
|
CLayer* pLayer = pLayerList->GetAt(layerPos);
|
|
|
CString layerPath = pLayer->GetPathName();
|
|
|
if (IsSubLayerOf(layerPath, sourceFullPath))
|
|
|
{
|
|
|
CString newLayerPath = parentFullPath + _T("\\") + CLayerName(layerPath).GetPathName();
|
|
|
CLayer* pFindLayer = pXy->FindLayer(newLayerPath);
|
|
|
if (pFindLayer == nullptr) // 情况3、如果新的图层不存在,直接将当前图层改名
|
|
|
{
|
|
|
pLayer->SetName(CLayerName(newLayerPath).GetPathName());
|
|
|
}
|
|
|
else // 情况4、如果新的图层本身就存在,合并图层元素
|
|
|
{
|
|
|
MergeLayerElements(*pXy, *pLayer, *pFindLayer);
|
|
|
layersToRemove.push_back(layerPath);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
for (const CString& layerName : layersToRemove)
|
|
|
{
|
|
|
pXy->RemoveLayer(layerName);
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 将图层转换 dfd 字符串
|
|
|
*
|
|
|
* \param pXy 图件对象
|
|
|
* \return dfd 字符串
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
BSTR XyToDfdString(CXy* pXy)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
TRACE("pXy 不能为 nullptr");
|
|
|
return CString().AllocSysString();
|
|
|
}
|
|
|
|
|
|
const UINT MB = 1024 * 1024;
|
|
|
const UINT blockSize = 16 * MB;
|
|
|
|
|
|
CMemFile memFile(blockSize);
|
|
|
int ret = pXy->DFD_Write(memFile, CUR_VERSION, true);
|
|
|
|
|
|
DWORD size = memFile.GetLength();
|
|
|
std::vector<BYTE> buffer(size + 1);
|
|
|
memFile.SeekToBegin();
|
|
|
memFile.Read(buffer.data(), size);
|
|
|
buffer[size] = '\0';
|
|
|
|
|
|
CString result{ buffer.data() };
|
|
|
|
|
|
return result.AllocSysString();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 将图件中指定图层内容保存到另一图件中
|
|
|
*
|
|
|
* \param pXy 图件
|
|
|
* \param filePath 要保存的文件路径
|
|
|
* \param layerName 要保存的图层名
|
|
|
* \return
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
extern bool XySaveLayer(CXy* pXy, LPCTSTR filePath, LPCTSTR layerName)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
TRACE("pXy 不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if (filePath == nullptr)
|
|
|
{
|
|
|
TRACE("filePath 不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if (layerName == nullptr)
|
|
|
{
|
|
|
TRACE("layerName 不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
CFileHelper fileHelper(filePath, CFile::modeCreate | CFile::modeWrite);
|
|
|
if (fileHelper.IsOpen())
|
|
|
{
|
|
|
CPositionList select;
|
|
|
pXy->GetElement(layerName, select, FALSE, TRUE);
|
|
|
pXy->DFD_Write(fileHelper.GetFile(), select);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyAddPoint(CXy* pXy, LPCTSTR layerName, LPCTSTR pointName, double x, double y, double z)
|
|
|
{
|
|
|
if (pXy == nullptr || layerName == nullptr || pointName == nullptr)
|
|
|
{
|
|
|
TRACE("pXy layerName 和 pointName 均不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
CLayer* pLayer = pXy->FindAddLayer(layerName);
|
|
|
if (pLayer == nullptr)
|
|
|
{
|
|
|
TRACE("查找或添加图层失败\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
auto pPoint = std::make_unique<CPointNameEx>();
|
|
|
pPoint->SetName(pointName);
|
|
|
pPoint->x0 = x;
|
|
|
pPoint->y0 = y;
|
|
|
pPoint->z0 = z;
|
|
|
|
|
|
auto pOne = std::make_unique<COne>();
|
|
|
pOne->SetValueSafe(pPoint.release());
|
|
|
pOne->SetLayer(pLayer);
|
|
|
|
|
|
pXy->AddTailOne(pOne.release());
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 添加曲线
|
|
|
*
|
|
|
* \param pXy 图件对象
|
|
|
* \param layerName 图层名称
|
|
|
* \param curveName 曲线名称
|
|
|
* \param x x坐标数组
|
|
|
* \param y y坐标数组
|
|
|
* \param z z坐标数组
|
|
|
* \param hasZ 是否有 z 值
|
|
|
* \param pointCount 曲线点个数
|
|
|
* \return 成功,失败
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
extern bool XyCurveAdd(CXy* pXy, LPCTSTR layerName, LPCTSTR curveName, const double* x, const double* y, const double* z, bool hasZ, int pointCount)
|
|
|
{
|
|
|
if (pXy == nullptr || layerName == nullptr || curveName == nullptr)
|
|
|
{
|
|
|
TRACE("pXy layerName 和 curveName 均不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
CLayer* pLayer = pXy->FindAddLayer(layerName);
|
|
|
if (pLayer == nullptr)
|
|
|
{
|
|
|
TRACE("查找或添加图层失败\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
auto pCurve = std::make_unique<CCurveEx>();
|
|
|
pCurve->SetName(curveName);
|
|
|
pCurve->Create(pointCount);
|
|
|
|
|
|
for (int i = 0; i < pointCount; i++)
|
|
|
{
|
|
|
pCurve->x[i] = x[i];
|
|
|
pCurve->y[i] = y[i];
|
|
|
if (hasZ)
|
|
|
{
|
|
|
pCurve->z[i] = z[i];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
auto pOne = std::make_unique<COne>();
|
|
|
pOne->color = Color::Black;
|
|
|
pOne->SetValueSafe(pCurve.release());
|
|
|
pOne->SetLayer(pLayer);
|
|
|
|
|
|
pXy->AddTailOne(pOne.release());
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 将文件里面的符号复制到当前图件
|
|
|
*
|
|
|
* \param pXy 当前图件
|
|
|
* \param filePath 从这个图件去拷贝符号
|
|
|
* \return
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyMergeSymbol(CXy* pXy, LPCTSTR filePath)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
TRACE("pXy 不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if (filePath == nullptr)
|
|
|
{
|
|
|
TRACE("filePath 不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
CMapStringToPtrNoCase& mark = pXy->mark;
|
|
|
|
|
|
auto pTargetXy = std::make_unique<CXy>();
|
|
|
if (!pTargetXy->OpenFile(filePath, true))
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
CMapStringToPtrNoCase& targetMark = pTargetXy->mark;
|
|
|
|
|
|
POSITION pos = targetMark.GetStartPosition();
|
|
|
while (pos != nullptr)
|
|
|
{
|
|
|
CString name;
|
|
|
void* pDraw = nullptr;
|
|
|
targetMark.GetNextAssoc(pos, name, pDraw);
|
|
|
|
|
|
auto pCloneDraw = std::make_unique<CXy>();
|
|
|
*pCloneDraw = *(reinterpret_cast<CXy*>(pDraw));
|
|
|
|
|
|
pXy->AddMark(pCloneDraw.release(), TRUE);
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
static void CCurveColor(COne &one, COLORREF color)
|
|
|
{
|
|
|
auto property = std::make_unique<CCurvePropertiesEx>();
|
|
|
property->color = color;
|
|
|
|
|
|
// 这个功能目前是给断层处理用的,为了避免用户点击重新着色时不断增加曲线属性条目(即曲线里出现多个“常规”),这里直接把原来的清理掉
|
|
|
SafeDelete(one.HowToViewCurve);
|
|
|
|
|
|
one.HowToViewCurve = new CHowToViewCurve();
|
|
|
|
|
|
one.HowToViewCurve->Add(property.release());
|
|
|
}
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyClearLayerElementsEmbellish(CXy* pXy, LPCTSTR layerName, bool includeSubLayer)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
TRACE("pXy 不能为 nullptr\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (layerName == nullptr)
|
|
|
{
|
|
|
TRACE("layerName 不能为 nullptr\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
CPositionList select;
|
|
|
CXyElementFilter filter;
|
|
|
filter.addLayer(layerName, includeSubLayer);
|
|
|
pXy->GetElement(filter, select);
|
|
|
|
|
|
POSITION pos = select.GetHeadPosition();
|
|
|
while (pos != nullptr)
|
|
|
{
|
|
|
POSITION pt = select.GetNext(pos);
|
|
|
COne* pOne = pXy->GetAt(pt);
|
|
|
SafeDelete(pOne->HowToViewCurve);
|
|
|
SafeDelete(pOne->HowToViewPoint);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool XyCurveMappingRandColor(CXy* pXy, LPCTSTR layerName, bool includeSubLayer)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
TRACE("pXy 不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if (layerName == nullptr)
|
|
|
{
|
|
|
TRACE("layerName 不能为 nullptr\n");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
CPositionList select;
|
|
|
CXyElementFilter filter;
|
|
|
filter.addLayer(layerName, includeSubLayer);
|
|
|
filter.addType(DOUBLEFOX_CURVE);
|
|
|
pXy->GetElement(filter, select);
|
|
|
|
|
|
// 故意用一个固定的随机数种,确保相同的图件,每次打开随机颜色都一样
|
|
|
std::mt19937 gen(123);
|
|
|
std::uniform_int_distribution<int> dist(30, 235); // 30 - 235,把一些接近黑色和接近白色的排除掉
|
|
|
|
|
|
// 颜色生成参数
|
|
|
const int MIN_BRIGHTNESS = 60;
|
|
|
const int MIN_SATURATION_DIFF = 50;
|
|
|
|
|
|
for (POSITION pos = select.GetHeadPosition(); pos != nullptr; select.GetNext(pos))
|
|
|
{
|
|
|
POSITION pt = select.GetAt(pos);
|
|
|
COne* pOne = pXy->GetAt(pt);
|
|
|
|
|
|
if (pOne != nullptr)
|
|
|
{
|
|
|
while (true)
|
|
|
{
|
|
|
int r = dist(gen);
|
|
|
int g = dist(gen);
|
|
|
int b = dist(gen);
|
|
|
|
|
|
// 排除低亮度
|
|
|
double brightness = 0.299 * r + 0.587 * g + 0.114 * b;
|
|
|
if (brightness < 60)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
#pragma push_macro("min")
|
|
|
#pragma push_macro("max")
|
|
|
|
|
|
#undef min
|
|
|
#undef max
|
|
|
// 检查饱和度(颜色差异),饱和度太低的排除掉
|
|
|
int maxVal = std::max({r, g, b});
|
|
|
int minVal = std::min({r, g, b});
|
|
|
if (maxVal - minVal < MIN_SATURATION_DIFF)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
#pragma pop_macro("min")
|
|
|
#pragma pop_macro("max")
|
|
|
|
|
|
CCurveColor(*pOne, RGB(r, g, b));
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
struct ElementEmbellish
|
|
|
{
|
|
|
COne *pOne;
|
|
|
CString DML;
|
|
|
};
|
|
|
|
|
|
class ElementsEmbellishStack
|
|
|
{
|
|
|
public:
|
|
|
ElementsEmbellishStack() = default;
|
|
|
|
|
|
ElementsEmbellishStack(CXy* pXy)
|
|
|
{
|
|
|
m_pXy = pXy;
|
|
|
}
|
|
|
|
|
|
void Save(const CPositionList& positions)
|
|
|
{
|
|
|
StackItem item;
|
|
|
|
|
|
for (POSITION pos = positions.GetHeadPosition(); pos != nullptr; positions.GetNext(pos))
|
|
|
{
|
|
|
POSITION pt = positions.GetAt(pos);
|
|
|
COne* pOne = m_pXy->GetAt(pt);
|
|
|
|
|
|
CString text = GetOneEmbellish(pOne);
|
|
|
|
|
|
ElementEmbellish embellish{ pOne, text };
|
|
|
item.push_back(embellish);
|
|
|
}
|
|
|
|
|
|
m_stack.push(item);
|
|
|
}
|
|
|
|
|
|
void Restore()
|
|
|
{
|
|
|
if (m_stack.empty())
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
StackItem& item = m_stack.top();
|
|
|
auto set = Cache();
|
|
|
|
|
|
for (auto &embellish : item)
|
|
|
{
|
|
|
if (set.contains(embellish.pOne))
|
|
|
{
|
|
|
SetOneEmbellish(embellish.pOne, embellish.DML);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
m_stack.pop();
|
|
|
}
|
|
|
|
|
|
bool IsEmpty() const
|
|
|
{
|
|
|
return m_stack.empty();
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
CString GetOneEmbellish(COne* pOne) const
|
|
|
{
|
|
|
CMemFile memFile;
|
|
|
|
|
|
pOne->WriteDML(memFile, CUR_VERSION, 0);
|
|
|
|
|
|
memFile.SeekToBegin();
|
|
|
|
|
|
auto length = memFile.GetLength();
|
|
|
int nChars = length / sizeof(TCHAR);
|
|
|
|
|
|
CString result;
|
|
|
result.GetBufferSetLength(nChars);
|
|
|
|
|
|
memFile.Read(result.GetBuffer(), length);
|
|
|
|
|
|
result.ReleaseBuffer();
|
|
|
|
|
|
memFile.Close();
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
void SetOneEmbellish(COne* pOne, const CString& text)
|
|
|
{
|
|
|
CMemFile memFile;
|
|
|
|
|
|
memFile.Write(text.GetString(), text.GetLength() * sizeof(TCHAR));
|
|
|
|
|
|
memFile.SeekToBegin();
|
|
|
|
|
|
auto pTempOne = std::make_unique<COne>();
|
|
|
pTempOne->ReadDML(memFile, CUR_VERSION);
|
|
|
|
|
|
memFile.Close();
|
|
|
|
|
|
SwapHowtoView(*pTempOne, *pOne);
|
|
|
}
|
|
|
|
|
|
ankerl::unordered_dense::set<COne*> Cache()
|
|
|
{
|
|
|
ankerl::unordered_dense::set<COne*> set;
|
|
|
|
|
|
CPtrList& values = *(m_pXy->GetValueList());
|
|
|
|
|
|
for (POSITION pos = values.GetHeadPosition(); pos != nullptr; values.GetNext(pos))
|
|
|
{
|
|
|
set.insert(reinterpret_cast<COne*>(values.GetAt(pos)));
|
|
|
}
|
|
|
|
|
|
return set;
|
|
|
}
|
|
|
|
|
|
using StackItem = std::vector<ElementEmbellish>;
|
|
|
using Stack = std::stack<StackItem>;
|
|
|
|
|
|
Stack m_stack;
|
|
|
CXy* m_pXy = nullptr;
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* 统一的元素修饰管理器,目前仅用于断层处理结束时暂时原来的修饰
|
|
|
*/
|
|
|
class ElementsEmbellishManager
|
|
|
{
|
|
|
public:
|
|
|
void SaveElementsEmbellish(CXy* pXy, CPositionList& select)
|
|
|
{
|
|
|
std::lock_guard locker(m_mutex);
|
|
|
|
|
|
auto it = m_map.find(pXy);
|
|
|
if (it == m_map.end())
|
|
|
{
|
|
|
m_map[pXy] = ElementsEmbellishStack(pXy);
|
|
|
}
|
|
|
|
|
|
m_map[pXy].Save(select);
|
|
|
}
|
|
|
|
|
|
void RestoreElementsEmbellish(CXy* pXy)
|
|
|
{
|
|
|
std::lock_guard locker(m_mutex);
|
|
|
|
|
|
auto it = m_map.find(pXy);
|
|
|
if (it != m_map.end())
|
|
|
{
|
|
|
it->second.Restore();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
ankerl::unordered_dense::map<CXy*, ElementsEmbellishStack> m_map;
|
|
|
std::mutex m_mutex;
|
|
|
};
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XySaveElementsEmbellish(CXy* pXy, LPCTSTR layerName, bool includeSubLayer)
|
|
|
{
|
|
|
CPositionList select;
|
|
|
pXy->GetElement(layerName, select, includeSubLayer);
|
|
|
|
|
|
GetInstace<ElementsEmbellishManager>().SaveElementsEmbellish(pXy, select);
|
|
|
}
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
void XyRestoreElementsEmbellish(CXy* pXy)
|
|
|
{
|
|
|
GetInstace<ElementsEmbellishManager>().RestoreElementsEmbellish(pXy);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 保存pdf文件
|
|
|
*
|
|
|
* \param pXy 当前图件
|
|
|
* \param filePath 文件保存全路径
|
|
|
* \param paperType pdf纸张大小 0-A3 1-A4 2-A5 3-B4
|
|
|
* \param cType 0居中 1拉伸
|
|
|
* \param dType 0自适应, 1为纵向, 2横向
|
|
|
* \param left pdf边距
|
|
|
* \param right
|
|
|
* \param top
|
|
|
* \param bottom
|
|
|
* \return
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool SavePDFFile(CXy* pXy, LPCTSTR filePath, int paperType, int cType, int dType, double left, double right, double top, double bottom, int num)
|
|
|
{
|
|
|
if (pXy == NULL || filePath == "")
|
|
|
return FALSE;
|
|
|
|
|
|
NBase::CRect8 rect(1e100, -1e100, -1e100, 1e100);
|
|
|
rect = pXy->m_range;
|
|
|
double dx = rect.Width();
|
|
|
double dy = rect.Height();
|
|
|
if (dx < 1e-20 || dy < 1e-20)
|
|
|
{
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
NBase::CRect8 pRect(left, top, right, bottom);
|
|
|
CDC dc; dc.CreateCompatibleDC(NULL);
|
|
|
CRect rt(0, 0, dx, dy);
|
|
|
CXyDC *pDc = new CXyDC;
|
|
|
pDc->Extend(rect, rt, EXTEND_MODE_STRECH);
|
|
|
pDc->SetViewRect(rt);
|
|
|
pDc->SetPdfPrintState(TRUE);
|
|
|
pDc->SetFilePath(filePath);
|
|
|
pDc->Create(&dc, false);
|
|
|
pDc->SetPdfData(pXy, pRect, paperType, cType, dType, num);
|
|
|
|
|
|
pXy->Draw(*(CXyDC*)pDc, true);
|
|
|
pDc->CloseFile();
|
|
|
delete pDc;
|
|
|
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 合并pdf文件
|
|
|
*
|
|
|
* \param list 需要合并的pdf文件路径(合并顺序按照列表顺序)
|
|
|
* \param count
|
|
|
* \param filePath 合并后的文件
|
|
|
* \return
|
|
|
*/
|
|
|
extern "C" __declspec(dllexport)
|
|
|
bool MergePDFFiles(const wchar_t** list, int count, const wchar_t* filePath)
|
|
|
{
|
|
|
std::vector<CString> vListFile;
|
|
|
for (int i = 0; i < count; i++)
|
|
|
{
|
|
|
CString strFile(list[i]);
|
|
|
vListFile.push_back(strFile);
|
|
|
}
|
|
|
|
|
|
CString strOutFile(filePath);
|
|
|
std::unique_ptr<MergePDFFile> pMerge = std::make_unique<MergePDFFile>();
|
|
|
bool state = pMerge->MergePDFFiles(vListFile, strOutFile);
|
|
|
|
|
|
return state;
|
|
|
}
|
|
|
|
|
|
static std::shared_ptr<ElementFilter> createFilterFromXml(TiXmlElement* elem)
|
|
|
{
|
|
|
if (!elem)
|
|
|
{
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
CString elemName = elem->Value();
|
|
|
|
|
|
if (elemName == _T("TrueFilter"))
|
|
|
{
|
|
|
return std::make_shared<TrueFilter>();
|
|
|
}
|
|
|
else if (elemName == _T("FalseFilter"))
|
|
|
{
|
|
|
return std::make_shared<FalseFilter>();
|
|
|
}
|
|
|
else if (elemName == _T("LayerFilter"))
|
|
|
{
|
|
|
CString layerName = CA2T(elem->Attribute("layerName"));
|
|
|
bool includeSublayer = false;
|
|
|
const char* includeAttr = elem->Attribute("includeSublayer");
|
|
|
if (includeAttr)
|
|
|
{
|
|
|
includeSublayer = (strcmp(includeAttr, "true") == 0);
|
|
|
}
|
|
|
|
|
|
return std::make_shared<LayerFilter>(layerName, includeSublayer);
|
|
|
}
|
|
|
else if (elemName == _T("TypeFilter"))
|
|
|
{
|
|
|
int type = -1;
|
|
|
elem->Attribute("type", &type);
|
|
|
return std::make_shared<TypeFilter>(type);
|
|
|
}
|
|
|
else if (elemName == _T("VisibilityFilter"))
|
|
|
{
|
|
|
bool includeHidden = false;
|
|
|
const char* attr = elem->Attribute("includeHidden");
|
|
|
if (attr)
|
|
|
{
|
|
|
includeHidden = (strcmp(attr, "true") == 0);
|
|
|
}
|
|
|
return std::make_shared<VisibilityFilter>(includeHidden);
|
|
|
}
|
|
|
else if (elemName == _T("EditableFilter"))
|
|
|
{
|
|
|
bool includeNotEditable = false;
|
|
|
const char* attr = elem->Attribute("includeNotEditable");
|
|
|
if (attr)
|
|
|
{
|
|
|
includeNotEditable = (strcmp(attr, "true") == 0);
|
|
|
}
|
|
|
return std::make_shared<EditableFilter>(includeNotEditable);
|
|
|
}
|
|
|
else if (elemName == _T("AndFilter"))
|
|
|
{
|
|
|
auto andFilter = std::make_shared<AndFilter>();
|
|
|
|
|
|
for (TiXmlElement* child = elem->FirstChildElement(); child; child = child->NextSiblingElement())
|
|
|
{
|
|
|
auto childFilter = createFilterFromXml(child);
|
|
|
if (childFilter)
|
|
|
{
|
|
|
andFilter->addFilter(childFilter);
|
|
|
}
|
|
|
}
|
|
|
return andFilter;
|
|
|
}
|
|
|
else if (elemName == _T("OrFilter"))
|
|
|
{
|
|
|
auto orFilter = std::make_shared<OrFilter>();
|
|
|
|
|
|
for (TiXmlElement* child = elem->FirstChildElement(); child; child = child->NextSiblingElement())
|
|
|
{
|
|
|
auto childFilter = createFilterFromXml(child);
|
|
|
if (childFilter)
|
|
|
{
|
|
|
orFilter->addFilter(childFilter);
|
|
|
}
|
|
|
}
|
|
|
return orFilter;
|
|
|
}
|
|
|
else if (elemName == _T("NotFilter"))
|
|
|
{
|
|
|
TiXmlElement* child = elem->FirstChildElement();
|
|
|
if (child)
|
|
|
{
|
|
|
auto childFilter = createFilterFromXml(child);
|
|
|
return std::make_shared<NotFilter>(childFilter);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// 没有子过滤器,默认不匹配
|
|
|
return std::make_shared<NotFilter>(nullptr);
|
|
|
}
|
|
|
}
|
|
|
else if (elemName == _T("NameFilter"))
|
|
|
{
|
|
|
CString nameValue;
|
|
|
bool ignoreCase = true;
|
|
|
bool matchAll = true;
|
|
|
|
|
|
// name
|
|
|
if (const char* attr = elem->Attribute("name"))
|
|
|
{
|
|
|
nameValue = CA2T(attr);
|
|
|
}
|
|
|
|
|
|
// ignoreCase
|
|
|
if (const char* attr = elem->Attribute("ignoreCase"))
|
|
|
{
|
|
|
ignoreCase = (strcmp(attr, "true") == 0);
|
|
|
}
|
|
|
|
|
|
// matchAll
|
|
|
if (const char* attr = elem->Attribute("matchAll"))
|
|
|
{
|
|
|
matchAll = (strcmp(attr, "true") == 0);
|
|
|
}
|
|
|
|
|
|
return std::make_shared<NameFilter>(nameValue, ignoreCase, matchAll);
|
|
|
}
|
|
|
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
extern "C" __declspec(dllexport)
|
|
|
BSTR XyGetElement(CXy* pXy, LPCTSTR filterXml)
|
|
|
{
|
|
|
if (pXy == nullptr)
|
|
|
{
|
|
|
TRACE("pXy 不能为 nullptr\n");
|
|
|
return CString().AllocSysString();
|
|
|
}
|
|
|
|
|
|
if (filterXml == nullptr)
|
|
|
{
|
|
|
TRACE("filterXml 不能为 nullptr\n");
|
|
|
return CString().AllocSysString();
|
|
|
}
|
|
|
|
|
|
TiXmlDocument doc;
|
|
|
doc.Parse(filterXml);
|
|
|
|
|
|
TiXmlElement* pRoot = doc.RootElement();
|
|
|
auto pFilter = createFilterFromXml(pRoot);
|
|
|
if (pFilter == nullptr)
|
|
|
{
|
|
|
TRACE("解析 xml 失败\n");
|
|
|
return CString().AllocSysString();
|
|
|
}
|
|
|
|
|
|
CPositionList select;
|
|
|
pXy->GetElement(pFilter, select);
|
|
|
|
|
|
std::vector<CString> positions;
|
|
|
for (POSITION pos = select.GetHeadPosition(); pos != nullptr; select.GetNext(pos))
|
|
|
{
|
|
|
POSITION pt = select.GetAt(pos);
|
|
|
|
|
|
CString str;
|
|
|
str.Format("%I64d", pt);
|
|
|
positions.push_back(str);
|
|
|
}
|
|
|
|
|
|
return JoinStrings(positions, ",").AllocSysString();
|
|
|
} |