#include "stdafx.h" #include "Util.h" #include "VoronoiMap/InterfaceElements.h" #include 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(first).GetPoint(i); CPointXYZ& p2 = const_cast(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& polylines, const CPolyline & polyline) { return AnyOf(polylines, [&polyline](const CPolyline &e) { return IsEqual(e, polyline); }); } bool CPointXYZContains(const std::vector& pointXYZs, const CPointXYZ &pointXYZ) { return AnyOf(pointXYZs, [&pointXYZ](const CPointXYZ &e) { return IsEqual(e, pointXYZ); }); } std::list PtrsToCOnes(const CPtrList& pList) { std::list result; CListForEach(pos, pList) { COne *pOne = (COne *)pList.GetAt(pos); result.push_back(pOne); } return result; } std::list ConesFilter(const std::list &cones, std::function pred) { return Filter(cones, pred); } bool IsEqual(double a, double b) { constexpr double epsilon = std::numeric_limits::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& 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 SplitString(const CString& string, const CString& delimiter) { std::vector 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 GetValidPositions(CXy* pXy, POSITION positions[], int count) { std::vector 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(wstr.size()), nullptr, 0); if (len == 0) { throw std::runtime_error("Failed to convert string to wstring."); } std::vector buffer(len + 1); if (MultiByteToWideChar(CP_ACP, 0, wstr.c_str(), static_cast(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(wstr.size()), nullptr, 0, nullptr, nullptr); if (len <= 0) { return res; } res.resize(len); WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), static_cast(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(wbuffer.length())); #endif // Get the length after conversion length = WideCharToMultiByte(CP_UTF8, 0, wbuffer.data(), static_cast(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(utf8str.size()), NULL, 0); // Convert to Unicode std::wstring wbuffer; wbuffer.resize(nLen); ::MultiByteToWideChar(CP_UTF8, NULL, utf8str.data(), static_cast(utf8str.size()), (LPWSTR)(wbuffer.data()), static_cast(wbuffer.length())); #ifdef UNICODE return CString(wbuffer.data(), wbuffer.length()); #else // Convert to ANSI nLen = WideCharToMultiByte(CP_ACP, 0, wbuffer.data(), static_cast(wbuffer.length()), NULL, 0, NULL, NULL); std::string ansistr; ansistr.resize(nLen); WideCharToMultiByte(CP_ACP, 0, (LPWSTR)(wbuffer.data()), static_cast(wbuffer.length()), (LPSTR)(ansistr.data()), static_cast(ansistr.size()), NULL, NULL); return CString(ansistr.data(), static_cast(ansistr.length())); #endif }