22
33namespace  ipc  {
44
5+ namespace  {
6+     bool  smooth_point2_term_type (
7+         const  Eigen::Ref<const  Vector2d>& v,
8+         const  Eigen::Ref<const  Vector2d>& direc,
9+         const  Eigen::Ref<const  Vector2d>& e0 ,
10+         const  Eigen::Ref<const  Vector2d>& e1 ,
11+         const  ParameterType& param,
12+         const  bool  orientable)
13+     {
14+         const  Vector2d dn = -direc.normalized ();
15+         const  Vector2d t0 = (e0  - v).normalized (), t1 = (e1  - v).normalized ();
16+     
17+         if  (dn.dot (t0) <= -param.alpha_t  || dn.dot (t1) <= -param.alpha_t )
18+             return  false ;
19+     
20+         if  (orientable)
21+         {
22+             const  double  tmp = Math<double >::smooth_heaviside (-Math<double >::cross2 (dn, t0), param.alpha_n , param.beta_n ) + 
23+                                 Math<double >::smooth_heaviside (Math<double >::cross2 (dn, t1), param.alpha_n , param.beta_n );
24+             if  (tmp <= 1 . - param.alpha_n )
25+                 return  false ;
26+         }
27+     
28+         return  true ;
29+     }
30+ 
31+     template  <class  scalar >
32+     scalar smooth_point2_term (
33+         const  Eigen::Ref<const  Vector2<scalar>>& v,
34+         const  Eigen::Ref<const  Vector2<scalar>>& direc,
35+         const  Eigen::Ref<const  Vector2<scalar>>& e0 ,
36+         const  Eigen::Ref<const  Vector2<scalar>>& e1 ,
37+         const  ParameterType& param,
38+         const  bool  orientable)
39+     {
40+         const  Vector2<scalar> dn = -direc.normalized ();
41+         const  Vector2<scalar> t0 = (e0  - v).normalized (), t1 = (v - e1 ).normalized ();
42+     
43+         scalar val = Math<scalar>::smooth_heaviside (dn.dot (t0), param.alpha_t , param.beta_t ) *
44+                             Math<scalar>::smooth_heaviside (-dn.dot (t1), param.alpha_t , param.beta_t );
45+     
46+         if  (orientable)
47+         {
48+             const  scalar tmp = Math<scalar>::smooth_heaviside (-Math<scalar>::cross2 (dn, t0), param.alpha_n , param.beta_n ) + 
49+                                     Math<scalar>::smooth_heaviside (-Math<scalar>::cross2 (dn, t1), param.alpha_n , param.beta_n );
50+             val = val * Math<scalar>::smooth_heaviside (tmp - 1 ., param.alpha_n , 0 );
51+         }
52+     
53+         return  val * ((e0  - v).norm () + (e1  - v).norm ()) / 2 .;
54+     }
55+ 
56+     template  <class  scalar >
57+     scalar smooth_point2_term_one_side (
58+         const  Eigen::Ref<const  Vector2<scalar>>& v,
59+         const  Eigen::Ref<const  Vector2<scalar>>& direc,
60+         const  Eigen::Ref<const  Vector2<scalar>>& e0 ,
61+         const  ParameterType& param)
62+     {
63+         const  Vector2<scalar> dn = -direc.normalized ();
64+         const  Vector2<scalar> t0 = e0  - v;
65+     
66+         const  scalar tangent_term = Math<scalar>::smooth_heaviside (dn.dot (t0) / t0.norm (), param.alpha_t , param.beta_t );
67+         
68+         return  tangent_term * t0.norm ();
69+     }
70+ }
71+ 
572Point2::Point2 (const  long  &id, 
673    const  CollisionMesh& mesh,
774    const  Eigen::MatrixXd& vertices,
875    const  VectorMax3d& d,
976    const  ParameterType& param)
1077: Primitive(id, param)
1178{
12-     _vert_ids = {{-1 , -1 , -1 }};
13-     _vert_ids[0 ] = id;
79+     orientable = !mesh.is_codim_vertex (id);
80+     auto  neighbor_verts = mesh.find_vertex_adjacent_vertices (id);
81+     has_neighbor_1 = neighbor_verts[0 ] >= 0 ;
82+     has_neighbor_2 = neighbor_verts[1 ] >= 0 ;
1483
15-     if  (mesh.vertex_edge_adjacencies ()[id].size () != 2 )
16-         logger ().error (" Invalid number of vertex neighbor in 2D! {} should be 2." vertex_edge_adjacencies ()[id].size ());
17-     for  (long  i : mesh.vertex_edge_adjacencies ()[id])
84+     if  (has_neighbor_1 && has_neighbor_2)
1885    {
19-         if  (mesh.edges ()(i, 0 ) == id)
20-             _vert_ids[1 ] = mesh.edges ()(i, 1 );
21-         else  if  (mesh.edges ()(i, 1 ) == id)
22-             _vert_ids[2 ] = mesh.edges ()(i, 0 );
23-         else 
24-             logger ().error (" Wrong edge-vertex adjacency!" 
86+         _vert_ids = {{id, neighbor_verts[0 ], neighbor_verts[1 ]}};
87+         is_active_ = smooth_point2_term_type (vertices.row (id), d, vertices.row (_vert_ids[1 ]), vertices.row (_vert_ids[2 ]), _param, orientable);
2588    }
89+     else  if  (has_neighbor_1 || has_neighbor_2)
90+     {
91+         _vert_ids = {{id, has_neighbor_1 ? neighbor_verts[0 ] : neighbor_verts[1 ]}};
2692
27-     is_active_ = smooth_point2_term_type (vertices.row (id), d, vertices.row (_vert_ids[1 ]), vertices.row (_vert_ids[2 ]), _param);
93+         const  Vector2d dn = -d.normalized ();
94+         const  Vector2d t0 = (vertices.row (_vert_ids[1 ]) - vertices.row (_vert_ids[0 ])).normalized ();
95+     
96+         is_active_ = dn.dot (t0) > -param.alpha_t ;
97+     }
98+     else 
99+     {
100+         _vert_ids = {{id}};
101+         is_active_ = true ;
102+     }
28103}
29104
30105int  Point2::n_vertices () const 
31106{
32-     return  3 ;
107+     return  _vert_ids. size () ;
33108}
34109
35110double  Point2::potential (const  Vector<double , dim> &d, const  Vector<double , -1 , max_size> &x) const 
36111{
37-     return  smooth_point2_term<double >(x.segment <dim>(0 ), d, x.segment <dim>(dim), x.segment <dim>(2  * dim), _param);
112+     if  (has_neighbor_1 && has_neighbor_2)
113+         return  smooth_point2_term<double >(x.segment <dim>(0 ), d, x.segment <dim>(dim), x.segment <dim>(2  * dim), _param, orientable);
114+     else  if  (has_neighbor_1 || has_neighbor_2)
115+         return  smooth_point2_term_one_side<double >(x.segment <dim>(0 ), d, x.segment <dim>(dim), _param);
116+     else 
117+         return  1 .;
38118}
39119Vector<double , -1 , Point2::max_size+Point2::dim> Point2::grad (const  Vector<double , dim> &d, const  Vector<double , -1 , max_size> &x) const 
40120{
41-     DiffScalarBase::setVariableCount (4 *dim);
42-     using  T = ADGrad<4 *dim>;
43-     Vector<double , 4 *dim> tmp;
44-     tmp << d, x;
45-     Eigen::Matrix<T, 4 , dim> X = slice_positions<T, 4 , dim>(tmp);
46-     return  smooth_point2_term<T>(X.row (1 ), X.row (0 ), X.row (2 ), X.row (3 ), _param).getGradient ();
121+     if  (has_neighbor_1 && has_neighbor_2)
122+     {
123+         DiffScalarBase::setVariableCount (4 *dim);
124+         using  T = ADGrad<4 *dim>;
125+         Vector<double , 4 *dim> tmp;
126+         tmp << d, x;
127+         Eigen::Matrix<T, 4 , dim> X = slice_positions<T, 4 , dim>(tmp);
128+         return  smooth_point2_term<T>(X.row (1 ), X.row (0 ), X.row (2 ), X.row (3 ), _param, orientable).getGradient ();
129+     }
130+     else  if  (has_neighbor_1 || has_neighbor_2)
131+     {
132+         DiffScalarBase::setVariableCount (3 *dim);
133+         using  T = ADGrad<3 *dim>;
134+         Vector<double , 3 *dim> tmp;
135+         tmp << d, x;
136+         Eigen::Matrix<T, 3 , dim> X = slice_positions<T, 3 , dim>(tmp);
137+         return  smooth_point2_term_one_side<T>(X.row (1 ), X.row (0 ), X.row (2 ), _param).getGradient ();
138+     }
139+     else 
140+         return  Vector<double , -1 , Point2::max_size+Point2::dim>::Zero (x.size () + d.size ());
47141}
48142MatrixMax<double , Point2::max_size+Point2::dim, Point2::max_size+Point2::dim> Point2::hessian (const  Vector<double , dim> &d, const  Vector<double , -1 , max_size> &x) const 
49143{
50-     DiffScalarBase::setVariableCount (4 *dim);
51-     using  T = ADHessian<4 *dim>;
52-     Vector<double , 4 *dim> tmp;
53-     tmp << d, x;
54-     Eigen::Matrix<T, 4 , dim> X = slice_positions<T, 4 , dim>(tmp);
55-     return  smooth_point2_term<T>(X.row (1 ), X.row (0 ), X.row (2 ), X.row (3 ), _param).getHessian ();
56- }
57- 
58- template  <class  scalar >
59- scalar smooth_point2_term (
60-     const  Eigen::Ref<const  Vector2<scalar>>& v,
61-     const  Eigen::Ref<const  Vector2<scalar>>& direc,
62-     const  Eigen::Ref<const  Vector2<scalar>>& e0 ,
63-     const  Eigen::Ref<const  Vector2<scalar>>& e1 ,
64-     const  ParameterType& param)
65- {
66-     const  Vector2<scalar> dn = -direc.normalized ();
67-     const  Vector2<scalar> t0 = (e0  - v).normalized (), t1 = (v - e1 ).normalized ();
68- 
69-     const  scalar tangent_term = Math<scalar>::smooth_heaviside (dn.dot (t0), param.alpha_t , param.beta_t ) *
70-                         Math<scalar>::smooth_heaviside (-dn.dot (t1), param.alpha_t , param.beta_t );
71- 
72-     const  scalar tmp = Math<scalar>::smooth_heaviside (-Math<scalar>::cross2 (dn, t0), param.alpha_n , param.beta_n ) + 
73-                          Math<scalar>::smooth_heaviside (-Math<scalar>::cross2 (dn, t1), param.alpha_n , param.beta_n );
74-     const  scalar normal_term = Math<scalar>::smooth_heaviside (tmp - 1 ., param.alpha_n , 0 );
75- 
76-     return  tangent_term * normal_term * ((e0  - v).norm () + (e1  - v).norm ()) / 2 .;
77- }
78- 
79- bool  smooth_point2_term_type (
80-     const  Eigen::Ref<const  Vector2d>& v,
81-     const  Eigen::Ref<const  Vector2d>& direc,
82-     const  Eigen::Ref<const  Vector2d>& e0 ,
83-     const  Eigen::Ref<const  Vector2d>& e1 ,
84-     const  ParameterType& param)
85- {
86-     const  Vector2d dn = -direc.normalized ();
87-     const  Vector2d t0 = (e0  - v).normalized (), t1 = (v - e1 ).normalized ();
88- 
89-     if  (dn.dot (t0) <= -param.alpha_t  || -dn.dot (t1) <= -param.alpha_t )
90-         return  false ;
91- 
92-     const  double  tmp = Math<double >::smooth_heaviside (-Math<double >::cross2 (dn, t0), param.alpha_n , param.beta_n ) + 
93-                          Math<double >::smooth_heaviside (-Math<double >::cross2 (dn, t1), param.alpha_n , param.beta_n );
94-     if  (tmp <= 1 . - param.alpha_n )
95-         return  false ;
96- 
97-     return  true ;
144+     if  (has_neighbor_1 && has_neighbor_2)
145+     {
146+         DiffScalarBase::setVariableCount (4 *dim);
147+         using  T = ADHessian<4 *dim>;
148+         Vector<double , 4 *dim> tmp;
149+         tmp << d, x;
150+         Eigen::Matrix<T, 4 , dim> X = slice_positions<T, 4 , dim>(tmp);
151+         return  smooth_point2_term<T>(X.row (1 ), X.row (0 ), X.row (2 ), X.row (3 ), _param, orientable).getHessian ();
152+     }
153+     else  if  (has_neighbor_1 || has_neighbor_2)
154+     {
155+         DiffScalarBase::setVariableCount (3 *dim);
156+         using  T = ADHessian<3 *dim>;
157+         Vector<double , 3 *dim> tmp;
158+         tmp << d, x;
159+         Eigen::Matrix<T, 3 , dim> X = slice_positions<T, 3 , dim>(tmp);
160+         return  smooth_point2_term_one_side<T>(X.row (1 ), X.row (0 ), X.row (2 ), _param).getHessian ();
161+     }
162+     else 
163+         return  MatrixMax<double , -1 , Point2::max_size+Point2::dim>::Zero (x.size () + d.size (), x.size () + d.size ());
98164}
99165}
0 commit comments