#pragma once #include "ItemCurve.h" #include #include /** * @brief 样条曲线数据模型 * * 控制点为唯一数据源,通过段元数据生成渲染点。n 个控制点对应 n-1 段, * 渲染点带段索引用于绘制和命中检测,最终通过 ToCCurveEx() 输出供文档使用。 */ /** @brief 段来源:Algorithm 由 Catmull-Rom 计算;Original 使用存储点 */ enum class SegmentSource { Algorithm, Original }; /** @brief 段元数据,存储该段采样点 */ struct SegmentMeta { SegmentSource source = SegmentSource::Algorithm; std::vector points; }; /** @brief 渲染点,带所属段索引,用于绘制和命中检测 */ struct RenderPointWithSeg { dfPoint point; int segIndex; }; /** * @brief 样条曲线模型 * * 数据流:控制点 → 段元数据 → 渲染点缓存 → CCurveEx */ class SplineCurveModel { public: explicit SplineCurveModel(int samplesPerSegment = 30); const std::vector& GetControlPoints() const; std::vector& GetControlPoints(); const std::vector& GetSegmentMeta() const; const std::vector& 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* 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 m_controlPoints; std::vector m_segmentMeta; std::vector m_renderPoints; int m_samplesPerSegment; void InitSegmentMeta(); /** * Catmull-Rom 单段采样(4 控制点 p0..p3,绘制 p1→p2) */ static std::vector SampleSegment( const dfPoint& p0, const dfPoint& p1, const dfPoint& p2, const dfPoint& p3, int samplesPerSegment); static std::pair GetAffectedSegmentRange(int controlPointIndex, int segmentCount); };