NURBS曲线

本文深入探讨了NURBS曲线的概念、原理及应用,揭示了其在数字设计领域的独特价值和广泛影响。NURBS曲线作为一种强大的数学工具,为设计师们提供了更加灵活、精确的曲线创建方式,从而极大地提升了设计作品的质感和表现力。本文首先介绍了NURBS曲线的基本概念和数学原理,进而分析了其在工业设计、动画制作、3D打印等领域的实际应用。此外,本文还探讨了NURBS曲线的未来发展前景,以及它如何继续推动数字设计领域的创新和进步。

1. 基本理论

NURBS是非均匀有理B样条(Non-Uniform Rational B-Splines)的缩写。

学习得从更特殊的形式学起,否则会比较懵。来看看各种曲线的关系图。

所以,似乎先学贝塞尔曲线应该是个好的开始。

2. C++代码实现

2.1. 辅助结构体定义

struct ColOfMatrix {
  int32_t start_;
  int32_t end_;
  std::vector<double> vec_;
  ColOfMatrix() : start_(-1), end_(0) {
  }
};

2.2. 分割参数空间

template<class Point3_T>
bool splitParamSpace(const std::vector<Point3_T> &vInputPoint,
                     const std::vector<int> &vDPIndex,
                     std::vector<float> &vU,
                     std::vector<float> &vKnot) const {
  bool bRet = true;
  if (vInputPoint.empty() || vDPIndex.empty()) {
    LOG(ERROR) << "vInputPoint.size() = " << vInputPoint.size() << ", vDPIndex.size() = " << vDPIndex.size();
    bRet = false;
  } else if (vDPIndex.front() != 0 || vDPIndex.back() != static_cast<int>(vInputPoint.size()) - 1) {
    LOG(ERROR) << "The first and last element of vDPIndex is: " << vDPIndex.front() << ", " << vDPIndex.back()
               << "vInputPoint.size() = " << vInputPoint.size();
    bRet = false;
  } else {
    int32_t numDistance = static_cast<int>(vInputPoint.size()) - 1;
    std::vector<float> vDistance;
    vDistance.reserve(numDistance);

    double tmpDistance, tmpDiff;
    for (auto first = vInputPoint.begin(), second = first + 1; second < vInputPoint.end(); ++first, ++second) {
      tmpDiff = first->x - second->x;
      tmpDistance = tmpDiff * tmpDiff;

      tmpDiff = first->z - second->z;
      tmpDistance += tmpDiff * tmpDiff;

      vDistance.emplace_back(std::sqrt(tmpDistance));
    }

    double sumDistance = std::accumulate(vDistance.begin(), vDistance.end(), 0.f);

    //Generate the vector U, U is u bar
    vU.clear();
    vU.reserve(vInputPoint.size());

    if (sumDistance < 0.1f) {
      LOG(ERROR) << "The line is too short.";
      bRet = false;
    } else {
      double divisor = 1.f / sumDistance, elem(0);
      for (auto it = vDistance.begin(); it < vDistance.end(); ++it) {
        vU.emplace_back(elem);
        elem += (*it) * divisor;
        if (elem - 1.f > FLT_MIN) {
          elem = 1.f;
        }
      }
      vU.emplace_back(1.f);
    }

    if (bRet) {
      //generate knot
      vKnot.clear();
      vKnot.reserve(vDPIndex.size() + 4u);
      vKnot.emplace_back(0);
      vKnot.emplace_back(0);

      for (auto it = vDPIndex.begin(); it < vDPIndex.end(); ++it) {
        vKnot.emplace_back(vU[*it]);
      }

      vKnot.emplace_back(1);
      vKnot.emplace_back(1);
    }
  }

  return bRet;
}

2.3. 计算控制点到曲线的映射矩阵

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值