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.

407 lines
8.9 KiB
C++

1 month ago
#include "stdafx.h"
#include "Util.h"
#include "VoronoiMap/InterfaceElements.h"
#include <algorithm>
bool IsEqual(const CCurveEx * first, const CCurveEx * second)
{
if (first->num != second->num)
{
return false;
}
for (int i = 0; i < first->num; i++)
{
if (!IsEqual(first->x[i], second->x[i])
|| !IsEqual(first->y[i], second->y[i]))
{
return false;
break;
}
}
return true;
}
bool IsEqual(const CPolyline & first, const CPolyline & second)
{
if (first.GetSize() != second.GetSize())
{
return false;
}
for (int i = 0; i < first.GetSize(); i++)
{
CPointXYZ& p1 = const_cast<CPolyline&>(first).GetPoint(i);
CPointXYZ& p2 = const_cast<CPolyline&>(second).GetPoint(i);
if (!IsEqual(p1, p2))
{
return false;
}
}
return true;
}
bool IsEqual(const CPointXYZ & first, const CPointXYZ & second)
{
return IsEqual(first.x0, second.x0)
&& IsEqual(first.y0, second.y0)
&& IsEqual(first.z0, second.z0);
}
bool CPolylinesContains(const std::list<CPolyline>& polylines, const CPolyline & polyline)
{
return AnyOf(polylines, [&polyline](const CPolyline &e)
{
return IsEqual(e, polyline);
});
}
bool CPointXYZContains(const std::vector<CPointXYZ>& pointXYZs, const CPointXYZ &pointXYZ)
{
return AnyOf(pointXYZs, [&pointXYZ](const CPointXYZ &e)
{
return IsEqual(e, pointXYZ);
});
}
std::list<COne*> PtrsToCOnes(const CPtrList& pList)
{
std::list<COne*> result;
CListForEach(pos, pList)
{
COne *pOne = (COne *)pList.GetAt(pos);
result.push_back(pOne);
}
return result;
}
std::list<COne*> ConesFilter(const std::list<COne*> &cones, std::function<bool(COne*)> pred)
{
return Filter(cones, pred);
}
bool IsEqual(double a, double b)
{
constexpr double epsilon = std::numeric_limits<double>::epsilon(); // ȡ<><C8A1><EFBFBD><EFBFBD><E3BEAB>
return std::fabs(a - b) < epsilon;
}
bool IsLessThan(double a, double b)
{
return !IsEqual(a, b) && a < b;
}
bool IsGreaterThan(double a, double b)
{
return !IsEqual(a, b) && a > b;
}
bool IsPolygon(const CCurveEx* pCurve)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3<EFBFBD><33><EFBFBD><EFBFBD>
if (pCurve->num < 3)
{
return false;
}
int last = pCurve->num - 1;
// <20><><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>ʹ<EFBFBD><CAB9> = <20>е<EFBFBD><D0B5>ǰ<EFBFBD>ȫ<EFBFBD>ģ<EFBFBD><C4A3><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ͬһ<CDAC><D2BB><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD>жԱ<D0B6>
return pCurve->x[0] == pCurve->x[last]
&& pCurve->y[0] == pCurve->y[last]
&& pCurve->z[0] == pCurve->z[last];
}
bool IsApproximatePolygon(const CCurveEx* pCurve)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3<EFBFBD><33><EFBFBD><EFBFBD>
if (pCurve->num < 3)
{
return false;
}
if (IsPolygon(pCurve))
{
return true;
}
int num = pCurve->num;
double x1 = pCurve->x[num - 2];
double y1 = pCurve->y[num - 2];
double x2 = pCurve->x[num - 1];
double y2 = pCurve->y[num - 1];
// δ<>պϳ<D5BA><CFB3><EFBFBD>
double distance = CalcDistance(x1, y1, x2, y2);
// <20><><EFBFBD>߳<EFBFBD><DFB3><EFBFBD>
double sum = CalcCurveDistance(pCurve);
return distance <= sum / 10;
}
CCurveEx* CreateCloseCurve(const CCurveEx* pCurve)
{
// <20><><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>һ<EFBFBD><D2BB><EFBFBD>߻<EFBFBD><DFBB><EFBFBD><EFBFBD>٣<EFBFBD><D9A3>޷<EFBFBD><DEB7>պϣ<D5BA>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD> nullptr
1 month ago
if (pCurve == nullptr || pCurve->num < 2)
1 month ago
{
return nullptr;
}
// <20>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>պ<EFBFBD>
bool isClosed = IsPolygon(pCurve);
// <20><><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD> CCurveEx <20><><EFBFBD>󣬲<EFBFBD><F3A3ACB2><EFBFBD><EFBFBD>ݱպ<DDB1>״̬<D7B4><CCAC><EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int num = isClosed ? pCurve->num : pCurve->num + 1;
1 month ago
1 month ago
CCurveEx *pNewCurve = new CCurveEx();
pNewCurve->Create(num);
// <20><><EFBFBD><EFBFBD>ԭʼ<D4AD><CABC><EFBFBD>ߵĵ<DFB5>
1 month ago
memcpy(pNewCurve->x, pCurve->x, sizeof(double) * pCurve->num);
memcpy(pNewCurve->y, pCurve->y, sizeof(double) * pCurve->num);
memcpy(pNewCurve->z, pCurve->z, sizeof(double) * pCurve->num);
pNewCurve->GetLocation();
1 month ago
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD>պϣ<D5BA><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׵<EFBFBD><D7B5><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>Ապ<D4B1><D5BA><EFBFBD><EFBFBD><EFBFBD>
if (!isClosed)
{
pNewCurve->x[pCurve->num] = pCurve->x[0];
pNewCurve->y[pCurve->num] = pCurve->y[0];
pNewCurve->z[pCurve->num] = pCurve->z[0];
}
pNewCurve->GetLocation();
return pNewCurve;
}
double CalcDistance(double x1, double y1, double x2, double y2)
{
double a = x2 - x1;
double b = y2 - y1;
return sqrt(a * a + b * b);
}
double CalcCurveDistance(const CCurveEx* pCurve)
{
double sum = 0;
for (int i = 0; i < pCurve->num - 1; i++)
{
double x1 = pCurve->x[i];
double y1 = pCurve->y[i];
double x2 = pCurve->x[i + 1];
double y2 = pCurve->y[i + 1];
sum += CalcDistance(x1, y1, x2, y2);
}
return sum;
}
double CalcSlope(double x1, double y1, double x2, double y2)
{
assert(!IsEqual(x1, x2));
return (y2 - y1) / (x2 - x1);
}
bool SearchMatch(const CString& source, const CString& search, bool ignoreCase, bool matchWholeWord)
{
CString sourceText = source;
CString searchText = search;
if (ignoreCase)
{
sourceText.MakeLower();
searchText.MakeLower();
}
if (matchWholeWord)
{
return sourceText == searchText;
}
else
{
return sourceText.Find(searchText) == 0;
}
}
CString GetParentLayerPath(const CString& pLayer)
{
int pos = pLayer.ReverseFind(_T('\\'));
if (pos == -1)
{
return _T("");
}
return pLayer.Left(pos);
}
bool IsSameLayerName(const CString& layerName1, const CString& layerName2)
{
return CLayerName(layerName1).GetFullPathNameA() == CLayerName(layerName2).GetFullPathNameA();
}
CString JoinStrings(const std::vector<CString>& strings, const CString& delimiter)
{
CString result;
for (size_t i = 0; i < strings.size(); ++i)
{
result += strings[i];
if (i != strings.size() - 1)
{
result += delimiter;
}
}
return result;
}
std::vector<CString> SplitString(const CString& string, const CString& delimiter)
{
std::vector<CString> result;
int start = 0;
int end = string.Find(delimiter, start);
while (end != -1)
{
result.push_back(string.Mid(start, end - start));
start = end + delimiter.GetLength();
end = string.Find(delimiter, start);
}
if (start < string.GetLength())
{
result.push_back(string.Mid(start));
}
return result;
}
bool IsValidPosition(CXy *pXy, POSITION position)
{
CPtrList* pValueList = pXy->GetValueList();
for (POSITION pos = pValueList->GetHeadPosition(); pos != nullptr; pValueList->GetNext(pos))
{
if (pos == position)
{
return true;
}
}
return false;
}
std::vector<POSITION> GetValidPositions(CXy* pXy, POSITION positions[], int count)
{
std::vector<POSITION > result;
CPtrList* pValueList = pXy->GetValueList();
for (POSITION pos = pValueList->GetHeadPosition(); pos != nullptr; pValueList->GetNext(pos))
{
for (int i = 0; i < count; i++)
{
if (positions[i] == pos)
{
result.push_back(positions[i]);
}
}
}
return result;
}
std::wstring StringToWString(const std::string& wstr)
{
std::wstring res;
int len = MultiByteToWideChar(CP_ACP, 0, wstr.c_str(), static_cast<int>(wstr.size()), nullptr, 0);
if (len == 0)
{
throw std::runtime_error("Failed to convert string to wstring.");
}
std::vector<wchar_t> buffer(len + 1);
if (MultiByteToWideChar(CP_ACP, 0, wstr.c_str(), static_cast<int>(wstr.size()), buffer.data(), len) == 0)
{
throw std::runtime_error("Failed to convert string to wstring.");
}
res.assign(buffer.begin(), buffer.end());
return res;
}
std::string WStringToString(const std::wstring &wstr)
{
std::string res;
int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), static_cast<int>(wstr.size()), nullptr, 0, nullptr, nullptr);
if (len <= 0)
{
return res;
}
res.resize(len);
WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), static_cast<int>(wstr.size()), &res[0], len, nullptr, nullptr);
return res;
}
std::string CStringToUtf8String(const CString& strValue)
{
if (strValue.IsEmpty())
{
return std::string();
}
std::wstring wbuffer;
#ifdef _UNICODE
wbuffer.assign(strValue.GetString(), strValue.GetLength());
#else
// Convert ANSI to UNICODE
int length = ::MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, (LPCTSTR)strValue, -1, NULL, 0);
wbuffer.resize(length);
MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)strValue, -1, (LPWSTR)(wbuffer.data()), static_cast<int>(wbuffer.length()));
#endif
// Get the length after conversion
length = WideCharToMultiByte(CP_UTF8, 0, wbuffer.data(), static_cast<int>(wbuffer.size()), NULL, 0, NULL, NULL);
// Get the converted content
std::string buffer;
buffer.resize(length);
WideCharToMultiByte(CP_UTF8, 0, wbuffer.data(), -1, (LPSTR)(buffer.data()), length, NULL, NULL);
// FIXME: <20><><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD> BUG<55><47><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E2B4A6>һ<EFBFBD><D2BB>
buffer.resize(strlen(buffer.data()));
return buffer;
}
CString Utf8StringToCString(const std::string& utf8str)
{
// Pre-convert to get the required space size
int nLen = ::MultiByteToWideChar(CP_UTF8, NULL, utf8str.data(), static_cast<int>(utf8str.size()), NULL, 0);
// Convert to Unicode
std::wstring wbuffer;
wbuffer.resize(nLen);
::MultiByteToWideChar(CP_UTF8, NULL, utf8str.data(), static_cast<int>(utf8str.size()), (LPWSTR)(wbuffer.data()), static_cast<int>(wbuffer.length()));
#ifdef UNICODE
return CString(wbuffer.data(), wbuffer.length());
#else
// Convert to ANSI
nLen = WideCharToMultiByte(CP_ACP, 0, wbuffer.data(), static_cast<int>(wbuffer.length()), NULL, 0, NULL, NULL);
std::string ansistr;
ansistr.resize(nLen);
WideCharToMultiByte(CP_ACP, 0, (LPWSTR)(wbuffer.data()), static_cast<int>(wbuffer.length()), (LPSTR)(ansistr.data()), static_cast<int>(ansistr.size()), NULL, NULL);
return CString(ansistr.data(), static_cast<int>(ansistr.length()));
#endif
}