有没有办法使用CGAL生成2D拉伸网格?

时间:2017-01-20 12:43:52

标签: mesh cgal delaunay stretched

我目前使用CGAL生成2D Delaunay三角剖分。网格控制参数之一是三角形边的最大长度。示例表明此参数是常量。我想知道这个参数如何成为其他东西的功能,例如空间位置。

3 个答案:

答案 0 :(得分:0)

我认为,尽管您可以独立地对您的区域进行网格划分,但CGAL并不直接支持Delaunay与变密度的网格划分。或者,您可以查看:http://www.geom.at/advanced-mesh-generation/我将其实现为回调函数。

enter image description here

答案 1 :(得分:0)

CGAL似乎没有提供这样的示例,但是它们的作用就在那里。由于控制是否需要精炼三角形的对象还必须了解精炼三角形的优先级,因此细节变得有些复杂。

为此,我复制了Delaunay_mesh_size_criteria_2以创建一个新类(Delaunay_mesh_user_criteria_2),该类具有随空间变化的大小字段。该类中包含一个函数(user_sizing_field),该函数可以根据位置使用不同大小的字段来实现。下面的代码将三角形的最长边的大小与三个顶点处的大小域的最小值进行比较,但是如果您有一个重心,则可以在重心或外心使用大小,甚至可以将整个三角形发送给大小函数一种计算三角形上最小允许尺寸的好方法。

这是一个起点,尽管有更好的解决方案,

  • 重构某些内容以避免与现有的Delaunay_mesh_size_criteria重复太多,
  • 允许用户将大小调整功能作为参数传递给条件对象,并且
  • 随CGAL一起运送。
template <class CDT>
class Delaunay_mesh_user_criteria_2 : 
    public virtual Delaunay_mesh_criteria_2<CDT>
{
protected:
  typedef typename CDT::Geom_traits Geom_traits;
  double sizebound;

public:
  typedef Delaunay_mesh_criteria_2<CDT> Base;

  Delaunay_mesh_user_criteria_2(const double aspect_bound = 0.125,
                                const Geom_traits& traits = Geom_traits())
    : Base(aspect_bound, traits){}

  // first: squared_minimum_sine
  // second: size
  struct Quality : public std::pair<double, double>
  {
    typedef std::pair<double, double> Base;

    Quality() : Base() {};
    Quality(double _sine, double _size) : Base(_sine, _size) {}

    const double& size() const { return second; }
    const double& sine() const { return first; }

    // q1<q2 means q1 is prioritised over q2
    // ( q1 == *this, q2 == q )
    bool operator<(const Quality& q) const
    {
      if( size() > 1 )
        if( q.size() > 1 )
          return ( size() > q.size() );
        else
          return true; // *this is big but not q
      else
        if( q.size() >  1 )
          return false; // q is big but not *this
      return( sine() < q.sine() );
    }

    std::ostream& operator<<(std::ostream& out) const
    {
      return out << "(size=" << size()
         << ", sine=" << sine() << ")";
    }
  };

  class Is_bad: public Base::Is_bad
  {
  public:
    typedef typename Base::Is_bad::Point_2 Point_2;

    Is_bad(const double aspect_bound,
           const Geom_traits& traits)
      : Base::Is_bad(aspect_bound, traits) {}

    Mesh_2::Face_badness operator()(const Quality q) const
    {
      if( q.size() > 1 )
        return Mesh_2::IMPERATIVELY_BAD;
      if( q.sine() < this->B )
        return Mesh_2::BAD;
      else
    return Mesh_2::NOT_BAD;
    }

    double user_sizing_function(const Point_2 p) const
    {
      // IMPLEMENT YOUR CUSTOM SIZING FUNCTION HERE.
      // BUT MAKE SURE THIS RETURNS SOMETHING LARGER
      // THAN ZERO TO ALLOW THE ALGORITHM TO TERMINATE
      return std::abs(p.x()) + .025;
    }

    Mesh_2::Face_badness operator()(const typename CDT::Face_handle& fh,
                    Quality& q) const
    {
      typedef typename CDT::Geom_traits Geom_traits;
      typedef typename Geom_traits::Compute_area_2 Compute_area_2;
      typedef typename Geom_traits::Compute_squared_distance_2 Compute_squared_distance_2;

      Geom_traits traits; /** @warning traits with data!! */

      Compute_squared_distance_2 squared_distance = 
        traits.compute_squared_distance_2_object();

      const Point_2& pa = fh->vertex(0)->point();
      const Point_2& pb = fh->vertex(1)->point();
      const Point_2& pc = fh->vertex(2)->point();

      double size_bound = std::min(std::min(user_sizing_function(pa),
                                            user_sizing_function(pb)),
                                   user_sizing_function(pc));
      double
        a = CGAL::to_double(squared_distance(pb, pc)),
        b = CGAL::to_double(squared_distance(pc, pa)),
        c = CGAL::to_double(squared_distance(pa, pb));

      double max_sq_length; // squared max edge length
      double second_max_sq_length;

      if(a<b)
      {
        if(b<c) {
          max_sq_length = c;
          second_max_sq_length = b;
        }
        else { // c<=b
          max_sq_length = b;
          second_max_sq_length = ( a < c ? c : a );
        }
      }
      else // b<=a
      {
        if(a<c) {
          max_sq_length = c;
          second_max_sq_length = a;
        }
        else { // c<=a
          max_sq_length = a;
          second_max_sq_length = ( b < c ? c : b );
        }
      }

      q.second = 0;

      q.second = max_sq_length / (size_bound*size_bound);
      // normalized by size bound to deal
      // with size field
      if( q.size() > 1 )
      {
        q.first = 1; // (do not compute sine)
        return Mesh_2::IMPERATIVELY_BAD;
      }

      Compute_area_2 area_2 = traits.compute_area_2_object();

      double area = 2*CGAL::to_double(area_2(pa, pb, pc));

      q.first = (area * area) / (max_sq_length * second_max_sq_length); // (sine)

      if( q.sine() < this->B )
        return Mesh_2::BAD;
      else
        return Mesh_2::NOT_BAD;
    }
  };

  Is_bad is_bad_object() const
  { return Is_bad(this->bound(), this->traits /* from the bad class */); }
};

答案 2 :(得分:-1)

我也对使用CGAL的domaine上的变量网格标准感兴趣。多年前我找到了另一种选择:https://www.cs.cmu.edu/~quake/triangle.html

但我仍然有兴趣用CGAL做同样的事情......我不知道是否有可能......