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/SplineCurveModel.h

102 lines
2.7 KiB
C

1 month ago
#pragma once
#include "ItemCurve.h"
#include <vector>
#include <utility>
/**
* @brief 线
*
* n n-1
* ToCCurveEx() 使
*/
/** @brief 段来源Algorithm 由 Catmull-Rom 计算Original 使用存储点 */
enum class SegmentSource
{
Algorithm,
Original
};
/** @brief 段元数据,存储该段采样点 */
struct SegmentMeta
{
SegmentSource source = SegmentSource::Algorithm;
std::vector<dfPoint> points;
};
/** @brief 渲染点,带所属段索引,用于绘制和命中检测 */
struct RenderPointWithSeg
{
dfPoint point;
int segIndex;
};
/**
* @brief 线
*
* CCurveEx
*/
class SplineCurveModel
{
public:
explicit SplineCurveModel(int samplesPerSegment = 30);
const std::vector<dfPoint>& GetControlPoints() const;
std::vector<dfPoint>& GetControlPoints();
const std::vector<SegmentMeta>& GetSegmentMeta() const;
const std::vector<RenderPointWithSeg>& GetRenderPoints() const;
int GetControlPointCount() const;
int GetSegmentCount() const;
bool IsValid() const;
/**
* @brief index -1
*/
int InsertControlPoint(int index, const dfPoint& point);
/**
* @brief index 3
*/
bool RemoveControlPoint(int index);
/** @brief 更新控制点坐标,仅重算受影响的段 */
void UpdateControlPoint(int index, double x, double y);
/**
* @brief
* @param affectedRange nullptr
*/
void RebuildRenderPoints(const std::pair<int, int>* affectedRange = nullptr);
/**
* @brief CCurveEx/使
*/
void ToCCurveEx(CCurveEx& outCurve) const;
/**
* @brief CCurveEx 使 SplineAlgorithm
*/
bool InitFromCCurveEx(const CCurveEx& curve, double splineStep);
int GetSamplesPerSegment() const;
void SetSamplesPerSegment(int n);
private:
std::vector<dfPoint> m_controlPoints;
std::vector<SegmentMeta> m_segmentMeta;
std::vector<RenderPointWithSeg> m_renderPoints;
int m_samplesPerSegment;
void InitSegmentMeta();
/**
* Catmull-Rom 4 p0..p3 p1p2
*/
static std::vector<dfPoint> SampleSegment(
const dfPoint& p0, const dfPoint& p1, const dfPoint& p2, const dfPoint& p3,
int samplesPerSegment);
static std::pair<int, int> GetAffectedSegmentRange(int controlPointIndex, int segmentCount);
};