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.

408 lines
8.8 KiB
C++

This file contains ambiguous Unicode characters!

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

#include "stdafx.h"
#include "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(); // 取浮点精度
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)
{
// 多边形至少3条边
if (pCurve->num < 3)
{
return false;
}
int last = pCurve->num - 1;
// 这里直接使用 = 判等是安全的,因为是拿同一曲线内部的点进行对比
return pCurve->x[0] == pCurve->x[last]
&& pCurve->y[0] == pCurve->y[last]
&& pCurve->z[0] == pCurve->z[last];
}
bool IsApproximatePolygon(const CCurveEx* pCurve)
{
// 多边形至少3条边
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];
// 未闭合长度
double distance = CalcDistance(x1, y1, x2, y2);
// 曲线长度
double sum = CalcCurveDistance(pCurve);
return distance <= sum / 10;
}
CCurveEx* CreateCloseCurve(const CCurveEx* pCurve)
{
// 如果只有一条边或更少,无法闭合,直接返回 nullptr
if (pCurve->num < 2)
{
return nullptr;
}
// 判断曲线是否闭合
bool isClosed = IsPolygon(pCurve);
// 创建新的 CCurveEx 对象,并根据闭合状态设置点的数量
int num = isClosed ? pCurve->num : pCurve->num + 1;
CCurveEx *pNewCurve = new CCurveEx();
pNewCurve->Create(num);
// 复制原始曲线的点
for (int i = 0; i < pCurve->num; i++)
{
pNewCurve->x[i] = pCurve->x[i];
pNewCurve->y[i] = pCurve->y[i];
pNewCurve->z[i] = pCurve->z[i];
}
// 如果曲线未闭合,添加首点作为最后一个点以闭合曲线
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: 这里的长度有 BUG先特殊处理一下
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
}