00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <pcl/surface/on_nurbs/nurbs_data.h>
00039 #include <pcl/surface/on_nurbs/triangulation.h>
00040 #include <pcl/surface/on_nurbs/fitting_curve_2d_apdm.h>
00041 #include <pcl/conversions.h>
00042
00043 using namespace pcl;
00044 using namespace on_nurbs;
00045
00046 void
00047 Triangulation::createIndices (std::vector<pcl::Vertices> &vertices, unsigned vidx, unsigned segX, unsigned segY)
00048 {
00049 for (unsigned j = 0; j < segY; j++)
00050 {
00051 for (unsigned i = 0; i < segX; i++)
00052 {
00053 unsigned i0 = vidx + (segX + 1) * j + i;
00054 unsigned i1 = vidx + (segX + 1) * j + i + 1;
00055 unsigned i2 = vidx + (segX + 1) * (j + 1) + i + 1;
00056 unsigned i3 = vidx + (segX + 1) * (j + 1) + i;
00057
00058 pcl::Vertices v1;
00059 v1.vertices.push_back (i0);
00060 v1.vertices.push_back (i1);
00061 v1.vertices.push_back (i2);
00062 vertices.push_back (v1);
00063
00064 pcl::Vertices v2;
00065 v2.vertices.push_back (i0);
00066 v2.vertices.push_back (i2);
00067 v2.vertices.push_back (i3);
00068 vertices.push_back (v2);
00069 }
00070 }
00071 }
00072
00073 void
00074 Triangulation::createVertices (pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud, float x0, float y0, float z0, float width,
00075 float height, unsigned segX, unsigned segY)
00076 {
00077 pcl::PointXYZ v;
00078 float dx = width / float (segX);
00079 float dy = height / float (segY);
00080
00081 for (unsigned j = 0; j <= segY; j++)
00082 {
00083 for (unsigned i = 0; i <= segX; i++)
00084 {
00085 v.x = x0 + float (i) * dx;
00086 v.y = y0 + float (j) * dy;
00087 v.z = z0;
00088 cloud->push_back (v);
00089 }
00090 }
00091 }
00092
00093 bool
00094 Triangulation::isInside(const ON_NurbsCurve &curve, const pcl::PointXYZ &v)
00095 {
00096 Eigen::Vector2d vp (v.x, v.y);
00097
00098 Eigen::Vector3d a0, a1;
00099 pcl::on_nurbs::NurbsTools::computeBoundingBox (curve, a0, a1);
00100 double rScale = 1.0 / pcl::on_nurbs::NurbsTools::computeRScale (a0, a1);
00101
00102 Eigen::Vector2d pc, tc;
00103 double err, param;
00104
00105 if (curve.Order () == 2)
00106 param = pcl::on_nurbs::FittingCurve2dAPDM::inverseMappingO2 (curve, vp, err, pc, tc);
00107 else
00108 {
00109 param = pcl::on_nurbs::FittingCurve2dAPDM::findClosestElementMidPoint (curve, vp);
00110 param = pcl::on_nurbs::FittingCurve2dAPDM::inverseMapping (curve, vp, param, err, pc, tc, rScale);
00111 }
00112
00113 Eigen::Vector3d a (vp (0) - pc (0), vp (1) - pc (1), 0.0);
00114 Eigen::Vector3d b (tc (0), tc (1), 0.0);
00115 Eigen::Vector3d z = a.cross (b);
00116
00117 return (z (2) >= 0.0);
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 void
00164 Triangulation::convertSurface2PolygonMesh (const ON_NurbsSurface &nurbs, PolygonMesh &mesh, unsigned resolution)
00165 {
00166
00167 if (nurbs.KnotCount (0) <= 1 || nurbs.KnotCount (1) <= 1)
00168 {
00169 printf ("[Triangulation::convertSurface2PolygonMesh] Warning: ON knot vector empty.\n");
00170 return;
00171 }
00172
00173 double x0 = nurbs.Knot (0, 0);
00174 double x1 = nurbs.Knot (0, nurbs.KnotCount (0) - 1);
00175 double w = x1 - x0;
00176 double y0 = nurbs.Knot (1, 0);
00177 double y1 = nurbs.Knot (1, nurbs.KnotCount (1) - 1);
00178 double h = y1 - y0;
00179
00180 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
00181 mesh.polygons.clear ();
00182 createVertices (cloud, float (x0), float (y0), 0.0f, float (w), float (h), resolution, resolution);
00183 createIndices (mesh.polygons, 0, resolution, resolution);
00184
00185 for (unsigned i = 0; i < cloud->size (); i++)
00186 {
00187 pcl::PointXYZ &v = cloud->at (i);
00188
00189 double point[9];
00190 nurbs.Evaluate (v.x, v.y, 1, 3, point);
00191
00192 v.x = float (point[0]);
00193 v.y = float (point[1]);
00194 v.z = float (point[2]);
00195 }
00196
00197 toPCLPointCloud2 (*cloud, mesh.cloud);
00198 }
00199
00200 void
00201 Triangulation::convertTrimmedSurface2PolygonMesh (const ON_NurbsSurface &nurbs, const ON_NurbsCurve &curve,
00202 PolygonMesh &mesh, unsigned resolution)
00203 {
00204
00205 if (nurbs.KnotCount (0) <= 1 || nurbs.KnotCount (1) <= 1 || curve.KnotCount () <= 1)
00206 {
00207 printf ("[Triangulation::convertTrimmedSurface2PolygonMesh] Warning: ON knot vector empty.\n");
00208 return;
00209 }
00210
00211 mesh.polygons.clear ();
00212
00213 double x0 = nurbs.Knot (0, 0);
00214 double x1 = nurbs.Knot (0, nurbs.KnotCount (0) - 1);
00215 double w = x1 - x0;
00216 double y0 = nurbs.Knot (1, 0);
00217 double y1 = nurbs.Knot (1, nurbs.KnotCount (1) - 1);
00218 double h = y1 - y0;
00219
00220 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
00221 std::vector<pcl::Vertices> polygons;
00222 createVertices (cloud, float (x0), float (y0), 0.0f, float (w), float (h), resolution, resolution);
00223 createIndices (polygons, 0, resolution, resolution);
00224
00225 vector_vec2d points (cloud->size (), Eigen::Vector2d ());
00226 std::vector<double> params (cloud->size (), 0.0);
00227 std::vector<bool> pt_is_in (cloud->size (), false);
00228
00229 Eigen::Vector3d a0, a1;
00230 pcl::on_nurbs::NurbsTools::computeBoundingBox (curve, a0, a1);
00231 double rScale = 1.0 / pcl::on_nurbs::NurbsTools::computeRScale (a0, a1);
00232
00233 std::vector<uint32_t> out_idx;
00234 pcl::on_nurbs::vector_vec2d out_pc;
00235
00236 for (unsigned i = 0; i < cloud->size (); i++)
00237 {
00238 double err, param;
00239 Eigen::Vector2d pc, tc;
00240 pcl::PointXYZ &v = cloud->at (i);
00241 Eigen::Vector2d vp (v.x, v.y);
00242
00243 if (curve.Order () == 2)
00244 param = pcl::on_nurbs::FittingCurve2dAPDM::inverseMappingO2 (curve, vp, err, pc, tc);
00245 else
00246 {
00247 param = pcl::on_nurbs::FittingCurve2dAPDM::findClosestElementMidPoint (curve, vp);
00248 param = pcl::on_nurbs::FittingCurve2dAPDM::inverseMapping (curve, vp, param, err, pc, tc, rScale);
00249 }
00250
00251 Eigen::Vector3d a (vp (0) - pc (0), vp (1) - pc (1), 0.0);
00252 Eigen::Vector3d b (tc (0), tc (1), 0.0);
00253 Eigen::Vector3d z = a.cross (b);
00254
00255 points[i] = pc;
00256 params[i] = param;
00257 pt_is_in[i] = (z (2) >= 0.0);
00258 }
00259
00260 for (unsigned i = 0; i < polygons.size (); i++)
00261 {
00262 unsigned in (0);
00263 pcl::Vertices &poly = polygons[i];
00264
00265 std::vector<uint32_t> out_idx_tmp;
00266 pcl::on_nurbs::vector_vec2d out_pc_tmp;
00267
00268 for (std::size_t j = 0; j < poly.vertices.size (); j++)
00269 {
00270 uint32_t &vi = poly.vertices[j];
00271 if (pt_is_in[vi])
00272 in++;
00273 else
00274 {
00275 out_idx_tmp.push_back (vi);
00276 out_pc_tmp.push_back (points[vi]);
00277 }
00278 }
00279
00280 if (in > 0)
00281 {
00282 mesh.polygons.push_back (poly);
00283 if (in < poly.vertices.size ())
00284 {
00285 for (std::size_t j = 0; j < out_idx_tmp.size (); j++)
00286 {
00287 out_idx.push_back (out_idx_tmp[j]);
00288 out_pc.push_back (out_pc_tmp[j]);
00289 }
00290 }
00291 }
00292 }
00293
00294 for (std::size_t i = 0; i < out_idx.size (); i++)
00295 {
00296 pcl::PointXYZ &v = cloud->at (out_idx[i]);
00297 Eigen::Vector2d &pc = out_pc[i];
00298 v.x = float (pc (0));
00299 v.y = float (pc (1));
00300 }
00301
00302 for (std::size_t i = 0; i < cloud->size (); i++)
00303 {
00304 pcl::PointXYZ &v = cloud->at (i);
00305 Eigen::Vector3d tu, tv;
00306
00307 double point[3];
00308 nurbs.Evaluate (v.x, v.y, 0, 3, point);
00309
00310 v.x = float (point[0]);
00311 v.y = float (point[1]);
00312 v.z = float (point[2]);
00313
00314
00315
00316
00317
00318
00319
00320
00321 }
00322
00323 toPCLPointCloud2 (*cloud, mesh.cloud);
00324 }
00325
00326 void
00327 Triangulation::convertTrimmedSurface2PolygonMesh (const ON_NurbsSurface &nurbs, const ON_NurbsCurve &curve,
00328 PolygonMesh &mesh, unsigned resolution, vector_vec3d &start,
00329 vector_vec3d &end)
00330 {
00331
00332 if (nurbs.KnotCount (0) <= 1 || nurbs.KnotCount (1) <= 1 || curve.KnotCount () <= 1)
00333 {
00334 printf ("[Triangulation::convertTrimmedSurface2PolygonMesh] Warning: ON knot vector empty.\n");
00335 return;
00336 }
00337
00338 mesh.polygons.clear ();
00339
00340 double x0 = nurbs.Knot (0, 0);
00341 double x1 = nurbs.Knot (0, nurbs.KnotCount (0) - 1);
00342 double w = x1 - x0;
00343 double y0 = nurbs.Knot (1, 0);
00344 double y1 = nurbs.Knot (1, nurbs.KnotCount (1) - 1);
00345 double h = y1 - y0;
00346
00347 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
00348 std::vector<pcl::Vertices> polygons;
00349 createVertices (cloud, float (x0), float (y0), 0.0f, float (w), float (h), resolution, resolution);
00350 createIndices (polygons, 0, resolution, resolution);
00351
00352 vector_vec2d points (cloud->size (), Eigen::Vector2d ());
00353 std::vector<double> params (cloud->size (), 0.0);
00354 std::vector<bool> pt_is_in (cloud->size (), false);
00355
00356 std::vector<uint32_t> out_idx;
00357 pcl::on_nurbs::vector_vec2d out_pc;
00358
00359 Eigen::Vector3d a0, a1;
00360 pcl::on_nurbs::NurbsTools::computeBoundingBox (curve, a0, a1);
00361 double rScale = 1.0 / pcl::on_nurbs::NurbsTools::computeRScale (a0, a1);
00362
00363 for (unsigned i = 0; i < cloud->size (); i++)
00364 {
00365 double err, param;
00366 Eigen::Vector2d pc, tc;
00367 pcl::PointXYZ &v = cloud->at (i);
00368 Eigen::Vector2d vp (v.x, v.y);
00369
00370 if (curve.Order () == 2)
00371 param = pcl::on_nurbs::FittingCurve2dAPDM::inverseMappingO2 (curve, vp, err, pc, tc);
00372 else
00373 {
00374 param = pcl::on_nurbs::FittingCurve2dAPDM::findClosestElementMidPoint (curve, vp);
00375 param = pcl::on_nurbs::FittingCurve2dAPDM::inverseMapping (curve, vp, param, err, pc, tc, rScale, 100, 1e-4, true);
00376 }
00377
00378 Eigen::Vector3d a (vp (0) - pc (0), vp (1) - pc (1), 0.0);
00379 Eigen::Vector3d b (tc (0), tc (1), 0.0);
00380 Eigen::Vector3d z = a.cross (b);
00381
00382 points[i] = pc;
00383 params[i] = param;
00384 pt_is_in[i] = (z (2) >= 0.0);
00385
00386 end.push_back (Eigen::Vector3d (pc (0), pc (1), 0.0));
00387 start.push_back (Eigen::Vector3d (vp (0), vp (1), 0.0));
00388 }
00389
00390 for (unsigned i = 0; i < polygons.size (); i++)
00391 {
00392 unsigned in (0);
00393 pcl::Vertices &poly = polygons[i];
00394
00395 std::vector<uint32_t> out_idx_tmp;
00396 pcl::on_nurbs::vector_vec2d out_pc_tmp;
00397
00398 for (std::size_t j = 0; j < poly.vertices.size (); j++)
00399 {
00400 uint32_t &vi = poly.vertices[j];
00401 if (pt_is_in[vi])
00402 in++;
00403 else
00404 {
00405 out_idx_tmp.push_back (vi);
00406 out_pc_tmp.push_back (points[vi]);
00407 }
00408 }
00409
00410 if (in > 0)
00411 {
00412 mesh.polygons.push_back (poly);
00413 if (in < poly.vertices.size ())
00414 {
00415 for (std::size_t j = 0; j < out_idx_tmp.size (); j++)
00416 {
00417 out_idx.push_back (out_idx_tmp[j]);
00418 out_pc.push_back (out_pc_tmp[j]);
00419 }
00420 }
00421 }
00422 }
00423
00424 for (std::size_t i = 0; i < out_idx.size (); i++)
00425 {
00426 pcl::PointXYZ &v = cloud->at (out_idx[i]);
00427 Eigen::Vector2d &pc = out_pc[i];
00428 v.x = float (pc (0));
00429 v.y = float (pc (1));
00430 }
00431
00432 for (std::size_t i = 0; i < cloud->size (); i++)
00433 {
00434 pcl::PointXYZ &v = cloud->at (i);
00435
00436 double point[3];
00437 nurbs.Evaluate (v.x, v.y, 0, 3, point);
00438
00439 v.x = float (point[0]);
00440 v.y = float (point[1]);
00441 v.z = float (point[2]);
00442 }
00443
00444 for (std::size_t i = 0; i < start.size (); i++)
00445 {
00446 Eigen::Vector3d &p1 = start[i];
00447 Eigen::Vector3d &p2 = end[i];
00448
00449 double point[3];
00450 nurbs.Evaluate (p1 (0), p1 (1), 0, 3, point);
00451 p1 (0) = point[0];
00452 p1 (1) = point[1];
00453 p1 (2) = point[2];
00454
00455 nurbs.Evaluate (p2 (0), p2 (1), 0, 3, point);
00456 p2 (0) = point[0];
00457 p2 (1) = point[1];
00458 p2 (2) = point[2];
00459 }
00460
00461 toPCLPointCloud2 (*cloud, mesh.cloud);
00462 }
00463
00464 void
00465 Triangulation::convertSurface2Vertices (const ON_NurbsSurface &nurbs, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
00466 std::vector<pcl::Vertices> &vertices, unsigned resolution)
00467 {
00468
00469 if (nurbs.KnotCount (0) <= 1 || nurbs.KnotCount (1) <= 1)
00470 {
00471 printf ("[Triangulation::convertSurface2Vertices] Warning: ON knot vector empty.\n");
00472 return;
00473 }
00474
00475 cloud->clear ();
00476 vertices.clear ();
00477
00478 double x0 = nurbs.Knot (0, 0);
00479 double x1 = nurbs.Knot (0, nurbs.KnotCount (0) - 1);
00480 double w = x1 - x0;
00481 double y0 = nurbs.Knot (1, 0);
00482 double y1 = nurbs.Knot (1, nurbs.KnotCount (1) - 1);
00483 double h = y1 - y0;
00484
00485 createVertices (cloud, float (x0), float (y0), 0.0f, float (w), float (h), resolution, resolution);
00486 createIndices (vertices, 0, resolution, resolution);
00487
00488 for (unsigned i = 0; i < cloud->size (); i++)
00489 {
00490 pcl::PointXYZ &v = cloud->at (i);
00491
00492 double point[9];
00493 nurbs.Evaluate (v.x, v.y, 1, 3, point);
00494
00495 v.x = static_cast<float> (point[0]);
00496 v.y = static_cast<float> (point[1]);
00497 v.z = static_cast<float> (point[2]);
00498 }
00499 }
00500
00501 void
00502 Triangulation::convertCurve2PointCloud (const ON_NurbsCurve &nurbs, pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud,
00503 unsigned resolution)
00504 {
00505
00506 if (nurbs.m_knot_capacity <= 1)
00507 {
00508 printf ("[Triangulation::convertCurve2PointCloud] Warning: ON knot vector empty.\n");
00509 return;
00510 }
00511
00512 cloud->clear ();
00513
00514 if (resolution < 2)
00515 resolution = 2;
00516
00517 int cp_red = nurbs.Order () - 2;
00518
00519
00520 for (int i = cp_red; i < nurbs.KnotCount () - 1 - cp_red; i++)
00521 {
00522 double dr = 1.0 / (resolution - 1);
00523 double xi0 = nurbs.m_knot[i];
00524 double xid = (nurbs.m_knot[i + 1] - xi0);
00525
00526 for (unsigned j = 0; j < resolution; j++)
00527 {
00528 double xi = (xi0 + dr * xid * j);
00529 pcl::PointXYZRGB p;
00530
00531 double points[3];
00532 nurbs.Evaluate (xi, 0, 3, points);
00533 p.x = static_cast<float> (points[0]);
00534 p.y = static_cast<float> (points[1]);
00535 p.z = static_cast<float> (points[2]);
00536 p.r = 255;
00537 p.g = 0;
00538 p.b = 0;
00539
00540 cloud->push_back (p);
00541 }
00542
00543 }
00544 }
00545
00546 void
00547 Triangulation::convertCurve2PointCloud (const ON_NurbsCurve &curve, const ON_NurbsSurface &surf,
00548 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud, unsigned resolution)
00549 {
00550
00551 if (curve.m_knot_capacity <= 1)
00552 {
00553 printf ("[Triangulation::convertCurve2PointCloud] Warning: ON knot vector empty.\n");
00554 return;
00555 }
00556
00557 cloud->clear ();
00558
00559 if (resolution < 2)
00560 resolution = 2;
00561
00562 int cp_red = curve.Order () - 2;
00563
00564
00565 for (int i = 1; i < curve.KnotCount () - 1 - cp_red; i++)
00566 {
00567 double dr = 1.0 / (resolution - 1);
00568
00569 double xi0 = curve.m_knot[i];
00570 double xid = (curve.m_knot[i + 1] - xi0);
00571
00572 for (unsigned j = 0; j < resolution; j++)
00573 {
00574 pcl::PointXYZRGB pt;
00575
00576 double xi = (xi0 + j * dr * xid);
00577
00578 double p[3];
00579 double pp[3];
00580 curve.Evaluate (xi, 0, 2, pp);
00581 surf.Evaluate (pp[0], pp[1], 0, 3, p);
00582 pt.x = float (p[0]);
00583 pt.y = float (p[1]);
00584 pt.z = float (p[2]);
00585 pt.r = 255;
00586 pt.g = 0;
00587 pt.b = 0;
00588
00589 cloud->push_back (pt);
00590 }
00591
00592 }
00593 }