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.

1491 lines
31 KiB
C

1 month ago
#pragma once
#include <algorithm>
#include <functional>
#include <chrono>
#include <ctime>
#include <iomanip>
#include "DrawOperator/RTree.h"
#include "VoronoiMap/InterfaceElements.h"
/**
* CList <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \list CList <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \pos POSITION <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>λ<EFBFBD>ã<EFBFBD>Ҫȡ<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> list.GetAt(pos)
*/
#define CListForEach(pos, list) \
for (POSITION pos = (list).GetHeadPosition(); pos != nullptr; (list).GetNext(pos))
/**
* CList <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \list CList <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \pos POSITION <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>λ<EFBFBD>ã<EFBFBD>Ҫȡ<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> list.GetAt(pos)
*/
#define CListForEachReverse(pos, list) \
for (POSITION pos = (list).GetTailPosition(); pos != nullptr; (list).GetPrev(pos))
template <typename T>
inline CString ToCString(const T& value)
{
return _T("");
}
template <>
inline CString ToCString<int32_t>(const int32_t& value)
{
CString str;
str.Format(_T("%d"), value);
return str;
}
template <>
inline CString ToCString<uint32_t>(const uint32_t& value)
{
CString str;
str.Format(_T("%u"), value);
return str;
}
template <>
inline CString ToCString<long>(const long& value)
{
CString str;
str.Format(_T("%ld"), value);
return str;
}
template <>
inline CString ToCString<unsigned long>(const unsigned long& value)
{
CString str;
str.Format(_T("%lu"), value);
return str;
}
template <>
inline CString ToCString<int64_t>(const int64_t& value)
{
CString str;
str.Format(_T("%lld"), value);
return str;
}
template <>
inline CString ToCString<uint64_t>(const uint64_t& value)
{
CString str;
str.Format(_T("%llu"), value);
return str;
}
template <>
inline CString ToCString<float>(const float& value)
{
CString str;
str.Format(_T("%f"), value);
return str;
}
template <>
inline CString ToCString<double>(const double& value)
{
CString str;
str.Format(_T("%f"), value);
return str;
}
template <>
inline CString ToCString<bool>(const bool& value)
{
return value ? _T("true") : _T("false");
}
template <>
inline CString ToCString<CString>(const CString& value)
{
return value;
}
template <typename T>
T& GetInstance()
{
static T instance;
return instance;
}
/**
* CList <EFBFBD>б<EFBFBD><EFBFBD>ϲ<EFBFBD>
*
* \param source Դ<EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>
* \param target <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>Ԫ<EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
*/
template<typename T, typename E>
void CListAddRange(CList<T, E> &source, const CList<T, E> &target)
{
for (POSITION pos = (target).GetHeadPosition(); pos != nullptr; (target).GetNext(pos))
{
source.AddTail(target.GetAt(pos));
}
}
/**
* CList <EFBFBD>б<EFBFBD><EFBFBD>Ƴ<EFBFBD>
*
* <EFBFBD><EFBFBD> source <EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> target <EFBFBD>д<EFBFBD><EFBFBD>ڵ<EFBFBD>Ԫ<EFBFBD><EFBFBD>
*
* \param source Դ<EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>
* \param target Ҫ<EFBFBD>Ƴ<EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ؼ<EFBFBD><EFBFBD><EFBFBD>
*/
template<typename T, typename E>
void CListRemoveRange(CList<T, E>& source, const CList<T, E>& target)
{
// <20><><EFBFBD><EFBFBD>Դ<EFBFBD>б<EFBFBD>
POSITION pos = source.GetHeadPosition();
while (pos != nullptr)
{
POSITION currentPos = pos;
T& element = source.GetNext(pos);
if (target.Find(element) != nullptr)
{
source.RemoveAt(currentPos);
}
}
}
/**
* <EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param first
* \param second
* \return
*/
bool IsEqual(const CCurveEx *first, const CCurveEx *second);
/**
* <EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param first
* \param second
* \return
*/
bool IsEqual(const CPolyline &first, const CPolyline &second);
/**
* <EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param first
* \param second
* \return
*/
bool IsEqual(const CPointXYZ &first, const CPointXYZ &second);
/**
* double <EFBFBD>еȲ<EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> =
*/
bool IsEqual(double a, double b);
/**
* double <EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
*/
bool IsGreaterThan(double a, double b);
/**
* double <EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
*/
bool IsLessThan(double a, double b);
/**
* <EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ򵥵<EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>β<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
bool IsPolygon(const CCurveEx * pCurve);
/**
* <EFBFBD>ж<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> x,y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> z ֵ
* \return <EFBFBD><EFBFBD>βδ<EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܳ<EFBFBD><EFBFBD>ȵ<EFBFBD>ʮ<EFBFBD><EFBFBD>֮һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> true<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>򷵻<EFBFBD> false<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> true
*/
bool IsApproximatePolygon(const CCurveEx * pCurve);
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>պ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><EFBFBD><EFBFBD>β<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \return <EFBFBD><EFBFBD><EFBFBD><EFBFBD> pCurve <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> nullptr, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><EFBFBD>DZպϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>򷵻<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>պϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \note <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>п<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><EFBFBD><EFBFBD>ͬһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD>պ<EFBFBD>
*/
CCurveEx* CreateCloseCurve(const CCurveEx * pCurve);
/**
* <EFBFBD>ж<EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD> polyline <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>ڼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param polylines
* \param polyline
* \return
*/
bool CPolylinesContains(const std::list<CPolyline> &polylines, const CPolyline &polyline);
/**
* <EFBFBD>ж<EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param pointXYZs
* \param pointXYZ
*/
bool CPointXYZContains(const std::vector<CPointXYZ> &pointXYZs, const CPointXYZ &pointXYZ);
/**
* <EFBFBD>ж<EFBFBD> x y <EFBFBD><EFBFBD><EFBFBD>ɵĵ<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD> rect <EFBFBD><EFBFBD>
*
* \param x x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param y y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param rect <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \return
*/
inline bool IsInRect(double x, double y, const NBase::CRect8& rect)
{
return x >= rect.left && x <= rect.right && y >= rect.bottom && y <= rect.top;
}
inline bool IsInRect(const NBase::CRect8& subRect, const NBase::CRect8& rect)
{
return (subRect.left >= rect.left) &&
(subRect.right <= rect.right) &&
(subRect.bottom >= rect.bottom) &&
(subRect.top <= rect.top);
}
/**
* <EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>
* \param
*/
inline bool IsIntersecting(const NBase::CRect8& rect1, const NBase::CRect8& rect2)
{
return rect1.right > rect2.left
&& rect1.left < rect2.right
&& rect1.top > rect2.bottom
&& rect1.bottom < rect2.top;
}
/**
* <EFBFBD>ж<EFBFBD><EFBFBD>±<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD>±<EFBFBD>
*
* \param curve <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param index <EFBFBD>±<EFBFBD>
* \return
*/
inline bool IsFirstIndex(CCurveEx& curve, int32_t index)
{
return curve.num > 0 && index == 0;
}
/**
* <EFBFBD>ж<EFBFBD><EFBFBD>±<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߵĽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD>
*
* \param curve <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param index <EFBFBD>±<EFBFBD>
* \return
*/
inline bool IsLastIndex(CCurveEx& curve, int32_t index)
{
return curve.num > 0 && index == curve.num - 1;
}
/**
* @brief <EFBFBD>жϵ<EFBFBD> (px0, py0) <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD> (px1,py1)-(px2,py2) <EFBFBD><EFBFBD>
*
* @param px0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param py0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param px1 <EFBFBD>߶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param py1 <EFBFBD>߶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param px2 <EFBFBD>߶<EFBFBD><EFBFBD>յ<EFBFBD><EFBFBD><EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param py2 <EFBFBD>߶<EFBFBD><EFBFBD>յ<EFBFBD><EFBFBD><EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return true <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><EFBFBD><EFBFBD>
* @return false <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><EFBFBD><EFBFBD>
*/
inline bool IsPointOnLine(double px0, double py0, double px1, double py1, double px2, double py2)
{
double crossProduct = (px1 - px0) * (py2 - py0) - (px2 - px0) * (py1 - py0);
return (std::abs(crossProduct) < std::numeric_limits<double>::epsilon()) &&
((px0 - px1) * (px0 - px2) <= 0) &&
((py0 - py1) * (py0 - py2) <= 0);
}
/**
* @brief <EFBFBD>ж<EFBFBD><EFBFBD>߶<EFBFBD> (px1,py1)-(px2,py2) <EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD> (px3,py3)-(px4,py4) <EFBFBD>Ƿ<EFBFBD><EFBFBD>
*
* @note <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶β<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD>ߵĽ<EFBFBD><EFBFBD><EFBFBD>
* @param px1 <EFBFBD><EFBFBD>һ<EFBFBD>߶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param py1 <EFBFBD><EFBFBD>һ<EFBFBD>߶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param px2 <EFBFBD><EFBFBD>һ<EFBFBD>߶<EFBFBD><EFBFBD>յ<EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param py2 <EFBFBD><EFBFBD>һ<EFBFBD>߶<EFBFBD><EFBFBD>յ<EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param px3 <EFBFBD>ڶ<EFBFBD><EFBFBD>߶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param py3 <EFBFBD>ڶ<EFBFBD><EFBFBD>߶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param px4 <EFBFBD>ڶ<EFBFBD><EFBFBD>߶<EFBFBD><EFBFBD>յ<EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param py4 <EFBFBD>ڶ<EFBFBD><EFBFBD>߶<EFBFBD><EFBFBD>յ<EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return true <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><EFBFBD>ڷǹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return false <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶β<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
inline bool IsIntersect(double px1, double py1, double px2, double py2, double px3, double py3, double px4, double py4)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ
double denominator = (px2 - px1) * (py4 - py3) - (py2 - py1) * (px4 - px3);
// ƽ<><C6BD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
if (std::abs(denominator) < std::numeric_limits<double>::epsilon())
{
return false;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5>
double r_numerator = (py1 - py3) * (px4 - px3) - (px1 - px3) * (py4 - py3);
double s_numerator = (py1 - py3) * (px2 - px1) - (px1 - px3) * (py2 - py1);
double r = r_numerator / denominator;
double s = s_numerator / denominator;
return (r >= 0 && r <= 1 && s >= 0 && s <= 1);
}
/**
* @brief <EFBFBD>жϵ<EFBFBD> (x, y) <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> curve <EFBFBD><EFBFBD>ʾ<EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @note ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߷<EFBFBD><EFBFBD><EFBFBD>Ray Casting Algorithm<EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD>
* <EFBFBD>ӵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˮƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD>ͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>αߵĽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>/<EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>ż<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD><EFBFBD>
* https://www.cnblogs.com/charlee44/p/10704156.html
*
* @param x <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param y <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param curve <EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><EFBFBD><EFBFBD>
* @return true <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return false <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⲿ
*/
inline bool IsPointInPolygon(double x, double y, const CCurveEx& curve)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><DFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㹻Զ<E3B9BB><D4B6>
const double RAY_LENGTH = 1e9; // ʹ<>ù̶<C3B9><CCB6>󳤶<EFBFBD>
double rayEndX = x - RAY_LENGTH;
int intersectCount = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>
for (int i = 0; i < curve.num; ++i) {
int next = (i + 1) % curve.num; // <20>Զ<EFBFBD><D4B6>պ϶<D5BA><CFB6><EFBFBD><EFBFBD><EFBFBD>
double x1 = curve.x[i];
double y1 = curve.y[i];
double x2 = curve.x[next];
double y2 = curve.y[next];
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6><EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>true
if (IsPointOnLine(x, y, x1, y1, x2, y2))
{
return true;
}
// <20>ų<EFBFBD>ˮƽ<CBAE>߶<EFBFBD>
if (std::abs(y2 - y1) < std::numeric_limits<double>::epsilon()) continue;
// <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (IsIntersect(x1, y1, x2, y2, x, y, rayEndX, y)) {
// <20><>ȡ<EFBFBD>߶ζ˵<CEB6>Y<EFBFBD><59><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
#pragma push_marco("max")
#undef max
double topY = std::max(y1, y2);
#pragma pop_marco("max")
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶ζ<DFB6><CEB6><EFBFBD>ʱ
if (IsPointOnLine(x1, y1, x, y, rayEndX, y)) {
if (y1 == topY) intersectCount++;
}
else if (IsPointOnLine(x2, y2, x, y, rayEndX, y)) {
if (y2 == topY) intersectCount++;
}
else {
intersectCount++;
}
}
}
// <20><>ż<EFBFBD>ж<EFBFBD>
return (intersectCount % 2 == 1);
}
/**
* <EFBFBD>ϲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param rects <EFBFBD><EFBFBD><EFBFBD>о<EFBFBD><EFBFBD><EFBFBD>
* \return <EFBFBD>ϲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD><EFBFBD><EFBFBD>
*/
inline std::vector<NBase::CRect8> MergeRects(const std::vector<NBase::CRect8>& rects)
{
if (rects.empty())
{
return {};
}
std::vector<NBase::CRect8> data = rects;
std::sort(data.begin(), data.end(), [](const NBase::CRect8& a, const NBase::CRect8& b)
{
return a.left < b.left;
});
bool changed;
do {
changed = false;
for (size_t i = 0; i < data.size(); ++i) {
for (size_t j = i + 1; j < data.size() && !changed; ++j) {
if (IsIntersecting(data[i], data[j])) {
double newLeft = min(data[i].left, data[j].left);
double newTop = max(data[i].top, data[j].top);
double newRight = max(data[i].right, data[j].right);
double newBottom = min(data[i].bottom, data[j].bottom);
data[i] = NBase::CRect8(newLeft, newTop, newRight, newBottom);
data.erase(data.begin() + j);
changed = true;
}
}
}
} while (changed);
return data;
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD>ĵ<EFBFBD>
*
* \param curve
* \return
*/
inline std::unique_ptr<CCurveEx> DeduplicateCurvePoints(const CCurveEx& curve)
{
if (curve.num == 0)
{
return std::make_unique<CCurveEx>();
}
auto pNewCurve = std::make_unique<CCurveEx>();
pNewCurve->Create(curve.num); // Ԥ<><D4A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棨curve.num<75><6D>
double lastX = curve.x[0];
double lastY = curve.y[0];
double lastZ = curve.z[0];
pNewCurve->x[0] = lastX;
pNewCurve->y[0] = lastY;
pNewCurve->z[0] = lastZ;
int32_t index = 1;
for (int32_t i = 1; i < curve.num; i++)
{
double currentX = curve.x[i];
double currentY = curve.y[i];
double currentZ = curve.z[i];
if (currentX != lastX || currentY != lastY || currentZ != lastZ)
{
pNewCurve->x[index] = currentX;
pNewCurve->y[index] = currentY;
pNewCurve->z[index] = currentZ;
lastX = currentX;
lastY = currentY;
lastZ = currentZ;
index++;
}
}
pNewCurve->num = index; // <20><><EFBFBD>ǵ<EFBFBD> x y z <20><><EFBFBD>ܻ<EFBFBD><DCBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬<DAB4><E6A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8> num <20><><EFBFBD>Ʋ<EFBFBD>Ҫȥ<D2AA><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pNewCurve->GetLocation();
return pNewCurve;
}
/**
* <EFBFBD>Ƴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>±<EFBFBD><EFBFBD>Ľڵ<EFBFBD>
*
* \param pCurve <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param index Ҫ<EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD>
* \return <EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>ַ
*/
inline void RemoveCurveIndex(CCurveEx& pCurve, int index)
{
if (index < 0 || index >= pCurve.num)
{
return;
}
for (int i = index; i + 1 < pCurve.num; i++)
{
pCurve.x[i] = pCurve.x[i + 1];
pCurve.y[i] = pCurve.y[i + 1];
pCurve.z[i] = pCurve.z[i + 1];
}
pCurve.num -= 1;
pCurve.GetLocation();
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> R <EFBFBD><EFBFBD>
*
* \param xy ͼ<EFBFBD><EFBFBD>
* \param filter <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>ƥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼԪ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> R <EFBFBD><EFBFBD>
* \return R <EFBFBD><EFBFBD>
*/
inline std::unique_ptr<RTree<POSITION, double, 2>> BuildRTree(CXy& xy, const CXyElementFilter& filter)
{
auto tree = std::make_unique<RTree<POSITION, double, 2>>();
NBase::CPositionList select;
xy.GetElement(filter, select);
POSITION pos = select.GetHeadPosition();
while (pos != nullptr)
{
POSITION pt = select.GetNext(pos);
COne* pOne = xy.GetAt(pt);
if (pOne == nullptr)
{
continue;
}
NBase::CRect8 range(1e100, -1e100, -1e100, 1e100);
pOne->GetRange(range);
double minX = min(range.left, range.right);
double minY = min(range.top, range.bottom);
double maxX = max(range.left, range.right);
double maxY = max(range.top, range.bottom);
double minValue[2]{ minX, minY };
double maxValue[2]{ maxX, maxY };
tree->Insert(minValue, maxValue, pt);
}
return tree;
}
/**
* <EFBFBD><EFBFBD><EFBFBD>ݿɵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD>vector,list)<EFBFBD>Ƶ<EFBFBD>Ԫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
template <typename IteratorType>
using ItemType = typename std::iterator_traits<typename IteratorType::iterator>::value_type;
/**
* ForEach, std::for_each <EFBFBD>򻯰<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param items
* \param pred
*/
template <typename IteratorType>
void ForEach(IteratorType &items, std::function<void(ItemType<IteratorType> &item)> pred)
{
for (typename IteratorType::iterator ptr = items.begin(); ptr != items.end(); ptr++)
{
pred(*ptr);
}
}
/**
* <EFBFBD>ж<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param items
* \param pred
* \return
*/
template <typename IteratorType>
bool AnyOf(const IteratorType &items, std::function<bool(const ItemType<IteratorType> &item)> pred)
{
return std::any_of(items.begin(), items.end(), pred);
}
/**
* <EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD><EFBFBD>Ƿ񶼲<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param items
* \param pred
* \return
*/
template <typename IteratorType>
bool NoneOf(const IteratorType &items, std::function<bool(const ItemType<IteratorType> &item)> pred)
{
return std::none_of(items.begin(), items.end(), pred);
}
/**
* <EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param items
* \param pred
* \return
*/
template <typename IteratorType>
bool AllOf(const IteratorType &items, std::function<bool(const ItemType<IteratorType> &item)> pred)
{
return std::all_of(items.begin(), items.end(), pred);
}
/**
* <EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>
*
* \param items
* \param pred
* \return
*/
template <typename IteratorType>
IteratorType Filter(const IteratorType &items, std::function<bool(const ItemType<IteratorType> &item)> pred)
{
IteratorType filteredIterator{};
ForEach<IteratorType>(const_cast<IteratorType&>(items), [&filteredIterator, &pred](auto &item)
{
if (pred(item))
{
filteredIterator.push_back(item);
}
});
return filteredIterator;
}
/**
* <EFBFBD>ͷż<EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param items
*/
template <typename IteratorType>
void DeleteAll(IteratorType& items)
{
static_assert(std::is_pointer<ItemType<IteratorType>>::value);
for (auto* p : items)
{
delete p;
}
items.clear();
}
/**
* <EFBFBD>ж<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>
*
* \param items
* \param item
* \return
*/
template <typename IteratorType>
bool Contains(const IteratorType &items, const ItemType<IteratorType> &item)
{
for (const auto &e : items)
{
if (e == item)
{
return true;
}
}
return false;
}
/**
* <EFBFBD><EFBFBD>ȡͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>
*
* \param xy
* \return
*/
inline std::vector<CLayer*> CollectAllLayers(const CXy& xy)
{
std::vector<CLayer*> layers;
CClassList* pClassList = const_cast<CXy&>(xy).GetClassList();
for (POSITION classPos = pClassList->GetHeadPosition(); classPos != nullptr; pClassList->GetNext(classPos))
{
CLayerList* pLayerList = pClassList->GetAt(classPos);
for (POSITION pos = pLayerList->GetHeadPosition(); pos != nullptr; pLayerList->GetNext(pos))
{
CLayer* pLayer = pLayerList->GetAt(pos);
layers.push_back(pLayer);
}
}
return layers;
}
/**
* <EFBFBD><EFBFBD> CList ת<EFBFBD><EFBFBD>Ϊ std::vector<EFBFBD><EFBFBD><EFBFBD>ʺ<EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸ĵ<EFBFBD> CList Ԫ<EFBFBD><EFBFBD><EFBFBD>г<EFBFBD><EFBFBD><EFBFBD>
*
* \param list
* \return
*/
template <typename T>
std::vector<T> CListToStdVector(const CList<T, T> &list)
{
std::vector<T> result;
CListForEach(pos, list)
{
result.push_back(list.GetAt(pos));
}
return result;
}
/**
* <EFBFBD><EFBFBD> CList ת<EFBFBD><EFBFBD>Ϊ std::list<EFBFBD><EFBFBD><EFBFBD>ʺ<EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸ĵ<EFBFBD> CList Ԫ<EFBFBD><EFBFBD><EFBFBD>г<EFBFBD><EFBFBD><EFBFBD>
*
* \param list
* \return
*/
template <typename T>
std::list<T> CListToStdList(const CList<T, T> &list)
{
std::list<T> result;
CListForEach(pos, list)
{
result.push_back(list.GetAt(pos));
}
return result;
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD> CList <EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ POSITION<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> POSITION <EFBFBD><EFBFBD> Ԫ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param list
* \return
*/
template <typename T>
std::list<std::pair<POSITION, T>> CListToStdList2(const CList<T, T> &list)
{
std::list<std::pair<POSITION, T>> result;
CListForEach(pos, list)
{
result.push_back({ pos, list.GetAt(pos) });
}
return result;
}
/**
* <EFBFBD><EFBFBD> POSITION <EFBFBD>б<EFBFBD>ת<EFBFBD><EFBFBD>Ϊ COne <EFBFBD>б<EFBFBD>
*
* \param positions <EFBFBD><EFBFBD><EFBFBD>ͼԪ POSITION <EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
* \return
*/
std::list<COne*> PtrsToCOnes(const CPtrList& pList);
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Cone<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɸѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> COne
*
* \param list
* \param pred <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \return
*/
std::list<COne*> ConesFilter(const std::list<COne*> &cones, std::function<bool(COne*)> pred);
/**
* CList <EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD> =<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щʵ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ͨ<EFBFBD>ú<EFBFBD><EFBFBD><EFBFBD>
*
* \param target <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> = <EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD><EFBFBD>б<EFBFBD>
* \param source <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> = <EFBFBD>ұߵ<EFBFBD><EFBFBD>б<EFBFBD>
*/
template <typename T>
void Assign(CList<T, T> &target, const CList<T, T> &source)
{
CListForEach(pos, source)
{
target.AddTail(source.GetAt(pos));
}
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD><EFBFBD><EFBFBD>
*/
double CalcDistance(double x1, double y1, double x2, double y2);
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߵij<EFBFBD><EFBFBD><EFBFBD>
*/
double CalcCurveDistance(const CCurveEx* pCurve);
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD>
* x1 x2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>Ͼͼ<EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>ʶ<EFBFBD><EFBFBD>ԣ<EFBFBD>y1 y2 Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>÷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
double CalcSlope(double x1, double y1, double x2, double y2);
/**
* <EFBFBD><EFBFBD> CList ȥ<EFBFBD><EFBFBD>
*
* \param items <EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD>ص<EFBFBD> items
*/
template <typename T>
void CListUnique(CList<T, T> &items)
{
std::vector<T> cacheItems;
std::vector<POSITION> removePositions;
CListForEach(pos, items)
{
T& value = items.GetAt(pos);
if (Contains(cacheItems, value))
{
removePositions.push_back(pos);
}
else
{
cacheItems.push_back(value);
}
}
for (POSITION pos : removePositions)
{
items.RemoveAt(pos);
}
}
/**
* <EFBFBD>ж<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>ܹ<EFBFBD>ƥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param source <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
* \param search <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param ignoreCase <EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>Сд
* \param matchWholeWord <EFBFBD><EFBFBD>ȫƥ<EFBFBD><EFBFBD>
* \return
*/
bool SearchMatch(const CString& source, const CString& search, bool ignoreCase, bool matchWholeWord);
// <20><>ȡ<EFBFBD><C8A1>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CString GetParentLayerPath(const CString& pLayer);
/**
* <EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>пո<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> class <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param layerName1 ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>1
* \param layerName2 ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>2
* \return ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>ͬ
*/
bool IsSameLayerName(const CString& layerName1, const CString& layerName2);
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
* \param <EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
* \param delimiter <EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD>
* \return <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
*/
CString JoinStrings(const std::vector<CString>& strings, const CString& delimiter);
/**
* <EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
*
* \param string <EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
* \param delimiter <EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>
* \return <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<CString> SplitString(const CString& string, const CString& delimiter);
/**
* <EFBFBD>ж<EFBFBD> position <EFBFBD>Ƿ<EFBFBD><EFBFBD>Ϸ<EFBFBD>
* \param pXy
* \param position <EFBFBD><EFBFBD><EFBFBD>жϵ<EFBFBD> position
* \return
*/
bool IsValidPosition(CXy *pXy, POSITION position);
/**
* <EFBFBD><EFBFBD>ȡ<EFBFBD>Ϸ<EFBFBD><EFBFBD><EFBFBD> position <EFBFBD>б<EFBFBD>
* \param pXy
* \param position <EFBFBD><EFBFBD><EFBFBD>жϵ<EFBFBD> position <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param count position <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \return
*/
std::vector<POSITION> GetValidPositions(CXy* pXy, POSITION positions[], int count);
std::wstring StringToWString(const std::string& str);
std::string WStringToString(const std::wstring &wstr);
/**
* CString ת utf-8
*
* \param str Ҫ<EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
* \return ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
*/
std::string CStringToUtf8String(const CString& str);
/**
* utf8 std::string ת CString
*/
CString Utf8StringToCString(const std::string& utf8Str);
/**
* Ĩƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Сѡ<EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param value Ŀ<EFBFBD><EFBFBD>ֵ
* \param min <EFBFBD><EFBFBD>Сֵ
* \param max <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
* \return
*/
inline double Flatten(double value, double min, double max)
{
assert(min <= max);
if (value < min)
{
return min;
}
if (value > max)
{
return max;
}
return value;
}
/**
* <EFBFBD>ж<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>ڷ<EFBFBD>Χ<EFBFBD><EFBFBD>
*
* \param value Ŀ<EFBFBD><EFBFBD>ֵ
* \param min <EFBFBD><EFBFBD>Сֵ
* \param max <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
* \return
*/
inline bool InRange(double value, double min, double max)
{
assert(min < max);
return (value >= min && value <= max);
}
/**
* <EFBFBD>ж<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD>Χ<EFBFBD><EFBFBD>
*
* \param value Ŀ<EFBFBD><EFBFBD>ֵ
* \param min <EFBFBD><EFBFBD>Сֵ
* \param max <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
* \return
*/
inline bool OutOfRange(double value, double min, double max)
{
assert(min < max);
return !InRange(value, min, max);
}
/**
* <EFBFBD><EFBFBD> COne <EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param pOne
* \return
*/
inline std::vector<BYTE> SerializeCOneToByteArray(COne* pOne)
{
CMemFile memFile;
CArchive archive(&memFile, CArchive::store);
pOne->Serialize(archive, 2022);
archive.Close();
size_t dataSize = memFile.GetLength();
std::vector<BYTE> result(dataSize);
memFile.SeekToBegin();
memFile.Read(result.data(), static_cast<UINT>(dataSize));
return result;
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD> COne
*
* \param array
* \return
*/
inline std::unique_ptr<COne> DeserializeCOneFromByteArray(const std::vector<BYTE>& byteArray)
{
CMemFile memFile(const_cast<BYTE*>(byteArray.data()), static_cast<UINT>(byteArray.size()));
CArchive archive(&memFile, CArchive::load);
std::unique_ptr<COne> pOne = std::make_unique<COne>();
pOne->Serialize(archive, 2022);
return pOne;
}
/**
* <EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>Ϊ "<EFBFBD><EFBFBD>.<2E><>.<2E><> ʱ:<3A><>:<3A><>.<2E><><EFBFBD><EFBFBD>" <EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
*
* \param timepoint ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \return <EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
*/
inline std::string FormatTime(const std::chrono::system_clock::time_point& timepoint)
{
std::time_t time_t = std::chrono::system_clock::to_time_t(timepoint);
std::tm tm = *std::localtime(&time_t);
std::stringstream ss;
ss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
// <20><>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBA3AC><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̫<EFBFBD><CCAB><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>
auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(timepoint.time_since_epoch()) % 1000;
ss << "." << now_ms.count();
return ss.str();
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽΪ "<EFBFBD><EFBFBD>.<2E><>.<2E><> ʱ:<3A><>:<3A><>.<2E><><EFBFBD><EFBFBD>" <EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>Ϊʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param timeString <EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
* \return ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
inline std::chrono::system_clock::time_point ParseTime(const std::string& timeString)
{
std::stringstream ss(timeString);
std::tm tm {};
ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
std::time_t time_t = std::mktime(&tm);
auto timePoint = std::chrono::system_clock::from_time_t(time_t);
// <20><>ȡ<EFBFBD><C8A1><EFBFBD>벿<EFBFBD><EBB2BF>
char dot = 0; // <20>Ⱥ<EFBFBD><C8BA>Ե<EFBFBD> "."
ss >> dot;
int ms = 0;
ss >> ms;
timePoint += std::chrono::milliseconds(ms);
return timePoint;
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> uuid
*
* \return
*/
inline std::string GenerateUUID()
{
GUID guid{};
CoInitialize(&guid);
HRESULT hr = CoCreateGuid(&guid);
char buf[40] = { 0 };
sprintf_s(buf, sizeof(buf),
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
return std::string(buf);
}
/**
* <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \return
*/
template <typename T>
T& GetInstace()
{
static T instance;
return instance;
}
/**
* <EFBFBD>ļ<EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Path <EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
class Path
{
public:
/**
* ·<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD>
*
* \param path
* \return
*/
static CString GetFileName(const CString& path)
{
return PathFindFileName(path);
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param path <EFBFBD>ļ<EFBFBD>·<EFBFBD><EFBFBD>
* \return <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (.) <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>
*/
static CString GetFileNameWithoutExtension(const CString& path)
{
CString fileName = PathFindFileName(path);
CString fileExtenstion = PathFindExtension(path);
return fileName.Left(fileName.GetLength() - fileExtenstion.GetLength());
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>·<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param path
* \return
*/
static CString GetExtension(const CString& path)
{
return PathFindExtension(path);
}
};
/**
* <EFBFBD>ж<EFBFBD> z <EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Чֵ
* \param z Ҫ<EFBFBD>жϵ<EFBFBD> z ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
inline bool IsUnvalidValue(double z)
{
const double invalidZ = -1E300;
return z <= invalidZ;
}
/**
* <EFBFBD>ͷ<EFBFBD> CPtrList <EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD> new <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param T <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ЩԪ<EFBFBD>ص<EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɺܶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param ptrList Ҫ<EFBFBD>ͷŵ<EFBFBD><EFBFBD>б<EFBFBD>
*/
template<typename T>
void DeleteAll(CPtrList& ptrList)
{
for (POSITION pos = ptrList.GetHeadPosition(); pos != nullptr; ptrList.GetNext(pos))
{
delete reinterpret_cast<T*>(ptrList.GetAt(pos));
}
ptrList.RemoveAll();
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD>յģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD>Ҫʹ<EFBFBD><EFBFBD> void * <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> T*
*
* \param first
* \param second
*/
template <typename T>
void SwapPointer(T*& first, T*& second)
{
T* temp = first;
first = second;
second = temp;
}
/**
* <EFBFBD><EFBFBD>ԭʼ<EFBFBD><EFBFBD> CPtrList <EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ψһ<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD>µ<EFBFBD> CPtrList <EFBFBD><EFBFBD>
*
* @param ԭʼ<EFBFBD><EFBFBD> CPtrList<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>
* @param ȥ<EFBFBD>غ<EFBFBD><EFBFBD><EFBFBD> CPtrList<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ψһ<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>
*/
inline void UniquePtrList(const CPtrList& ptrList, CPtrList& newPtrList)
{
newPtrList.RemoveAll();
for (POSITION pos = ptrList.GetHeadPosition(); pos != nullptr; ptrList.GetNext(pos))
{
void* ptr = const_cast<CPtrList&>(ptrList).GetAt(pos);
if (newPtrList.Find(ptr) == nullptr)
{
newPtrList.AddTail(ptr);
}
}
}
/**
* <EFBFBD><EFBFBD>ԭʼ<EFBFBD><EFBFBD> CPositionList <EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD> POSITION<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ψһ<EFBFBD><EFBFBD> POSITION <EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD>µ<EFBFBD> CPositionList <EFBFBD><EFBFBD>
*
* @param posList ԭʼ<EFBFBD><EFBFBD> CPositionList<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD> POSITION
* @param newPosList ȥ<EFBFBD>غ<EFBFBD><EFBFBD><EFBFBD> CPositionList<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ψһ<EFBFBD><EFBFBD> POSITION
*/
inline void UniquePositionList(const NBase::CPositionList& posList, NBase::CPositionList& newPosList)
{
newPosList.RemoveAll();
std::unordered_set<POSITION> seenPositions;
for (POSITION pos = posList.GetHeadPosition(); pos != nullptr; posList.GetNext(pos))
{
POSITION pt = posList.GetAt(pos);
if (seenPositions.find(pt) == seenPositions.end())
{
seenPositions.insert(pt);
newPosList.AddTail(pt);
}
}
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶ν<EFBFBD><EFBFBD><EFBFBD>
* https://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect/565282#
*
* \param p0_x <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param p0_y <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param p1_x <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param p1_y <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param p2_x <EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param p2_y <EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param p3_x <EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param p3_y <EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param i_x <EFBFBD><EFBFBD><EFBFBD><EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param i_y <EFBFBD><EFBFBD><EFBFBD><EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \return 1 <EFBFBD><EFBFBD>ʾ<EFBFBD>н<EFBFBD><EFBFBD>0 <EFBFBD><EFBFBD>ʾû<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
inline int GetLineIntersection(double p0_x, double p0_y, double p1_x, double p1_y,
double p2_x, double p2_y, double p3_x, double p3_y,
double& i_x, double& i_y)
{
double s1_x = p1_x - p0_x;
double s1_y = p1_y - p0_y;
double s2_x = p3_x - p2_x;
double s2_y = p3_y - p2_y;
double s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
double t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
{
// Collision detected
i_x = p0_x + (t * s1_x);
i_y = p0_y + (t * s1_y);
return 1;
}
return 0; // No collision
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param first <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ͼԪ
* \param second <EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD>ͼԪ
*/
inline void SwapHowtoView(COne& first, COne& second)
{
auto* pViewPoint = first.HowToViewPoint;
auto* pViewCurve = first.HowToViewCurve;
first.HowToViewPoint = second.HowToViewPoint;
first.HowToViewCurve = second.HowToViewCurve;
second.HowToViewPoint = pViewPoint;
second.HowToViewCurve = pViewCurve;
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param sourceLayer <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD>ͼ<EFBFBD><EFBFBD>
* \param targetLayer <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>
*/
inline void CopyLayerHowtoViewTo(const CLayer* pSourceLayer, CLayer* pTargetLayer)
{
assert(pSourceLayer != nullptr);
assert(pTargetLayer != nullptr);
SafeDelete(pTargetLayer->HowToViewCurve);
SafeDelete(pTargetLayer->HowToViewPoint);
if (pSourceLayer->HowToViewCurve != nullptr)
{
pTargetLayer->HowToViewCurve = new CHowToViewCurve();
*(pTargetLayer->HowToViewCurve) = *(pSourceLayer->HowToViewCurve);
}
if (pSourceLayer->HowToViewPoint != nullptr)
{
pTargetLayer->HowToViewPoint = new CHowToViewPoint();
*(pTargetLayer->HowToViewPoint) = *(pSourceLayer->HowToViewPoint);
}
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼԪ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param sourceOne <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD>ͼ<EFBFBD><EFBFBD>
* \param targetOne <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>
*/
inline void CopyOneHowtoViewTo(const COne* pSourceOne, COne* pTargetOne)
{
assert(pSourceOne != nullptr);
assert(pTargetOne != nullptr);
SafeDelete(pTargetOne->HowToViewCurve);
SafeDelete(pTargetOne->HowToViewPoint);
if (pSourceOne->HowToViewCurve != nullptr)
{
pTargetOne->HowToViewCurve = new CHowToViewCurve();
*(pTargetOne->HowToViewCurve) = *(pSourceOne->HowToViewCurve);
}
if (pSourceOne->HowToViewPoint != nullptr)
{
pTargetOne->HowToViewPoint = new CHowToViewPoint();
*(pTargetOne->HowToViewPoint) = *(pSourceOne->HowToViewPoint);
}
}
/**
* <EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD>ʱִ<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
class FinalAction
{
public:
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param func <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param ...args <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
template <typename Callable, typename... Args>
explicit FinalAction(Callable&& func, Args&&... args)
: callable(std::bind(std::forward<Callable>(func), std::forward<Args>(args)...)), active(true)
{
}
FinalAction(FinalAction&& other) noexcept
: callable(std::move(other.callable)), active(other.active)
{
}
FinalAction(const FinalAction&) = delete;
FinalAction& operator=(const FinalAction&) = delete;
void Cancel()
{
active = false;
}
~FinalAction() noexcept
{
if (active)
{
callable();
}
}
private:
std::function<void()> callable;
bool active = true;
};
/**
* CFile RAII <EFBFBD><EFBFBD>װ
*/
class CFileHelper
{
public:
CFileHelper(const CFileHelper&) = delete;
CFileHelper& operator=(const CFileHelper&) = delete;
CFileHelper(const CFileHelper&&) = delete;
CFileHelper& operator=(const CFileHelper&&) = delete;
CFileHelper(const CString& filePath, UINT openFlags)
{
m_isOpen = m_file.Open(filePath, CFile::modeCreate | CFile::modeWrite);
}
~CFileHelper()
{
if (m_isOpen)
{
m_file.Close();
}
m_isOpen = false;
}
bool IsOpen() const
{
return m_isOpen;
}
UINT Read(void* lpBuf, UINT nCount)
{
Validate();
return m_file.Read(lpBuf, nCount);
}
void Write(const void* lpBuf, UINT nCount)
{
Validate();
m_file.Write(lpBuf, nCount);
}
ULONGLONG GetPosition() const
{
Validate();
return m_file.GetPosition();
}
ULONGLONG Seek(LONGLONG lOff, UINT nFrom)
{
Validate();
return m_file.Seek(lOff, nFrom);
}
ULONGLONG GetLength() const
{
Validate();
return m_file.GetLength();
}
void SetLength(ULONGLONG nLength)
{
Validate();
return m_file.SetLength(nLength);
}
CString GetFileName() const
{
Validate();
return m_file.GetFileName();
}
CString GetFilePath() const
{
Validate();
return m_file.GetFilePath();
}
CString GetFileTitle() const
{
Validate();
return m_file.GetFileTitle();
}
CFile& GetFile()
{
Validate();
return m_file;
}
private:
void Validate() const
{
if (!m_isOpen)
{
throw std::runtime_error("File not open");
}
}
bool m_isOpen = false;
CFile m_file;
};