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

373 lines
10 KiB
C++

1 month ago
#include "stdafx.h"
#include "TableDataImporter.h"
#include "TsvParser.h"
#include "SigmaView.h"
#include <map>
//-----------------------------------------------------------------------------
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>ʹ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><C2B6>
//-----------------------------------------------------------------------------
namespace
{
static const CString COL_X(_T("X"));
static const CString COL_Y(_T("Y"));
static const CString COL_Z(_T("Z"));
static const CString COL_L(_T("L"));
static const CString COL_NAME(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
static const CString COL_LAYER(_T("ͼ<EFBFBD><EFBFBD>"));
static const CString DEFAULT_LAYER(_T("0"));
/** <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰУ<C7B0>鲢ȡ<E9B2A2><C8A1>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܷ<EFBFBD><DCB7><EFBFBD> nullptr */
CXy* GetXyForTableImport(CSigmaView* pView, const TsvParser::TableData& tableData, const TCHAR* tracePrefix)
{
if (pView == nullptr || pView->m_pDoc == nullptr)
{
TRACE("%s - <20><>ͼ<EFBFBD><CDBC><EFBFBD>ĵ<EFBFBD>Ϊ<EFBFBD><CEAA>\n", tracePrefix);
return nullptr;
}
CXy* pXy = pView->m_pDoc->GetDraw();
if (pXy == nullptr)
{
TRACE("%s - <20>޷<EFBFBD><DEB7><EFBFBD>ȡ<EFBFBD><C8A1>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>\n", tracePrefix);
return nullptr;
}
if (tableData.IsEmpty())
{
TRACE("%s - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>\n", tracePrefix);
return nullptr;
}
if (tableData.GetColumnIndex(COL_X) < 0 || tableData.GetColumnIndex(COL_Y) < 0)
{
TRACE("%s - ȱ<>ٱ<EFBFBD><D9B1><EFBFBD><EFBFBD><EFBFBD> X <20><> Y <20><>\n", tracePrefix);
return nullptr;
}
return pXy;
}
/** <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>layerName <20><><EFBFBD>name Ϊ<><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD> */
void AddOnePointToDocument(CXy* pXy, double x, double y, double z, const CString& layerName, const CString& name)
{
CPointNameEx* pPoint = new CPointNameEx();
pPoint->x0 = x;
pPoint->y0 = y;
pPoint->z0 = z;
if (!name.IsEmpty())
pPoint->SetName(name);
CLayer* pLayer = pXy->FindAddLayer(layerName);
POSITION pos = pXy->AddElement(pPoint, DOUBLEFOX_POINT);
COne* pOne = pXy->GetAt(pos);
pOne->SetLayer(pLayer);
}
}
namespace
{
struct CurveEntry
{
double x, y, z, length;
CString name;
CString layer;
};
/** <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD><DFB5><EFBFBD><EBA3BA><EFBFBD><EFBFBD> <20><> <20><>ͼ<EFBFBD><CDBC>/<2F><><EFBFBD>Ʒ<EFBFBD><C6B7><EFBFBD> <20><> д<><D0B4><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>ʵ<EFBFBD><CAB5>ϸ<EFBFBD>ڼ<EFBFBD><DABC><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD> */
class CurveTableImporter
{
public:
/** @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD> -1 */
int Import(CXy* pXy, const TsvParser::TableData& tableData)
{
std::vector<CurveEntry> entries = ParseTableToCurveEntries(tableData);
if (entries.empty())
return -1;
std::map<CString, std::vector<std::vector<CurveEntry>>> layerCurves = GroupEntriesByLayerAndCurveName(entries);
return AddCurvesToDocument(pXy, layerCurves);
}
private:
static std::vector<CurveEntry> ParseTableToCurveEntries(const TsvParser::TableData& tableData)
{
std::vector<CurveEntry> entries;
for (const auto& row : tableData.rows)
{
CString strX = tableData.GetValue(row, COL_X);
CString strY = tableData.GetValue(row, COL_Y);
if (strX.IsEmpty() || strY.IsEmpty())
continue;
CurveEntry entry;
entry.x = _tstof(strX);
entry.y = _tstof(strY);
entry.z = tableData.GetDoubleValue(row, COL_Z, 0.0);
entry.length = tableData.GetDoubleValue(row, COL_L, 0.0);
entry.name = tableData.GetValue(row, COL_NAME);
entry.layer = tableData.GetValue(row, COL_LAYER);
if (entry.layer.IsEmpty())
entry.layer = DEFAULT_LAYER;
entries.push_back(entry);
}
return entries;
}
/** <20><>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>飬ͬһͼ<D2BB><CDBC><EFBFBD><EFBFBD><EFBFBD>ٰ<EFBFBD><D9B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD><C6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>з<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
static std::map<CString, std::vector<std::vector<CurveEntry>>> GroupEntriesByLayerAndCurveName(const std::vector<CurveEntry>& entries)
{
std::map<CString, std::vector<CurveEntry>> layerEntries;
for (const auto& entry : entries)
layerEntries[entry.layer].push_back(entry);
std::map<CString, std::vector<std::vector<CurveEntry>>> layerCurves;
for (const auto& layerPair : layerEntries)
{
const CString& layerName = layerPair.first;
const auto& layerPoints = layerPair.second;
std::vector<std::vector<CurveEntry>> curves;
std::vector<CurveEntry> currentCurve;
CString currentName;
for (const auto& entry : layerPoints)
{
if (currentCurve.empty() || currentName != entry.name)
{
if (!currentCurve.empty())
{
curves.push_back(currentCurve);
currentCurve.clear();
}
currentName = entry.name;
}
currentCurve.push_back(entry);
}
if (!currentCurve.empty())
curves.push_back(currentCurve);
layerCurves[layerName] = curves;
}
return layerCurves;
}
static int AddCurvesToDocument(CXy* pXy, const std::map<CString, std::vector<std::vector<CurveEntry>>>& layerCurves)
{
int importCount = 0;
for (const auto& layerPair : layerCurves)
{
const CString& layerName = layerPair.first;
const auto& curves = layerPair.second;
CLayer* pLayer = pXy->FindAddLayer(layerName);
for (const auto& curvePoints : curves)
{
if (curvePoints.empty())
continue;
CCurveEx* pCurve = new CCurveEx();
pCurve->SetName(curvePoints[0].name);
pCurve->Create((int)curvePoints.size());
pCurve->width = 1;
for (size_t i = 0; i < curvePoints.size(); i++)
{
pCurve->x[i] = curvePoints[i].x;
pCurve->y[i] = curvePoints[i].y;
pCurve->z[i] = curvePoints[i].z;
pCurve->l[i] = curvePoints[i].length;
}
pCurve->GetLocation();
POSITION pos = pXy->AddElement(pCurve, DOUBLEFOX_CURVE);
COne* pOne = pXy->GetAt(pos);
pOne->SetLayer(pLayer);
importCount++;
}
}
return importCount;
}
};
}
int ImportTableAsCurves(CSigmaView* pView, const TsvParser::TableData& tableData)
{
CXy* pXy = GetXyForTableImport(pView, tableData, _T("ImportTableAsCurves"));
if (pXy == nullptr)
return -1;
int importCount = CurveTableImporter().Import(pXy, tableData);
if (importCount < 0)
{
TRACE("ImportTableAsCurves - û<><C3BB><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n");
return -1;
}
TRACE("ImportTableAsCurves - <20>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD> %d <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n", importCount);
return importCount;
}
//=============================================================================
// <20><>ʽ<EFBFBD><CABD><EFBFBD>е<EFBFBD><D0B5><EFBFBD>
//=============================================================================
void BuildColumnIndexMapFromHeaders(const std::vector<CString>& headers, std::map<CString, int>& outMap)
{
outMap.clear();
for (size_t i = 0; i < headers.size(); i++)
{
CString key = headers[i];
key.MakeUpper();
key.Trim();
outMap[key] = (int)i;
}
}
CString GetRowValue(const std::vector<CString>& row, const std::map<CString, int>& columnIndexMap, const CString& columnName)
{
CString key = columnName;
key.MakeUpper();
key.Trim();
auto it = columnIndexMap.find(key);
if (it != columnIndexMap.end() && it->second >= 0 && it->second < (int)row.size())
{
CString v = row[it->second];
v.Trim();
return v;
}
return _T("");
}
double GetRowDoubleValue(const std::vector<CString>& row, const std::map<CString, int>& columnIndexMap, const CString& columnName, double defaultValue)
{
CString s = GetRowValue(row, columnIndexMap, columnName);
if (s.IsEmpty())
return defaultValue;
return _tstof(s);
}
namespace
{
/** <20><>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>е㣬withName Ϊ true ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD><C6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD><C3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>з<EFBFBD><D0B7><EFBFBD> true<75><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD> */
bool ImportPointRowStreamImpl(CSigmaView* pView, const std::map<CString, int>& columnIndexMap, const std::vector<CString>& row, bool withName)
{
if (pView == nullptr || pView->m_pDoc == nullptr)
{
return false;
}
CXy* pXy = pView->m_pDoc->GetDraw();
if (pXy == nullptr)
{
return false;
}
CString strX = GetRowValue(row, columnIndexMap, COL_X);
CString strY = GetRowValue(row, columnIndexMap, COL_Y);
if (strX.IsEmpty() || strY.IsEmpty())
{
return true; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
}
double x = _tstof(strX);
double y = _tstof(strY);
double z = GetRowDoubleValue(row, columnIndexMap, COL_Z, 0.0);
CString layerName = GetRowValue(row, columnIndexMap, COL_LAYER);
if (layerName.IsEmpty())
{
layerName = DEFAULT_LAYER;
}
CString name;
if (withName)
{
name = GetRowValue(row, columnIndexMap, COL_NAME);
}
AddOnePointToDocument(pXy, x, y, z, layerName, name);
return true;
}
}
bool ImportPointRow(CSigmaView* pView, const std::map<CString, int>& columnIndexMap, const std::vector<CString>& row)
{
return ImportPointRowStreamImpl(pView, columnIndexMap, row, true);
}
bool ImportXyzPointRow(CSigmaView* pView, const std::map<CString, int>& columnIndexMap, const std::vector<CString>& row)
{
return ImportPointRowStreamImpl(pView, columnIndexMap, row, false);
}
// ---------------------------------------------------------------------------
// CurveStreamImporter
// ---------------------------------------------------------------------------
CurveStreamImporter::CurveStreamImporter(CSigmaView* pView)
: m_pView(pView)
{
if (pView && pView->m_pDoc)
m_pXy = pView->m_pDoc->GetDraw();
}
void CurveStreamImporter::OnRow(const std::map<CString, int>& columnIndexMap, const std::vector<CString>& row)
{
if (m_pXy == nullptr)
return;
CString strX = GetRowValue(row, columnIndexMap, COL_X);
CString strY = GetRowValue(row, columnIndexMap, COL_Y);
if (strX.IsEmpty() || strY.IsEmpty())
return;
double x = _tstof(strX);
double y = _tstof(strY);
double z = GetRowDoubleValue(row, columnIndexMap, COL_Z, 0.0);
double l = GetRowDoubleValue(row, columnIndexMap, COL_L, 0.0);
CString name = GetRowValue(row, columnIndexMap, COL_NAME);
CString layer = GetRowValue(row, columnIndexMap, COL_LAYER);
if (layer.IsEmpty())
layer = DEFAULT_LAYER;
if (!m_curX.empty() && (m_currentLayer != layer || m_currentName != name))
FlushCurrentCurve();
m_currentLayer = layer;
m_currentName = name;
m_curName = name;
m_curX.push_back(x);
m_curY.push_back(y);
m_curZ.push_back(z);
m_curL.push_back(l);
}
void CurveStreamImporter::FlushCurrentCurve()
{
if (m_pXy == nullptr || m_curX.empty())
return;
CLayer* pLayer = m_pXy->FindAddLayer(m_currentLayer);
CCurveEx* pCurve = new CCurveEx();
pCurve->SetName(m_curName);
pCurve->Create((int)m_curX.size());
pCurve->width = 1;
for (size_t i = 0; i < m_curX.size(); i++)
{
pCurve->x[i] = m_curX[i];
pCurve->y[i] = m_curY[i];
pCurve->z[i] = m_curZ[i];
pCurve->l[i] = m_curL[i];
}
pCurve->GetLocation();
POSITION pos = m_pXy->AddElement(pCurve, DOUBLEFOX_CURVE);
COne* pOne = m_pXy->GetAt(pos);
pOne->SetLayer(pLayer);
m_curX.clear();
m_curY.clear();
m_curZ.clear();
m_curL.clear();
m_importCount++;
}
void CurveStreamImporter::End()
{
FlushCurrentCurve();
}