@@ -111,9 +111,9 @@ void ContactPatchSolver::computePatch(const ShapeType1& s1,
111
111
// expects points to be ranked counter-clockwise.
112
112
this ->reset (s1, tf1, s2, tf2, contact_patch);
113
113
assert (this ->num_samples_curved_shapes > 3 );
114
- SupportSet& current = const_cast <SupportSet&>(this ->current ());
114
+ SupportSet& current_set = const_cast <SupportSet&>(this ->current ());
115
115
this ->supportFuncShape1 (
116
- &s1, current , this ->support_guess [0 ], this ->supports_data [0 ],
116
+ &s1, current_set , this ->support_guess [0 ], this ->supports_data [0 ],
117
117
this ->num_samples_curved_shapes , this ->patch_tolerance );
118
118
SupportSet& clipper = const_cast <SupportSet&>(this ->clipper ());
119
119
this ->supportFuncShape2 (
@@ -122,46 +122,85 @@ void ContactPatchSolver::computePatch(const ShapeType1& s1,
122
122
123
123
// We can immediatly return if one of the support set has only
124
124
// one point.
125
- if (current .size () <= 1 || clipper.size () <= 1 ) {
125
+ if (current_set .size () <= 1 || clipper.size () <= 1 ) {
126
126
contact_patch.addPoint (contact.pos );
127
127
return ;
128
128
}
129
129
130
- //
131
- // Step 3 - Main loop of the algorithm: use the "clipper"
132
- // to clip the current contact patch. The resulting intersection is the
133
- // contact patch of the contact between s1 and s2.
134
- // Currently, to clip one patch with the other, we use the Sutherland-Hodgman
135
- // algorithm:
136
- // https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm
137
- //
138
- this ->m_id_current = 0 ;
139
- const size_t clipper_size = this ->clipper ().points ().size ();
140
- for (size_t i = 0 ; i < clipper_size; ++i) {
141
- const Vec2f a = this ->clipper ().point (i);
142
- const Vec2f b = this ->clipper ().point ((i + 1 ) % clipper_size);
130
+ if (clipper.size () == 2 ) {
131
+ if (current_set.size () == 2 ) {
132
+ // Segment - Segment case
133
+ const Vec2f a = this ->clipper ().point (0 );
134
+ const Vec2f b = this ->clipper ().point (1 );
135
+
136
+ ContactPatch& current = const_cast <ContactPatch&>(this ->current ());
137
+ const Vec2f c = current.point (0 );
138
+ const Vec2f d = current.point (1 );
143
139
144
- this ->m_id_current = 1 - this ->m_id_current ;
145
- ContactPatch& current = const_cast <ContactPatch&>(this ->current ());
146
- current.points ().clear ();
147
- const size_t previous_size = this ->previous ().size ();
148
- for (size_t j = 0 ; j < previous_size; ++j) {
149
- const Vec2f vcurrent = this ->previous ().point (j);
150
- const Vec2f vnext = this ->previous ().point ((j + 1 ) % previous_size);
151
- if (pointIsInsideClippingRegion (vcurrent, a, b)) {
152
- current.points ().emplace_back (vcurrent);
153
- if (!pointIsInsideClippingRegion (vnext, a, b)) {
140
+ const Vec2f p = computeLineSegmentIntersection (a, b, c, d);
141
+ current.points ().clear ();
142
+ current.points ().emplace_back (p);
143
+ } else {
144
+ // Segment - Polygon case
145
+ const Vec2f a = this ->clipper ().point (0 );
146
+ const Vec2f b = this ->clipper ().point (1 );
147
+
148
+ this ->m_id_current = 1 - this ->m_id_current ;
149
+ ContactPatch& current = const_cast <ContactPatch&>(this ->current ());
150
+ current.points ().clear ();
151
+ const size_t previous_size = this ->previous ().size ();
152
+ for (size_t j = 0 ; j < previous_size; ++j) {
153
+ const Vec2f vcurrent = this ->previous ().point (j);
154
+ const Vec2f vnext = this ->previous ().point ((j + 1 ) % previous_size);
155
+ if (pointIsInsideClippingRegion (vcurrent, a, b)) {
156
+ if (!pointIsInsideClippingRegion (vnext, a, b)) {
157
+ const Vec2f p =
158
+ computeLineSegmentIntersection (a, b, vcurrent, vnext);
159
+ current.points ().emplace_back (p);
160
+ }
161
+ } else if (pointIsInsideClippingRegion (vnext, a, b)) {
154
162
const Vec2f p = computeLineSegmentIntersection (a, b, vcurrent, vnext);
155
163
current.points ().emplace_back (p);
156
164
}
157
- } else if (pointIsInsideClippingRegion (vnext, a, b)) {
158
- const Vec2f p = computeLineSegmentIntersection (a, b, vcurrent, vnext);
159
- current.points ().emplace_back (p);
160
165
}
161
166
}
162
- if (this ->current ().size () == 0 ) {
163
- // No intersection found, the algo can early stop.
164
- break ;
167
+ } else {
168
+ //
169
+ // Step 3 - Main loop of the algorithm: use the "clipper"
170
+ // to clip the current contact patch. The resulting intersection is the
171
+ // contact patch of the contact between s1 and s2.
172
+ // Currently, to clip one patch with the other, we use the
173
+ // Sutherland-Hodgman algorithm:
174
+ // https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm
175
+ //
176
+ const size_t clipper_size = this ->clipper ().points ().size ();
177
+ for (size_t i = 0 ; i < clipper_size; ++i) {
178
+ const Vec2f a = this ->clipper ().point (i);
179
+ const Vec2f b = this ->clipper ().point ((i + 1 ) % clipper_size);
180
+
181
+ this ->m_id_current = 1 - this ->m_id_current ;
182
+ ContactPatch& current = const_cast <ContactPatch&>(this ->current ());
183
+ current.points ().clear ();
184
+ const size_t previous_size = this ->previous ().size ();
185
+ for (size_t j = 0 ; j < previous_size; ++j) {
186
+ const Vec2f vcurrent = this ->previous ().point (j);
187
+ const Vec2f vnext = this ->previous ().point ((j + 1 ) % previous_size);
188
+ if (pointIsInsideClippingRegion (vcurrent, a, b)) {
189
+ current.points ().emplace_back (vcurrent);
190
+ if (!pointIsInsideClippingRegion (vnext, a, b)) {
191
+ const Vec2f p =
192
+ computeLineSegmentIntersection (a, b, vcurrent, vnext);
193
+ current.points ().emplace_back (p);
194
+ }
195
+ } else if (pointIsInsideClippingRegion (vnext, a, b)) {
196
+ const Vec2f p = computeLineSegmentIntersection (a, b, vcurrent, vnext);
197
+ current.points ().emplace_back (p);
198
+ }
199
+ }
200
+ if (this ->current ().size () == 0 ) {
201
+ // No intersection found, the algo can early stop.
202
+ break ;
203
+ }
165
204
}
166
205
}
167
206
0 commit comments