00001
00002
00003 #include "Iguana/Inventor/interface/IgSoRotSolid.h"
00004 #include <Inventor/nodes/SoIndexedFaceSet.h>
00005 #include <Inventor/nodes/SoIndexedLineSet.h>
00006 #include <Inventor/nodes/SoVertexProperty.h>
00007 #include <Inventor/nodes/SoShapeHints.h>
00008 #include <Inventor/SbLinear.h>
00009
00010
00011
00012
00013
00014
00015
00016
00017 SO_KIT_SOURCE (IgSoRotSolid);
00018
00019
00020
00021
00022
00023 void
00024 IgSoRotSolid::initClass (void)
00025 { SO_KIT_INIT_CLASS (IgSoRotSolid, IgSoShapeKit, "IgSoShapeKit"); }
00026
00027 IgSoRotSolid::IgSoRotSolid (void)
00028 {
00029 SO_KIT_CONSTRUCTOR (IgSoRotSolid);
00030 SO_KIT_ADD_FIELD (phiStart, (0.0));
00031 SO_KIT_ADD_FIELD (phiDelta, (2 * M_PI));
00032 SO_KIT_ADD_FIELD (polygon, (0, 0));
00033 SO_KIT_ADD_FIELD (divisions, (4));
00034 SO_KIT_ADD_FIELD (smooth, (TRUE));
00035 SO_KIT_ADD_FIELD (showLines, (FALSE));
00036 SO_KIT_ADD_CATALOG_ENTRY (hints, SoShapeHints, FALSE, separator,\x0, TRUE);
00037 SO_KIT_ADD_CATALOG_ENTRY (faces, SoIndexedFaceSet, FALSE, separator,\x0, TRUE);
00038 SO_KIT_ADD_CATALOG_ENTRY (lines, SoIndexedLineSet, FALSE, separator,\x0, TRUE);
00039
00040 SO_KIT_INIT_INSTANCE ();
00041 setUpConnections (true, true);
00042
00043 SbVec2f defaultShape [] =
00044 {
00045 SbVec2f (0, 0),
00046 SbVec2f (1, 1),
00047 SbVec2f (1, 0)
00048 };
00049
00050 polygon.setValues (0, 3, defaultShape);
00051 }
00052
00053 void
00054 IgSoRotSolid::cleanParts (void)
00055 {
00056 setPart ("hints", NULL);
00057 setPart ("faces", NULL);
00058 setPart ("lines", NULL);
00059 }
00060
00061 void
00062 IgSoRotSolid::refresh (void)
00063 {
00064
00065
00066 if (polygon.getNum () < 3)
00067 {
00068 cleanParts ();
00069 return;
00070 }
00071
00072 SoShapeHints *hints = new SoShapeHints;
00073 SoIndexedFaceSet *faces = new SoIndexedFaceSet;
00074 SoVertexProperty *vtx = new SoVertexProperty;
00075
00076 int divisions = this->divisions.getValue ();
00077 float phiStart = this->phiStart.getValue ();
00078 float phiDelta = this->phiDelta.getValue ();
00079 bool smooth = this->smooth.getValue ();
00080 int numEdges = polygon.getNum ();
00081
00082 bool edgeVertical = false;
00083 bool closedShape = true;
00084
00085
00086 if (fabs (phiDelta) < 2 * M_PI) closedShape = false;
00087
00088 if (smooth) divisions = (int) (phiDelta / (M_PI / 36.0)) + 2;
00089 float delta = phiDelta / divisions;
00090
00091
00092 std::vector<SbVec3f> crossSection;
00093
00094 for (int i = 0; i < numEdges; i++)
00095 {
00096 crossSection.push_back (SbVec3f (polygon [i][0], 0, polygon [i][1]));
00097 }
00098 crossSection.push_back (SbVec3f (polygon [0][0], 0, polygon [0][1]));
00099
00100 int totalPoints = 0;
00101
00102 std::vector<SbVec3f> vertexData;
00103 std::vector<int> indices;
00104 std::vector<int> lineIndices;
00105 std::vector<SbVec3f>::iterator it = crossSection.begin ();
00106 for (int i = 0; i < numEdges; i++, it++)
00107 {
00108 int nLeftPoints = 0;
00109 int nRightPoints = 0;
00110
00111 SbVec3f leftPoint = *it;
00112 SbVec3f rightPoint = *(it + 1);
00113
00114 (leftPoint [2] == rightPoint [2]) ? edgeVertical = true : edgeVertical = false;
00115
00116
00117
00118 if (leftPoint [0] != 0)
00119 {
00120
00121 for (float phi = phiStart; phi < phiStart + phiDelta; phi += delta)
00122 {
00123 SbMatrix transform;
00124 transform.setRotate (SbRotation (SbVec3f (0, 0, 1), phi));
00125 SbVec3f dst;
00126 transform.multVecMatrix (leftPoint, dst);
00127 vertexData.push_back (dst);
00128 lineIndices.push_back (totalPoints);
00129 totalPoints++;
00130 nLeftPoints++;
00131 }
00132
00133
00134 SbMatrix transform;
00135 transform.setRotate (SbRotation (SbVec3f (0, 0, 1), phiStart + phiDelta));
00136 SbVec3f dst;
00137 transform.multVecMatrix (leftPoint, dst);
00138 vertexData.push_back (dst);
00139 lineIndices.push_back (totalPoints);
00140 totalPoints++;
00141 nLeftPoints++;
00142 lineIndices.push_back (SO_END_LINE_INDEX);
00143 } else
00144 {
00145 if (edgeVertical)
00146 {
00147 if (!closedShape)
00148 {
00149 vertexData.push_back (leftPoint);
00150 totalPoints++;
00151 nLeftPoints++;
00152 }
00153 } else
00154 {
00155 vertexData.push_back (leftPoint);
00156 totalPoints++;
00157 nLeftPoints++;
00158 }
00159 }
00160
00161 if (rightPoint [0] != 0)
00162 {
00163
00164 for (float phi = phiStart; phi < phiStart + phiDelta; phi += delta)
00165 {
00166 SbMatrix transform;
00167 transform.setRotate (SbRotation (SbVec3f (0, 0, 1), phi));
00168 SbVec3f dst;
00169 transform.multVecMatrix (rightPoint, dst);
00170 vertexData.push_back (dst);
00171 lineIndices.push_back (totalPoints);
00172 totalPoints++;
00173 nRightPoints++;
00174 }
00175
00176
00177 SbMatrix transform;
00178 transform.setRotate (SbRotation (SbVec3f (0, 0, 1), phiStart + phiDelta));
00179 SbVec3f dst;
00180 transform.multVecMatrix (rightPoint, dst);
00181 vertexData.push_back (dst);
00182 lineIndices.push_back (totalPoints);
00183 totalPoints++;
00184 nRightPoints++;
00185 lineIndices.push_back (SO_END_LINE_INDEX);
00186 } else
00187 {
00188 if (edgeVertical)
00189 {
00190 if (!closedShape)
00191 {
00192 vertexData.push_back (rightPoint);
00193 totalPoints++;
00194 nRightPoints++;
00195 }
00196 } else
00197 {
00198 vertexData.push_back (rightPoint);
00199 totalPoints++;
00200 nRightPoints++;
00201 }
00202 }
00203
00204 int edgePoints = nRightPoints + nLeftPoints;
00205 int startPoint = totalPoints - edgePoints;
00206 int nEdgePoints = 0;
00207 (nLeftPoints >= nRightPoints) ? nEdgePoints = nLeftPoints : nEdgePoints = nRightPoints;
00208
00209 for (int npe = 0; npe < nEdgePoints - 1; npe++)
00210 {
00211 switch (nLeftPoints)
00212 {
00213 case 0:
00214 break;
00215 case 1:
00216 indices.push_back (startPoint);
00217 break;
00218 default:
00219 if (nRightPoints != 0)
00220 {
00221 indices.push_back (startPoint + npe);
00222 indices.push_back (startPoint + npe + 1);
00223 } else
00224 {
00225 indices.push_back (startPoint + npe);
00226 }
00227 break;
00228 }
00229
00230 switch (nRightPoints)
00231 {
00232 case 0:
00233 break;
00234 case 1:
00235 indices.push_back (totalPoints);
00236 indices.push_back (SO_END_FACE_INDEX);
00237 break;
00238 default:
00239 if (nLeftPoints != 0)
00240 {
00241 indices.push_back (totalPoints - nRightPoints + npe + 1);
00242 indices.push_back (totalPoints - nRightPoints + npe);
00243 indices.push_back (SO_END_FACE_INDEX);
00244
00245 if (!smooth)
00246 {
00247 if (nLeftPoints == 1)
00248 lineIndices.push_back (startPoint);
00249 else
00250 lineIndices.push_back (startPoint + npe);
00251 lineIndices.push_back (totalPoints - nRightPoints + npe);
00252 lineIndices.push_back (SO_END_LINE_INDEX);
00253 }
00254 } else
00255 {
00256 indices.push_back (totalPoints - npe - 1);
00257 }
00258 break;
00259 }
00260 }
00261 if (!indices.empty () && (indices.back () != SO_END_FACE_INDEX))
00262 indices.push_back (SO_END_FACE_INDEX);
00263 }
00264
00265 if (!closedShape)
00266 {
00267 std::vector<SbVec3f> edgeVertexData;
00268 std::vector<int> edgeIndices;
00269
00270 for (std::vector<SbVec3f>::iterator it = crossSection.begin (); it != crossSection.end (); it++)
00271 {
00272 SbMatrix transform;
00273 transform.setRotate (SbRotation (SbVec3f (0, 0, 1), phiStart));
00274 SbVec3f src = *it;
00275 SbVec3f dst;
00276 transform.multVecMatrix (src, dst);
00277 vertexData.push_back (dst);
00278 indices.push_back (totalPoints);
00279 totalPoints++;
00280 }
00281 indices.push_back (SO_END_FACE_INDEX);
00282
00283 float phi = phiDelta + phiStart;
00284 for (std::vector<SbVec3f>::reverse_iterator it = crossSection.rbegin (); it != crossSection.rend (); it++)
00285 {
00286 SbMatrix transform;
00287 transform.setRotate (SbRotation (SbVec3f (0, 0, 1), phi));
00288 SbVec3f src = *it;
00289 SbVec3f dst;
00290 transform.multVecMatrix (src, dst);
00291 vertexData.push_back (dst);
00292 indices.push_back (totalPoints);
00293 totalPoints++;
00294 }
00295 indices.push_back (SO_END_FACE_INDEX);
00296 }
00297
00298 vtx->vertex.setValues (0, vertexData.size (), &vertexData [0]);
00299 faces->vertexProperty = vtx;
00300 faces->coordIndex.setValues (0, indices.size (), &indices [0]);
00301
00302
00303 hints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
00304 hints->shapeType = SoShapeHints::SOLID;
00305 if (smooth)
00306 hints->creaseAngle = 10.0;
00307
00308 setPart ("hints", hints);
00309 setPart ("faces", faces);
00310
00311 if (showLines.getValue () == true)
00312 {
00313 SoIndexedLineSet *lines = new SoIndexedLineSet;
00314 lines->coordIndex.setValues (0, lineIndices.size (), &lineIndices [0]);
00315 lines->vertexProperty = vtx;
00316 setPart ("lines", lines);
00317 }
00318 else
00319 {
00320 setPart ("lines", NULL);
00321 }
00322 }
00323
00324 void
00325 IgSoRotSolid::makePgon (const std::vector<float> &zvals,
00326 const std::vector<float> &rmin,
00327 const std::vector<float> &rmax,
00328 float phiStart,
00329 float phiDelta,
00330 int divisions)
00331 {
00332 this->divisions.setValue (divisions);
00333 this->phiStart.setValue (phiStart);
00334 this->phiDelta.setValue (phiDelta);
00335 if (divisions < 0)
00336 this->smooth = TRUE;
00337 else
00338 this->smooth = FALSE;
00339
00340 std::vector<SbVec2f> contour (2 * zvals.size ());
00341 int k = 0;
00342
00343 for (int i = 0; i < (int) zvals.size (); i++)
00344 {
00345 contour [k][0] = rmax [i];
00346 contour [k][1] = zvals [i];
00347 k++;
00348 }
00349
00350 for (int i = (int) zvals.size () - 1; i >= 0 ; i--)
00351 {
00352 contour [k][0] = rmin [i];
00353 contour [k][1] = zvals [i];
00354 k++;
00355 }
00356 this->polygon.setValues (0, 2 * zvals.size (), &contour [0]);
00357 }
00358
00359 void
00360 IgSoRotSolid::makePcon (const std::vector<float> &zvals,
00361 const std::vector<float> &rmin,
00362 const std::vector<float> &rmax,
00363 float phiStart,
00364 float phiDelta,
00365 int divisions)
00366 {
00367 makePgon (zvals, rmin, rmax, phiStart, phiDelta, divisions);
00368 }
00369
00370 void
00371 IgSoRotSolid::makeCons (float rmin1,
00372 float rmax1,
00373 float rmin2,
00374 float rmax2,
00375 float dz,
00376 float phiStart,
00377 float phiDelta,
00378 int divisions)
00379 {
00380 std::vector<float> zvals (2);
00381 std::vector<float> rminTemp (2);
00382 std::vector<float> rmaxTemp (2);
00383
00384 zvals [0] = -dz;
00385 zvals [1] = dz;
00386 rminTemp [0] = rmin1;
00387 rminTemp [1] = rmin2;
00388 rmaxTemp [0] = rmax1;
00389 rmaxTemp [1] = rmax2;
00390
00391 makePcon (zvals, rminTemp, rmaxTemp, phiStart, phiDelta, divisions);
00392 }
00393
00394 void
00395 IgSoRotSolid::makeTubs (float rmin,
00396 float rmax,
00397 float dz,
00398 float phiStart,
00399 float phiDelta,
00400 int divisions)
00401 {
00402 std::vector<float> zvals (2);
00403 std::vector<float> rminTemp (2);
00404 std::vector<float> rmaxTemp (2);
00405
00406 zvals [0] = -dz;
00407 zvals [1] = dz;
00408 rminTemp [0] = rmin;
00409 rminTemp [1] = rmin;
00410 rmaxTemp [0] = rmax;
00411 rmaxTemp [1] = rmax;
00412
00413 makePcon (zvals, rminTemp, rmaxTemp, phiStart, phiDelta, divisions);
00414 }