Directory: | ./ |
---|---|
File: | src/affordance-extraction.cc |
Date: | 2025-03-07 12:08:39 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 80 | 175 | 45.7% |
Branches: | 69 | 316 | 21.8% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | // | ||
2 | // Copyright (c) 2016 CNRS | ||
3 | // Authors: Anna Seppala | ||
4 | // | ||
5 | // This file is part of hpp-core | ||
6 | // hpp-core is free software: you can redistribute it | ||
7 | // and/or modify it under the terms of the GNU Lesser General Public | ||
8 | // License as published by the Free Software Foundation, either version | ||
9 | // 3 of the License, or (at your option) any later version. | ||
10 | // | ||
11 | // hpp-core is distributed in the hope that it will be | ||
12 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty | ||
13 | // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | // General Lesser Public License for more details. You should have | ||
15 | // received a copy of the GNU Lesser General Public License along with | ||
16 | // hpp-core If not, see | ||
17 | // <http://www.gnu.org/licenses/>. | ||
18 | |||
19 | #include <coal/BVH/BVH_model.h> | ||
20 | #include <coal/collision.h> | ||
21 | #include <coal/collision_object.h> | ||
22 | |||
23 | #include <algorithm> | ||
24 | #include <hpp/affordance/affordance-extraction.hh> | ||
25 | #include <hpp/affordance/operations.hh> | ||
26 | |||
27 | namespace hpp { | ||
28 | namespace affordance { | ||
29 | |||
30 | 17 | BVHModelOBConst_Ptr_t GetModel(FclConstCollisionObjectPtr_t object) { | |
31 |
2/4✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
|
17 | assert(object->collisionGeometry()->getNodeType() == coal::BV_OBBRSS); |
32 | const BVHModelOBConst_Ptr_t model = | ||
33 | 17 | std::static_pointer_cast<const BVHModelOB>(object->collisionGeometry()); | |
34 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
|
17 | assert(model->getModelType() == coal::BVH_MODEL_TRIANGLES); |
35 | 17 | return model; | |
36 | } | ||
37 | |||
38 | 51 | void searchLinkedTriangles(std::vector<unsigned int>& listPotential, | |
39 | const OperationBasePtr_t& refOp, | ||
40 | const std::vector<Triangle>& allTris, | ||
41 | std::vector<unsigned int>& searchableTris, | ||
42 | const unsigned int& refTriIdx, double& area) { | ||
43 | // TODO: think of a better way of declaring margins? | ||
44 | 51 | const double margin = 1e-15; | |
45 | 51 | const Triangle& refTri = allTris[refTriIdx]; | |
46 |
1/2✓ Branch 3 taken 51 times.
✗ Branch 4 not taken.
|
102 | searchableTris.erase( |
47 |
1/2✓ Branch 3 taken 51 times.
✗ Branch 4 not taken.
|
51 | std::remove(searchableTris.begin(), searchableTris.end(), refTriIdx), |
48 | 51 | searchableTris.end()); | |
49 |
2/2✓ Branch 1 taken 233 times.
✓ Branch 2 taken 51 times.
|
284 | for (unsigned int searchIdx = 0; searchIdx < allTris.size(); searchIdx++) { |
50 | std::vector<unsigned int>::iterator it = | ||
51 |
1/2✓ Branch 3 taken 233 times.
✗ Branch 4 not taken.
|
233 | std::find(searchableTris.begin(), searchableTris.end(), searchIdx); |
52 |
2/2✓ Branch 2 taken 197 times.
✓ Branch 3 taken 36 times.
|
233 | if (it == searchableTris.end()) { |
53 | 197 | continue; | |
54 | } | ||
55 | 36 | std::vector<coal::Vec3f> refPoints; | |
56 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 | refPoints.push_back(refTri.points.p1); |
57 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 | refPoints.push_back(refTri.points.p2); |
58 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 | refPoints.push_back(refTri.points.p3); |
59 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | for (unsigned int vertIdx = 0; vertIdx < 3; vertIdx++) { |
60 | 36 | const Triangle& searchTri = allTris[searchIdx]; | |
61 |
2/4✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
|
36 | if ((refPoints[vertIdx] - searchTri.points.p1).squaredNorm() < margin || |
62 |
1/8✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
36 | (refPoints[vertIdx] - searchTri.points.p2).squaredNorm() < margin || |
63 |
1/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 36 times.
✗ Branch 10 not taken.
|
36 | (refPoints[vertIdx] - searchTri.points.p3).squaredNorm() < margin) { |
64 |
2/4✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
|
36 | if (refOp->requirement(searchTri.normal)) { |
65 |
2/4✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
|
36 | if ((searchTri.normal - refTri.normal).squaredNorm() < |
66 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 | refOp->neighbouringTriangleMargin_) { |
67 | 36 | area += searchTri.area; | |
68 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 | listPotential.push_back(searchIdx); |
69 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 | searchLinkedTriangles(listPotential, refOp, allTris, searchableTris, |
70 | searchIdx, area); | ||
71 | } | ||
72 | } else { | ||
73 | // if linked face does not fulfil global requirement, discard | ||
74 | ✗ | searchableTris.erase(std::remove(searchableTris.begin(), | |
75 | searchableTris.end(), searchIdx), | ||
76 | ✗ | searchableTris.end()); | |
77 | } | ||
78 | 36 | break; // jump out of vertex loop if triangle already tested for | |
79 | // affordance | ||
80 | } | ||
81 | } | ||
82 | 36 | } | |
83 | 51 | } | |
84 | |||
85 | 17 | SemanticsDataPtr_t affordanceAnalysis(FclConstCollisionObjectPtr_t colObj, | |
86 | const OperationBases_t& opVec) { | ||
87 |
1/2✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
|
17 | BVHModelOBConst_Ptr_t model = GetModel(colObj); |
88 | |||
89 | 17 | std::vector<Triangle> triangles; | |
90 | 17 | std::vector<unsigned int> unsetTriangles; | |
91 | 17 | double totArea = .0; | |
92 |
1/2✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
|
17 | std::vector<std::vector<unsigned int> > potentialAffordances(opVec.size()); |
93 |
2/4✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
|
17 | SemanticsDataPtr_t foundAffordances(new SemanticsData()); |
94 |
1/2✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
|
17 | foundAffordances->affordances_.resize(opVec.size()); |
95 | |||
96 |
2/2✓ Branch 1 taken 66 times.
✓ Branch 2 taken 17 times.
|
83 | for (int i = 0; i < model->num_tris; ++i) { |
97 |
1/2✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
|
66 | TrianglePoints tri; |
98 | 66 | coal::Triangle coaltri = (*model->tri_indices)[i]; | |
99 |
2/4✓ Branch 6 taken 66 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 66 times.
✗ Branch 10 not taken.
|
66 | tri.p1 = colObj->getRotation() * (*model->vertices)[coaltri[0]] + |
100 |
1/2✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
|
132 | colObj->getTranslation(); |
101 |
2/4✓ Branch 6 taken 66 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 66 times.
✗ Branch 10 not taken.
|
66 | tri.p2 = colObj->getRotation() * (*model->vertices)[coaltri[1]] + |
102 |
1/2✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
|
132 | colObj->getTranslation(); |
103 |
2/4✓ Branch 6 taken 66 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 66 times.
✗ Branch 10 not taken.
|
66 | tri.p3 = colObj->getRotation() * (*model->vertices)[coaltri[2]] + |
104 |
1/2✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
|
132 | colObj->getTranslation(); |
105 | |||
106 |
2/4✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 66 times.
✗ Branch 5 not taken.
|
66 | triangles.push_back(Triangle(tri)); |
107 | // save vector index of triangles and their quantity. | ||
108 |
1/2✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
|
66 | unsetTriangles.push_back(i); |
109 | } | ||
110 | 17 | std::vector<unsigned int> unseenTriangles; | |
111 |
2/2✓ Branch 1 taken 66 times.
✓ Branch 2 taken 17 times.
|
83 | for (unsigned int triIdx = 0; triIdx < triangles.size(); triIdx++) { |
112 | // look for triangle in set of triangles not yet given an affordance: | ||
113 | std::vector<unsigned int>::iterator it = | ||
114 |
1/2✓ Branch 3 taken 66 times.
✗ Branch 4 not taken.
|
66 | std::find(unsetTriangles.begin(), unsetTriangles.end(), triIdx); |
115 |
2/2✓ Branch 2 taken 36 times.
✓ Branch 3 taken 30 times.
|
66 | if (it == unsetTriangles.end()) { |
116 | 36 | continue; | |
117 | } | ||
118 | // set list of searchable (unseen) triangles equal to all triangles not yet | ||
119 | // given an affordance. | ||
120 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | unseenTriangles = unsetTriangles; |
121 |
2/2✓ Branch 1 taken 52 times.
✓ Branch 2 taken 15 times.
|
67 | for (unsigned int opIdx = 0; opIdx < opVec.size(); opIdx++) { |
122 |
3/4✓ Branch 4 taken 52 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
✓ Branch 7 taken 37 times.
|
52 | if (opVec[opIdx]->requirement(triangles[triIdx].normal)) { |
123 | 15 | totArea += triangles[triIdx].area; | |
124 |
1/2✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
15 | potentialAffordances[opIdx].push_back(triIdx); |
125 |
1/2✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
|
15 | searchLinkedTriangles(potentialAffordances[opIdx], opVec[opIdx], |
126 | triangles, unseenTriangles, triIdx, totArea); | ||
127 |
1/2✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
15 | if (totArea > opVec[opIdx]->minArea_) { |
128 | // save totArea for further use as well? | ||
129 | AffordancePtr_t aff( | ||
130 |
3/6✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 15 times.
✗ Branch 9 not taken.
|
15 | new Affordance(potentialAffordances[opIdx], colObj)); |
131 |
1/2✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
|
15 | foundAffordances->affordances_[opIdx].push_back(aff); |
132 | 66 | for (unsigned int removeIdx = 0; | |
133 |
2/2✓ Branch 2 taken 51 times.
✓ Branch 3 taken 15 times.
|
66 | removeIdx < potentialAffordances[opIdx].size(); removeIdx++) { |
134 |
1/2✓ Branch 3 taken 51 times.
✗ Branch 4 not taken.
|
51 | std::remove(unsetTriangles.begin(), unsetTriangles.end(), |
135 | 51 | potentialAffordances[opIdx][removeIdx]); | |
136 | 51 | unsetTriangles.pop_back(); | |
137 | } | ||
138 | // potentialAffordances [opIdx].clear (); | ||
139 | 15 | } | |
140 | 15 | potentialAffordances[opIdx].clear(); | |
141 | 15 | totArea = .0; | |
142 | 15 | break; | |
143 |
2/2✓ Branch 1 taken 15 times.
✓ Branch 2 taken 22 times.
|
37 | } else if (opIdx >= opVec.size() - 1) { |
144 | // delete triangle if it did not fulfil any requirements | ||
145 |
1/2✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
|
15 | std::remove(unsetTriangles.begin(), unsetTriangles.end(), triIdx); |
146 | 15 | unsetTriangles.pop_back(); | |
147 | } | ||
148 | } | ||
149 | } | ||
150 | 34 | return foundAffordances; | |
151 | 17 | } | |
152 | |||
153 | ✗ | Eigen::Matrix3d GetRotationMatrix(const Eigen::Vector3d& from, | |
154 | const Eigen::Vector3d& to) { | ||
155 | ✗ | Eigen::Quaterniond quat; | |
156 | ✗ | quat.setFromTwoVectors(from, to); | |
157 | ✗ | return quat.toRotationMatrix(); | |
158 | } | ||
159 | |||
160 | ✗ | Eigen::Matrix3d GetRotationMatrix(const std::vector<coal::Vec3f>& points) { | |
161 | ✗ | assert(points.size() > 2); | |
162 | ✗ | coal::Vec3f z(0., 0., 1.); | |
163 | ✗ | coal::Vec3f normal = (points[1] - points[0]).cross(points[2] - points[0]); | |
164 | ✗ | return GetRotationMatrix(normal, z); | |
165 | } | ||
166 | |||
167 | typedef coal::Vec3f Point; | ||
168 | typedef std::vector<Point> T_Point; | ||
169 | typedef T_Point::const_iterator CIT_Point; | ||
170 | |||
171 | ✗ | std::vector<coal::Vec3f> projectPoints(const Eigen::Matrix3d& project, | |
172 | const std::vector<coal::Vec3f>& points) { | ||
173 | ✗ | std::vector<coal::Vec3f> res; | |
174 | ✗ | for (CIT_Point cit = points.begin(); cit != points.end(); ++cit) | |
175 | ✗ | res.push_back(project * (*cit)); | |
176 | ✗ | return res; | |
177 | } | ||
178 | |||
179 | ✗ | coal::Vec3f computeCentroid(const std::vector<coal::Vec3f>& points) { | |
180 | ✗ | coal::Vec3f acc(0., 0., 0.); | |
181 | ✗ | for (CIT_Point cit = points.begin(); cit != points.end(); ++cit) | |
182 | ✗ | acc += (*cit); | |
183 | ✗ | return acc / points.size(); | |
184 | } | ||
185 | |||
186 | ✗ | std::vector<coal::Vec3f> translatePoints(const std::vector<coal::Vec3f>& points, | |
187 | const double reduceSize) { | ||
188 | ✗ | coal::Vec3f centroid = computeCentroid(points); | |
189 | ✗ | coal::Vec3f dir; | |
190 | ✗ | std::vector<coal::Vec3f> res; | |
191 | ✗ | for (CIT_Point cit = points.begin(); cit != points.end(); ++cit) { | |
192 | ✗ | dir = centroid - (*cit); | |
193 | ✗ | dir.normalize(); | |
194 | ✗ | res.push_back((*cit) + dir * reduceSize); | |
195 | } | ||
196 | ✗ | return res; | |
197 | } | ||
198 | |||
199 | ✗ | void createAffordanceModel(hpp::affordance::AffordancePtr_t affPtr, | |
200 | const std::vector<coal::Vec3f>& vertices, | ||
201 | const std::vector<coal::Triangle>& triangles, | ||
202 | const unsigned int affIdx, | ||
203 | std::vector<CollisionObjects_t>& affObjs) { | ||
204 | ✗ | BVHModelOB_Ptr_t model1(new BVHModelOB()); | |
205 | // add the mesh data into the BVHModel structure | ||
206 | ✗ | model1->beginModel(); | |
207 | ✗ | model1->addSubModel(vertices, triangles); | |
208 | ✗ | model1->endModel(); | |
209 | // create affordance collision object from created affModel and | ||
210 | // tranformation of corresponding reference collision object. | ||
211 | coal::CollisionObjectPtr_t obj( | ||
212 | ✗ | new coal::CollisionObject(model1, affPtr->colObj_->getTransform())); | |
213 | ✗ | affObjs[affIdx].push_back(obj); | |
214 | } | ||
215 | |||
216 | ✗ | void addTriangles(hpp::affordance::AffordancePtr_t affPtr, | |
217 | BVHModelOBConst_Ptr_t model, | ||
218 | std::vector<std::size_t>& triIndices, | ||
219 | const unsigned int triIdx, std::vector<coal::Vec3f>& vertices, | ||
220 | std::vector<coal::Triangle>& triangles) { | ||
221 | // give triangles of new object new vertex indices (start from 0 | ||
222 | // and go up to 3*nbTris - 1 [all tris have 3 unique indices]) | ||
223 | ✗ | std::vector<std::size_t> triPoints; | |
224 | const coal::Triangle& refTri = | ||
225 | ✗ | (*model->tri_indices)[affPtr->indices_[triIdx]]; | |
226 | // triangles.push_back (refTri); | ||
227 | ✗ | for (unsigned int vertIdx = 0; vertIdx < 3; vertIdx++) { | |
228 | std::vector<std::size_t>::iterator it = | ||
229 | ✗ | std::find(triIndices.begin(), triIndices.end(), refTri[vertIdx]); | |
230 | ✗ | if (it == triIndices.end()) { | |
231 | ✗ | triIndices.push_back(refTri[vertIdx]); | |
232 | ✗ | vertices.push_back((*model->vertices)[refTri[vertIdx]]); | |
233 | ✗ | triPoints.push_back(std::size_t(vertices.size() - 1)); | |
234 | } else { | ||
235 | ✗ | triPoints.push_back(it - triIndices.begin()); | |
236 | } | ||
237 | } | ||
238 | ✗ | if (triPoints.size() != 3) { | |
239 | ✗ | std::ostringstream oss("wrong number of vertex indices in triangle!!"); | |
240 | ✗ | throw std::runtime_error(oss.str()); | |
241 | } | ||
242 | ✗ | triangles.push_back(coal::Triangle(triPoints[0], triPoints[1], triPoints[2])); | |
243 | } | ||
244 | |||
245 | ✗ | std::vector<CollisionObjects_t> getAffordanceObjects( | |
246 | const SemanticsDataPtr_t& sData) { | ||
247 | ✗ | std::vector<CollisionObjects_t> affObjs; | |
248 | ✗ | for (unsigned int affIdx = 0; affIdx < sData->affordances_.size(); affIdx++) { | |
249 | ✗ | std::vector<coal::CollisionObjectPtr_t> objVec; | |
250 | ✗ | affObjs.push_back(objVec); | |
251 | // get number of affordances of specific type (lean OR support etc) | ||
252 | // this corresponds to number of objects to be created for specific aff type | ||
253 | ✗ | long unsigned int len = sData->affordances_[affIdx].size(); | |
254 | ✗ | for (unsigned int idx = 0; idx < len; idx++) { | |
255 | ✗ | std::vector<coal::Vec3f> vertices; | |
256 | ✗ | std::vector<coal::Triangle> triangles; | |
257 | ✗ | std::vector<std::size_t> triIndices; | |
258 | hpp::affordance::AffordancePtr_t affPtr = | ||
259 | ✗ | sData->affordances_[affIdx][idx]; | |
260 | ✗ | BVHModelOBConst_Ptr_t model = GetModel(affPtr->colObj_); | |
261 | ✗ | for (unsigned int triIdx = 0; triIdx < affPtr->indices_.size(); triIdx++) | |
262 | ✗ | addTriangles(affPtr, model, triIndices, triIdx, vertices, triangles); | |
263 | ✗ | createAffordanceModel(affPtr, vertices, triangles, affIdx, affObjs); | |
264 | } | ||
265 | } | ||
266 | ✗ | return affObjs; | |
267 | } | ||
268 | |||
269 | // same as getAffordanceObject but apply a reduction of a given size on the mesh | ||
270 | ✗ | std::vector<CollisionObjects_t> getReducedAffordanceObjects( | |
271 | const SemanticsDataPtr_t& sData, std::vector<double> reduceSizes) { | ||
272 | ✗ | if (reduceSizes.size() != sData->affordances_.size()) { | |
273 | std::ostringstream oss( | ||
274 | "Error : the vector 'reduceSizes' must have one element per affordance " | ||
275 | ✗ | "types"); | |
276 | ✗ | throw std::runtime_error(oss.str()); | |
277 | } | ||
278 | ✗ | std::vector<CollisionObjects_t> affObjs; | |
279 | ✗ | affObjs.clear(); | |
280 | ✗ | for (unsigned int affIdx = 0; affIdx < sData->affordances_.size(); affIdx++) { | |
281 | ✗ | std::vector<coal::CollisionObjectPtr_t> objVec; | |
282 | ✗ | affObjs.push_back(objVec); | |
283 | // get number of affordances of specific type (lean OR support etc) | ||
284 | // this corresponds to number of objects to be created for specific aff type | ||
285 | ✗ | long unsigned int len = sData->affordances_[affIdx].size(); | |
286 | ✗ | for (unsigned int idx = 0; idx < len; idx++) { | |
287 | ✗ | std::vector<coal::Vec3f> vertices; | |
288 | ✗ | std::vector<coal::Triangle> triangles; | |
289 | ✗ | std::vector<std::size_t> triIndices; | |
290 | hpp::affordance::AffordancePtr_t affPtr = | ||
291 | ✗ | sData->affordances_[affIdx][idx]; | |
292 | ✗ | BVHModelOBConst_Ptr_t model = GetModel(affPtr->colObj_); | |
293 | ✗ | for (unsigned int triIdx = 0; triIdx < affPtr->indices_.size(); triIdx++) | |
294 | ✗ | addTriangles(affPtr, model, triIndices, triIdx, vertices, triangles); | |
295 | |||
296 | ✗ | if (reduceSizes[affIdx] > std::numeric_limits<double>::epsilon()) { | |
297 | // std::cout<<"For points of affordance : "<<std::endl; | ||
298 | ✗ | for (unsigned int id = 0; id < vertices.size(); ++id) | |
299 | ✗ | std::cout << "( " << vertices[id][0] << " , " << vertices[id][1] | |
300 | ✗ | << " , " << vertices[id][2] << " ) " << std::endl; | |
301 | |||
302 | // first we need to sort the vertices in clockwise order. | ||
303 | // but as we cannot change the order in the 'vertices' vector we use | ||
304 | // another vector for correspondance of index first getTransformation | ||
305 | // matrix to project triangles in a 2d plane | ||
306 | ✗ | Eigen::Matrix3d project = GetRotationMatrix(vertices); | |
307 | std::vector<coal::Vec3f> projectedVertices = | ||
308 | ✗ | projectPoints(project, vertices); | |
309 | |||
310 | // now translate each point by the reducesize factor in the direction | ||
311 | // towards the centroid | ||
312 | std::vector<coal::Vec3f> translatedVertices = | ||
313 | ✗ | translatePoints(projectedVertices, reduceSizes[affIdx]); | |
314 | ✗ | vertices = projectPoints(project.transpose(), translatedVertices); | |
315 | } | ||
316 | ✗ | createAffordanceModel(affPtr, vertices, triangles, affIdx, affObjs); | |
317 | } | ||
318 | } | ||
319 | ✗ | return affObjs; | |
320 | } | ||
321 | |||
322 | } // namespace affordance | ||
323 | } // namespace hpp | ||
324 |