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." , mesh.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