//=========================================================================== // GoTools Core - SINTEF Geometry Tools Core library, version 2.0.1 // // Copyright (C) 2000-2007, 2010 SINTEF ICT, Applied Mathematics, Norway. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., // 59 Temple Place - Suite 330, // Boston, MA 02111-1307, USA. // // Contact information: E-mail: tor.dokken@sintef.no // SINTEF ICT, Department of Applied Mathematics, // P.O. Box 124 Blindern, // 0314 Oslo, Norway. // // Other licenses are also available for this software, notably licenses // for: // - Building commercial software. // - Building software whose source code you wish to keep private. //=========================================================================== 00106 #ifndef DBG 00107 const bool dbg = false; 00108 #endif 00109 00110 if (!degenerate_triangle(vert_p[c1], vert_p[c2], vert_p[c3] DBG_FLAG)) 00111 { 00112 mesh.push_back(c1); 00113 mesh.push_back(c2); 00114 mesh.push_back(c3); 00115 } 00116 else 00117 if (dbg) 00118 { 00119 printf(" add_triangle(): Not adding triangle. Degenerate.\n"); 00120 printf("\n"); 00121 printf(" hold on; plot(%f, %f, 'ro', 'markersize', 10, 'linewidth', 2);\n", vert_p[c1][0], vert_p[c1][1]); 00122 printf(" plot(%f, %f, 'go', 'markersize', 10, 'linewidth', 2);\n", vert_p[c2][0], vert_p[c2][1]); 00123 printf(" plot(%f, %f, 'bo', 'markersize', 10, 'linewidth', 2); hold off\n", vert_p[c3][0], vert_p[c3][1]); 00124 printf("\n"); 00125 // const bool tmp = degenerate_triangle(vert_p[c1], vert_p[c2], vert_p[c3] DBG_FLAG); 00126 } 00127 }
std::vector< CurveLoop > Go::allBoundarySfLoops | ( | boost::shared_ptr< ParamSurface > | surf, | |
double | degenerate_epsilon | |||
) |
Definition at line 99 of file SurfaceTools.C.
References outerBoundarySfLoop().
00102 { 00103 boost::shared_ptr<SplineSurface> spline_sf = 00104 boost::shared_dynamic_cast<SplineSurface, ParamSurface>(surf); 00105 00106 if (spline_sf.get()) 00107 { 00108 // There is only one boundary loop... 00109 std::vector<CurveLoop> cvloopvec; 00110 cvloopvec.push_back(outerBoundarySfLoop(surf, degenerate_epsilon)); 00111 return cvloopvec; 00112 } 00113 else 00114 { 00115 // VSK, 1109. A similar problem as for spline surface occurs for 00116 // elementary surfaces, but it is currently not handled 00117 // VSK, 0510. Add the surface back pointer 00118 vector<CurveLoop> cv_loops = surf->allBoundaryLoops(degenerate_epsilon); 00119 if (cv_loops.size() == 0) 00120 return cv_loops; 00121 00122 if (cv_loops[0].size() == 0) 00123 return cv_loops; 00124 00125 shared_ptr<CurveOnSurface> cv = 00126 shared_dynamic_cast<CurveOnSurface,ParamCurve>(cv_loops[0][0]); 00127 if (cv.get()) 00128 return cv_loops; // Already curve on surface curves 00129 00130 vector<CurveLoop> cv_loops2; 00131 for (size_t kj=0; kj<cv_loops.size(); ++kj) 00132 { 00133 int nmb_cvs = cv_loops[kj].size(); 00134 vector< shared_ptr< ParamCurve > > vec; 00135 for (int ki=0; ki<nmb_cvs; ++ki) 00136 { 00137 shared_ptr<ParamCurve> sfcv = 00138 shared_ptr<ParamCurve>(new CurveOnSurface(surf, cv_loops[kj][ki], false)); 00139 vec.push_back(sfcv); 00140 } 00141 cv_loops2.push_back(CurveLoop(vec, degenerate_epsilon)); 00142 } 00143 return cv_loops2; 00144 } 00145 }
int Go::analyzePeriodicity | ( | const BsplineBasis & | basis, | |
double | knot_tol = 1e-12 | |||
) |
Analyze periodicity of basis based on number of repeating knots.
The return value is -1 if there is no repeating (or order-tuple end knots), up to k if there are (order-1-k)-tuple end knots and sufficient repeats for a C^k curve. This is mostly a helper function for the curve and surface analysis functions.
basis | reference to the BsplineBasis to analyze | |
knot_tol | the tolerance used when comparing knots and knot intervals |
Definition at line 114 of file GeometryTools.C.
References Go::BsplineBasis::begin(), Go::BsplineBasis::endMultiplicity(), Go::BsplineBasis::endparam(), Go::BsplineBasis::numCoefs(), Go::BsplineBasis::order(), and Go::BsplineBasis::startparam().
00116 { 00117 // Check if the first knots are repeated 00118 // (translated) at the end. 00119 // We must first find our 'target' number of repeats, 00120 // by checking the multiplicity of the startparam() knot. 00121 int emul = basis.endMultiplicity(true); 00122 if (basis.endMultiplicity(false) != emul) { 00123 return -1; 00124 } 00125 int k = basis.order(); 00126 int n = basis.numCoefs(); 00127 double delta = basis.endparam() - basis.startparam(); 00128 std::vector<double>::const_iterator kn = basis.begin(); 00129 int i = 1; 00130 for (; i < k-emul+1; ++i) { 00131 double d1 = kn[n+emul-1+i] - kn[k-1+i]; 00132 double d2 = kn[n-i] - kn[k-emul-i]; 00133 // We only allow minimal floating point errors 00134 if (std::max(std::abs(d1-delta), std::abs(d2-delta)) > knot_tol) { 00135 break; 00136 } 00137 } 00138 return i - 2; 00139 }
int Go::analyzePeriodicity | ( | const SplineSurface & | sf, | |
int | direction, | |||
double | knot_tol = 1e-12 | |||
) |
Analyze periodicity of surface based on number of repeating knots and control points.
The return value is -1 if the surface edges are disjoint, otherwise k if sf is C^k continuous across the seam. These are sufficient but not necessary conditions for periodicity, so it is possible that a call to analyzePeriodicityDerivs() will yield a higher degree of periodicity. The current implementation is quite slow, and not optimized for speed.
sf | reference to the SplineSurface to be analyzed | |
direction | specify 'direction' to be '0' to check for periodicity in the first parameter direction, or '1' to check the second parameter direction. | |
knot_tol | the tolerance used when comparing knot intervals |
Definition at line 100 of file GeometryTools.C.
References analyzePeriodicity(), representSurfaceAsCurve(), and THROW.
00102 { 00103 if (direction < 0 || direction > 1) { 00104 THROW("Error in direction parameter. Must be 0 or 1."); 00105 } 00106 // Make a hypercurve from this surface. 00107 // Direction parameter is one more for representSurface...() :-P 00108 boost::shared_ptr<SplineCurve> cv 00109 = representSurfaceAsCurve(sf, direction + 1); 00110 return analyzePeriodicity(*cv, knot_tol); 00111 }
int Go::analyzePeriodicity | ( | const SplineCurve & | cv, | |
double | knot_tol = 1e-12 | |||
) |
Analyze periodicity of curve based on number of repeating knots and control points.
The return value is -1 if the curve ends are disjoint, otherwise k if cv is C^k continuous. These are sufficient but not necessary conditions for periodicity, so it is possible that a call to analyzePeriodicityDerivs() will yield a higher degree of periodicity.
cv | the curve to analyse | |
knot_tol | the tolerance used when comparing knot intervals. |
Definition at line 51 of file GeometryTools.C.
References Go::SplineCurve::basis(), Go::SplineCurve::coefs_begin(), Go::SplineCurve::dimension(), Go::SplineCurve::numCoefs(), Go::SplineCurve::rational(), and Go::SplineCurve::rcoefs_begin().
Referenced by analyzePeriodicity(), Go::SplineCurve::appendSelfPeriodic(), and main().
00053 { 00054 // Analyze the knot vectors for periodicity. 00055 // That is, check if the first knots are repeated 00056 // (translated) at the end. 00057 int basper = analyzePeriodicity(cv.basis(), knot_tol); 00058 if (basper == -1) return -1; 00059 00060 // Analyze the coefficient vector for periodicity. 00061 // The (basper+1) first must equal the (basper+1) last. 00062 int n = cv.numCoefs() - basper - 1; 00063 int dim = cv.dimension(); 00064 std::vector<double>::const_iterator c = cv.coefs_begin(); 00065 if (cv.rational()) { 00066 ++dim; 00067 c = cv.rcoefs_begin(); 00068 } 00069 for (int i = 0; i < basper + 1; ++i) { 00070 for (int dd = 0; dd < dim; ++dd) { 00071 if (c[dim*i + dd] != c[dim*(i+n) + dd]) { 00072 return -1; 00073 } 00074 } 00075 } 00076 return basper; 00077 }
int Go::analyzePeriodicityDerivs | ( | const SplineSurface & | sf, | |
int | direction, | |||
int | max_derivs, | |||
double | tol = 1e-14 | |||
) |
Analyze periodicity of surface based on evaluating derivatives at opposing ends of the surface.
The return value is -1 if the surface edges are disjoint, otherwise k if sf is C^k continuous across the seam. These are sufficient but not necessary conditions for periodicity, so it is possible that a call to analyzePeriodicityDerivs() will yield a higher degree of periodicity. The current implementation is quite slow, and not optimized for speed.
sf | the SplineSurface to analyze for periodicity | |
direction | the parameter direction to check for periodicity (0 to check in the first parameter direction, 1 to check in the second. | |
max_derivs | the maximum of computed derivatives (the analysis cannot detect continuities beyond this value | |
tol | the tolerance used when comparing points and derivatives for approximate equality. |
Definition at line 81 of file GeometryTools.C.
References analyzePeriodicityDerivs(), representSurfaceAsCurve(), and THROW.
00086 { 00087 if (direction < 0 || direction > 1) { 00088 THROW("Error in direction parameter. Must be 0 or 1."); 00089 } 00090 // Make a hypercurve from this surface. 00091 // Direction parameter is one more for representSurface...() :-P 00092 boost::shared_ptr<SplineCurve> cv 00093 = representSurfaceAsCurve(sf, direction + 1); 00094 return analyzePeriodicityDerivs(*cv, max_derivs, tol); 00095 }
int Go::analyzePeriodicityDerivs | ( | const ParamCurve & | cv, | |
int | max_derivs, | |||
double | tol = 1e-14 | |||
) |
Analyze periodicity of curve based on evaluating derivatives at both endpoints.
The return value is -1 if the curve ends are disjoint, otherwise k if cv is C^k continuous. A maximum of max_derivs derivatives are computed, so the analysis cannot yield a higher return value then max_derivs. The tolerance is the amount the point and derivatives are allowed to be different at the two ends. The default is quite tight!
cv | the curve to be analyzed for periodicity | |
max_derivs | the maximum of computed derivatives (the analysis can not detect continuities beyond this value). | |
tol | the tolerance used when comparing points and derivatives for approximate equality |
Definition at line 32 of file GeometryTools.C.
References Go::ParamCurve::endparam(), Go::ParamCurve::point(), and Go::ParamCurve::startparam().
Referenced by analyzePeriodicityDerivs(), and main().
00034 { 00035 // Compute derivatives at start and end. 00036 std::vector<Point> ptsbeg(max_derivs + 1); 00037 std::vector<Point> ptsend(max_derivs + 1); 00038 cv.point(ptsbeg, cv.startparam(), max_derivs); 00039 cv.point(ptsend, cv.endparam(), max_derivs); 00040 00041 // Compare computed points 00042 int i = 0; 00043 for (; i <= max_derivs; ++i) { 00044 double diff = ptsbeg[i].distInf(ptsend[i]); 00045 if (diff > tol) break; 00046 } 00047 return i - 1; 00048 }
T Go::area | ( | const Array< T, 3 > * | c | ) | [inline] |
Computes the area of a 2-dimensional triangle.
Input is an array of corner points. Same function also exists for 2-dimensional triangles.
Definition at line 73 of file Volumes.h.
References Go::Array< T, Dim >::cross(), and Go::Array< T, Dim >::length().
T Go::area | ( | const Array< T, 2 > * | c | ) | [inline] |
Computes the area of a 2-dimensional triangle.
Input is an array of corner points. Same function also exists for 3-dimensional triangles.
Definition at line 66 of file Volumes.h.
References simplex_volume().
Referenced by Go::SmoothSurf::approxOrigRational(), Go::BoundedSurface::area(), Go::SplineSurface::areaDiagonalCross(), Go::BaryCoordSystemTriangle3D::BaryCoordSystemTriangle3D(), evaluateMinCurvatureRadius(), main(), and Go::SmoothSurf::setOptimizeRational().
00067 { return simplex_volume(c); }
void Go::averageBoundaryCoefs | ( | boost::shared_ptr< SplineSurface > & | srf1, | |
int | bd1, | |||
bool | keep_first, | |||
boost::shared_ptr< SplineSurface > & | srf2, | |||
int | bd2, | |||
bool | keep_second, | |||
bool | found_corner1, | |||
Point | corner1, | |||
bool | found_corner2, | |||
Point | corner2, | |||
bool | opposite | |||
) |
Average specified boundary coefficients between two spline surfaces to ensure a C0 transition.
Definition at line 1214 of file GeometryTools.C.
References unifySurfaceSplineSpace().
01219 { 01220 // Make sure that the parameter directions of the two surfaces correspond 01221 // Let the coefficients with constant v-parameter be the ones to average 01222 if (bd1 <= 1) 01223 srf1->swapParameterDirection(); 01224 if (bd2 <= 1) 01225 srf2->swapParameterDirection(); 01226 01227 if (opposite) 01228 srf2->reverseParameterDirection(true); 01229 01230 // Make sure that the parameter interval in u-direction is unique 01231 double umin1 = srf1->startparam_u(); 01232 double umax1 = srf1->endparam_u(); 01233 double umin2 = srf2->startparam_u(); 01234 double umax2 = srf2->endparam_u(); 01235 double ptol = 1.0e-12; 01236 if (fabs(umin1-umin2) > ptol || fabs(umax1-umax2) > ptol) 01237 { 01238 double umin = 0.5*(umin1 + umin2); 01239 double umax = 0.5*(umax1 + umax2); 01240 01241 srf1->setParameterDomain(umin, umax, srf1->startparam_v(), srf1->endparam_v()); 01242 srf2->setParameterDomain(umin, umax, srf2->startparam_v(), srf2->endparam_v()); 01243 } 01244 01245 // Ensure the same spline space in the u-direction 01246 vector<shared_ptr<SplineSurface> > sfs(2); 01247 sfs[0] = srf1; 01248 sfs[1] = srf2; 01249 unifySurfaceSplineSpace(sfs, ptol, 1); 01250 srf1 = sfs[0]; 01251 srf2 = sfs[1]; 01252 01253 // Check degeneracy 01254 double deg_tol = 1.0e-6; 01255 bool b1, r1, t1, l1, b2, r2, t2, l2; 01256 bool degen1 = srf1->isDegenerate(b1, r1, t1, l1, deg_tol); 01257 bool degen2 = srf2->isDegenerate(b2, r2, t2, l2, deg_tol); 01258 degen1 = (bd1 == 1 || bd1 == 3) ? t1 : b1; 01259 degen2 = (bd2 == 1 || bd2 == 3) ? t2 : b2; 01260 // Replace the specified boundary coefficients with the average ones. It is either the first 01261 // or the last row of coefficients 01262 // Be careful not to destroy degenerate boundaries 01263 int dim = srf1->dimension(); 01264 vector<double>::iterator c1 = srf1->coefs_begin(); 01265 int in1 = srf1->numCoefs_u(); 01266 vector<double>::iterator c2 = srf2->coefs_begin(); 01267 if (bd1 == 1 || bd1 == 3) 01268 c1 += (srf1->numCoefs_v()-1)*in1*dim; 01269 if (bd2 == 1 || bd2 == 3) 01270 c2 += (srf2->numCoefs_v()-1)*in1*dim; 01271 01272 // Check if the corner information corresponds to the boundary orientation 01273 vector<double> d1(dim), d2(dim); 01274 vector<double>::iterator c3 = c1; 01275 vector<double>::iterator c4 = c1 + (in1-1)*dim; 01276 for (int kr=0; kr<dim; kr++, c3++, c4++) 01277 { 01278 d1[kr] = *c3; 01279 d2[kr] = *c4; 01280 } 01281 Point pt1(d1.begin(), d1.end()); 01282 Point pt2(d2.begin(), d2.end()); 01283 if ((found_corner1 && found_corner2 && pt1.dist(corner1) > pt1.dist(corner2)) || 01284 (!found_corner1 && pt1.dist(corner2) < pt2.dist(corner2)) || 01285 (!found_corner2 && pt2.dist(corner1) < pt1.dist(corner1))) 01286 { 01287 // Switch 01288 std::swap(found_corner1,found_corner2); 01289 std::swap(corner1,corner2); 01290 } 01291 01292 if (!(degen1 && degen2)) 01293 { 01294 for (int ki=0; ki<in1*dim; ki++, c1++, c2++) 01295 { 01296 bool start = (ki==0 || ki==1 || ki==2); 01297 bool end = (ki==in1*dim-3 || ki==in1*dim-2 || ki==in1*dim-1); 01298 if (start && l1 && l2) 01299 continue; 01300 if (end && r1 && r2) 01301 continue; 01302 double tmid = 0.5*((*c1) + (*c2)); 01303 if (start && found_corner1) 01304 tmid = corner1[ki%dim]; 01305 if (end && found_corner2) 01306 tmid = corner2[ki%dim]; 01307 if (keep_first || degen1 || (start && l1) || (end && r1)) 01308 tmid = *c1; 01309 if (keep_second || degen2 || (start && l2) || (end && r2)) 01310 tmid = *c2; 01311 *c1 = tmid; 01312 *c2 = tmid; 01313 } 01314 } 01315 01316 if (srf1->rational()) 01317 { 01318 // This fix will not work for all configuration of rational surfaces. 01319 // Update the rational coefficients with respect to the divided 01320 // ones 01321 c1 = srf1->coefs_begin(); 01322 vector<double>::iterator r1 = srf1->rcoefs_begin(); 01323 int kn = srf1->numCoefs_u()*srf1->numCoefs_v(); 01324 for (int ki=0; ki<kn; ++ki) 01325 { 01326 for (int kr=0; kr<dim; ++kr) 01327 r1[kr] = c1[kr]*r1[dim]; 01328 c1 += dim; 01329 r1 += (dim+1); 01330 } 01331 } 01332 01333 if (srf2->rational()) 01334 { 01335 // This fix will not work for all configuration of rational surfaces. 01336 // Update the rational coefficients with respect to the divided 01337 // ones 01338 c2 = srf2->coefs_begin(); 01339 vector<double>::iterator r2 = srf2->rcoefs_begin(); 01340 int kn = srf2->numCoefs_u()*srf2->numCoefs_v(); 01341 for (int ki=0; ki<kn; ++ki) 01342 { 01343 for (int kr=0; kr<dim; ++kr) 01344 r2[kr] = c2[kr]*r2[dim]; 01345 c2 += dim; 01346 r2 += (dim+1); 01347 } 01348 } 01349 01350 // Set the surfaces back to the initial parameter domain 01351 if (fabs(umin1-umin2) > ptol || fabs(umax1-umax2) > ptol) 01352 { 01353 srf1->setParameterDomain(umin1, umax1, srf1->startparam_v(), srf1->endparam_v()); 01354 srf2->setParameterDomain(umin2, umax2, srf2->startparam_v(), srf2->endparam_v()); 01355 } 01356 01357 if (opposite) 01358 srf2->reverseParameterDirection(true); 01359 01360 if (bd1 <= 1) 01361 srf1->swapParameterDirection(); 01362 if (bd2 <= 1) 01363 srf2->swapParameterDirection(); 01364 01365 01366 }
void Go::backwardSubstitution | ( | const SquareMatrix & | U, | |
std::vector< double > * | x, | |||
int | num_unknowns | |||
) | [inline] |
Using backward substitution to calculate x on the system Ux = b, where U is an upper triangular matrix with unitary diagonal.
U | The upper triangular matrix. The actually used class must support the operation [][] and return 'double'. | |
x | At function invocation, x should point to a vector of doubles, containing the vector 'b'. On successful completion of the function, this vector will contain the solution for x. | |
num_unknowns | The system size (number of unknowns). |
Definition at line 167 of file LUDecomp_implementation.h.
00169 { 00170 const int dim = int(x[0].size()); 00171 for (int dd = 0; dd < dim; ++dd) { 00172 x[num_unknowns-1][dd] /= A[num_unknowns-1][num_unknowns-1]; 00173 } 00174 for (int i = num_unknowns - 2; i >= 0; --i) { 00175 for (int j = i+1; j < num_unknowns; ++j) { 00176 for (int dd = 0; dd < dim; ++dd) { 00177 x[i][dd] -= A[i][j] * x[j][dd]; 00178 } 00179 } 00180 for (int dd = 0; dd < dim; ++dd) { 00181 x[i][dd] /= A[i][i]; 00182 } 00183 } 00184 }
void Go::backwardSubstitution | ( | const SquareMatrix & | U, | |
T * | x, | |||
int | num_unknowns | |||
) | [inline] |
Using backward substitution to calculate x on the system Ux = b, where U is an upper triangular matrix with unitary diagonal.
U | The upper triangular matrix. The actually used class must support the operation [][] and return 'double'. | |
x | At function invocation, x should point to an array of T, containing the vector 'b'. On successful completion of the function, this array will contain the solution for x. | |
num_unknowns | The system size (number of unknowns). |
Definition at line 153 of file LUDecomp_implementation.h.
Referenced by Go::SmoothCurve::equationSolve(), and LUsolveSystem().
double Go::binom | ( | int | n, | |
int | i | |||
) | [inline] |
Computes the binomial coefficient: n! / (i! (n-i)!).
Definition at line 25 of file binom.h.
Referenced by curve_ratder(), Go::SplineSurface::normalSurface(), quadrinomial(), surface_ratder(), and trinomial().
00026 { 00027 if (i < 0 || i > n) 00028 return 0.0; 00029 00030 static std::vector<std::vector<double> > pascals_triangle(10); 00031 static bool first_time = true; 00032 if (first_time) { 00033 first_time = false; 00034 pascals_triangle.resize(1); 00035 pascals_triangle[0].resize(1); 00036 pascals_triangle[0][0] = 1; 00037 } 00038 int old_size = pascals_triangle.size(); 00039 if (old_size < n+1) { 00040 // We must expand the triangle 00041 pascals_triangle.resize(n+1); 00042 // Compute the terms of the new rows 00043 for (int nr = old_size; nr < n+1; ++nr) { 00044 pascals_triangle[nr].resize(nr+1); 00045 pascals_triangle[nr][0] = 1.0; 00046 for (int j = 1; j < nr; ++j) { 00047 pascals_triangle[nr][j] 00048 = pascals_triangle[nr-1][j-1] + pascals_triangle[nr-1][j]; 00049 } 00050 pascals_triangle[nr][nr] = 1.0; 00051 } 00052 } 00053 return pascals_triangle[n][i]; 00054 }
double Go::brent_minimize | ( | const Functor & | f, | |
double | a, | |||
double | b, | |||
double | c, | |||
double & | parmin, | |||
const double | rel_tolerance = std::sqrt(std::numeric_limits<double>::epsilon()) | |||
) | [inline] |
Definition at line 44 of file brent_minimize.h.
References f(), Go::FunctionMinimizer< Functor >::getPar(), and Go::FunctionMinimizer< Functor >::linminBrent().
00049 { 00050 Fun2Fun<Functor> f2(f, a, c); 00051 Go::FunctionMinimizer<Fun2Fun<Functor> > fmin(1, f2, &a, rel_tolerance); 00052 Go::Point dir(1); 00053 dir[0] = 1.0; 00054 double bracket[3]; 00055 double fval_brak[3]; 00056 bracket[0] = 0.0; 00057 bracket[1] = b-a; 00058 bracket[2] = c-a; 00059 fval_brak[0] = f(a); 00060 fval_brak[1] = f(b); 00061 fval_brak[2] = f(c); 00062 double minimum = fmin.linminBrent(dir, bracket, fval_brak); 00063 parmin = fmin.getPar(0); 00064 return minimum; 00065 }
bool Go::checkConstantCoef | ( | SplineCurve & | cv, | |
int | idx, | |||
double | val, | |||
double | max_dist, | |||
double | tol | |||
) |
Check if a curve coefficient is equal to a constant in a specified dimension provided it already lies close.
Definition at line 303 of file GeometryTools.C.
References Go::SplineCurve::coefs_begin(), Go::SplineCurve::dimension(), and Go::SplineCurve::numCoefs().
00309 { 00310 int ncoef = cv.numCoefs(); 00311 int dim = cv.dimension(); 00312 vector<double>::const_iterator coef = cv.coefs_begin(); 00313 00314 if (idx >= dim) 00315 return false; // Question does not make sense 00316 00317 bool identical = true; 00318 for (int ki=0; ki<ncoef; ki++, coef+=dim) 00319 { 00320 double d1 = fabs(coef[idx]-val); 00321 if (d1 > max_dist) 00322 return false; // Curve does not lie close the given value 00323 if (d1 > tol) 00324 identical = false; 00325 } 00326 return (!identical); 00327 }
int Go::closest_in_array | ( | const double * | pt, | |
const double * | array, | |||
int | n, | |||
int | dim | |||
) |
Find the point in an array closest to the given base point (measured in the usual, Euclidean distance).
pt | pointer to the base point (of dimension 'n') | |
array | pointer to the array in which we will search | |
n | number of elements in the array | |
dim | dimension of the elements/base point |
Definition at line 48 of file Utils.C.
References distance_squared().
00050 { 00051 double best_dist2 = distance_squared(pt, pt+dim, array); 00052 int best_index = 0; 00053 double dist2; 00054 for (int i = 1; i < n; ++i) { 00055 dist2 = distance_squared(pt, pt+dim, array + i*dim); 00056 if (dist2 < best_dist2) { 00057 best_dist2 = dist2; 00058 best_index = i; 00059 } 00060 } 00061 return best_index; 00062 }
double GO_API Go::closest_on_line_segment | ( | const Vector3D & | pt, | |
const Vector3D & | beg, | |||
const Vector3D & | end | |||
) |
Find the closest point on a line segment to a given point.
pt | the point for which we want to find the closest point on the line segment | |
beg | the start point of the line segment | |
end | the end point of the line segment |
Definition at line 250 of file Utils.C.
References Go::Array< T, Dim >::dist2().
Referenced by closest_on_triangle().
void Go::closest_on_rectgrid | ( | const double * | pt, | |
const double * | array, | |||
int | u_min, | |||
int | u_max, | |||
int | v_min, | |||
int | v_max, | |||
int | nmb_coefs_u, | |||
double & | clo_u, | |||
double & | clo_v | |||
) |
Find an approximate closest point on a sub-grid of a rectangular grid of 3-dimensional points.
The method used is to 'triangulate' the grid, and locate the closest point on this triangulation. We imagine that the parametrization of the sub-grid is from 'u_min' to 'u_max' along each row and from 'v_min' to 'v_max' along each column.
pt | the point we want to search the closest point for | |
array | pointer to the array of 3D-points; coordinates should be stored consecutively in a row-wise fashion. | |
u_min | lowest column index of the subgrid we want to search | |
u_max | highest column index of the subgrid we want to search | |
v_min | lowest row index of the subgrid we want to search | |
v_max | highest row index of the subgrid we want to search | |
nmb_coefs_u | total number of columns in the complete grid (necessary to know in order to determine how far to jump to get to the next row in the subgrid. | |
clo_u | upon function return; the u-parameter of the closest point, using the parametrization explained above. | |
clo_v | upon function return; the v-parameter of the closest point, using the parametrization explained above. |
Definition at line 137 of file Utils.C.
References closest_on_triangle(), and Go::Array< T, Dim >::setValue().
00142 { 00143 // m is number of columns 00144 // n is number of rows 00145 // in array, the column index runs fastest. 00146 00147 // For each (not necessarily planar) quadrangle, split into 2 00148 // triangles. Then find distance to triangle, and closest point 00149 // in triangle. 00150 00151 Vector3D pnt(pt); 00152 Vector3D p[4]; 00153 Vector3D tri[3]; 00154 00155 Vector3D umask1(0, 1, 0); 00156 Vector3D umask2(1, 1, 0); 00157 Vector3D vmask1(0, 0, 1); 00158 Vector3D vmask2(0, 1, 1); 00159 00160 double bestdist2 = 1e100; 00161 double best_u = 0; 00162 double best_v = 0; 00163 00164 for (int i = u_min; i < u_max; ++i) { 00165 for (int j = v_min; j < v_max; ++j) { 00166 // Pick the corner points counterclockwise 00167 p[0].setValue(array + (j*nmb_coefs_u + i)*3); 00168 p[1].setValue(array + (j*nmb_coefs_u + i+1)*3); 00169 p[2].setValue(array + ((j+1)*nmb_coefs_u + i+1)*3); 00170 p[3].setValue(array + ((j+1)*nmb_coefs_u + i)*3); 00171 // Lower triangle, points 0, 1, 3. 00172 tri[0] = p[0]; 00173 tri[1] = p[1]; 00174 tri[2] = p[3]; 00175 double clo_dist2; 00176 Vector3D cltri = closest_on_triangle(pnt, tri, clo_dist2); 00177 if (clo_dist2 < bestdist2) { 00178 best_u = i + umask1*cltri; 00179 best_v = j + vmask1*cltri; 00180 bestdist2 = clo_dist2; 00181 } 00182 // Upper triangle, points 1, 2, 3. 00183 tri[0] = p[1]; 00184 tri[1] = p[2]; 00185 tri[2] = p[3]; 00186 cltri = closest_on_triangle(pnt, tri, clo_dist2); 00187 if (clo_dist2 < bestdist2) { 00188 best_u = i + umask2*cltri; 00189 best_v = j + vmask2*cltri; 00190 bestdist2 = clo_dist2; 00191 } 00192 } 00193 } 00194 clo_u = best_u; 00195 clo_v = best_v; 00196 int ii = min(int(floor(clo_u)), u_max - 1); 00197 int jj = min(int(floor(clo_v)), v_max - 1); 00198 p[0].setValue(array + (jj*nmb_coefs_u + ii)*3); 00199 p[1].setValue(array + (jj*nmb_coefs_u + ii+1)*3); 00200 p[2].setValue(array + ((jj+1)*nmb_coefs_u + ii+1)*3); 00201 p[3].setValue(array + ((jj+1)*nmb_coefs_u + ii)*3); 00202 }
void Go::closest_on_rectgrid | ( | const double * | pt, | |
const double * | array, | |||
int | m, | |||
int | n, | |||
double & | clo_u, | |||
double & | clo_v | |||
) |
Find an approximate closest point on a rectangular grid of 3-dimensional points.
The method used is to 'triangulate' the grid, and locate the closest point on this triangulation. We imagine that the point grid is uniformly parametrized from 0 to m-1 along each row and from 0 to n-1 along each column, and we refer to these parameters as 'u' and 'v'.
pt | the point we want to search the closest point for | |
array | pointer to the array of 3D-points; coordinates should be stored consecutively in a row-wise fashion. | |
m | number of columns in the point array | |
n | number of rows in the point array | |
clo_u | upon function return; the u-parameter of the closest point, using the parametrization explained above. | |
clo_v | upon function return; the v-parameter of the closest point, using the parametrization explained above. |
Definition at line 66 of file Utils.C.
References closest_on_triangle(), and Go::Array< T, Dim >::setValue().
00070 { 00071 // m is number of columns 00072 // n is number of rows 00073 // in array, the column index runs fastest. 00074 00075 // For each (not necessarily planar) quadrangle, split into 2 00076 // triangles. Then find distance to triangle, and closest point 00077 // in triangle. 00078 00079 Vector3D pnt(pt); 00080 Vector3D p[4]; 00081 Vector3D tri[3]; 00082 00083 Vector3D umask1(0, 1, 0); 00084 Vector3D umask2(1, 1, 0); 00085 Vector3D vmask1(0, 0, 1); 00086 Vector3D vmask2(0, 1, 1); 00087 00088 double bestdist2 = 1e100; 00089 double best_u = 0; 00090 double best_v = 0; 00091 00092 for (int col = 0; col < m-1; ++col) { 00093 for (int row = 0; row < n-1; ++row) { 00094 // Pick the corner points counterclockwise 00095 p[0].setValue(array + (row*m + col)*3); 00096 p[1].setValue(array + (row*m + col+1)*3); 00097 p[2].setValue(array + ((row+1)*m + col+1)*3); 00098 p[3].setValue(array + ((row+1)*m + col)*3); 00099 // Lower triangle, points 0, 1, 3. 00100 tri[0] = p[0]; 00101 tri[1] = p[1]; 00102 tri[2] = p[3]; 00103 double clo_dist2; 00104 Vector3D cltri = closest_on_triangle(pnt, tri, clo_dist2); 00105 if (clo_dist2 < bestdist2) { 00106 best_u = col + umask1*cltri; 00107 best_v = row + vmask1*cltri; 00108 bestdist2 = clo_dist2; 00109 } 00110 // Upper triangle, points 1, 2, 3. 00111 tri[0] = p[1]; 00112 tri[1] = p[2]; 00113 tri[2] = p[3]; 00114 cltri = closest_on_triangle(pnt, tri, clo_dist2); 00115 if (clo_dist2 < bestdist2) { 00116 best_u = col + umask2*cltri; 00117 best_v = row + vmask2*cltri; 00118 bestdist2 = clo_dist2; 00119 } 00120 } 00121 } 00122 clo_u = best_u; 00123 clo_v = best_v; 00124 int i = int(floor(clo_u)); 00125 if (i >= m-1) 00126 i = m-2; 00127 int j = int(floor(clo_v)); 00128 if (j >= n-1) 00129 j = n-2; 00130 p[0].setValue(array + (j*m + i)*3); 00131 p[1].setValue(array + (j*m + i+1)*3); 00132 p[2].setValue(array + ((j+1)*m + i+1)*3); 00133 p[3].setValue(array + ((j+1)*m + i)*3); 00134 }
Vector3D GO_API Go::closest_on_triangle | ( | const Vector3D & | pt, | |
const Vector3D | tri[3], | |||
double & | clo_dist2 | |||
) |
Find the closest point on a triangle, in barycentric coordinates.
pt | the point for which we want to find the closest point on the triangle | |
tri | the triangle, specified by its three corners | |
clo_dist2 | the squared Euclidean distance from 'pt' to the closest point in the triangle. |
Definition at line 205 of file Utils.C.
References Go::BaryCoordSystemTriangle3D::baryToCart(), Go::BaryCoordSystemTriangle3D::cartToBary(), closest_on_line_segment(), Go::Array< T, Dim >::dist2(), and Go::Array< T, Dim >::normalize().
Referenced by closest_on_rectgrid().
00209 { 00210 // Project the point to the triangle plane. 00211 Vector3D norm = (tri[1]-tri[0]) % (tri[2]-tri[0]); 00212 norm.normalize(); 00213 Vector3D diff = pt-tri[0]; 00214 Vector3D proj_pt = pt - (diff*norm)*norm; 00215 double proj_dist2 = (diff*norm)*(diff*norm); 00216 BaryCoordSystemTriangle3D cs(tri); 00217 Vector3D bc = cs.cartToBary(proj_pt); 00218 bool allpos = true; 00219 double bestdist2 = 1e100; 00220 Vector3D bestb; 00221 for (int i = 0; i < 3; ++i) { 00222 if (bc[i] < 0) { 00223 allpos = false; 00224 // Closest point may be on the segment given 00225 // by the two other points. 00226 double lp = closest_on_line_segment(proj_pt, 00227 tri[(i+1)%3], 00228 tri[(i+2)%3]); 00229 Vector3D b; 00230 b[i] = 0; 00231 b[(i+1)%3] = 1.0 - lp; 00232 b[(i+2)%3] = lp; 00233 Vector3D realpt = cs.baryToCart(b); 00234 double dist2 = proj_pt.dist2(realpt); 00235 if (dist2 < bestdist2) { 00236 bestb = b; 00237 bestdist2 = dist2; 00238 } 00239 } 00240 } 00241 if (allpos) { 00242 bestb = bc; 00243 bestdist2 = 0; 00244 } 00245 clo_dist2 = bestdist2 + proj_dist2; 00246 return bestb; 00247 }
void Go::closestPtCurves | ( | SplineCurve * | cv1, | |
SplineCurve * | cv2, | |||
double | epsge, | |||
double & | par1, | |||
double & | par2, | |||
double & | dist | |||
) |
Compute the closest point between two curves.
cv1 | pointer to the first curve | |
cv2 | pointer to the second curve | |
epsge | geometrical tolerance |
par1 | parameter of the closest point in the first curve | |
par2 | parameter of the closest point in the second curve | |
dist | distance between the curves at the closest point |
void Go::closestPtCurves | ( | const ParamCurve * | cv1, | |
const ParamCurve * | cv2, | |||
double | tmin1, | |||
double | tmax1, | |||
double | tmin2, | |||
double | tmax2, | |||
double | seed1, | |||
double | seed2, | |||
double & | par1, | |||
double & | par2, | |||
double & | dist, | |||
Point & | ptc1, | |||
Point & | ptc2 | |||
) |
Newton iteration on the distance function between two curves to find a closest point or an intersection point.
The solution is restricted to the intervals [tmin1,tmax1] and [tmin2,tmax2] in the first and second curves's parameter domain. Ported from the sisl function s1770.
cv1 | Curve number one. | |
cv2 | Curve number two. | |
tmin1 | Min. parameter value. First curve | |
tmax1 | Max. parameter value. First curve | |
tmin2 | Min. parameter value. Second curve | |
tmax2 | Max. parameter value. Second curve | |
seed1 | Start point for iteration along curve number one. | |
seed2 | Start point for iteration along curve number two. |
par1 | Parameter value of the first curve's point. | |
par2 | Parameter value of the second curve's point. | |
dist | Distance between the points. | |
ptc1 | Point on curve number one. | |
ptc2 | Point on curve number two. |
Definition at line 88 of file closestPtCurves.C.
References Go::FunctionMinimizer< Functor >::fval(), Go::FunctionMinimizer< Functor >::getPar(), minimise_conjugated_gradient(), and Go::ParamCurve::point().
00102 { 00103 const double TOL = 1.0e-8; 00104 double seed[2]; 00105 seed[0] = u_seed; 00106 seed[1] = v_seed; 00107 double minpar[2]; 00108 minpar[0] = umin; 00109 minpar[1] = vmin; 00110 double maxpar[2]; 00111 maxpar[0] = umax; 00112 maxpar[1] = vmax; 00113 00114 // establing distance function to minimize 00115 CrvDistFun distfun(cv1, cv2, minpar, maxpar); 00116 00117 // minimize the distance function 00118 FunctionMinimizer<CrvDistFun> funmin(2, distfun, seed, TOL); 00119 minimise_conjugated_gradient(funmin);//, 3); // number of iterations in each cycle 00120 00121 // calculate and copy results 00122 par1 = funmin.getPar(0); 00123 par2 = funmin.getPar(1); 00124 dist = sqrt(funmin.fval()); 00125 ptc1 = cv1->point(par1); 00126 ptc2 = cv2->point(par2); 00127 }
void Go::closestPtCurves | ( | const ParamCurve * | cv1, | |
const ParamCurve * | cv2, | |||
double & | par1, | |||
double & | par2, | |||
double & | dist, | |||
Point & | ptc1, | |||
Point & | ptc2 | |||
) |
Compute a closest point or an intersection point between two curves.
Ported from the sisl-functions s1770, s1770_s9corr, s1770_s9dir
cv1 | Curve number one. | |
cv2 | Curve number two. |
par1 | Parameter value of the first curve's point. | |
par2 | Parameter value of the second curve's point. | |
dist | Distance between the points. | |
ptc1 | Point on curve number one. | |
ptc2 | Point on curve number two. |
Definition at line 49 of file closestPtCurves.C.
References Class_SplineCurve, computeSeedCvCv(), DEBUG_ERROR_IF, Go::GeomObject::dimension(), Go::ParamCurve::endparam(), Go::GeomObject::instanceType(), and Go::ParamCurve::startparam().
00055 { 00056 00057 DEBUG_ERROR_IF(cv1->dimension()!=cv2->dimension(), "Dimension mismatch."); 00058 00059 double seed1, seed2; 00060 double tmin1,tmax1,tmin2,tmax2; 00061 00062 // Use all of the parameter domain. 00063 tmin1 = cv1->startparam(); 00064 tmax1 = cv1->endparam(); 00065 tmin2 = cv2->startparam(); 00066 tmax2 = cv2->endparam(); 00067 00068 if (cv1->instanceType() == Class_SplineCurve && 00069 cv2->instanceType() == Class_SplineCurve) { 00070 const SplineCurve *pc1 = dynamic_cast<const SplineCurve*>(cv1); 00071 const SplineCurve *pc2 = dynamic_cast<const SplineCurve*>(cv2); 00072 00073 // Compute seed values 00074 computeSeedCvCv(pc1, pc2, seed1, seed2); 00075 } 00076 else { 00077 seed1 = 0.5*(tmin1+tmax1); 00078 seed2 = 0.5*(tmin2+tmax2); 00079 } 00080 00081 // Iterate for closest point 00082 closestPtCurves(cv1,cv2,tmin1,tmax1,tmin2,tmax2,seed1,seed2,par1,par2, 00083 dist,ptc1,ptc2); 00084 00085 }
void Go::closestPtCurves2D | ( | ParamCurve * | cv1, | |
ParamCurve * | cv2, | |||
double | aepsge, | |||
double | tmin1, | |||
double | tmax1, | |||
double | tmin2, | |||
double | tmax2, | |||
double | seed1, | |||
double | seed2, | |||
int | method, | |||
bool | quick, | |||
double & | par1, | |||
double & | par2, | |||
double & | dist, | |||
Point & | ptc1, | |||
Point & | ptc2, | |||
int & | istat | |||
) |
Newton iteration on the distance function between two curves in 2D to find a closest point or an intersection point.
The solution is restricted to the intervals [tmin1,tmax1] and [tmin2,tmax2] in the first and second curves's parameter domain. Ported from the sisl-function s1770_2D
.
cv1 | Curve number one. | |
cv2 | Curve number two. | |
aepsge | Geometry resolution. | |
tmin1 | Min. parameter value. First curve | |
tmax1 | Max. parameter value. First curve | |
tmin2 | Min. parameter value. Second curve | |
tmax2 | Max. parameter value. Second curve | |
seed1 | Start point for iteration along curve number one. | |
seed2 | Start point for iteration along curve number two. | |
method | 1 or 2. Using the the method in s1770_2D, starting with order one or two. method=3 uses the method from s1770 (order one). | |
quick | Reduce requirement on exactness. |
par1 | Parameter value of the first curve's point. | |
par2 | Parameter value of the second curve's point. | |
dist | Distance in space between the points. | |
ptc1 | Point on curve number one. | |
ptc2 | Point on curve number two. | |
istat | =1 Intersection. =2 Minimum value. =3 Nothing found. |
Definition at line 26 of file closestPtCurves2D.C.
References DEBUG_ERROR_IF, Go::GeomObject::dimension(), Go::ParamCurve::endparam(), Go::ParamCurve::point(), and Go::ParamCurve::startparam().
00033 : Newton iteration on the distance function between 00034 * two curves in 2D to find a closest point or an 00035 * intersection point. 00036 * 00037 * 00038 * INPUT : cv1 - Pointer to the first curve in the intersection. 00039 * cv2 - Pointer to the second curve in the intersection. 00040 * aepsge - Geometry resolution. 00041 * tmin1 - Start parameter value of the first curve. 00042 * tmax1 - End parameter value of the first curve. 00043 * tmin2 - Start parameter value of the second curve. 00044 * tmax2 - End parameter value of the second curve. 00045 * seed1 - Start parameter value of the iteration on 00046 * the first curve. 00047 * seed2 - Start parameter value of the iteration on 00048 * the second curve. 00049 * 00050 * 00051 * 00052 * OUTPUT : par1 - Parameter value of of first curve in intersection 00053 * point. 00054 * par2 - Parameter value of of second curve in intersection 00055 * point. 00056 * dist - Distance in space between the points. 00057 * ptc1 - Point on curve number one. 00058 * ptc2 - Point on curve number two. 00059 * istat - status messages. 00060 * = 1 : Intersection found. 00061 * = 2 : A minimum distance found. 00062 * = 3 : Nothing found. 00063 * 00064 * 00065 * METHOD : Newton iteration in two parameter directions. 00066 * 00067 ********************************************************************* 00068 */ 00069 { 00070 const double DZERO = (double)0.0; 00071 const int dim = cv1->dimension(); 00072 DEBUG_ERROR_IF(dim != cv2->dimension(), "Dimension mismatch."); 00073 DEBUG_ERROR_IF(dim != 2, "Only implemented for 2D"); 00074 00075 00076 // Estimated start values 00077 Point par_val(seed1, seed2); 00078 00079 // Parameter end points 00080 double aend1 = cv1->endparam(); 00081 double aend2 = cv2->endparam(); 00082 00083 double delta[2]; // Parameter interval of the curves. 00084 delta[0] = aend1 - cv1->startparam(); 00085 delta[1] = aend2 - cv2->startparam(); 00086 00087 // double tprev = MAXDOUBLE; 00088 bool from_right; 00089 int alt_method; 00090 if (method==2) 00091 alt_method=1; 00092 else 00093 alt_method=method; 00094 00095 int order; 00096 if (method==2) 00097 order=2; 00098 else 00099 order=1; 00100 00101 // Evaluate 0-2.st derivatives of both curves. 00102 std::vector<Point> sval1(3,Point(0.0,0.0)), sval2(3,Point(0.0,0.0)); 00103 from_right = (par_val[0] == aend1) ? false : true; 00104 cv1->point(sval1, par_val[0], 2, from_right); 00105 from_right = (par_val[1] == aend2) ? false : true; 00106 cv2->point(sval2, par_val[1], 2, from_right); 00107 00108 Point d(2), c_d(2), nc_d(2); // Distances between old and new parameter- 00109 // value in the two parameter directions. 00110 Point normal_cv1(dim), normal_cv2(dim); // Curve normals 00111 Point diff(dim), prev_diff(dim); //Difference vector between the curves. 00112 00113 // Compute the distance vector, value and the new step. 00114 double det; 00115 int kstat; 00116 nextStep2D(dist, diff, c_d, det, kstat, sval1, sval2, method); 00117 00118 if (kstat == 1) { 00119 // Singular matrix. Try second order. 00120 if (order!=2) { 00121 order=2; 00122 method=2; 00123 nextStep2D(dist, diff, c_d, det, kstat, sval1, sval2, method); 00124 } 00125 if (kstat == 1) { 00126 // Singular matrix. 00127 if (dist > aepsge) 00128 // Singularity (closest point) found. 00129 singular(cv1,cv2,par_val,dist,quick,aepsge,c_d[0],diff,sval1,sval2, 00130 tmin1,tmin2,tmax1,tmax2); 00131 setReturnValues(par_val,cv1,cv2,aepsge,istat,par1,par2,dist,ptc1,ptc2); 00132 return; 00133 } 00134 } 00135 00136 if (method == 4) { 00137 secant2D(cv1,cv2,par_val,dist,kstat,c_d[0],aepsge, 00138 tmin1,tmin2,tmax1,tmax2); 00139 setReturnValues(par_val,cv1,cv2,aepsge,istat,par1,par2,dist,ptc1,ptc2); 00140 return; 00141 } 00142 00143 00144 double prev_dist; // Previous difference between the curves. 00145 int max_it = 20; // Maximum number of iterations. 00146 int sing = 0; // Mark that singularity has ocured. 00147 int p_dir; // Changing direction in par-space. 00148 int keep_order = 0; 00149 int corr = 0; 00150 int div2 = 0; 00151 int g_up,ng_up,g_dir; // Changing direction in geometric space. 00152 00153 if(quick) 00154 max_it=10; 00155 00156 // Adjust the step size if we are not inside the parameter interval 00157 d = c_d; 00158 normal_cv1[0] = -sval1[1][1]; normal_cv1[1] = sval1[1][0]; // Only 2D 00159 normal_cv2[0] = -sval2[1][1]; normal_cv2[1] = sval2[1][0]; 00160 g_up = (diff*normal_cv2 >= 0.0) ? 1 : -1; 00161 g_up += (diff*normal_cv1 >= 0.0) ? 10 : -10; 00162 insideParamDomain2D(d,par_val,tmin1,tmax1,tmin2,tmax2,corr); 00163 00164 prev_dist = dist; 00165 prev_diff = diff; 00166 00167 00168 // Start of iteration to find the intersection point 00169 int knbit; 00170 for (knbit = 0; knbit < max_it; knbit++) { 00171 par_val+=d; 00172 00173 // Test if the current method is OK, or should we change method? 00174 while (1) { 00175 // Evaluate derivatives of curve 00176 from_right = (par_val[0] == aend1) ? false : true; 00177 cv1->point(sval1, par_val[0], order, from_right); 00178 from_right = (par_val[1] == aend2) ? false: true; 00179 cv2->point(sval2, par_val[1], order, from_right); 00180 00181 // Compute the distanse vector and value and the new step. 00182 nextStep2D(dist, diff, nc_d, det, kstat, sval1, sval2, method); 00183 if (kstat == 1) { 00184 // Singular matrix. 00185 sing++; 00186 if (order==2) { 00187 if (dist>aepsge) 00188 // Singularity (closest point) found. 00189 singular(cv1,cv2,par_val,dist,quick,aepsge,nc_d[0],diff, 00190 sval1,sval2,tmin1,tmin2,tmax1,tmax2); 00191 setReturnValues(par_val,cv1,cv2,aepsge,istat,par1,par2,dist,ptc1,ptc2); 00192 return; 00193 } 00194 else { 00195 order=2; // Use more terms in the series expansion 00196 method=2; 00197 } 00198 } 00199 else { 00200 // Normal to curve 1 00201 normal_cv1[0] = -sval1[1][1]; normal_cv1[1] = sval1[1][0]; 00202 // Normal to curve 2 00203 normal_cv2[0] = -sval2[1][1]; normal_cv2[1] = sval2[1][0]; 00204 00205 // Have normal and difference vectors the same direction ? 00206 ng_up = (diff*normal_cv2 >= 0.0) ? 1 : -1; 00207 ng_up += (diff*normal_cv1 >= 0.0) ? 10 : -10; 00208 00209 // g_dir=1 if we have not changed position to the other side 00210 // of the intersection point. 0 if changed. 00211 g_dir = (ng_up+g_up != 0); 00212 00213 // p_dir=1 if the steps in the parameter interval continues 00214 // in the same direction. 0 if direction has changed. 00215 p_dir = (c_d[0]*nc_d[0] >= DZERO && 00216 c_d[1]*nc_d[1] >= DZERO); 00217 00218 if (order!=2 && g_dir && (!p_dir || dist > 0.4*prev_dist) 00219 && !keep_order) { // Few terms in the series expansion. 00220 if (!quick && div2) div2 = 0; // Not good enough convergence. 00221 order=2; // Change method. 00222 method=2; 00223 } 00224 else if (order==2 && !g_dir) { // Max terms in the series expansion. 00225 if (sing) { // Found closest point? 00226 if (dist>aepsge) 00227 singular(cv1,cv2,par_val,dist,quick,aepsge,nc_d[0],diff, 00228 sval1,sval2,tmin1,tmin2,tmax1,tmax2); 00229 00230 setReturnValues(par_val,cv1,cv2,aepsge,istat,par1,par2,dist, 00231 ptc1,ptc2); 00232 return; 00233 } 00234 if (div2) div2 = 0; // Closest point not found. Change method 00235 order=1; 00236 method=alt_method; 00237 } 00238 else { // Decreasing distance. 00239 keep_order = 0; // Continue with current method. 00240 if (sing) sing = 0; 00241 break; 00242 } 00243 } 00244 } // end while(1) 00245 00246 00247 // We have decided method and computed a new step. 00248 // Test if we are inside the intervals, and if the iteration is 00249 // converging fast enough. 00250 if (corr) 00251 if (!(p_dir && g_dir)) corr = 0; 00252 00253 if (dist < prev_dist || p_dir) { 00254 // Adjust if we are not inside the parameter interval. 00255 00256 g_up = ng_up; 00257 d = c_d = nc_d; 00258 insideParamDomain2D(d,par_val,tmin1,tmax1,tmin2,tmax2,corr); 00259 00260 prev_dist = dist; 00261 prev_diff = diff; 00262 00263 // if (corr > 3) break; 00264 00265 if (corr > 2 || 00266 ((fabs(d[0]/std::max(par_val[0],delta[0])) <= REL_COMP_RES) && 00267 (fabs(d[1]/std::max(par_val[1],delta[1])) <= REL_COMP_RES))) 00268 break; 00269 if (div2) div2 = 0; 00270 00271 if (corr > 1 && order==2) { 00272 keep_order = 1; 00273 order=1; 00274 method=alt_method; 00275 } 00276 } 00277 else if (corr > 2 || 00278 ((fabs(d[0]/std::max(par_val[0],delta[0])) <= REL_COMP_RES) && 00279 (fabs(d[1]/std::max(par_val[1],delta[1])) <= REL_COMP_RES))) 00280 break; 00281 else { 00282 // Not converging, adjust and try again. 00283 if (dist > prev_dist && div2 > 5) 00284 break; 00285 if (quick && dist > prev_dist && div2 > 3) 00286 break; 00287 div2++; // Try half of the step length 00288 par_val -= d; 00289 d[0] *= 0.5; d[1] *=0.5; 00290 } 00291 } 00292 00293 00294 // Iteration stopped, test if point found is within resolution 00295 00296 if (fabs(det)<0.1) { 00297 if (order < 2) { // Make sure we have enough derivatives for 00298 order=2; // further computations 00299 method=2; 00300 00301 from_right = (par_val[0] == aend1) ? false : true; 00302 cv1->point(sval1, par_val[0], order, from_right); 00303 from_right = (par_val[1] == aend2) ? false : true; 00304 cv2->point(sval2, par_val[1], order, from_right); 00305 } 00306 singular(cv1,cv2,par_val,dist,quick,aepsge,d[0],diff,sval1,sval2, 00307 tmin1,tmin2,tmax1,tmax2); 00308 } 00309 00310 setReturnValues(par_val,cv1,cv2,aepsge, istat,par1,par2,dist,ptc1,ptc2); 00311 00312 // Iteration completed. 00313 00314 00315 }
void Go::closestPtCurveSurf | ( | ParamCurve * | pcurve, | |
ParamSurface * | psurf, | |||
double | aepsge, | |||
double | astart1, | |||
double | estart2[], | |||
double | aend1, | |||
double | eend2[], | |||
double | anext1, | |||
double | enext2[], | |||
double & | cpos1, | |||
double | gpos2[], | |||
double & | dist, | |||
Point & | pt_cv, | |||
Point & | pt_su, | |||
int & | istat, | |||
bool | second_order = false | |||
) |
Newton iteration on the distance function between a curve and a surface to find a closest point or an intersection point.
The solution is restricted to the interval [astart1,aend1] in the curves's parameter domain and [estart2[],eend2[]] in the surface's parameter domain. Ported from the sisl-function s1772
.
pcurve | Pointer to the curve in the intersection. | |
psurf | Pointer to the surface in the intersection. | |
aepsge | Geometry resolution. | |
astart1 | Start parameter value of the curve. | |
estart2[] | Start parameter values of surface. | |
aend1 | End parameter value of the curve. | |
eend2[] | End parameter values of the surface. | |
anext1 | Start point for iteration along curve number one. | |
enext2[] | Start parameter values of the iteration on the surface. | |
second_order | if 'true' the function will attempt a second-order method directly. |
cpos1 | Parameter value of the curve in the intersection point. | |
gpos2[] | Parameter values of the surface in the intersection point. | |
dist | Distance between the points. | |
pt_cv | The point on the curve. | |
pt_su | The point on the surface. | |
istat | =1 Intersection. =2 Minimum value. =3 Nothing found. |
Definition at line 123 of file closestPtCurveSurf.C.
References Go::ParamSurface::containingDomain(), Go::Point::cross(), DEBUG_ERROR_IF, Go::GeomObject::dimension(), Go::ParamCurve::endparam(), insideParamDomain(), nextStep(), Go::ParamSurface::point(), Go::ParamCurve::point(), Go::ParamCurve::startparam(), Go::RectDomain::umax(), Go::RectDomain::umin(), Go::RectDomain::vmax(), and Go::RectDomain::vmin().
00131 : Newton iteration on the distance function between 00132 * a curve and a surface to find a closest point 00133 * or an intersection point. 00134 * Ported from the sisl-function s1772. 00135 * 00136 * 00137 * INPUT : pcurve - Pointer to the curve in the intersection. 00138 * psurf - Pointer to the surface in the intersection. 00139 * aepsge - Geometry resolution. 00140 * astart1 - Start parameter value of the curve. 00141 * estart2[] - Start parameter values of surface. 00142 * aend1 - End parameter value of the curve. 00143 * eend2[] - End parameter values of the surface. 00144 * anext1 - Start parameter value of the iteration on 00145 * the curve. 00146 * enext2[] - Start parameter values of the iteration on 00147 * the surface. 00148 * 00149 * 00150 * OUTPUT : cpos1 - Parameter value of the curve in the intersection 00151 * point. 00152 * gpos2[] - Parameter values of the surface in the 00153 * intersection point. 00154 * dist - Distance between the points. 00155 * pt_cv - The point on the curve. 00156 * pt_su - The point on the surface. 00157 * istat - status messages 00158 * = 1 : Intersection found. 00159 * = 2 : A minimum distance found. 00160 * = 3 : Nothing found. 00161 * 00162 * 00163 * METHOD : Newton iteration in tree parameter directions. 00164 * 00165 ********************************************************************* 00166 */ 00167 { 00168 00169 const int dim = pcurve->dimension(); 00170 DEBUG_ERROR_IF(dim != psurf->dimension(), "Dimension mismatch."); 00171 DEBUG_ERROR_IF(dim != 3, "Only implemented for 3D"); 00172 00173 00174 // Parameter interval of surface and curve 00175 Point delta(3); 00176 delta[0]=psurf->containingDomain().umax() - psurf->containingDomain().umin(); 00177 delta[1]=psurf->containingDomain().vmax() - psurf->containingDomain().vmin(); 00178 delta[2]=pcurve->endparam() - pcurve->startparam(); 00179 00180 00181 int knbit; // Number of iterations. 00182 int p_dir; // Changing direction in par-space. 00183 int g_up,ng_up,g_dir; // Changing direction in geometric space. 00184 int order; // Order of method. 00185 int sing = 0; // Mark that singularity has occured. 00186 int left[3]; // Variables used in the evaluator. 00187 Point d(3); // Clipped distances between old and new par. 00188 // value in the tree parameter directions. 00189 Point c_d(3); // Computed distances .... 00190 Point nc_d(3); // New computed distances .... 00191 double prev_dist; // Previous difference between curve and surface. 00192 Point par_val(3); // Parameter values 00193 Point norm_vec(dim); // Normal vector to the surface 00194 Point diff(dim); // Difference vector between points. 00195 int corr = 0, div2 = 0; 00196 std::vector<Point> c0(3,Point(dim)), s0(6,Point(dim)); 00197 00198 par_val[0] = enext2[0]; 00199 par_val[1] = enext2[1]; 00200 par_val[2] = anext1; 00201 00202 left[0]=left[1]=left[2]=0; 00203 00204 bool from_right; 00205 int ki, kstat; 00206 00207 00208 for (ki=1; ki<3; ki++) { 00209 if (second_order && ki==1) 00210 continue; 00211 order=ki; 00212 00213 // Evaluate 0-order derivatives of curve 00214 from_right = (par_val[2] == aend1) ? false : true; 00215 pcurve->point(c0, par_val[2], order, from_right); 00216 00217 // Evaluate 0-order derivatives of surface 00218 psurf->point(s0, par_val[0], par_val[1], order); 00219 00220 // Compute the distance vector, value and the new step. 00221 nextStep(dist,diff,c_d,kstat,c0,s0,order); 00222 00223 // Surface's normal vector 00224 norm_vec=s0[1].cross(s0[2]); 00225 00226 if (kstat == 1) { // Singular matrix 00227 if (order == 2) { 00228 singular(pcurve,psurf,par_val,dist,aepsge,c_d[0],diff,norm_vec,c0, 00229 s0, astart1,estart2,aend1,eend2); 00230 setReturnValues(par_val,pcurve,psurf,aepsge,istat,cpos1,gpos2,dist, 00231 pt_cv,pt_su); 00232 istat += 10; 00233 return; 00234 } 00235 } 00236 else break; 00237 } 00238 00239 00240 // Adjust the step size if we are not inside the parameter interval 00241 00242 g_up = (diff*norm_vec >= DZERO) ? 1 : -1; 00243 d = c_d; 00244 insideParamDomain(d,par_val, astart1,aend1,estart2,eend2,corr); 00245 00246 prev_dist = dist; 00247 00248 // Start of iteration to find the intersection point 00249 const int max_it=30; 00250 for (knbit = 0; knbit < max_it; knbit++) { 00251 par_val+=d; 00252 00253 // Test if the current method is OK, or should we change method? 00254 while (1) { 00255 // Evaluate derivatives of the curve 00256 from_right = (par_val[2] == aend1) ? false : true; 00257 pcurve->point(c0, par_val[2], order, from_right); 00258 00259 // Evaluate derivatives of the surface 00260 psurf->point(s0, par_val[0], par_val[1], order); 00261 00262 // Compute the distanse vector and value and the new step. 00263 nextStep(dist,diff,nc_d,kstat,c0,s0,order); 00264 if (kstat == 1) { 00265 // Singular matrix. 00266 sing++; 00267 if (order==2) { 00268 // Singularity (closest point) found. 00269 singular(pcurve,psurf,par_val,dist,aepsge,nc_d[0],diff, 00270 norm_vec,c0,s0, astart1,estart2,aend1,eend2); 00271 setReturnValues(par_val,pcurve,psurf,aepsge,istat,cpos1,gpos2,dist, 00272 pt_cv,pt_su); 00273 istat += 10; 00274 return; 00275 } 00276 else 00277 order=2; // Use more terms in the series expansion 00278 } 00279 else { 00280 norm_vec=s0[1].cross(s0[2]); 00281 00282 // Have normal and difference vectors the same direction ? 00283 ng_up = (diff*norm_vec >= DZERO) ? 1 : -1; 00284 00285 // g_dir=1 if we have not changed position to the other side 00286 // of the intersection point. 0 if changed. 00287 g_dir = (ng_up+g_up != 0); 00288 00289 // p_dir=1 if the steps in the parameter interval continues 00290 // in the same direction. 0 if direction has changed. 00291 p_dir = (c_d*nc_d >= DZERO); 00292 00293 if (order!=2 && g_dir && (!p_dir || dist > 0.3*prev_dist)) { 00294 if (div2) // Few terms in the series expansion. 00295 div2 = 0; // Not good enough convergence. 00296 order=2; // Change method. 00297 } 00298 else if (order==2 && !g_dir) { // Max terms in the series expansion. 00299 if (sing) { // Found closest point? 00300 singular(pcurve,psurf,par_val,dist,aepsge,nc_d[0],diff, 00301 norm_vec,c0,s0, astart1,estart2,aend1,eend2); 00302 setReturnValues(par_val,pcurve,psurf,aepsge,istat,cpos1,gpos2,dist, 00303 pt_cv,pt_su); 00304 istat += 10; 00305 return; 00306 } 00307 if (div2) 00308 div2 = 0; // Closest point not found. Change method 00309 order=1; 00310 } 00311 else { // Decreasing distance. 00312 if (sing) // Continue with current method. 00313 sing = 0; 00314 break; 00315 } 00316 } 00317 } // end while(1) 00318 00319 00320 // We have decided method and computed a new step. 00321 // Test if we are inside the intervals, and if the iteration is 00322 // converging fast enough. 00323 if (corr) 00324 if (!(p_dir && g_dir)) 00325 corr = 0; 00326 00327 if (dist < prev_dist) { 00328 // Adjust if we are not inside the parameter interval. 00329 if (div2) 00330 div2 = 0; 00331 g_up = ng_up; 00332 d = c_d = nc_d; 00333 insideParamDomain(d,par_val, astart1,aend1,estart2,eend2,corr); 00334 00335 prev_dist = dist; 00336 00337 00338 if (corr > 3) 00339 break; 00340 } 00341 else if ( corr > 3 || 00342 ((fabs(d[0]/delta[0]) <= REL_COMP_RES) && 00343 (fabs(d[1]/delta[1]) <= REL_COMP_RES) && 00344 (fabs(d[2]/delta[2]) <= REL_COMP_RES))) 00345 break; 00346 else { 00347 // Not converging, adjust and try again. 00348 if (corr) 00349 corr++; 00350 00351 if (dist > prev_dist && div2) 00352 break; 00353 div2++; // Try half of the step length 00354 par_val -= d; 00355 d[0] *= 0.5; d[1] *=0.5; d[2] *=0.5; 00356 } 00357 00358 } 00359 00360 // end of iteration. 00361 00362 00363 setReturnValues(par_val,pcurve,psurf,aepsge, istat,cpos1,gpos2,dist, 00364 pt_cv,pt_su); 00365 00366 00367 }
void Go::closestPtCurveSurf | ( | ParamCurve * | pcurve, | |
ParamSurface * | psurf, | |||
double | aepsge, | |||
double | astart1, | |||
double | aend1, | |||
RectDomain * | domain, | |||
double | anext1, | |||
double | enext2[], | |||
double & | cpos1, | |||
double | gpos2[], | |||
double & | dist, | |||
Point & | pt_cv, | |||
Point & | pt_su, | |||
bool | second_order = false | |||
) |
Newton iteration on the distance function between a curve and a surface to find a closest point or an intersection point.
The solution is restricted to the interval [astart1,aend1] in the curves's parameter domain and [estart2[],eend2[]] in the surface's parameter domain. Ported from the sisl-function s1772
.
pcurve | Pointer to the curve in the intersection. | |
psurf | Pointer to the surface in the intersection. | |
aepsge | Geometry resolution. | |
astart1 | Start parameter value of the curve. | |
aend1 | End parameter value of the curve. | |
domain | the parametric domain of interest of the surface | |
anext1 | Start point for iteration along curve number one. | |
enext2[] | Start parameter values of the iteration on the surface. | |
second_order | if 'true' the function will attempt a second-order method directly. |
cpos1 | Parameter value of the curve in the intersection point. | |
gpos2[] | Parameter values of the surface in the intersection point. | |
dist | Distance between the points. | |
pt_cv | The point on the curve. | |
pt_su | The point on the surface. |
Definition at line 62 of file closestPtCurveSurf.C.
References DEBUG_ERROR_IF, Go::FunctionMinimizer< Functor >::fval(), Go::FunctionMinimizer< Functor >::getPar(), minimise_conjugated_gradient(), Go::ParamSurface::point(), Go::ParamCurve::point(), Go::RectDomain::umax(), Go::RectDomain::umin(), Go::RectDomain::vmax(), and Go::RectDomain::vmin().
00069 { 00070 int status = 0; 00071 double rel_comp_res = 1.0e-15; 00072 double sstart[2], send[2]; 00073 sstart[0] = domain->umin(); 00074 sstart[1] = domain->vmin(); 00075 send[0] = domain->umax(); 00076 send[1] = domain->vmax(); 00077 closestPtCurveSurf(pcurve, psurf, aepsge, astart1, sstart, aend1, 00078 send, anext1, enext2, cpos1, gpos2, dist, 00079 pt_cv, pt_su, status, second_order); 00080 DEBUG_ERROR_IF(status < 0,"Error in closest point"); 00081 00082 if (status >= 10 && dist > rel_comp_res && !second_order) 00083 { 00084 // Iteration encountered a singularity. Try fallback iteration 00085 const double TOL = 1.0e-8; 00086 double seed[3], minpar[3], maxpar[3]; 00087 double dist2; 00088 minpar[0] = sstart[0]; 00089 minpar[1] = sstart[1]; 00090 minpar[2] = astart1; 00091 maxpar[0] = send[0]; 00092 maxpar[1] = send[1]; 00093 maxpar[2] = aend1; 00094 seed[0] = gpos2[0]; 00095 seed[1] = gpos2[1]; 00096 seed[2] = cpos1; 00097 00098 CrvSrfDistFun distfun(psurf, pcurve, minpar, maxpar); 00099 FunctionMinimizer<CrvSrfDistFun> funmin(3, distfun, seed, TOL); 00100 minimise_conjugated_gradient(funmin);//, 3); // number of iterations in each cycle 00101 00102 dist2 = sqrt(funmin.fval()); 00103 if (dist2 < dist) 00104 { 00105 dist = dist2; 00106 cpos1 = funmin.getPar(2); 00107 gpos2[0] = funmin.getPar(0); 00108 gpos2[1] = funmin.getPar(1); 00109 00110 pcurve->point(pt_cv, cpos1); 00111 psurf->point(pt_su, gpos2[0], gpos2[1]); 00112 00113 status = (dist <= aepsge) ? 1 : 2; 00114 } 00115 else 00116 status = status % 10; 00117 } 00118 00119 }
void Go::closestPtSislCurves | ( | SplineCurve * | cv1, | |
SplineCurve * | cv2, | |||
double | epsge, | |||
double & | par1, | |||
double & | par2, | |||
double & | dist | |||
) |
Definition at line 19 of file closestPtSislCurves.C.
References ALWAYS_ERROR_IF, Go::SplineCurve::basis(), Go::BsplineBasis::begin(), Go::SplineCurve::coefs_begin(), Go::SplineCurve::coefs_end(), Curve2SISL(), Go::SplineCurve::dimension(), Go::Point::dist(), Go::SplineCurve::endparam(), Go::SplineCurve::order(), Go::SplineCurve::point(), and Go::SplineCurve::startparam().
00026 { 00027 00028 // Make guess point to the iteration 00029 // Find position of closest vertices 00030 std::vector<double>::const_iterator co1 = cv1->coefs_begin(); 00031 std::vector<double>::const_iterator co2 = cv2->coefs_begin(); 00032 std::vector<double>::const_iterator co3; 00033 std::vector<double>::const_iterator co12 = cv1->coefs_end(); 00034 std::vector<double>::const_iterator co22 = cv2->coefs_end(); 00035 int dim = cv1->dimension(); 00036 double td, tmin=1.0e8; 00037 int minidx1=0, minidx2=0; 00038 int ki, k1, k2; 00039 for (k1=0; co1<co12; co1+=dim, k1++) 00040 for (k2=0, co3=co2; co3<co22; co3+=dim, k2++) 00041 { 00042 for (td=0.0, ki=0; ki<dim; ki++) 00043 td += (co1[ki]-co3[ki])*(co1[ki]-co3[ki]); 00044 if (td < tmin) 00045 { 00046 tmin = td; 00047 minidx1 = k1; 00048 minidx2 = k2; 00049 } 00050 } 00051 00052 // Estimate parameter value of vertices 00053 std::vector<double>::const_iterator st; 00054 int kk = cv1->order(); 00055 00056 for (k1=minidx1+1, st=cv1->basis().begin(), par1=0.0; 00057 k1<minidx1+kk; par1+=st[k1], k1++); 00058 par1 /=(double)(kk-1); 00059 00060 kk = cv2->order(); 00061 for (k1=minidx2+1, st=cv2->basis().begin(), par2=0.0; 00062 k1<minidx2+kk; par2+=st[k1], k1++); 00063 par2 /=(double)(kk-1); 00064 00065 // Make sisl curves and call sisl. 00066 SISLCurve *pc1 = Curve2SISL(*cv1, false); 00067 SISLCurve *pc2 = Curve2SISL(*cv2, false); 00068 00069 // Iterate for closest point 00070 int stat = 0; 00071 s1770(pc1, pc2, epsge, cv1->startparam(), cv2->startparam(), 00072 cv1->endparam(), cv2->endparam(), par1, par2, &par1, &par2, 00073 &stat); 00074 ALWAYS_ERROR_IF(stat<0,"Error in closest point, code: " << stat); 00075 00076 00077 Point pt1, pt2; 00078 cv1->point(pt1, par1); 00079 cv2->point(pt2, par2); 00080 dist = pt1.dist(pt2); 00081 00082 if (pc1 != 0) freeCurve(pc1); 00083 if (pc2 != 0) freeCurve(pc2); 00084 }
void Go::closestPtSurfSurfPlane | ( | const std::vector< Point > & | epoint, | |
const std::vector< Point > & | epnt1, | |||
const std::vector< Point > & | epnt2, | |||
const Point & | epar1, | |||
const Point & | epar2, | |||
const ParamSurface * | psurf1, | |||
const ParamSurface * | psurf2, | |||
double | aepsge, | |||
std::vector< Point > & | gpnt1, | |||
std::vector< Point > & | gpnt2, | |||
Point & | gpar1, | |||
Point & | gpar2, | |||
int & | jstat, | |||
AlgorithmChoice | algo = FUNCTIONAL | |||
) |
Newton iteration on the distance function between two surfaces and a plane to find a closest point or an intersection point.
Ported from the sisl-function s9iterate
.
epoint | - Vector of Points containing parts of plane description. epoint[0] contains a point in the plane. epoint[1] contains the normal vector to the plane. | |
epnt1 | 0-2 Derivatives + normal of start point for iteration in first surface. | |
epnt2 | 0-2 Derivatives + normal of start point for iteration in second surface. | |
epar1 | Parameter pair of start point in first surface. | |
epar2 | Parameter pair of start point in second surface. | |
psurf1 | Pointer to the first surface. | |
psurf2 | Pointer to the second surface. | |
aepsge | Absolute tolerance. | |
gpnt1 | 0-2 Derivatives + normal of result of iteration in first surface. | |
gpnt2 | 0-2 Derivatives + normal of result of iteration in second surface. | |
gpar1 | Parameter pair of result of iteration in first surface. | |
gpar2 | Parameter pair of result of iteration in second surface. | |
jstat | =1 Intersection. =2 Minimum value. =3 Nothing found. | |
algo | choose whether the implementation of the algorithm should be based on general function minimization, or a geometric approach |
Definition at line 20 of file closestPtSurfSurfPlane.C.
References closestPtSurfSurfPlaneFunctional(), closestPtSurfSurfPlaneGeometrical(), and GEOMETRICAL.
Referenced by Go::IntCrvEvaluator::evaluate().
00035 { 00036 if (algo == GEOMETRICAL) { 00037 closestPtSurfSurfPlaneGeometrical(epoint, 00038 epnt1, 00039 epnt2, 00040 epar1, 00041 epar2, 00042 psurf1, 00043 psurf2, 00044 aepsge, 00045 gpnt1, 00046 gpnt2, 00047 gpar1, 00048 gpar2, 00049 jstat); 00050 } else { 00051 // algo == FUNCTIONAL 00052 closestPtSurfSurfPlaneFunctional(epoint, 00053 epnt1, 00054 epnt2, 00055 epar1, 00056 epar2, 00057 psurf1, 00058 psurf2, 00059 aepsge, 00060 gpnt1, 00061 gpnt2, 00062 gpar1, 00063 gpar2, 00064 jstat); 00065 } 00066 }
void Go::closestPtSurfSurfPlaneFunctional | ( | const std::vector< Point > & | epoint, | |
const std::vector< Point > & | epnt1, | |||
const std::vector< Point > & | epnt2, | |||
const Point & | epar1, | |||
const Point & | epar2, | |||
const ParamSurface * | psurf1, | |||
const ParamSurface * | psurf2, | |||
double | aepsge, | |||
std::vector< Point > & | gpnt1, | |||
std::vector< Point > & | gpnt2, | |||
Point & | gpar1, | |||
Point & | gpar2, | |||
int & | jstat | |||
) |
This is the functional-based implementation of closestPtSurfSurfPlane.
It is called from the function above (closestPtSurfSurfPlane()) if it is called with algo = FUNCTIONAL. The user can also choose to call this function directly. The parameter description is the same as in closestPtSurfSurfPlane().
Definition at line 83 of file closestPtSurfSurfPlane_functional.C.
References Go::FunctionMinimizer< Functor >::getPar(), minimise_conjugated_gradient(), and Go::ParamSurface::point().
Referenced by closestPtSurfSurfPlane().
00095 { 00096 // we formulate the problem as minimizing f(x) + c_k P(x), where f(x) is the distance 00097 // of the points in surface 1 and surface 2, and P(x) is the distance to the plane. 00098 // The criteria that the points must be lying in the plane is approached as the 00099 // multiplicative constant c_k increases. By choosing a sufficiently high value 00100 // for c_k, we expect to converge within the specified tolerance. 00101 00102 gpar1 = gpar2 = Point(2); 00103 gpnt1.resize(3); gpnt2.resize(3); 00104 00105 const Point plane_normal = epoint[1] / epoint[1].length(); 00106 00107 double C = 1; // = compute_constraint_multiplier(plane_normal, epnt1, epnt2, aepsge); 00108 00109 double dist_to_plane, old_dist_to_plane; 00110 double seed[4]; 00111 seed[0] = epar1[0]; seed[1] = epar1[1]; 00112 seed[2] = epar2[0]; seed[3] = epar2[1]; 00113 00114 dist_to_plane = numeric_limits<double>::max(); 00115 00116 while(true) { 00117 old_dist_to_plane = dist_to_plane; 00118 00119 // make function object here 00120 SurfDistFun distfun(psurf1, psurf2, C, epoint[0], plane_normal); 00121 00122 // specify function minimizer 00123 FunctionMinimizer<SurfDistFun> dfmin(4, distfun, seed, aepsge); 00124 00125 // use conjugated gradient algorithm to minimize this function 00126 minimise_conjugated_gradient(dfmin);//, 5); // number of iterations in each cycle 00127 00128 dist_to_plane = 00129 compute_distance_to_plane(psurf1->point(dfmin.getPar(0), dfmin.getPar(1)), 00130 psurf2->point(dfmin.getPar(2), dfmin.getPar(3)), 00131 epoint[0], 00132 plane_normal); 00133 00134 if ( (dist_to_plane < aepsge) || (dist_to_plane >= old_dist_to_plane)) { 00135 // we will quit the loop at this point 00136 gpar1[0] = dfmin.getPar(0); 00137 gpar1[1] = dfmin.getPar(1); 00138 gpar2[0] = dfmin.getPar(2); 00139 gpar2[1] = dfmin.getPar(3); 00140 00141 gpnt1.resize(3); 00142 gpnt2.resize(3); 00143 psurf1->point(gpnt1, gpar1[0], gpar1[1], 1); 00144 psurf2->point(gpnt2, gpar2[0], gpar2[1], 1); 00145 00146 if (dist_to_plane < aepsge) { 00147 jstat = (gpnt1[0].dist(gpnt2[0]) < aepsge) ? 1 : 2; 00148 } else { 00149 // we are not able to converge properly to plane 00150 jstat = 3; 00151 } 00152 00153 // to fulfill the contract that second derivatives and normal should also 00154 // be computed, we will do that here. Note, however, that these values 00155 // were used nowhere else in this algorithm. 00156 gpnt1.resize(7); 00157 gpnt2.resize(7); 00158 psurf1->point(gpnt1, gpar1[0], gpar1[1], 2); 00159 psurf2->point(gpnt2, gpar2[0], gpar2[1], 2); 00160 gpnt1[6] = gpnt1[1].cross(gpnt1[2]); // nb: not normalized here! 00161 gpnt2[6] = gpnt2[1].cross(gpnt2[2]); // nb: not normalized here! 00162 return; 00163 } 00164 00165 cout << "multiplying C! New C is : " << C * 10 << endl; 00166 C *= 10; // if we redo the loop, we need to augment the value of C 00167 copy(dfmin.getPar(), dfmin.getPar() + 4, seed); 00168 } 00169 }
void Go::closestPtSurfSurfPlaneGeometrical | ( | const std::vector< Point > & | epoint, | |
const std::vector< Point > & | epnt1, | |||
const std::vector< Point > & | epnt2, | |||
const Point & | epar1, | |||
const Point & | epar2, | |||
const ParamSurface * | psurf1, | |||
const ParamSurface * | psurf2, | |||
double | aepsge, | |||
std::vector< Point > & | gpnt1, | |||
std::vector< Point > & | gpnt2, | |||
Point & | gpar1, | |||
Point & | gpar2, | |||
int & | jstat | |||
) |
This is the geometrically-based implementation of closestPtSurfSurfPlane.
It is called from the function above (closestPtSurfSurfPlane()) if it is called with algo = GEOMETRICAL. The user can also choose to call this function directly. The parameter description is the same as in closestPtSurfSurfPlane().
Definition at line 41 of file closestPtSurfSurfPlane_geometrical.C.
References Go::ParamSurface::containingDomain(), DEBUG_ERROR_IF, Go::GeomObject::dimension(), Go::Point::length(), Go::RectDomain::lowerLeft(), nextStep(), Go::ParamSurface::normal(), Go::ParamSurface::point(), Go::Point::swap(), and Go::RectDomain::upperRight().
Referenced by closestPtSurfSurfPlane().
00054 : To iterate to an intersection point between two surfaces 00055 * and a plane. 00056 * Ported from the sisl function s9iterate. 00057 * 00058 * 00059 * 00060 * INPUT : epoint - Vector of Points containing parts of plane description. 00061 * epoint[0] contains a point in the plane. 00062 * epoint[1] contains the normal vector to the plane 00063 * epnt1 - 0-2 Derivatives + normal of start point for 00064 * iteration in first surface 00065 * epnt2 - 0-2 Derivatives + normal of start point for 00066 * iteration in second surface 00067 * epar1 - Parameter pair of start point in first surface 00068 * epar2 - Parameter pair of start point in second surface 00069 * psurf1 - Pointer to the first surface 00070 * psurf2 - Pointer to the second surface 00071 * aepsge - Absolute tolerance 00072 * 00073 * 00074 * OUTPUT : gpnt1 - 0-2 Derivatives + normal of result of iteration 00075 * in first surface 00076 * gpnt2 - 0-2 Derivatives + normal of result of iteration 00077 * in second surface 00078 * gpar1 - Parameter pair of result of iteration in first surface 00079 * gpar2 - Parameter pair of result of iteration in second 00080 * surface 00081 * jstat - status messages 00082 * = 3 : Iteration diverged or too many iterations 00083 * = 2 : iteration converged, singular point found 00084 * = 1 : ok, iteration converged 00085 * 00086 * 00087 * METHOD : 00088 * 00089 * USE : The function is only working in 3-D 00090 * 00091 00092 * 00093 ********************************************************************* 00094 */ 00095 { 00096 const int kdim = psurf1->dimension(); 00097 DEBUG_ERROR_IF(kdim != psurf2->dimension(), "Dimension mismatch."); 00098 DEBUG_ERROR_IF(kdim != 3, "The function is only working i 3-D"); 00099 00100 00101 00102 int kcont; /* Indicator telling if iteration is not finished */ 00103 int kder = 2; /* Derivative indicator */ 00104 int kstat1; /* Status variable */ 00105 int kstat2; /* Status variable */ 00106 int knbit; /* Counter for number of iterations */ 00107 int kmaxit = 100; /* Maximal number of iterations allowed */ 00108 Point sdiff(kdim); /* Difference between two vectors */ 00109 double tdum3; /* Dummy variables */ 00110 double tdist=0; /* Distance between two points in iteration */ 00111 Point normal_vec(3); /* Surface normal vector */ 00112 Point delta(2); /* Parameter step values in the iteration */ 00113 00114 // Make description of intersection plane 00115 00116 const Point& spoint = epoint[0]; // Point in the intersection plane. 00117 const Point& snorm = epoint[1]; // Normal vector of intersection plane 00118 00119 // determining parameter domain (only rectangular domain - trimmed surfaces not supported 00120 const RectDomain pdom1 = psurf1->containingDomain(); 00121 const RectDomain pdom2 = psurf2->containingDomain(); 00122 const Vector2D lower_left_1 = pdom1.lowerLeft(); 00123 const Vector2D lower_left_2 = pdom2.lowerLeft(); 00124 const Vector2D upper_right_1 = pdom1.upperRight(); 00125 const Vector2D upper_right_2 = pdom2.upperRight(); 00126 00127 // Copy input variables to output variables 00128 00129 for (int i=0; i<7; i++) { 00130 gpnt1[i] = epnt1[i]; 00131 gpnt2[i] = epnt2[i]; 00132 } 00133 00134 gpar1 = epar1; 00135 gpar2 = epar2; 00136 00137 // new values of gpnt1 and gpnt2 00138 vector<Point> gpnt1_new(7); 00139 vector<Point> gpnt2_new(7); 00140 Point gpar1_new, gpar2_new; 00141 00142 // At the start of the iteration the two points gpnt1 and gpnt2 might be very 00143 // close since we in most cases start from a point on the intersection curve. 00144 00145 kcont = 1; 00146 knbit = 0; 00147 00148 while (kcont) { 00149 00150 // Put a parametric representation of the tangent plane of surface 1 00151 // into the implicit representation of the tangent plane of surface 2 00152 // and also into the implicit representation of the intersection plane. 00153 // The solution of the equation system is the next step along 00154 // the two parameter directions of surface 1. 00155 00156 nextStep(gpnt1,gpnt2,snorm,spoint, delta,kstat1); 00157 gpar1_new = gpar1 + delta; 00158 //gpar1 += delta; 00159 00160 // Put a parametric representation of the tangent plane of surface 2 00161 // into the implicit representation of the tangent plane of surface 1 00162 // and also into the implicit representation of the intersection plane. 00163 // The solution of the equation system is the next step along 00164 // the two parameter directions of surface 2. 00165 00166 nextStep(gpnt2,gpnt1,snorm,spoint, delta,kstat2); 00167 gpar2_new = gpar2 + delta; 00168 //gpar2 += delta; 00169 00170 // domain checks, kick parameters back into domain! @@ does this always work? 00171 for (int i = 0; i < 2; ++i) { 00172 gpar1_new[i] = std::max(gpar1_new[i], lower_left_1[i]); 00173 gpar1_new[i] = std::min(gpar1_new[i], upper_right_1[i]); 00174 gpar2_new[i] = std::max(gpar2_new[i], lower_left_2[i]); 00175 gpar2_new[i] = std::min(gpar2_new[i], upper_right_2[i]); 00176 } 00177 00178 // Calculate values of new points and normal vector on surface 1. 00179 00180 psurf1->point(gpnt1_new, gpar1_new[0], gpar1_new[1], kder); 00181 psurf1->normal(normal_vec, gpar1_new[0], gpar1_new[1]); 00182 gpnt1_new[6]=normal_vec; 00183 00184 // If the surface normal has zero length no use in continuing 00185 if (normal_vec.length() == 0.0) { 00186 jstat=3; 00187 break; 00188 } 00189 00190 // Calculate values of new points and normal vector on surface 2. 00191 00192 psurf2->point(gpnt2_new, gpar2_new[0], gpar2_new[1], kder); 00193 psurf2->normal(normal_vec, gpar2_new[0], gpar2_new[1]); 00194 gpnt2_new[6]=normal_vec; 00195 00196 // If the surface normal has zero length no use in continuing 00197 if (normal_vec.length() == 0.0) { 00198 jstat=3; 00199 break; 00200 } 00201 00202 00203 // Make difference between the two points, 00204 // and calculate length of difference 00205 sdiff = gpnt1_new[0]; 00206 sdiff -= gpnt2_new[0]; 00207 00208 tdum3 = sdiff.length(); 00209 if (tdum3 < TOL) { 00210 // Length is zero. Iteration has converged. 00211 kcont = 0; 00212 jstat = 1; 00213 break; 00214 } 00215 00216 if (knbit==0) { 00217 // First iteration inititate distance variable, if the equation 00218 // systems were not singular 00219 00220 if (kstat1 || kstat2) { 00221 jstat=3; 00222 break; 00223 } 00224 tdist = tdum3; 00225 knbit = 1; 00226 } else { 00227 // More than one iteration done, stop if distance is not decreasing. 00228 // Then decide if we converge distance between the points is within 00229 // the tolerance and the last step had singular or none singular 00230 // equation systems. 00231 00232 knbit = knbit + 1; 00233 if (tdum3 >= tdist) { 00234 // Distance is not decreasing 00235 if (tdist <= aepsge) { 00236 // Distance within tolerance 00237 if (kstat1 || kstat2) { 00238 // Singular equation system 00239 jstat=2; 00240 return; // return without swapping new results to old 00241 //break; 00242 } 00243 else { 00244 // Nonsingular equation system 00245 jstat=1; 00246 return; // return without swapping new results to old 00247 //break; 00248 } 00249 } 00250 else { 00251 // Distance is not within tolerance, divergence 00252 jstat=3; 00253 return; // return without swapping new results to old 00254 //break; 00255 } 00256 } 00257 // Distance still decreasing 00258 tdist = tdum3; 00259 } 00260 00261 // Make sure that not too many iterations are being done 00262 if (knbit > kmaxit) { 00263 jstat=3; 00264 break; 00265 } 00266 gpnt1_new.swap(gpnt1); 00267 gpnt2_new.swap(gpnt2); 00268 // Hmm, seems to need an old-fashioned swap here in order to 00269 // get rid of and internal compiler error on gcc 4.2.4 in 00270 // optimized mode. @jbt 00271 Point tmp = gpar1_new; 00272 gpar1_new = gpar1; 00273 gpar1 = tmp; 00274 tmp = gpar2_new; 00275 gpar2_new = gpar2; 00276 gpar2 = tmp; 00277 // gpar1_new.swap(gpar1); 00278 // gpar2_new.swap(gpar2); 00279 } // while (kcont) 00280 00281 // If we got here, we want to keep the newly calculated values before returning. 00282 // Effectuating swap. 00283 gpnt1_new.swap(gpnt1); 00284 gpnt2_new.swap(gpnt2); 00285 gpar1_new.swap(gpar1); 00286 gpar2_new.swap(gpar2); 00287 00288 }
void Go::computeFirstFundamentalForm | ( | const ParamSurface & | sf, | |
double | u, | |||
double | v, | |||
int | derivs, | |||
std::vector< double > & | form | |||
) |
Computes the coefficients of the first fundamental form.
The returned values are stored { E F G [Eu Fu Gu Ev Fv Gv [Euu Fuu Guu Euv Fuv Guv Evv Fvv Gvv [...] ] ] }. Only one derivative is implemented so far.
sf | reference to the concerned surface | |
u | first parameter of point where we want to compute the first fundamental form | |
v | second parameter of point where we want to compute the first fundamental form | |
derivs | number of (partial) derivatives of the first fundamental form that we want to include in the result. So far, only the computation of the first derivative is actually implemented. | |
form | the computed values, on the format described above |
Definition at line 25 of file CurvatureAnalysis.C.
References Go::ParamSurface::point(), and THROW.
00029 { 00030 int sz = (derivs + 1)*(derivs + 2)/2; 00031 form.resize(3*sz); 00032 std::vector<Point> pts((derivs + 2)*(derivs + 3)/2); 00033 // To evaluate k derivatives of E, F, G we need k+1 derivatives 00034 // of the surface. 00035 sf.point(pts, u, v, derivs + 1); 00036 // Compute the first few terms 00037 form[0] = pts[1]*pts[1]; 00038 form[1] = pts[1]*pts[2]; 00039 form[2] = pts[2]*pts[2]; 00040 if (derivs > 0) { 00041 form[3] = 2.0*pts[1]*pts[3]; 00042 form[4] = pts[1]*pts[4] + pts[2]*pts[3]; 00043 form[5] = 2.0*pts[2]*pts[4]; 00044 form[6] = 2.0*pts[1]*pts[4]; 00045 form[7] = pts[1]*pts[5] + pts[2]*pts[4]; 00046 form[8] = 2.0*pts[2]*pts[5]; 00047 } 00048 // Using the 2-variable Leibniz rule, 00049 // we could eventually compute the higher derivatives. 00050 for (int i = 2; i <= derivs; ++i) { 00051 THROW("Higher derivatives of E, F, G not implemented."); 00052 } 00053 }
double Go::computeLoopGap | ( | const std::vector< PtrToCurveType > & | curves | ) | [inline] |
Computes the largest gap in the loop specified by the vector of curves.
Definition at line 186 of file CurveLoop.h.
References Go::Point::dist(), and THROW.
Referenced by Go::CurveLoop::fixInvalidLoop(), and Go::CurveLoop::setCurves().
00188 { 00189 00190 // Here, we should check that the given curves indeed are forming a 00191 // loop, so every endpoint is within space_epsilon of the start of the 00192 // next curve. 00193 // Also, we make sure that all curves have the same dimension 00194 // and that the curves are of the same type 00195 if ((curves.size() == 0) || (curves[0] == NULL)) 00196 return -1.0; 00197 00198 int dim = curves[0]->dimension(); 00199 // ClassType type = curves[0]->instanceType(); 00200 int n = curves.size(); 00201 int i; 00202 for (i = 1; i < n; ++i) { 00203 if (curves[i] == NULL) 00204 return -1.0; 00205 if (curves[i]->dimension() != dim) { 00206 THROW("Curves do not have the same dimension."); 00207 } 00208 // if (curves[i]->instanceType() != type) { 00209 // THROW("Not all curves are of the same type."); 00210 // } 00211 } 00212 Point startp(dim); 00213 Point endp(dim); 00214 double maxdist = -1.0; 00215 double dist; 00216 for (i = 1; i < n; ++i) { 00217 curves[i-1]->point(endp, curves[i-1]->endparam()); 00218 curves[i]->point(startp, curves[i]->startparam()); 00219 dist = endp.dist(startp); 00220 if (dist > maxdist) maxdist = dist; 00221 } 00222 curves[n-1]->point(endp, curves[n-1]->endparam()); 00223 curves[0]->point(startp, curves[0]->startparam()); 00224 dist = endp.dist(startp); 00225 if (dist > maxdist) maxdist = dist; 00226 return maxdist; 00227 }
void Go::computeSecondFundamentalForm | ( | const ParamSurface & | sf, | |
double | u, | |||
double | v, | |||
double | form1[3], | |||
double | form2[3] | |||
) |
Computes the coefficients of the first and second fundamental forms.
The returned values are stored { E F G } in form1 and { e f g } in form2. This function cannot compute derivatives.
sf | reference to the concerned surface | |
u | first parameter of point where we want to compute the fundamental forms. | |
v | second parameter of point where we want to compute the fundamental forms | |
form1 | the values associated with the first fundamental form will be returned here. | |
form2 | the values associated with the second fundamental form will be returned here. |
Definition at line 57 of file CurvatureAnalysis.C.
References Go::ParamSurface::normal(), and Go::ParamSurface::point().
Referenced by curvatures(), and principalCurvatures().
00062 { 00063 // To evaluate both fundamental forms, we need the second 00064 // derivatives and the normal. 00065 std::vector<Point> pts(6); 00066 Point normal; 00067 sf.point(pts, u, v, 2); 00068 sf.normal(normal, u, v); 00069 // Compute the first few terms 00070 form1[0] = pts[1]*pts[1]; 00071 form1[1] = pts[1]*pts[2]; 00072 form1[2] = pts[2]*pts[2]; 00073 form2[0] = normal*pts[3]; 00074 form2[1] = normal*pts[4]; 00075 form2[2] = normal*pts[5]; 00076 }
void Go::computeSeedCvCv | ( | const SplineCurve * | pc1, | |
const SplineCurve * | pc2, | |||
double & | seed1, | |||
double & | seed2 | |||
) |
Computes initial start points for iteration along the curves.
pc1 | Curve number one. | |
pc2 | Curve number two. |
seed1 | Start point for iteration along curve number one. | |
seed2 | Start point for iteration along curve number two. |
Definition at line 338 of file closestPtCurves.C.
References Go::SplineCurve::basis(), Go::BsplineBasis::begin(), Go::SplineCurve::coefs_begin(), Go::SplineCurve::coefs_end(), DEBUG_ERROR_IF, Go::SplineCurve::dimension(), and Go::SplineCurve::order().
Referenced by closestPtCurves().
00341 { 00342 00343 // Make guess point to the iteration. 00344 // Find position of closest vertices 00345 std::vector<double>::const_iterator co1 = cv1->coefs_begin(); 00346 std::vector<double>::const_iterator co2 = cv2->coefs_begin(); 00347 std::vector<double>::const_iterator co3; 00348 std::vector<double>::const_iterator co12 = cv1->coefs_end(); 00349 std::vector<double>::const_iterator co22 = cv2->coefs_end(); 00350 00351 const int dim = cv1->dimension(); 00352 DEBUG_ERROR_IF(dim!=cv2->dimension(), "Dimension mismatch."); 00353 double td, tmin=1.0e8; 00354 int minidx1=0, minidx2=0; 00355 int ki, k1, k2; 00356 for (k1=0; co1<co12; co1+=dim, k1++) { 00357 for (k2=0, co3=co2; co3<co22; co3+=dim, k2++) { 00358 for (td=0.0, ki=0; ki<dim; ki++) 00359 td += (co1[ki]-co3[ki])*(co1[ki]-co3[ki]); 00360 if (td < tmin) { 00361 tmin = td; 00362 minidx1 = k1; 00363 minidx2 = k2; 00364 } 00365 } 00366 } 00367 00368 // Estimate parameter value of vertices 00369 std::vector<double>::const_iterator st; 00370 int kk = cv1->order(); 00371 for (k1=minidx1+1, st=cv1->basis().begin(), seed1=0.0; 00372 k1<minidx1+kk; seed1+=st[k1], k1++); 00373 seed1 /= (double)(kk-1); 00374 kk = cv2->order(); 00375 for (k1=minidx2+1, st=cv2->basis().begin(), seed2=0.0; 00376 k1<minidx2+kk; seed2+=st[k1], k1++); 00377 seed2 /= (double)(kk-1); 00378 00379 }
void Go::construct_corner_lists | ( | boost::shared_ptr< SplineSurface > | srf, | |
vector< boost::shared_ptr< SplineCurve > > & | crv_set, | |||
const vector< Vector3D > & | vert, | |||
const vector< Vector2D > & | vert_p, | |||
const vector< Vector3D > & | norm, | |||
const vector< int > & | mesh, | |||
const vector< vector< Vector3D > > & | trim_curve_all, | |||
const vector< vector< Vector3D > > & | trim_curve_p_all, | |||
const int | dn, | |||
const int | dm, | |||
const double | bd_res_ratio, | |||
const double | eps, | |||
const double | cosangle_limit, | |||
const double | pt_edge_degen_limit, | |||
const double | pt_mult_def, | |||
const double | min_corner_dist, | |||
const double | max_corner_dist, | |||
vector< int > & | skip_quad, | |||
vector< vector< Vector3D > > & | quad_corner_trim_curve, | |||
vector< vector< Vector2D > > & | quad_corner_trim_curve_p, | |||
int & | quad_corners | |||
) |
Definition at line 1412 of file spline2mesh.C.
References M_PI, Go::Array< T, Dim >::normalize(), and THROW.
Referenced by make_trimmed_mesh().
01432 { 01433 // 090130: "Corner-handling", 1st step: Identify quads needing special treatment, i.e. extra refinement. 01434 // 090203: Note that we really want to avoid making almost-degenerate triangles... 01435 // Hmm... This should really be something relative to the extent of the quad... 01436 //const double delta=1e-8; // See above. 01437 skip_quad=vector<int>(dn*dm, 0); 01438 quad_corner_trim_curve.resize(dn*dm); 01439 quad_corner_trim_curve_p.resize(dn*dm); 01440 01441 const double u0=srf->startparam_u(); 01442 const double u1=srf->endparam_u(); 01443 const double v0=srf->startparam_v(); 01444 const double v1=srf->endparam_v(); 01445 const double dv=(v1-v0)/dm, du=(u1-u0)/dn; 01446 01447 #ifdef DBG 01448 // 100222: Producing matlab-scripts for debugging. 01449 { 01450 const double u02=vert_p[0][0], v02=vert_p[0][1]; 01451 const double u12=vert_p[(dn+1)*(dm+1)-1][0], v12=vert_p[(dn+1)*(dn+1)-1][1]; 01452 if (fabs(u02-u0)>eps) THROW("Huh?!"); 01453 if (fabs(u12-u1)>eps) THROW("Huh?!"); 01454 if (fabs(v02-v0)>eps) THROW("Huh?!"); 01455 if (fabs(v12-v1)>eps) THROW("Huh?!"); 01456 printf("Parameter domain: [%g, %g] x [%g, %g]\n", u02, u12, v02, v12); 01457 } 01458 FILE *f1=fopen("c1.m", "w"); // corners in quads 01459 FILE *f2=fopen("c2.m", "w"); // corner skipped due to small angle 01460 FILE *f3=fopen("c3.m", "w"); // corner skipped, is a duplicate 01461 FILE *f4=fopen("c4.m", "w"); // all points 01462 fprintf(f1, "hold on\ngrid on\n"); 01463 fprintf(f2, "hold on\ngrid on\n"); 01464 fprintf(f3, "hold on\ngrid on\n"); 01465 fprintf(f4, "hold on\ngrid on\n"); 01466 #endif 01467 01468 for (int curve=0; curve<int(crv_set.size()); curve++) 01469 { 01470 #ifdef CLC_DBG 01471 printf("curve %d\n", curve); 01472 #endif 01473 const vector<Vector3D> &trim_curve_p=trim_curve_p_all[curve]; 01474 const vector<Vector3D> &trim_curve=trim_curve_all[curve]; 01475 Vector2D last_dir(1.0, 0.0); // Will be kept normalized. The initial value will not be used, 01476 // ref. 'a_first_point_added' 01477 bool a_first_point_added=false; 01478 Vector2D last_used_p(0.0, 0.0); 01479 const int contour_points=trim_curve_p.size(); 01480 01481 for (int i=0; i<contour_points; i++) 01482 { 01483 double u=trim_curve_p[i][0], v=trim_curve_p[i][1]; 01484 // const int /* ip1=(i+1)%contour_points, */ im1=(i+contour_points-1)%contour_points; 01485 #ifdef CLC_DBG 01486 printf(" i=%4d u=%7.3f, v=%7.3f", i, u, v); 01487 #endif 01488 if ((u>=u0) && (u<=u1) && (v>=v0) && (v<=v1)) 01489 { 01490 const int p=std::min(int(floor((v-v0)/dv)), dm-1), q=std::min(int(floor((u-u0)/du)), dn-1); 01491 const int vert_indx=p*(dn+1)+q, quad_indx=p*dn+q; 01492 const double &u_left=vert_p[vert_indx][0], &v_left=vert_p[vert_indx][1]; 01493 const double &u_right=vert_p[vert_indx+dn+2][0], &v_right=vert_p[vert_indx+dn+2][1]; 01494 // if (u<u_left) 01495 // { 01496 // printf("\nu=%g, u_left=%g\n", u, u_left); 01497 // THROW("Huh?!"); 01498 // } 01499 // if (v<v_left) THROW("Huh?!"); 01500 // if ((u>u_right) && (q<n-1)) THROW("Huh?!"); 01501 // if ((v>v_right) && (p<n-1)) THROW("Huh?!"); 01502 // Note that due to rounding errors, discrete arithmetic, or floor's behaviour, u or v might 01503 // actually be outside the quads parameter (sub)domain. This should only happen on the right and 01504 // upper rim... 01505 // 090219: Doing a small adjustment for this... 01506 u=std::min(std::max(u_left, u), u_right); 01507 v=std::min(std::max(v_left, v), v_right); 01508 01509 // Need two things: 1) angle!=pi, 2) not duplicate point. And 3) not on the edges. 01510 // 090218: New criterium: Accumulating angle changes. 01511 // 090220: Taking care of weeding out duplicates in the calling function. (?) 01512 01513 if ( ((u-u_left<pt_edge_degen_limit) || (u_right-u<pt_edge_degen_limit) || 01514 (v-v_left<pt_edge_degen_limit) || (v_right-v<pt_edge_degen_limit) ) && (0) ) 01515 { 01516 //printf(" quad-corner too close to edge to split.\n"); 01517 // 090202: Hmmm... On second thought... We should still split here, it's just that we 01518 // shouldn't split into four new triangles. 01519 // 090203: Hmm... On third thought... It's ok *not* to "corner split" here, because 01520 // everything will be ok when we do the "ordinary" curve-splitting later. The 01521 // point about the corners is to force splitting in the corner, and when the 01522 // corner happens to be on a mesh-edge, this will happen automagically! 01523 // 090203: Note that even if we end up here, the angle, distance to previous point 01524 // etc. may still not warrant a splitting. This is likely often the case when the 01525 // trimming curve follows an edge of the surface! 01526 // 090203: No! If we don't add a corner even though on an edge, splitting may not occur 01527 // later either. (But why not? Was this not solved with the "boundary-fix" some 01528 // time earlier?) Another solution is to split, and then remove (or not add) 01529 // degenerate triangles... 01530 } 01531 else 01532 { 01533 const Vector2D current_p(trim_curve_p[i][0], trim_curve_p[i][1]); 01534 const Vector2D previous_p = 01535 i>0 ? Vector2D(trim_curve_p[i-1][0], trim_curve_p[i-1][1]) : Vector2D(1e99, 1e99); 01536 const double dist_since_last_used_p=sqrt((current_p-last_used_p)*(current_p-last_used_p)); 01537 const double dist_since_prev_p=sqrt((current_p-previous_p)*(current_p-previous_p)); 01538 01539 #ifdef DBG 01540 fprintf(f4, "plot(%f, %f, 'kd', 'markersize', 5);\n", current_p[0], current_p[1]); 01541 #endif 01542 01543 if ( (dist_since_prev_p>pt_mult_def) // a new distinct point 01544 || (!a_first_point_added) ) 01545 { 01546 const double cosangle = (last_dir*(current_p-last_used_p))/dist_since_last_used_p; 01547 // (Note: We have made sure 'dist_since_last_used_p' is non-zero!) 01548 #ifdef CLC_DBG 01549 printf(" [%7.3f %7.3f %7.3f %7.3f]", last_dir[0], last_dir[1], 01550 current_p[0]-last_used_p[0], current_p[1]-last_used_p[1]); 01551 printf(" angle=%7.3f", acos(std::min(cosangle, 1.0))/M_PI*180.0); 01552 printf(" cosangle=%6.3f", cosangle); 01553 #endif 01554 // if ( ((cosangle<cosangle_limit) || (b*b>max_corner_dist*max_corner_dist)) && 01555 // (b*b>min_corner_dist*max_corner_dist) ) 01556 if ((cosangle<cosangle_limit) || (!a_first_point_added)) 01557 { 01558 //const Vector2D previous_p(trim_curve_p[im1][0], trim_curve_p[im1][1]); 01559 // if ( (current_p-previous_p)*(current_p-previous_p) < 1e-15*1e-15 ) 01560 // { 01561 // #ifdef DBG 01562 // printf(" skipping point, same as previous. "); 01563 // #endif 01564 // } 01565 // else 01566 // { 01567 // Now we flag the quad as being split, and append the corner to the quad's list. 01568 //printf("dist from previous: %g ", sqrt((current_p-previous_p)*(current_p-previous_p))); 01569 skip_quad[quad_indx]=1; 01570 quad_corner_trim_curve[quad_indx].push_back(trim_curve[i]); 01571 quad_corner_trim_curve_p[quad_indx].push_back(current_p); 01572 quad_corners++; 01573 last_dir=current_p-last_used_p; 01574 //printf("\n last_dir 1 =%g %g\n", last_dir[0], last_dir[1]); 01575 last_dir.normalize(); 01576 //printf("\n last_dir 2 =%g %g\n", last_dir[0], last_dir[1]); 01577 last_used_p=current_p; 01578 a_first_point_added=true; 01579 #ifdef DBG 01580 fprintf(f1, "plot(%f, %f, 'm*');\n", current_p[0], current_p[1]); 01581 char *tmpstr=new char[100]; 01582 sprintf(tmpstr, "%d", i); 01583 fprintf(f1, "text(%f, %f, '%s');\n", current_p[0], current_p[1]+0.00005, tmpstr); 01584 # ifdef CLC_DBG 01585 printf(" (c1) USED"); 01586 # endif 01587 #endif 01588 // } 01589 } 01590 #ifdef DBG 01591 else 01592 { 01593 fprintf(f2, "plot(%f, %f, 'b+');\n", current_p[0], current_p[1]); 01594 char *tmpstr=new char[100]; 01595 sprintf(tmpstr, "%d", i); 01596 fprintf(f2, "text(%f, %f, '%s');\n", current_p[0], current_p[1]+0.00010, tmpstr); 01597 # ifdef CLC_DBG 01598 printf(" (c2) TOO SMALL ANGLE"); 01599 # endif 01600 } 01601 #endif 01602 } 01603 else 01604 { 01605 // Use it, but not if already used!!!! 01606 if (dist_since_last_used_p>1e-14) 01607 { 01608 01609 #ifdef DBG 01610 fprintf(f3, "plot(%f, %f, 'go', 'markersize', 4);\n", current_p[0], current_p[1]); 01611 char *tmpstr=new char[100]; 01612 sprintf(tmpstr, "%d", i); 01613 fprintf(f3, "text(%f, %f, '%s');\n", current_p[0], current_p[1]+0.00015, tmpstr); 01614 # ifdef CLC_DBG 01615 printf(" (c3) DUPLICATE: %f", dist_since_last_used_p); 01616 # endif 01617 #endif 01618 01619 // Multiple point, definitely use this one, since we assume it is due to a kink in 01620 // the curve. 01621 skip_quad[quad_indx]=1; 01622 quad_corner_trim_curve[quad_indx].push_back(trim_curve[i]); 01623 quad_corner_trim_curve_p[quad_indx].push_back(current_p); 01624 quad_corners++; 01625 last_dir=current_p-last_used_p; 01626 //printf("\n last_dir 3 =%g %g\n", last_dir[0], last_dir[1]); 01627 last_dir.normalize(); 01628 //printf("\n last_dir 4 =%g %g\n", last_dir[0], last_dir[1]); 01629 last_used_p=current_p; 01630 a_first_point_added=true; 01631 } 01632 // else 01633 // { 01634 // printf("\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %f\n", dist_since_last_used_p); 01635 // } 01636 01637 } 01638 } 01639 } // end of if-test ensuring that [u, v] is in the parameter domain. 01640 #ifdef CLC_DBG 01641 printf("\n"); 01642 #endif 01643 } // end of i-loop over points on curve 'curve'. 01644 } // end of 'curve'-loop 01645 01646 #ifdef DBG 01647 fprintf(f1, "hold off\n"); 01648 fprintf(f2, "hold off\n"); 01649 fprintf(f3, "hold off\n"); 01650 fprintf(f4, "hold off\n"); 01651 fclose(f1); 01652 fclose(f2); 01653 fclose(f3); 01654 fclose(f4); 01655 #endif 01656 }
bool Go::cornerToCornerSfs | ( | shared_ptr< ParamSurface > | sf1, | |
shared_ptr< CurveOnSurface > | sf_cv1, | |||
shared_ptr< ParamSurface > | sf2, | |||
shared_ptr< CurveOnSurface > | sf_cv2, | |||
double | tol | |||
) |
Definition at line 267 of file SurfaceTools.C.
References Go::Point::dist(), Go::RectDomain::umax(), Go::RectDomain::umin(), Go::RectDomain::vmax(), and Go::RectDomain::vmin().
00273 { 00274 int bd1, bd2; // Specifies the surface boundaries corresponding to 00275 // the current edges 00276 // 0 = umin, 1 = umax, 2 = vmin, 3 = vmax 00277 bool same_orient1, same_orient2; 00278 bd1 = sf_cv1->whichBoundary(tol, same_orient1); 00279 bd2 = sf_cv2->whichBoundary(tol, same_orient2); 00280 if (bd1 < 0 || bd2 < 0) 00281 return false; // Adjacency not along boundary 00282 00283 // Get surface parameters at corners 00284 RectDomain dom1 = sf1->containingDomain(); 00285 RectDomain dom2 = sf2->containingDomain(); 00286 double corn1_1[2], corn1_2[2], corn2_1[2], corn2_2[2]; 00287 if (bd1 == 0 || bd1 == 1) 00288 { 00289 if (bd1 == 0) 00290 corn1_1[0] = corn1_2[0] = dom1.umin(); 00291 else 00292 corn1_1[0] = corn1_2[0] = dom1.umax(); 00293 corn1_1[1] = dom1.vmin(); 00294 corn1_2[1] = dom1.vmax(); 00295 } 00296 else if (bd1 == 2 || bd1 == 3) 00297 { 00298 if (bd1 == 2) 00299 corn1_1[1] = corn1_2[1] = dom1.vmin(); 00300 else 00301 corn1_1[1] = corn1_2[1] = dom1.vmax(); 00302 corn1_1[0] = dom1.umin(); 00303 corn1_2[0] = dom1.umax(); 00304 } 00305 if (bd2 == 0 || bd2 == 1) 00306 { 00307 if (bd2 == 0) 00308 corn2_1[0] = corn2_2[0] = dom2.umin(); 00309 else 00310 corn2_1[0] = corn2_2[0] = dom2.umax(); 00311 corn2_1[1] = dom2.vmin(); 00312 corn2_2[1] = dom2.vmax(); 00313 } 00314 else if (bd2 == 2 || bd2 == 3) 00315 { 00316 if (bd2 == 2) 00317 corn2_1[1] = corn2_2[1] = dom2.vmin(); 00318 else 00319 corn2_1[1] = corn2_2[1] = dom2.vmax(); 00320 corn2_1[0] = dom2.umin(); 00321 corn2_2[0] = dom2.umax(); 00322 } 00323 00324 // Evaluate surface corners 00325 Point pt1 = sf1->point(corn1_1[0], corn1_1[1]); 00326 Point pt2 = sf1->point(corn1_2[0], corn1_2[1]); 00327 Point pt3 = sf2->point(corn2_1[0], corn2_1[1]); 00328 Point pt4 = sf2->point(corn2_2[0], corn2_2[1]); 00329 00330 if (pt1.dist(pt3) > tol && pt1.dist(pt4) > tol) 00331 return false; 00332 if (pt2.dist(pt3) > tol && pt2.dist(pt4) > tol) 00333 return false; 00334 if (pt3.dist(pt1) > tol && pt3.dist(pt2) > tol) 00335 return false; 00336 if (pt4.dist(pt1) > tol && pt4.dist(pt2) > tol) 00337 return false; 00338 00339 return true; 00340 }
bool Go::cornerToCornerSfs | ( | boost::shared_ptr< ParamSurface > | sf1, | |
boost::shared_ptr< CurveOnSurface > | sf_cv1, | |||
boost::shared_ptr< ParamSurface > | sf2, | |||
boost::shared_ptr< CurveOnSurface > | sf_cv2, | |||
double | tol | |||
) |
double Go::curvatureRadius | ( | const std::vector< Point > & | der, | |
std::vector< Point > & | unitder | |||
) |
Help functions in related to curvature.
Given position, first and second derivative of a curve passing through a point, compute the unit tangent, curvature vector and curvature radius of this curve.
Definition at line 28 of file CurvatureUtils.C.
References ASSERT, ltol, and THROW.
Referenced by getHermiteData(), and minimalCurvatureRadius().
00035 { 00036 00037 // Let c = c(w) be a parameterized curve. 00038 // The curvature vector is defined as the derivative of the unit tangent 00039 // vector with respect to the arc length a. If we don't have an arclength 00040 // parametrization then this parametrization can be written as a function 00041 // of the arc length w = w(a). By using the kernel rule for differentiation 00042 // we get: 00043 00044 // d d dw d c'(w) dw d c'(w) da 00045 // k(a) = -- T(w(a)) = -- T(w) -- = -- ---------- -- = -- ---------- / -- 00046 // da dw da dw sqrt(c'c') da dw sqrt(c'c') dw 00047 00048 // d c'(w) c" c' (c'c'') 00049 // -- ----------------- = ---------- - ------------- 00050 // dw sqrt(c'(w) c'(w)) sqrt(c'c') sqrt(c'c')**3 00051 00052 // da 00053 // -- = sqrt(c'c') 00054 // dw 00055 00056 // Assuming 2D or 3D 00057 ASSERT(der.size() >= 3); 00058 ASSERT(der[0].dimension() == 2 || der[0].dimension() == 3); 00059 00060 // Initiate output vector 00061 int ki; 00062 unitder.resize(3); 00063 for (ki=0; ki<3; ki++) 00064 unitder[ki] = der[ki]; 00065 00066 double length = unitder[1].length(); 00067 if (length < ltol) 00068 return -1; 00069 00070 unitder[1].normalize(); 00071 00072 // Check tangent length 00073 if (length < ltol) 00074 THROW("Tangent of length zero"); 00075 00076 // Make curvature vector 00077 double dum1 = (der[2] * unitder[1])/length; 00078 unitder[2] = (der[2]/length - unitder[1]*dum1)/length; 00079 00080 // Make curvature radius 00081 double dum2 = unitder[2].length(); 00082 if (dum2 < ltol) 00083 return -1; 00084 else 00085 return 1.0/dum2; 00086 }
void Go::curvatureRadiusPoints | ( | const SplineCurve & | curve, | |
double | curveRad, | |||
std::vector< double > & | pos | |||
) |
Definition at line 33 of file Curvature.C.
References Go::SplineInterpolator::basis(), Go::SplineCurve::basis(), Go::BsplineBasis::begin(), Curve2SISL(), Go::SplineCurve::derivCurve(), Go::SplineInterpolator::interpolate(), Go::BsplineBasis::knotMultiplicity(), Go::BsplineBasis::knotsSimple(), Go::Point::length2(), Go::BsplineBasis::order(), and Go::SplineInterpolator::setBasis().
Referenced by main().
00037 { 00038 00039 BsplineBasis basis = curve.basis(); 00040 int order = basis.order(); 00041 int new_order = 6 * order - 11; 00042 00043 vector<double> knots_simple; 00044 vector<double> new_knots; 00045 basis.knotsSimple(knots_simple); 00046 00047 for (size_t i = 0; i < knots_simple.size(); ++i) 00048 { 00049 int old_mult = basis.knotMultiplicity(knots_simple[i]); 00050 int new_mult = 5 * order - 9 + old_mult; 00051 if (old_mult >= order-1) new_mult -= 2 - order + old_mult; 00052 for (int j = 0; j < new_mult; ++j) new_knots.push_back(knots_simple[i]); 00053 } 00054 00055 int num_coefs = new_knots.size() - new_order; 00056 00057 BsplineBasis new_basis(new_order, new_knots.begin(), new_knots.end()); 00058 00059 vector<double> coefs_par; // Parameter values for the coefs (Greville) 00060 vector<double> coefs; 00061 00062 shared_ptr<SplineCurve> d_curve(curve.derivCurve(1)); 00063 shared_ptr<SplineCurve> dd_curve(d_curve->derivCurve(1)); 00064 00065 for (int i = 0; i < num_coefs; ) 00066 { 00067 int knot_pos = i + 1; 00068 while (knot_pos < int(new_knots.size()) && new_knots[knot_pos-1] == new_knots[knot_pos]) 00069 ++knot_pos; 00070 double step = (new_knots[knot_pos] - new_knots[knot_pos-1]) / double(knot_pos - i); 00071 double tpar = new_knots[knot_pos-1] + step/2.0; 00072 for (;i < knot_pos; ++i) 00073 { 00074 coefs_par.push_back(tpar); 00075 tpar += step; 00076 } 00077 } 00078 00079 for (int i = 0; i < num_coefs; ++i) 00080 { 00081 double tpar = coefs_par[i]; 00082 Point d_p, dd_p; 00083 d_curve->point(d_p, tpar); 00084 dd_curve->point(dd_p, tpar); 00085 double d_p_length2 = d_p.length2(); 00086 00087 coefs.push_back( (d_p % dd_p).length2() * curveRad * curveRad - d_p_length2*d_p_length2*d_p_length2); 00088 } 00089 00090 vector<double> curvature_coefs; 00091 vector<double> dummy_tangents; 00092 vector<int> dummy_index; 00093 SplineInterpolator interpolator; 00094 interpolator.setBasis(new_basis); 00095 interpolator.interpolate(coefs_par, coefs, dummy_index, 00096 dummy_tangents, curvature_coefs); 00097 00098 shared_ptr<SplineCurve> curvature_curve( 00099 new SplineCurve(num_coefs, new_order, 00100 interpolator.basis().begin(), 00101 curvature_coefs.begin(), 1)); 00102 00103 SISLCurve *num_sisl = Curve2SISL(*(curvature_curve.get()), false); 00104 SISLObject *qo1 = 0; 00105 SISLObject *qo2 = 0; 00106 SISLPoint *qp = 0; 00107 double spoint[1]; 00108 spoint[0] = 0.0; 00109 int kstat = 0; 00110 SISLIntdat *qintdat = 0; 00111 double aepsge = 1.0e-9; 00112 00113 if (!(qo1 = newObject(SISLCURVE))) goto error101; 00114 qo1 -> c1 = num_sisl; 00115 qo1 -> o1 = qo1; 00116 00117 if (!(qo2 = newObject(SISLPOINT))) goto error101; 00118 spoint[0] = 0.0; 00119 if(!(qp = newPoint(spoint,1,1))) goto error101; 00120 qo2 -> p1 = qp; 00121 00122 sh1761(qo1,qo2,aepsge,&qintdat,&kstat); 00123 if (kstat < 0) goto error101; 00124 00125 if (qintdat) 00126 { 00127 for (int i = 0; i < qintdat->ipoint; ++i) 00128 pos.push_back(qintdat->vpoint[i]->epar[0]); 00129 } 00130 00131 error101: 00132 if (qo1) freeObject(qo1); 00133 if (qo2) freeObject(qo2); 00134 if (qintdat) freeIntdat(qintdat); 00135 }
void Go::curvatures | ( | const ParamSurface & | sf, | |
double | u, | |||
double | v, | |||
double & | K, | |||
double & | H | |||
) |
Computes the Gaussian (K) and mean (H) curvatures.
sf | reference to the concerned surface | |
u | first parameter of point where we want to carry out computation | |
v | second parameter of point where weh want to carry out computation | |
K | value of Gaussian curvature returned here | |
H | value of mean curvature returned here |
Definition at line 80 of file CurvatureAnalysis.C.
References computeSecondFundamentalForm().
00084 { 00085 double I[3]; 00086 double II[3]; 00087 computeSecondFundamentalForm(sf, u, v, I, II); 00088 double denom = I[0]*I[2]-I[1]*I[1]; 00089 K = (II[0]*II[2]-II[1]*II[1])/denom; 00090 H = (II[0]*I[2]-2*II[1]*I[1]+II[2]*I[0])/(2*denom); 00091 }
SISLCurve * Go::Curve2SISL | ( | const SplineCurve & | cv, | |
bool | copy = true | |||
) |
Convert a SplineCurve to a SISLCurve.
cv | the SplineCurve to convert | |
copy | if 'true', then the generated SISLCurve will have its own copy of the coefficient information contained in 'cv'. Otherwise, it will share this information with 'cv' (ie. it will only contain a pointer into the corresponding storage array in 'cv'. |
Definition at line 23 of file SISLconversion.C.
References Go::SplineCurve::basis(), Go::BsplineBasis::begin(), Go::SplineCurve::coefs_begin(), Go::SplineCurve::dimension(), Go::SplineCurve::numCoefs(), Go::SplineCurve::order(), Go::SplineCurve::rational(), and Go::SplineCurve::rcoefs_begin().
Referenced by closestPtSislCurves(), curvatureRadiusPoints(), intersect2Dcurves(), intersectCurvePoint(), intersectcurves(), main(), and minimalCurvatureRadius().
00024 { 00025 std::vector<double>::const_iterator coef; 00026 int kind; 00027 if (cv.rational()) { 00028 coef = cv.rcoefs_begin(); 00029 kind = 2; 00030 } else { 00031 coef = cv.coefs_begin(); 00032 kind = 1; 00033 } 00034 return newCurve(cv.numCoefs(), cv.order(), 00035 const_cast<double*>(&(*(cv.basis().begin()))), 00036 const_cast<double*>(&(*coef)), 00037 kind, cv.dimension(), copy); 00038 }
SISLCurve * Go::Curve2SISL_rat | ( | const SplineCurve & | cv | ) |
Convert a SplineCurve to a rational SISLCurve Arrays are copied.
Definition at line 42 of file SISLconversion.C.
References Go::SplineCurve::basis(), Go::BsplineBasis::begin(), Go::SplineCurve::coefs_begin(), Go::SplineCurve::dimension(), Go::SplineCurve::numCoefs(), Go::SplineCurve::order(), Go::SplineCurve::rational(), and Go::SplineCurve::rcoefs_begin().
00043 { 00044 std::vector<double>::const_iterator coef; 00045 int kind = 2; 00046 if (cv.rational()) 00047 { 00048 coef = cv.rcoefs_begin(); 00049 return newCurve(cv.numCoefs(), cv.order(), 00050 const_cast<double*>(&(*(cv.basis().begin()))), 00051 const_cast<double*>(&(*coef)), 00052 kind, cv.dimension(), 1); 00053 } 00054 else 00055 { 00056 coef = cv.coefs_begin(); 00057 int in = cv.numCoefs(); 00058 int dim = cv.dimension(); 00059 vector<double> sc(in*(dim+1)); 00060 int ki; 00061 for (ki=0; ki<in; ++ki, coef+=dim) 00062 { 00063 std::copy(coef, coef+dim, sc.begin()+ki*(dim+1)); 00064 sc[ki*(dim+1)+dim] = 1.0; 00065 } 00066 return newCurve(cv.numCoefs(), cv.order(), 00067 const_cast<double*>(&(*(cv.basis().begin()))), 00068 const_cast<double*>(&(sc[0])), 00069 kind, cv.dimension(), 1); 00070 } 00071 }
void Go::curve_ratder | ( | double const | eder[], | |
int | idim, | |||
int | ider, | |||
double | gder[] | |||
) |
This function takes as input the position and a certain number of derivatives in homogenous space of a point on a rational curve.
It outputs the position and derivatives of this point in non-homogenous ("ordinary") space. (Corresponds to s6ratder in SISL)
eder | pointer to the array where the point's position and derivatives in homogenous coordinates (input) are consecutively stored | |
idim | the dimension of the non-homogenous space | |
ider | the number of derivatives sought (0 means that we only want to convert the position to non-homogenous coordinates). | |
gder | pointer to the array where the result will be written (in same order as 'eder'). |
Definition at line 22 of file ratder.C.
References ALWAYS_ERROR_IF, binom(), and sum().
Referenced by Go::SplineCurve::point().
00026 : To calculate the ider derivatives of a rational 00027 00028 * point described in homogenous coordinates 00029 * 00030 * INPUT : eder - The derivatives in homogenous coordinates 00031 * In sequence: 00032 * Position (x,y,...h) 00033 * 1st der (x,y,...h) 00034 * 2nd der (x,y,...h) 00035 * etc. 00036 * idim - The dimension of the non homogenous space 00037 * ider - The number of input derivatives 00038 * 00039 * 00040 * OUTPUT : gder - The derivatives in the nonhomogenous space 00041 * 00042 * 00043 * METHOD : The curve P(u) can be written as the quotient 00044 * P(u) = T(u) / w(u) where T and w are ordinary splines. 00045 * The dimensions of T and w are idim and 1 00046 * respectively. The array eder contains position 00047 * and derivatives of the idim+1 dimensional curve 00048 * (T(u),w(u)). 00049 * 00050 * Now, since wP = T, we find, by the Leibnitz formula, 00051 * 00052 * k 00053 * k! (k-i) (i) (k) 00054 * sum -------- w P = T . 00055 * i!(k-i)! 00056 * i=0 00057 * 00058 * Therefore 00059 * 00060 * 00061 * -- k-1 -- 00062 * (k) | (k) k! (k-i) (i) | 00063 * P = | T - sum -------- w P | / w . 00064 * | i!(k-i)! | 00065 * -- i=0 -- 00066 * 00067 * This formula is applied recursively to evaluate P's derivatives. 00068 * 00069 * MF. 00070 * 00071 * CALLS : 00072 * 00073 * WRITTEN BY : Tor Dokken, SI, Oslo, Norway. 1988-des-1988 00074 * REVISED BY : Michael Floater, SI, 30/9/91 Removed division by t=1. 00075 * REWRITTEN BY : Michael Floater, SI, 16/12/91. New algorithm. 00076 * REWRITTEN BY : Michael Floater, SI, 25/8/92. Extend to arbitrary 00077 * number of derivatives (by Leibnitz). Finally! 00078 * REVISED BY : Paal Fugelli, SINTEF, 07/07-94. Added free'ing of binom and 00079 * initiation to SISL_NULL to avoid memory leakage. 00080 * REVISED BY : Atgeirr F Rasmussen, SINTEF, 06/04/2001. Go and C++-ified. 00081 * 00082 ********************************************************************* 00083 */ 00084 { 00085 double w0; /* The denominator. */ 00086 int ki; /* Count through dimensions. */ 00087 int id; /* Count through derivatives. */ 00088 std::vector<double> binom; 00089 double sum; /* Binomial (Leibnitz) expansion. */ 00090 int idimp1; /* idim + 1. */ 00091 int iw; /* Pointer to a weight. */ 00092 int igder; /* Pointer to already calculated derivs. */ 00093 int i,j,k; /* Counters. */ 00094 int iwfix; /* Initial value of iw in Leibnitz loop. */ 00095 00096 ALWAYS_ERROR_IF(ider<0, "Less than zero derivatives ?!?"); 00097 ALWAYS_ERROR_IF(idim<1, "Less than zero derivatives ?!?"); 00098 00099 idimp1 = idim + 1; 00100 00101 /* Find denominator. */ 00102 00103 w0 = eder[idim]; 00104 if (fabs(w0)<1e-13) w0 = (double)1.0; // Maybe we should throw instead? 00105 00106 /* Set up initial binomial coefficient (1). */ 00107 00108 binom.resize(ider+1); 00109 00110 binom[0] = 1; 00111 00112 /* Calculate position first. */ 00113 00114 for(ki=0; ki<idim; ki++) 00115 { 00116 gder[ki] = eder[ki] / w0; 00117 } 00118 00119 00120 00121 /* Then derivatives if there are any. */ 00122 00123 for(id=1,j=idim,k=idimp1; id<=ider; id++,k++) 00124 { 00125 /* Calculate the new row of binomial coefficients. */ 00126 00127 binom[id] = 1; 00128 00129 for(i=id-1; i>=1; i--) 00130 { 00131 binom[i] += binom[i-1]; 00132 } 00133 00134 00135 /* Run through the idim dimensions, calculating each 00136 coefficient of the id'th derivative of 00137 the rational curve (in gder). */ 00138 00139 iwfix = k + idim; 00140 00141 for(ki=0; ki<idim; ki++,j++,k++) 00142 { 00143 /* Calculate the Leibnitz sum (the binomial 00144 coefficient in the first term is always 1). */ 00145 00146 sum = eder[iwfix] * gder[ki]; 00147 00148 for(i=1,igder=idim+ki,iw=iwfix-idimp1; 00149 i<id; 00150 i++,igder+=idim,iw-=idimp1) 00151 { 00152 sum += (double)binom[i] * eder[iw] * gder[igder]; 00153 } 00154 00155 gder[j] = (eder[k] - sum) / w0; 00156 00157 } 00158 00159 } 00160 00161 /* Done. */ 00162 00163 }
void Go::curveKinks | ( | const SplineCurve & | cv, | |
double | tol, | |||
double | ang_tol, | |||
std::vector< double > & | c1_disconts, | |||
std::vector< double > & | g1_disconts | |||
) |
Find parameter values where a curve is G1- or C1-discontinuous.
Definition at line 906 of file GeometryTools.C.
References Go::SplineCurve::basis(), Go::BsplineBasis::cNDiscontinuities(), Go::SplineCurve::dimension(), and Go::SplineCurve::point().
00908 { 00909 00910 // Get candidate discontinuity parameters 00911 vector<double> cand_disconts; 00912 cv.basis().cNDiscontinuities(cand_disconts, 1); 00913 00914 // Compare results of left- and right evaluation in the candidates 00915 int der = 1; 00916 int dim = cv.dimension(); 00917 vector<Point> pnt_left(2, Point(dim)), pnt_right(2, Point(dim)); 00918 for (size_t ki=0; ki<cand_disconts.size(); ++ki) 00919 { 00920 cv.point(pnt_left, cand_disconts[ki], der, false); 00921 cv.point(pnt_right, cand_disconts[ki], der, true); 00922 if (pnt_left[1].dist(pnt_right[1]) > tol) 00923 c1_disconts.push_back(cand_disconts[ki]); 00924 00925 if (pnt_left[1].angle(pnt_right[1]) > ang_tol || 00926 pnt_left[1]*pnt_right[1] < 0.0) 00927 g1_disconts.push_back(cand_disconts[ki]); 00928 } 00929 }
boost::shared_ptr< SplineCurve > Go::curveSum | ( | const SplineCurve & | crv1, | |
double | fac1, | |||
const SplineCurve & | crv2, | |||
double | fac2, | |||
double | num_tol = 1e-05 | |||
) |
Addition of two signed SplineCurves, i.e.
this function can also be used for subtraction. The curves is assumed to live on the same parameter domain, but may have different knot vectors. resulting curve = fac1 * crv1 + fac2 * crv2
crv1 | the first of the curves to be added | |
fac1 | multiplicative factor of the first curve | |
crv2 | the second of the curves to be added | |
fac2 | multiplicative factor of the second curve | |
num_tol | tolerance used when unifying the spline spaces in which 'crv1' and 'crv2' lie. |
Definition at line 18 of file curveSum.C.
References ALWAYS_ERROR_IF, Go::SplineCurve::clone(), Go::SplineCurve::endparam(), Go::SplineCurve::rational(), Go::SplineCurve::startparam(), THROW, and unifyCurveSplineSpace().
Referenced by Go::CrossTanOffDist::CrossTanOffDist().
00026 { 00027 // Check input 00028 ALWAYS_ERROR_IF(fabs(crv1.startparam() - crv2.startparam()) > num_tol || 00029 fabs(crv1.endparam() - crv2.endparam()) > num_tol, 00030 "Inconsistent parameter domain."); 00031 00032 // For the time being 00033 if (crv1.rational() || crv2.rational()) { 00034 THROW("Sum of rational curves is not impelemented"); 00035 } 00036 00037 // Make copy of curves 00038 vector<shared_ptr<SplineCurve> > curves; 00039 curves.reserve(2); 00040 shared_ptr<SplineCurve> cv; 00041 // #ifdef _MSC_VER 00042 // cv = shared_ptr<SplineCurve>(dynamic_cast<SplineCurve*>(crv1.clone())); 00043 // #else 00044 cv = shared_ptr<SplineCurve>(crv1.clone()); 00045 // #endif 00046 curves.push_back(cv); 00047 // #ifdef _MSC_VER 00048 // cv = shared_ptr<SplineCurve>(dynamic_cast<SplineCurve*>(crv2.clone())); 00049 // #else 00050 cv = shared_ptr<SplineCurve>(crv2.clone()); 00051 // #endif 00052 curves.push_back(cv); 00053 00054 // Make sure that the curves live on the same knot vector 00055 // double tol = 0.00001; 00056 try { 00057 unifyCurveSplineSpace(curves, num_tol); 00058 } catch (...) { 00059 THROW("Failed unifying spline spaces!"); 00060 } 00061 00062 // Add signed coefficients 00063 vector<double> coefs; 00064 int nmb_coefs = curves[0]->numCoefs(); 00065 int dim = curves[0]->dimension(); 00066 coefs.resize(dim*nmb_coefs); 00067 int ki; 00068 std::vector<double>::iterator c1 = curves[0]->coefs_begin(); 00069 std::vector<double>::iterator c2 = curves[1]->coefs_begin(); 00070 for (ki=0; ki<dim*nmb_coefs; ki++) 00071 coefs[ki] = fac1*c1[ki] + fac2*c2[ki]; 00072 00073 // Create output curve 00074 boost::shared_ptr<SplineCurve> 00075 curvesum(new SplineCurve(nmb_coefs, 00076 curves[0]->order(), 00077 curves[0]->basis().begin(), 00078 &coefs[0], 00079 dim, 00080 false)); 00081 return curvesum; 00082 }
Definition at line 1191 of file 2dpoly_for_s2m.C.
References f().
Referenced by add_triangle(), split_triangle(), and trim_a_triangle().
01196 { 01197 #ifndef DBG 01198 const bool dbg = false; 01199 #endif 01200 01201 // const double eps=1e-14; 01202 const double eps=1e-9; 01203 const double eps_squared=eps*eps; 01204 01205 Vector2D e=c2-c1, f=c3-c1; 01206 const double e_len_squared=e*e, f_len_squared=f*f, g_len_squared=(c2-c3)*(c2-c3); 01207 01208 if (dbg) printf(" degen_tri: edge lengths: %f %f %f\n", sqrt(e*e), sqrt(f*f), sqrt(g_len_squared)); 01209 01210 if ( (e_len_squared<eps_squared) || (f_len_squared<eps_squared) || (g_len_squared<eps_squared) ) 01211 return true; 01212 01213 // Ok, even if all lengths are non-zero, it may still be degenerate. Then the area will be zero. 01214 // 01215 // 100219: Hmm... come to think of it, this test should be the only one needed... But on the other hand, 01216 // if we use the division below, we must still test on the size of the denominator, so we might as 01217 // well keep it as it is. (Or maybe exchange the whole thing for an area-test?!) 01218 01219 const double ef=(e*f)/sqrt(e_len_squared*f_len_squared); 01220 01221 if (dbg) printf(" degen_tri: ef=%e, fabs(ef)-1.0=%e\n", ef, fabs(ef)-1.0); 01222 01223 if (fabs(fabs(ef)-1.0) < eps) 01224 return true; 01225 01226 return false; 01227 }
bool Go::degenerateToCurve | ( | const SplineSurface & | srf, | |
bool | dir_u, | |||
double | tol | |||
) |
Check if a given spline surface degnerates to a curve within a given tolerance.
Definition at line 230 of file GeometryTools.C.
References Go::SplineSurface::coefs_begin(), Go::SplineSurface::dimension(), distance_squared(), Go::SplineSurface::numCoefs_u(), and Go::SplineSurface::numCoefs_v().
00232 { 00233 // For each row of coefficients in the appropriate parameter 00234 // direction, make a rough over estimate of the curve length by 00235 // computing the length of the control polygon. Check if this length 00236 // exceeds the given tolerance. 00237 int nmb1 = (dir_u) ? srf.numCoefs_u() : srf.numCoefs_v(); 00238 int nmb2 = (dir_u) ? srf.numCoefs_v() : srf.numCoefs_u(); 00239 int dim = srf.dimension(); 00240 vector<double>::const_iterator coefs = srf.coefs_begin(); 00241 int ki, kj; 00242 int kr1 = (dir_u) ? dim : nmb2*dim; 00243 int kr2 = (dir_u) ? nmb1*dim : dim; 00244 for (kj=0; kj<nmb2; kj++) 00245 { 00246 vector<double>::const_iterator c1 = coefs + kr2; 00247 double tlen = 0.0; 00248 for (ki=1; ki<nmb1; ki++, c1+=kr1) 00249 { 00250 double d1 = distance_squared(&c1[0], &c1[0]+dim, &c1[0]+dim); 00251 tlen += d1; 00252 } 00253 if (tlen > tol) 00254 break; 00255 } 00256 00257 return (kj < nmb2) ? false : true; 00258 }
T Go::determinantOf | ( | const Array< T, 3 > * | a | ) | [inline] |
Calculates the determinant of a 3 x 3 matrix, represented in memory as a sequence of 3 Array s of length 3.
Same function also exists for 2 x 2 matrices.
T Go::determinantOf | ( | const Array< T, 2 > * | a | ) | [inline] |
Calculates the determinant of a 2 x 2 matrix, represented in memory as a sequence of 2 Array s of length 2.
Same function also exists for 3 x 3 matrices.
Definition at line 30 of file Volumes.h.
Referenced by simplex_volume().
go_iterator_traits<ForwardIterator>::value_type Go::distance_squared | ( | ForwardIterator | first1, | |
ForwardIterator | last1, | |||
ForwardIterator | first2 | |||
) | [inline] |
distance_squared
Definition at line 136 of file Utils.h.
Referenced by closest_in_array(), and degenerateToCurve().
00139 { 00140 typename go_iterator_traits<ForwardIterator>::value_type sum = 0; 00141 for (; first1 != last1; ++first1, ++first2) 00142 sum += (*first1 - *first2)*(*first1 - *first2); 00143 return sum; 00144 }
InputStream& Go::eatwhite | ( | InputStream & | is | ) | [inline] |
void Go::estimateIsoCurveLength | ( | const SplineSurface & | srf, | |
bool | dir_u, | |||
double | par, | |||
double & | length | |||
) |
estimate the length of an iso-curve on the surface
srf | the surface containing the iso-curve | |
dir_u | 'true' if the iso-curve is along the first parameter (second parameter fixed), 'false' if it is the first parameter that is fixed. | |
par | parameter value for the fixed parameter | |
length | returns the estimated length of the iso-curve |
Definition at line 204 of file GeometryTools.C.
References Go::Point::dist(), Go::SplineSurface::endparam_u(), Go::SplineSurface::endparam_v(), Go::SplineSurface::startparam_u(), and Go::SplineSurface::startparam_v().
00207 { 00208 int nptsample = 5; 00209 length = 0; 00210 int ki; 00211 double sfpar[2]; 00212 double ta = (dir_u) ? srf.startparam_u() : srf.startparam_v(); 00213 double tb = (dir_u) ? srf.endparam_u() : srf.endparam_v(); 00214 double tint = (tb - ta)/(double)(nptsample-1); 00215 int idxc = (dir_u) ? 1 : 0; // Index of constant parameter, i.e. par 00216 int idxv = 1 - idxc; 00217 sfpar[idxc] = par; 00218 sfpar[idxv] = ta; 00219 Point pt1, pt2; 00220 pt1 = srf.ParamSurface::point(sfpar[0],sfpar[1]); 00221 for (ki=1, sfpar[idxv]+=tint; ki<nptsample; ki++, sfpar[idxv]+=tint) 00222 { 00223 pt2 = srf.ParamSurface::point(sfpar[0],sfpar[1]); 00224 length += pt1.dist(pt2); 00225 pt1 = pt2; 00226 } 00227 }
void Go::estimateSurfaceSize | ( | const ParamSurface & | srf, | |
double & | length_u, | |||
double & | length_v, | |||
double * | area = NULL | |||
) |
Rough estimate of the size of a parametric surface.
srf | the surface we want to estimate the size of | |
length_u | the estimated average length of the surface, moving along the first parameter | |
length_v | the estimated average length of the surface, moving along the second parameter |
Definition at line 144 of file GeometryTools.C.
References Go::ParamSurface::containingDomain(), Go::Point::dist(), Go::ParamSurface::point(), Go::RectDomain::umax(), Go::RectDomain::umin(), Go::RectDomain::vmax(), and Go::RectDomain::vmin().
Referenced by evaluateMinCurvatureRadius(), and Go::TesselatorUtils::getResolution().
00147 { 00148 const int ncvsample = 3; 00149 const int nptsample = 5; 00150 length_u = length_v = 0.0; 00151 00152 int ki, kj; 00153 double umin, vmin, umax, vmax; 00154 if (area) 00155 { 00156 umin = area[0]; 00157 umax = area[1]; 00158 vmin = area[2]; 00159 vmax = area[3]; 00160 } 00161 else 00162 { 00163 RectDomain domain = srf.containingDomain(); 00164 umin = domain.umin(); 00165 vmin = domain.vmin(); 00166 umax = domain.umax(); 00167 vmax = domain.vmax(); 00168 } 00169 double uint = (umax - umin)/(double)(ncvsample-1); 00170 double vint = (vmax - vmin)/(double)(nptsample-1); 00171 00172 double par_u, par_v; 00173 Point pt1, pt2; 00174 for (ki=0, par_u=umin; ki<ncvsample; ki++, par_u+=uint) 00175 { 00176 par_v = vmin; 00177 pt1 = srf.point(par_u, par_v); 00178 for (kj=1; kj<=nptsample; kj++, par_v+=vint) 00179 { 00180 pt2 = srf.point(par_u, par_v); 00181 length_v += pt1.dist(pt2); 00182 pt1 = pt2; 00183 } 00184 } 00185 length_v /= (double)ncvsample; 00186 00187 uint = (umax - umin)/(double)(nptsample-1); 00188 vint = (vmax - vmin)/(double)(ncvsample-1); 00189 for (ki=0, par_v=vmin; ki<ncvsample; ki++, par_v+=vint) 00190 { 00191 par_u = umin; 00192 pt1 = srf.point(par_u, par_v); 00193 for (kj=1; kj<=nptsample; kj++, par_u+=uint) 00194 { 00195 pt2 = srf.point(par_u, par_v); 00196 length_u += pt1.dist(pt2); 00197 pt1 = pt2; 00198 } 00199 } 00200 length_u /= (double)ncvsample; 00201 }
void Go::evaluateMinCurvatureRadius | ( | const ParamSurface & | sf, | |
double | star_u, | |||
double | end_u, | |||
double | start_v, | |||
double | end_v, | |||
double | tolerance, | |||
std::vector< double > & | param_u, | |||
std::vector< double > & | param_v, | |||
std::vector< std::vector< double > > & | curvs, | |||
double & | mincurv, | |||
double & | minpos_u, | |||
double & | minpos_v, | |||
bool | initialize | |||
) |
Definition at line 348 of file CurvatureAnalysis.C.
References area(), estimateSurfaceSize(), Go::ParamSurface::inDomain(), Go::ParamSurface::isIsoTrimmed(), MAXDOUBLE, and principalCurvatures().
Referenced by minimalCurvatureRadius().
00358 { 00359 int minCells = 3; 00360 int maxCells = 20; 00361 00362 double area[4]; 00363 area[0] = start_u; 00364 area[1] = end_u; 00365 area[2] = start_v; 00366 area[3] = end_v; 00367 00368 double len_u, len_v; 00369 estimateSurfaceSize(sf, len_u, len_v, area); 00370 00371 double huge_rad = MAXDOUBLE; 00372 double tol2 = 10.0*tolerance; 00373 int pts_u = int (len_u / tol2) + 1; 00374 int pts_v = int (len_v / tol2) + 1; 00375 00376 double iso_trim_tol = 0.0001*std::min(end_u - start_u, end_v - start_v); 00377 iso_trim_tol = std::max(iso_trim_tol, 1.0e-7); 00378 00379 bool iso_trimmed = sf.isIsoTrimmed(iso_trim_tol); 00380 00381 pts_u = min(maxCells, max(minCells, pts_u)); 00382 pts_v = min(maxCells, max(minCells, pts_v)); 00383 00384 param_u.resize(pts_u); 00385 param_v.resize(pts_v); 00386 curvs.resize(pts_u); 00387 00388 double step_u = (end_u - start_u)/double(pts_u-1); 00389 double step_v = (end_v - start_v)/double(pts_v-1); 00390 00391 double pos_u = start_u; 00392 for (int i = 0; i < pts_u; pos_u += step_u, ++i) 00393 { 00394 curvs[i].resize(pts_v); 00395 param_u[i] = pos_u; 00396 00397 double pos_v = start_v; 00398 for (int j = 0; j < pts_v; pos_v += step_v, ++j) 00399 { 00400 if (i==0) param_v[j] = pos_v; 00401 double curveRad; 00402 if (iso_trimmed || sf.inDomain(pos_u, pos_v)) 00403 { 00404 // double gauss_curv, mean_curv; 00405 // curvatures(sf, pos_u, pos_v, gauss_curv, mean_curv); 00406 // if (gauss_curv < 0.0) gauss_curv = -gauss_curv; 00407 // if (gauss_curv < 1e-12) gauss_curv = 1e-12; 00408 // curveRad = 1.0 / gauss_curv; 00409 00410 // Evaluate principal curvatures 00411 Point d1, d2; 00412 double k1, k2; 00413 principalCurvatures(sf, pos_u, pos_v, k1, d1, k2, d2); 00414 double kmax = std::max(fabs(k1), fabs(k2)); 00415 curveRad = (kmax > 1.0e-12) ? 1.0 / kmax : MAXDOUBLE; 00416 } 00417 else 00418 curveRad = huge_rad; 00419 00420 curvs[i][j] = curveRad; 00421 if ( (i==0 && j==0 && initialize) || curveRad < mincurv) 00422 { 00423 mincurv = curveRad; 00424 minpos_u = pos_u; 00425 minpos_v = pos_v; 00426 } 00427 } 00428 00429 } 00430 00431 }
int Go::extremalPtSurfSurf | ( | ParamSurface * | psurf1, | |
ParamSurface * | psurf2, | |||
int | constraints[2], | |||
double | constraints_par[2], | |||
double | limit[], | |||
double | enext[], | |||
double | gpos[], | |||
double | angle_tol | |||
) |
Finds one point in each surface where the two normals are parallel to each other and to the difference vector between the two points.
The edge info makes it possible to constrain the search to an ISO-curve in one of or both surfaces. Ported from the sisl-function shsing_ext
.
METHOD : - Start with a guess value (u,v) in domain of surface 1 (S(u,v)) (a) - Find domain value (r,t) of closest point (to S(u,v) in surface 2 (Q(r,t)) - If vf1(u,v) = <Su,Normal(Q> and vf2(u,v)= <Sv,Normal(Q> is small enough stop (<,> means scalar prod.) - Find du and dv by taylorizing vf1 and vf2. This include finding the derivatives of the closest point function (r(u,v),t(u,v)) with respect to u and v. (called h(u,v) in article, see comments in shsing_s9dir) - u:= u+du v:= v+dv, goto (a) REFERENCES : Solutions of tangential surface and curve intersections. R P Markot and R L Magedson Computer-Aided Design; vol. 21, no 7 sept. 1989, page 421-429
psurf1 | Pointer to the first surface. | |
psurf2 | Pointer to the second surface | |
constraints | Constraints flag.
|
------------------ or ----------------
constraints
[0] Constraint 1. surface constraints
[1] Constraint 2. surface -1
No constraints. 0
Constant in 1. par direction 1
Constant in 2. par directionconstraints_par | Constraints parameters.
| |
limit | - Parameter borders of both surfaces.
| |
enext | Parameter start value for iteration(4 values). | |
angle_tol | The angular tolerance for success. | |
gpos | Parameter values of the found singularity(4 values). |
Definition at line 49 of file extremalPtSurfSurf.C.
References Go::Point::angle_smallest(), Go::ParamSurface::closestPoint(), DEBUG_ERROR_IF, Go::GeomObject::dimension(), insideParamDomain(), nextStep(), Go::ParamSurface::normal(), Go::Point::normalize(), Go::ParamSurface::point(), and THROW.
00056 : To find one point in each surface where the two normals 00057 * are parallel to each other and to the difference vector 00058 * between the two points. 00059 * The edge info makes it possible to constrain the search 00060 * to an ISO-curve in one of or both surfaces. 00061 * 00062 * INPUT : psurf1 - Pointer to first surface 00063 * psurf2 - Pointer to second surface 00064 * constraints[0]- Constraint 1. surface 00065 * constraints[1]- Constraint 2. surface 00066 * = -1 No constraints 00067 * = 0 Constant in 1. par direction 00068 * = 1 constant in 2. par direction 00069 * 00070 * Example constrains == 0 00071 * 00072 * ----------------- 00073 * ! | ! 00074 * ! | ! 00075 * ! | ! 00076 * ! | ! 00077 * ! | ! 00078 * ! | ! 00079 * ----------------- 00080 * ^ 00081 * | 00082 * constraints_par 00083 * constraints_par[0]- Constraints parameter 1. surface 00084 * constraints_par[1]- Constraints parameter 2. surface 00085 * 00086 * limit - Parameter borders of both surfaces. 00087 * limit[0] - limit[1] Parameter interval 1. surface 1. direction. 00088 * limit[2] - limit[3] Parameter interval 1. surface 2. direction. 00089 * limit[4] - limit[5] Parameter interval 2. surface 1. direction. 00090 * limit[6] - limit[7] Parameter interval 2. surface 2. direction. 00091 * enext - Parameter start value for iteration(4 values). 00092 * angle_tol - The angular tolerance for success. 00093 * 00094 * OUTPUT : gpos - Parameter values of the found singularity.(4 values) 00095 * kstat - status messages 00096 * = 1 : Extremum found. 00097 * = 0 : Extremum NOT found. 00098 * 00099 * 00100 * METHOD : - Start with a guess value (u,v) in domain of surface 1 (S(u,v)) 00101 * (a) - Find domain value (r,t) of closest point (to S(u,v) in surface 2 (Q(r,t)) 00102 * - If vf1(u,v) = <Su,Normal(Q> and vf2(u,v)= <Sv,Normal(Q> is small enough stop 00103 * (<,> means scalar prod.) 00104 * - Find du and dv by taylorizing vf1 and vf2. 00105 * This include finding the derivatives of the closest point function (r(u,v),t(u,v)) 00106 * with respect to u and v. (called h(u,v) in article, see comments in nextStep) 00107 * - u:= u+du v:= v+dv, goto (a) 00108 * 00109 * 00110 * REFERENCES : Solutions of tangential surface and curve intersections. 00111 * R P Markot and R L Magedson 00112 * Computer-Aided Design; vol. 21, no 7 sept. 1989, page 421-429 00113 * 00114 * 00115 ********************************************************************* 00116 */ 00117 { 00118 int kstat = 0; /* Local status variable. */ 00119 int ki; /* Loop control */ 00120 int kp; /* Loop control */ 00121 const int kder=2; /* Order of derivatives to be calulated */ 00122 const int kdim=3; /* Dimension of space the surface lies in */ 00123 int knbit; /* Number of iterations */ 00124 double tdelta[4]; /* Length of parameter intervals. */ 00125 double tdist; /* The current norm of the cross product */ 00126 /* between the two normals */ 00127 double tprev; /* The current norm of the cross product ? */ 00128 /* between the two normals */ 00129 double td[2],t1[2],tdn[2];/* Distances between old and new parameter */ 00130 /* value in the two parameter directions. */ 00131 std::vector<Point> sval1(7,Point(kdim)); /* Value ,first and second */ 00132 /* derivative of first surface */ 00133 Point& snorm1=sval1[6]; /* Normal vector of firstrface */ 00134 std::vector<Point> sval2(7,Point(kdim)); /* Value ,first and second */ 00135 /* derivative of second surface */ 00136 Point& snorm2=sval2[6]; /* Normal vector of second surface */ 00137 double snext[4]; /* Parameter values */ 00138 double start[2]; /* Parameters limit of second surface, used in */ 00139 /* call to closest point */ 00140 double end[2]; /* Parameters limit of second surface, used in */ 00141 /* call to closest point */ 00142 double guess[2]; /* Start point for closest point iteration */ 00143 Point& ppoint=sval1[0]; /* Contains the current position in first */ 00144 /* surface used in closest point iteration */ 00145 double min_tol = (double)10000.0*REL_COMP_RES; 00146 int max_iter=20; /* Maximal number of iteration allowed */ 00147 double limit_corr[8]; /* Copy of limit with edge constraints */ 00148 double clo_dist; /* Distance between point and closest point */ 00149 Point clo_pt(3); /* Closest point */ 00150 /* --------------------------------------------------------------------- */ 00151 00152 // Test input. 00153 DEBUG_ERROR_IF(kdim != psurf1->dimension(), "Dimension mismatch."); 00154 DEBUG_ERROR_IF(kdim != psurf2->dimension(), "Dimension mismatch."); 00155 00156 // Fetch referance numbers from the serach intervals for the surfaces. 00157 tdelta[0] = limit[1] - limit[0]; 00158 tdelta[1] = limit[3] - limit[2]; 00159 tdelta[2] = limit[5] - limit[4]; 00160 tdelta[3] = limit[7] - limit[6]; 00161 00162 // Set limit values, used in closest point iteration 00163 start[0] = limit[4]; 00164 start[1] = limit[6]; 00165 end[0] = limit[5]; 00166 end[1] = limit[7]; 00167 00168 // Take into account edge constraints 00169 for (int i=0;i<8;i++) 00170 limit_corr[i]=limit[i]; 00171 00172 for (ki=0,kp=0;ki<2;ki++,kp+=4) { 00173 switch (constraints[ki]) 00174 { 00175 case -1: 00176 break; 00177 case 0: 00178 limit_corr[kp] = limit_corr[kp+1] = constraints_par[ki]; 00179 break; 00180 case 1: 00181 limit_corr[kp+2] = limit_corr[kp+3] = constraints_par[ki]; 00182 break; 00183 default: 00184 THROW("Wrong constraint: " << constraints[ki]); 00185 00186 break; 00187 } 00188 } 00189 00190 Vector2D corner1(limit_corr[4],limit_corr[6]); 00191 Vector2D corner2(limit_corr[5],limit_corr[7]); 00192 RectDomain rect_dom2(corner1,corner2); 00193 00194 // Collapsed ? 00195 for (ki=0;ki<4;ki++) 00196 tdelta[ki] = max (tdelta[ki], min_tol); 00197 00198 // Initiate output variables. 00199 for (ki=0;ki<4;ki++) 00200 gpos[ki] = enext[ki]; 00201 00202 for (ki=0;ki<4;ki++) { 00203 // Snap to the limit box 00204 gpos[ki] = max(gpos[ki], limit_corr[2*ki]); 00205 gpos[ki] = min(gpos[ki], limit_corr[2*ki+1]); 00206 } 00207 00208 // Evaluate 0.-2. derivatives of first surface 00209 psurf1->point(sval1,gpos[0],gpos[1],kder); 00210 psurf1->normal(snorm1,gpos[0], gpos[1]); 00211 00212 // Get closest point in second surface. 00213 guess[0] = gpos[2]; 00214 guess[1] = gpos[3]; 00215 psurf2->closestPoint(ppoint,gpos[2],gpos[3],clo_pt,clo_dist, 00216 REL_PAR_RES, &rect_dom2,guess); 00217 // REL_COMP_RES, &rect_dom2,guess); @bsp 00218 00219 00220 // Evaluate 0.-2. derivatives of second surface 00221 psurf2->point(sval2,gpos[2],gpos[3],kder); 00222 psurf2->normal(snorm2,gpos[2], gpos[3]); 00223 00224 // Get length of normal cross product 00225 //s6crss(snorm1,snorm2,temp); 00226 //tprev = s6length(temp,kdim,&kstat); 00227 // temp = SIX_norm(snorm1); 00228 // temp = SIX_norm(snorm2); 00229 00230 // Angle between the normal vectors 00231 snorm1.normalize(); 00232 snorm2.normalize(); 00233 tprev = snorm1.angle_smallest(snorm2); 00234 00235 // Compute the Newton stepdistance vector in first surface. 00236 nextStep(td,sval1,sval2); 00237 00238 // Adjust if we are not inside the parameter intervall. 00239 for (ki=0;ki<2;ki++) 00240 t1[ki] = td[ki]; 00241 insideParamDomain(t1,gpos,limit_corr); 00242 00243 00244 // Iteratation loop. 00245 00246 for (knbit = 0; knbit < max_iter; knbit++) { 00247 00248 snext[0] = gpos[0] + t1[0]; 00249 snext[1] = gpos[1] + t1[1]; 00250 00251 // Evaluate 0.-2. derivatives of first surface 00252 psurf1->point(sval1,snext[0],snext[1],kder); 00253 psurf1->normal(snorm1,snext[0], snext[1]); 00254 sval1[6]=snorm1; 00255 00256 // Get closest point in second surface. 00257 guess[0] = gpos[2]; 00258 guess[1] = gpos[3]; 00259 psurf2->closestPoint(ppoint,snext[2],snext[3],clo_pt,clo_dist, 00260 REL_PAR_RES, &rect_dom2,guess); 00261 // REL_COMP_RES, &rect_dom2,guess); @bsp 00262 00263 // Since the last 2 values in snext has been changed in closestPoint: 00264 for (ki=2;ki<4;ki++) { 00265 // Snap to the limit box 00266 snext[ki] = max(snext[ki], limit_corr[2*ki]); 00267 snext[ki] = min(snext[ki], limit_corr[2*ki+1]); 00268 } 00269 00270 // Evaluate 0.-2. derivatives of second surface 00271 psurf2->point(sval2,snext[2],snext[3],kder); 00272 psurf2->normal(snorm2,snext[2], snext[3]); 00273 sval2[6]=snorm2; 00274 00275 00276 // Get length of normal cross product 00277 // s6crss(snorm1,snorm2,temp); 00278 // tdist = s6length(temp,kdim,&kstat); 00279 //temp = SIX_norm(snorm1); 00280 //temp = SIX_norm(snorm2); 00281 //tdist = s6ang(snorm1,snorm2,3); 00282 snorm1.normalize(); 00283 snorm2.normalize(); 00284 tdist = snorm1.angle_smallest(snorm2); 00285 00286 // Compute the Newton stepdistance vector. 00287 nextStep(tdn,sval1,sval2); 00288 00289 if (tdist <= tprev) { 00290 00291 // Ordinary converging. 00292 00293 for (ki=0;ki<4;ki++) 00294 gpos[ki] = snext[ki]; 00295 00296 td[0] = t1[0] = tdn[0]; 00297 td[1] = t1[1] = tdn[1]; 00298 00299 00300 // Adjust if we are not inside the parameter interval. 00301 insideParamDomain(t1,gpos,limit_corr); 00302 00303 tprev = tdist; 00304 00305 if ((fabs(t1[0]/tdelta[0]) <= REL_COMP_RES) && 00306 (fabs(t1[1]/tdelta[1]) <= REL_COMP_RES)) { 00307 00308 gpos[0] += t1[0]; 00309 gpos[1] += t1[1]; 00310 // Evaluate 0.-2. derivatives of first surface 00311 psurf1->point(sval1,gpos[0],gpos[1],kder); 00312 psurf1->normal(snorm1,gpos[0], gpos[1]); 00313 sval1[6]=snorm1; 00314 00315 00316 // Get closest point in second surface. 00317 guess[0] = gpos[2]; 00318 guess[1] = gpos[3]; 00319 psurf2->closestPoint(ppoint,gpos[2],gpos[3],clo_pt,clo_dist, 00320 REL_PAR_RES, &rect_dom2,guess); 00321 // REL_COMP_RES, &rect_dom2,guess); 00322 break; 00323 } 00324 } 00325 00326 else { 00327 00328 // Not converging, half step length and try again. 00329 00330 for (ki=0;ki<2;ki++) 00331 t1[ki] *= 0.5; 00332 } 00333 } 00334 00335 // Iteration stopped, test if point is extremum 00336 // Unsure about what is right here , angle between normals and difference vector ?? 00337 if (tprev <= angle_tol) 00338 kstat = 1; 00339 else 00340 kstat = 0; 00341 00342 00343 /* 00344 // Test if the iteration is close to a knot 00345 if (fabs(gpos[0] - psurf1->et1[kleftt])/tdelta[0] < min_tol) 00346 gpos[0] = psurf1->et1[kleftt]; 00347 else if (fabs(gpos[0] - psurf1->et1[kleftt+1])/tdelta[0] < min_tol) 00348 gpos[0] = psurf1->et1[kleftt+1]; 00349 00350 if (fabs(gpos[1] - psurf1->et2[klefts])/tdelta[1] < min_tol) 00351 gpos[1] = psurf1->et2[klefts]; 00352 else if (fabs(gpos[1] - psurf1->et2[klefts+1])/tdelta[1] < min_tol) 00353 gpos[1] = psurf1->et2[klefts+1]; 00354 00355 if (fabs(gpos[2] - psurf2->et1[kleftu])/tdelta[2] < min_tol) 00356 gpos[2] = psurf2->et1[kleftu]; 00357 else if (fabs(gpos[2] - psurf2->et1[kleftu+1])/tdelta[2] < min_tol) 00358 gpos[2] = psurf2->et1[kleftu+1]; 00359 00360 if (fabs(gpos[3] - psurf2->et2[kleftv])/tdelta[3] < min_tol) 00361 gpos[3] = psurf2->et2[kleftv]; 00362 else if (fabs(gpos[3] - psurf2->et2[kleftv+1])/tdelta[3] < min_tol) 00363 gpos[3] = psurf2->et2[kleftv+1]; 00364 */ 00365 00366 // Iteration completed. 00367 return kstat; 00368 }
double Go::factorial | ( | int | n | ) | [inline] |
void Go::findDominant | ( | const SplineSurface & | surface, | |
Vector3D & | dominant_u, | |||
Vector3D & | dominant_v | |||
) |
Finds the "dominant u- and v-vectors" for a surface, defined to be the sum of all the vectors pointing from one control point to the next in the u- and v-directions.
surface | the surface we want to analyze | |
dominant_u | returns the dominant u-vector for the surface | |
dominant_v | returns the dominant v-vector for the surface |
Definition at line 26 of file GGUdominant.C.
References Go::SplineSurface::coefs_begin(), Go::SplineSurface::numCoefs_u(), and Go::SplineSurface::numCoefs_v().
00029 { 00030 int nu = surface.numCoefs_u(); 00031 int nv = surface.numCoefs_v(); 00032 vector<double>::const_iterator start = surface.coefs_begin(); 00033 Vector3D temp; 00034 // Dominant in u-direction 00035 dominant_u = Vector3D(0.0, 0.0, 0.0); 00036 for (int j = 0; j < nv; ++j) { 00037 for (int dd = 0; dd < 3; ++dd) { 00038 temp[dd] = *(start + 3*(nu*j + (nu-1)) + dd) 00039 - *(start + 3*(nu*j) + dd); 00040 } 00041 dominant_u += temp; 00042 } 00043 // Dominant in v-direction 00044 dominant_v = Vector3D(0.0, 0.0, 0.0); 00045 for (int i = 0; i < nu; ++i) { 00046 for (int dd = 0; dd < 3; ++dd) { 00047 temp[dd] = *(start + 3*(nu*(nv-1) + i) + dd) 00048 - *(start + 3*i + dd); 00049 } 00050 dominant_v += temp; 00051 } 00052 00053 return; 00054 }
void Go::forwardSubstitution | ( | const SquareMatrix & | L, | |
std::vector< double > * | x, | |||
int | num_unknowns | |||
) | [inline] |
Using forward substitution to calculate x on the system Lx = b, where L is a lower triangular matrix with unitary diagonal.
L | The lower triangular matrix. The actually used class must support the operation [][] and return 'double'. | |
x | At function invocation, x should point to a vector of doubles, containing the vector 'b'. On successful completion of the function, this vector will contain the solution for x. | |
num_unknowns | The system size (number of unknowns). |
Definition at line 138 of file LUDecomp_implementation.h.
void Go::forwardSubstitution | ( | const SquareMatrix & | L, | |
T * | x, | |||
int | num_unknowns | |||
) | [inline] |
Using forward substitution to calculate x on the system Lx = b, where L is a lower triangular matrix with unitary diagonal.
L | The lower triangular matrix. The actually used class must support the operation [][] and return 'double'. | |
x | At function invocation, x should point to an array of T, containing the vector 'b'. On successful completion of the function, this array will contain the solution for x. | |
num_unknowns | The system size (number of unknowns). |
Definition at line 126 of file LUDecomp_implementation.h.
Referenced by Go::SmoothCurve::equationSolve(), and LUsolveSystem().
double Go::gaussian_quadrature | ( | Functor & | f, | |
double | a, | |||
double | b | |||
) | [inline] |
Routine to calculate the integral of the functor f from a to b using Gaussian quadrature with W=1 and N=10.
Definition at line 85 of file Integration.h.
References f().
Referenced by gaussian_quadrature2D().
00086 { 00087 static double x[] = { 0.1488743389, 00088 0.4333953941, 00089 0.6794095682, 00090 0.8650633666, 00091 0.9739065285 }; 00092 static double weight[] = { 0.2955242247, 00093 0.2692667193, 00094 0.2190863625, 00095 0.1494513491, 00096 0.0666713443 }; 00097 00098 double midpt = 0.5 * (b + a); 00099 double half_length = 0.5 * (b - a); 00100 double scaled_result = double(0); 00101 double step = double(0); 00102 for (int i = 0; i < 5; ++i) { 00103 step = half_length * x[i]; 00104 scaled_result += weight[i] * (f(midpt + step) + f(midpt - step)); 00105 } 00106 // rescale result to correspond to actual interval size 00107 return scaled_result * half_length; 00108 }
double Go::gaussian_quadrature2D | ( | Functor2D & | f, | |
double | ax, | |||
double | bx, | |||
double | ay, | |||
double | by | |||
) | [inline] |
Routine to integrate the two-dimensional functor f over the rectangle defined by ax, bx, ay and by.
Uses Gaussian quadrature.
Definition at line 148 of file Integration.h.
References gaussian_quadrature().
00150 { 00151 Integrate2ndFunctor<Functor2D> fu(f, ay, by); 00152 return gaussian_quadrature(fu, ax, bx); 00153 }
void Go::GaussQuadInner | ( | const BsplineBasis & | basis, | |
int | ider, | |||
double | lim1, | |||
double | lim2, | |||
double *** | integral | |||
) |
Compute all definite integrals of inner products of derivatives of B-splines up to a given order where the differentiation is of the same order for both B-splines.
The interval of integration are equal to the parameter intervals of the surface in the current par. dir.
basis | B-spline basis. | |
ider | Number of derivatives to compute. | |
lim1 | Start of parameter interval. | |
lim2 | End of parameter interval. | |
integral | Computed integrals. |
Definition at line 95 of file Integrate.C.
References Go::BsplineBasis::begin(), Go::BsplineBasis::computeBasisValues(), Go::BsplineBasis::lastKnotInterval(), Go::BsplineBasis::numCoefs(), and Go::BsplineBasis::order().
Referenced by Go::SmoothCurve::setOptim(), Go::SmoothSurfSet::setOptimize(), Go::SmoothCurveSet::setOptimize(), and Go::SmoothSurf::setOptimizeNonrational().
00103 : Compute all definite integrals of inner products of 00104 // derivatives of B-splines up to a given order where the 00105 // differentiation is of the same order for both B-splines. 00106 // The interval of integration are equal to the parameter 00107 // intervals of the surface in the current par. dir. 00108 // 00109 // Calls : BsplineBasis::computeBasisValues - 00110 // Compute derivatives of B-splines. 00111 // 00112 // Written by : Vibeke Skytt, SINTEF SI, 09.93. (04.02) 00113 //-------------------------------------------------------------------------- 00114 { 00115 int ki, kp, k1, k2, kl, kr; 00116 int kder; 00117 int kind; 00118 int kleft; 00119 double ta, tb; 00120 double tval; 00121 double tpar; 00122 int ik = basis.order(); 00123 int in = basis.numCoefs(); 00124 vector<double>::const_iterator et = basis.begin(); 00125 vector<double> sbder(ik*(ider+1), 0.0); 00126 00127 /* Traverse all knot intervals inside the limits of integration, computing 00128 the integral of the inner product of two B-splines defined in this 00129 interval. */ 00130 00131 kind = (ik-1 < 5) ? ik-1 : 5; 00132 for (kl=ik-1; kl<in; kl++) 00133 { 00134 ta = et[kl]; 00135 tb = et[kl+1]; 00136 if (tb <= lim1 || ta >= lim2) continue; 00137 00138 for (kr=0; kr<indices[kind]; kr++) 00139 { 00140 /* Compute parameter value in which to evaluate B-splines. */ 00141 00142 tpar = 0.5*(sample[kind][kr]*(tb-ta) + tb + ta); 00143 00144 /* Evaluate B-splines and derivatives of B-splines. */ 00145 00146 basis.computeBasisValues(tpar, &sbder[0], ider); 00147 kleft = basis.lastKnotInterval(); 00148 00149 for (ki=kleft-ik+1, k1=0; ki<=kleft; ki++, k1++) 00150 for (kp=ki, k2=k1; kp<=kleft; kp++, k2++) 00151 for (kder=0; kder<=ider; kder++) 00152 { 00153 tval = (double)0.5*(tb-ta)*weight[kind][kr]* 00154 sbder[k1*(ider+1)+kder]*sbder[k2*(ider+1)+kder]; 00155 00156 integral[kder][ki][kp] += tval; 00157 if (kp > ki) integral[kder][kp][ki] += tval; 00158 } 00159 } 00160 } 00161 }
void Go::GaussQuadInner2 | ( | const BsplineBasis & | basis, | |
int | ider, | |||
double | lim1, | |||
double | lim2, | |||
double ** | integral | |||
) |
Compute all definite integrals of inner products of derivatives of B-splines up to a given order where the differentiation is of the same order for both B-splines.
The interval of integration are equal to the parameter intervals of the surface in the current par. dir.
basis | B-spline basis. | |
ider | Number of derivatives to compute. | |
lim1 | Start of parameter interval. | |
lim2 | End of parameter interval. | |
integral | Computed integrals. |
Definition at line 241 of file Integrate.C.
References Go::BsplineBasis::begin(), Go::BsplineBasis::computeBasisValues(), Go::BsplineBasis::lastKnotInterval(), Go::BsplineBasis::numCoefs(), and Go::BsplineBasis::order().
00249 : Compute all definite integrals of inner products of 00250 // derivatives of B-splines of a given order where the 00251 // differentiation is of the same order for both B-splines. 00252 // The interval of integration are equal to the parameter 00253 // intervals of the surface in the current par. dir. 00254 // 00255 // Calls : BsplineBasis::computeBasisValues - 00256 // Compute derivatives of B-splines. 00257 // 00258 // Written by : Vibeke Skytt, SINTEF SI, 08.96. (04.02) 00259 //-------------------------------------------------------------------------- 00260 { 00261 int ki, kp, k1, k2, kl, kr; 00262 int kind; 00263 double ta, tb; 00264 double tval; 00265 double tpar; 00266 int kleft; 00267 int ik = basis.order(); 00268 int in = basis.numCoefs(); 00269 vector<double>::const_iterator et = basis.begin(); 00270 vector<double> sbder(ik*(ider+1), 0.0); 00271 00272 /* Traverse all knot intervals inside the limits of integration, computing 00273 the integral of the inner product of two B-splines defined in this 00274 interval. */ 00275 00276 kind = (ik-1 < 5) ? ik-1 : 5; 00277 for (kl=ik-1; kl<in; kl++) 00278 { 00279 ta = et[kl]; 00280 tb = et[kl+1]; 00281 if (tb <= lim1 || ta >= lim2) continue; 00282 00283 for (kr=0; kr<indices[kind]; kr++) 00284 { 00285 /* Compute parameter value in which to evaluate B-splines. */ 00286 00287 tpar = 0.5*(sample[kind][kr]*(tb-ta) + tb + ta); 00288 00289 /* Evaluate B-splines and derivatives of B-splines. */ 00290 00291 basis.computeBasisValues(tpar, &sbder[0], ider); 00292 kleft = basis.lastKnotInterval(); 00293 00294 for (ki=kleft-ik+1, k1=0; ki<=kleft; ki++, k1++) 00295 for (kp=ki, k2=k1; kp<=kleft; kp++, k2++) 00296 { 00297 tval = (double)0.5*(tb-ta)*weight[kind][kr]* 00298 sbder[k1*(ider+1)+ider]*sbder[k2*(ider+1)+ider]; 00299 00300 integral[ki][kp] += tval; 00301 if (kp > ki) integral[kp][ki] += tval; 00302 } 00303 } 00304 } 00305 }
void Go::GaussQuadInnerFlat | ( | const BsplineBasis & | basis, | |
int | derivs, | |||
int | start_der, | |||
int | gap, | |||
double | lim1, | |||
double | lim2, | |||
std::vector< double > & | integral | |||
) |
Compute all definite integrals of inner products of derivatives of B-splines up to a given order where the gap between the order of differentiation on the first and second B-spline is constant.
The interval of integration are equal to the parameter intervals of the surface in the current par. dir.
basis | B-spline basis. | |
derivs | Number of derivatives to compute. | |
gap | Difference between derivation order. | |
start_der | First derivative to compute. | |
lim1 | Start of parameter interval. | |
lim2 | End of parameter interval. | |
integral | Computed integrals. |
Definition at line 167 of file Integrate.C.
References Go::BsplineBasis::begin(), Go::BsplineBasis::computeBasisValues(), Go::BsplineBasis::lastKnotInterval(), Go::BsplineBasis::numCoefs(), and Go::BsplineBasis::order().
00177 : Compute all definite integrals of inner products of 00178 // derivatives of B-splines up to a given order where the 00179 // gap between the order of differentiation on the first and 00180 // second B-spline is constant. 00181 // The computation starts at a specified derivation depths, 00182 // assuming the lower derivation order integrals are 00183 // already found. 00184 // The interval of integration are equal to the parameter 00185 // intervals of the surface in the current par. dir. 00186 // 00187 // Calls : BsplineBasis::computeBasisValues - 00188 // Compute derivatives of B-splines. 00189 // 00190 // Written by : Kjell Fredrik Pettersen, SINTEF IKT, 2009-12-16, based on 00191 // GaussQuadInner() 00192 //-------------------------------------------------------------------------- 00193 { 00194 int order = basis.order(); 00195 int n_coefs = basis.numCoefs(); 00196 vector<double>::const_iterator et = basis.begin(); 00197 vector<double> sbder(order*(derivs+gap+1), 0.0); 00198 00199 /* Traverse all knot intervals inside the limits of integration, computing 00200 the integral of the inner product of two B-splines defined in this 00201 interval. */ 00202 00203 int kind = (order-1 < 5) ? order-1 : 5; 00204 for (int k = order - 1; k < n_coefs; ++k) // For every Bezier segment 00205 { 00206 double ta = et[k]; 00207 double tb = et[k + 1]; 00208 if (tb <= lim1 || ta >= lim2) continue; 00209 00210 for (int l = 0; l < indices[kind]; ++l) // For every sample value in segment 00211 { 00212 /* Compute parameter value in which to evaluate B-splines. */ 00213 00214 double tpar = 0.5 * (sample[kind][l]*(tb-ta) + tb + ta); 00215 00216 /* Evaluate B-splines and derivatives of B-splines. */ 00217 00218 basis.computeBasisValues(tpar, &sbder[0], derivs+gap); 00219 int left = basis.lastKnotInterval(); 00220 00221 for (int i = left - order + 1, k1 = 0; i <= left; ++i, ++k1) // For every first B-spline 00222 for (int j = i, k2 = k1; j <= left; ++j, ++k2) // For every second B-spline 00223 for (int der = start_der; der <= derivs; ++der) // For every derivation order 00224 { 00225 double tval = 0.5 * (tb-ta) * weight[kind][l] 00226 * sbder[k1*(derivs+gap+1)+der+gap] * sbder[k2*(derivs+gap+1)+der]; 00227 double tval_oposite = 0.5 * (tb-ta) * weight[kind][l] 00228 * sbder[k1*(derivs+gap+1)+der] * sbder[k2*(derivs+gap+1)+der+gap]; 00229 00230 integral[j-i+order-1 + (2*order-1)*(i + n_coefs*der)] += tval; 00231 if (j > i) 00232 integral[i-j+order-1 + (2*order-1)*(j + n_coefs*der)] += tval_oposite; 00233 } 00234 } 00235 } 00236 }
void Go::GaussQuadInnerRational | ( | const BsplineBasis & | basis, | |
int | ider, | |||
double | lim1, | |||
double | lim2, | |||
shared_ptr< SplineCurve > | bspline_curve, | |||
double *** | integral | |||
) |
Definition at line 309 of file Integrate.C.
References Go::BsplineBasis::begin(), Go::BsplineBasis::knotInterval(), Go::BsplineBasis::numCoefs(), and Go::BsplineBasis::order().
00318 : Compute all definite integrals of inner products of 00319 // derivatives of rational B-splines up to a given order where the 00320 // differentiation is of the same order for both B-splines. 00321 // The interval of integration are equal to the parameter 00322 // intervals of the surface in the current par. dir. 00323 // 00324 // Calls : BsplineBasis::computeBasisValues - 00325 // Compute derivatives of B-splines. 00326 // 00327 // Written by : Kjell Fredrik Pettersen, 2009-11-26, based on 00328 // GaussQuadInnerRational by Vibeke Skytt, SINTEF SI, 09.93. (04.02) 00329 //-------------------------------------------------------------------------- 00330 { 00331 int ki, kp, k1, k2, kl, kr; 00332 int kder; 00333 int kind; 00334 int kleft; 00335 double ta, tb; 00336 double tval; 00337 double tpar; 00338 int ik = basis.order(); 00339 int in = basis.numCoefs(); 00340 vector<double>::const_iterator et = basis.begin(); 00341 vector<double> sbder(ik*(ider+1), 0.0); 00342 00343 vector<double>::iterator bspl_it = bspline_curve->rcoefs_begin(); 00344 vector<Point> pts(ider+1); 00345 for (int i = 0; i <= ider; ++i) 00346 pts[i] = Point(1); 00347 00348 /* Traverse all knot intervals inside the limits of integration, computing 00349 the integral of the inner product of two B-splines defined in this 00350 interval. */ 00351 00352 kind = (ik-1 < 5) ? ik-1 : 5; 00353 for (kl=ik-1; kl<in; kl++) 00354 { 00355 ta = et[kl]; 00356 tb = et[kl+1]; 00357 if (tb <= lim1 || ta >= lim2) continue; 00358 00359 for (kr=0; kr<indices[kind]; kr++) 00360 { 00361 /* Compute parameter value in which to evaluate B-splines. */ 00362 00363 tpar = 0.5*(sample[kind][kr]*(tb-ta) + tb + ta); 00364 00365 /* Evaluate B-splines and derivatives of B-splines. */ 00366 00367 kleft = basis.knotInterval(tpar); 00368 for (ki=kleft-ik+1, k1=0; ki<=kleft; ki++, k1++) 00369 { 00370 bspl_it[ki*2] = 1.0; 00371 bspline_curve->point(pts, tpar, ider); 00372 for (int i = 0; i <= ider; ++i) 00373 sbder[k1*(ider+1)+i] = pts[i][0]; 00374 bspl_it[ki*2] = 0.0; 00375 } 00376 00377 for (ki=kleft-ik+1, k1=0; ki<=kleft; ki++, k1++) 00378 for (kp=ki, k2=k1; kp<=kleft; kp++, k2++) 00379 for (kder=0; kder<=ider; kder++) 00380 { 00381 tval = (double)0.5*(tb-ta)*weight[kind][kr]* 00382 sbder[k1*(ider+1)+kder]*sbder[k2*(ider+1)+kder]; 00383 00384 integral[kder][ki][kp] += tval; 00385 if (kp > ki) integral[kder][kp][ki] += tval; 00386 } 00387 } 00388 } 00389 }
void Go::GaussQuadInnerRational | ( | const BsplineBasis & | basis, | |
int | ider, | |||
double | lim1, | |||
double | lim2, | |||
boost::shared_ptr< SplineCurve > | bspline_curve, | |||
double *** | integral | |||
) |
Compute all definite integrals of inner products of derivatives of rational B-splines up to a given order where the differentiation is of the same order for both B-splines.
The interval of integration are equal to the parameter intervals of the surface in the current par. dir.
basis | B-spline basis. | |
ider | Number of derivatives to compute. | |
lim1 | Start of parameter interval. | |
lim2 | End of parameter interval. | |
bspline_curve | 1-dim rational 0-function defining weights | |
coefs | Wieghts for denominator function | |
integral | Computed integrals. |
Referenced by Go::SmoothCurve::setOptim().
void Go::GaussQuadValues | ( | const BsplineBasis & | basis, | |
std::vector< double > & | parameters, | |||
std::vector< double > & | par_weights | |||
) |
Functions used to compute integrals of inner products of B-splines.
Store parameters and weights used for numerical integration by Gauss quadrature. All parameter values for all Bezier segments are stored in parameters, while the weights within an interval is stored only once in weights. Thus, the lenght of weights gives the number of samples for each Bezier segment.
basis | B-spline basis | |
parameters | Parameter values for all points | |
par_weights | Weight for each parameter |
Definition at line 59 of file Integrate.C.
References Go::BsplineBasis::begin(), Go::BsplineBasis::numCoefs(), and Go::BsplineBasis::order().
Referenced by Go::SmoothSurf::approxOrigRational(), Go::SmoothSurf::setOptimizeRational(), and Go::SmoothSurf::setRationalCnAtSeem().
00065 : Store parameters and weights used for numerical integration 00066 // by Gauss quadrature. All parameter values for all Bezier segments 00067 // are stored in parameters, while the weights within an interval is 00068 // stored only once in weights. Thus, the lenght of weights gives 00069 // the number of samples for each Bezier segment. 00070 //-------------------------------------------------------------------------- 00071 { 00072 int ord = basis.order(); 00073 int ncoef = basis.numCoefs(); 00074 int kind = (ord-1 < 5) ? ord-1 : 5; 00075 00076 int w_size = indices[kind]; 00077 parameters.resize(w_size * (ncoef-ord+1)); 00078 par_weights.resize(w_size); 00079 00080 for (int i = 0; i < w_size; ++i) 00081 par_weights[i] = 0.5 * weight[kind][i]; 00082 00083 vector<double>::const_iterator it = basis.begin(); 00084 for (int i = 0, par_pos = 0; i < ncoef-ord+1; ++i) 00085 { 00086 double int_start = it[i+ord-1]; 00087 double int_end = it[i+ord]; 00088 for (int j = 0; j < w_size; ++j, ++par_pos) 00089 parameters[par_pos] = 0.5 * (sample[kind][j]*(int_end-int_start) + int_end + int_start); 00090 } 00091 }
bool Go::getCoefEnumeration | ( | boost::shared_ptr< SplineSurface > | sf, | |
int | bd, | |||
std::vector< int > & | enumeration | |||
) |
Definition at line 415 of file SurfaceTools.C.
00418 { 00419 if (bd < 0 || bd > 3) 00420 return false; 00421 00422 int kn1 = sf->numCoefs_u(); 00423 int kn2 = sf->numCoefs_v(); 00424 00425 int nmb = (bd == 0 || bd == 1) ? kn2 : kn1; 00426 enumeration.resize(nmb); 00427 int start = (bd == 0 || bd == 2) ? 0 : 00428 ((bd == 1) ? kn1-1 : kn1*(kn2-1)); 00429 int del = (bd == 0 || bd == 1) ? kn1 : 1; 00430 00431 int ki, idx; 00432 for (ki=0, idx=start; ki<nmb; ++ki, idx+=del) 00433 enumeration[ki] = idx; 00434 00435 return true; 00436 }
bool Go::getCorrCoefEnum | ( | shared_ptr< SplineSurface > | sf1, | |
shared_ptr< SplineSurface > | sf2, | |||
int | bd1, | |||
int | bd2, | |||
bool | same_orient, | |||
vector< pair< int, int > > & | enumeration | |||
) |
Definition at line 377 of file SurfaceTools.C.
00382 { 00383 int kn1 = sf1->numCoefs_u(); 00384 int kn2 = sf1->numCoefs_v(); 00385 int kn3 = sf2->numCoefs_u(); 00386 int kn4 = sf2->numCoefs_v(); 00387 00388 int nmb1 = (bd1 == 0 || bd1 == 1) ? kn2 : kn1; 00389 int nmb2 = (bd2 == 0 || bd2 == 1) ? kn4 : kn3; 00390 if (nmb1 != nmb2) 00391 return false; // No correspondence 00392 00393 enumeration.resize(nmb1); 00394 int start1 = (bd1 == 0 || bd1 == 2) ? 0 : 00395 ((bd1 == 1) ? kn1-1 : kn1*(kn2-1)); 00396 int del1 = (bd1 == 0 || bd1 == 1) ? kn1 : 1; 00397 00398 int start2 = (bd2 == 0 || bd2 == 2) ? 0 : 00399 ((bd2 == 1) ? kn3-1 : kn3*(kn4-1)); 00400 int del2 = (bd2 == 0 || bd2 == 1) ? kn3 : 1; 00401 if (!same_orient) 00402 { 00403 start2 += (nmb2-1)*del2; 00404 del2 *= -1; 00405 } 00406 00407 int ki, idx1, idx2; 00408 for (ki=0, idx1=start1, idx2=start2; ki<nmb1; ++ki, idx1+=del1, idx2+=del2) 00409 enumeration[ki] = make_pair(idx1, idx2); 00410 00411 return true; 00412 }
bool Go::getCorrCoefEnum | ( | boost::shared_ptr< SplineSurface > | sf1, | |
boost::shared_ptr< SplineSurface > | sf2, | |||
int | bd1, | |||
int | bd2, | |||
bool | same_orient, | |||
std::vector< std::pair< int, int > > & | enumeration | |||
) |
double Go::getCurrentTime | ( | ) |
Number of seconds since some (probably system-dependent) epoch.
Definition at line 98 of file timeutils.C.
Referenced by Go::CPUclock::CPUclock(), Go::CPUclock::getInterval(), Go::CPUclock::getTime(), and main().
00100 { 00101 #ifdef WIN32 00102 #ifndef _WIN32_WCE 00103 _ftime(&timeb_ptr_); 00104 return timeb2seconds(&timeb_ptr_); 00105 #else 00106 // Might overrun every month... 00107 SYSTEMTIME s; 00108 GetSystemTime(&s); 00109 return 0.001*s.wMilliseconds + s.wSecond + 60.0*s.wMinute 00110 + 3600.0*s.wHour + 3600.0*24.0*s.wDay; 00111 #endif 00112 #else 00113 #ifdef __GNUC__ 00114 timeval t; 00115 gettimeofday(&t,0); 00116 return t.tv_sec + 1e-6*t.tv_usec; 00117 #else 00118 timespec time_spec_; 00119 clock_gettime(CLOCK_REALTIME, &time_spec_); 00120 return timespec2seconds(&time_spec_); 00121 #endif 00122 #endif 00123 }
void Go::getGnJoints | ( | const CurveLoop & | loop, | |
const std::vector< double > & | cont, | |||
std::vector< std::vector< double > > & | gn_joints | |||
) |
Partition a given CurveLoop into segments where each segment is at least G^n continuous (currently supporting up to G2 continuity).
loop | the CurveLoop to analyze | |
cont | the tolerance used for defining continuity. cont[0] is the tolerance used for defining the G^0 continuity, cont[1] is used for checking G^1 continuity, etc. The length of this vector also determines 'n' ('n' is equal to cont.size() - 1). | |
gn_joints | a vector of a vector, reporting the result of the analysis. The outer vector contains one entry per curve in the CurveLoop. This entry contains the parameters for which that curve must be split in order to obtain G^n segments. NB: the start- and end parameters are NOT included here, as opposed to the result obtained from the other getGnJoints() function. The exception to this is when there is an G^n discontinuity at the transition between the curve 'i-1' and curve 'i' in the CurveLoop. To indicate this, the start parameter value for curve 'i' will be included in the corresponding entry in 'gn_joints'. |
Definition at line 541 of file GeometryTools.C.
References ASSERT, getGnJoints(), and Go::CurveLoop::size().
00544 { 00545 int n = cont.size() - 1; 00546 00547 int ki, kj; 00548 vector<vector<double> > poss_disc; 00549 for (ki = 0; ki < loop.size(); ++ki) { 00550 vector<double> gn_joints; 00551 getGnJoints(*(loop[ki]), cont, gn_joints); 00552 poss_disc.push_back(gn_joints); 00553 } 00554 00555 // We then must check cont between consecutive segments. 00556 int pds = poss_disc.size(); 00557 for (ki = 0; ki < pds; ++ki) { 00558 int fi = ki; 00559 int si = (fi + 1)%pds; 00560 vector<Point> from_left = loop[fi]->ParamCurve::point(poss_disc[fi].back(), n, false); 00561 vector<Point> from_right = loop[si]->ParamCurve::point(poss_disc[si].front(), n); 00562 ASSERT(int(from_left.size()) == n+1); 00563 for (kj = 0; kj < n+1; ++kj) { 00564 if (kj != 0) { 00565 from_left[kj].normalize(); 00566 from_right[kj].normalize(); 00567 } 00568 double dist = from_left[kj].dist(from_right[kj]); 00569 if (dist > cont[kj]) 00570 break; 00571 } 00572 poss_disc[fi].erase(poss_disc[fi].end() - 1); 00573 if (kj == n+1) { 00574 poss_disc[si].erase(poss_disc[si].begin()); 00575 } 00576 } 00577 00578 gn_joints = poss_disc; 00579 }
void Go::getGnJoints | ( | const ParamCurve & | curve, | |
const std::vector< double > & | cont, | |||
std::vector< double > & | gn_joints | |||
) |
Partition the given curve into segments where each segment is at least G^n continuous (currently supporting up to G2 continuity).
curve | the curve to analyze | |
cont | the tolerance used for defining continuity. cont[0] is the tolerance used for defining the G^0 continuity, cont[1] is used for checking G^1 continuity, etc. The length of this vector also determines 'n' ('n' is equal to cont.size() - 1). |
gn_joints | returns the parameter values where one segment stops and the next begins. The vector will at least contain two values (the start and end parameter of the curve). |
Definition at line 393 of file GeometryTools.C.
References Go::Point::angle_smallest(), ASSERT, Go::SplineCurve::basis(), Go::BsplineBasis::begin(), Class_CurveOnSurface, Class_SplineCurve, Go::SplineCurve::endparam(), Go::GeomObject::instanceType(), Go::Point::length(), M_PI, MESSAGE, Go::SplineCurve::order(), Go::CurveOnSurface::parameterCurve(), Go::CurveOnSurface::parPref(), Go::CurveOnSurface::spaceCurve(), Go::SplineCurve::startparam(), Go::SplineCurve::subCurve(), and THROW.
Referenced by getGnJoints().
00395 { 00396 int n = cont.size() - 1; 00397 // If input should be of higher order we should let kink be a corr vector. 00398 ASSERT(n >= 0 && n < 3); // Currently only implemented for pos, tangent and 2nd order geom cont. 00399 00400 int ki; 00401 vector<double> poss_disc; // We store all possible discontinuities. 00402 00403 // We begin by extracting all parameter values (knots) which 00404 const SplineCurve* spline_cv; 00405 if (curve.instanceType() == Class_SplineCurve) { 00406 spline_cv = dynamic_cast<const SplineCurve*>(&curve); 00407 } else if (curve.instanceType() == Class_CurveOnSurface) { 00408 const CurveOnSurface* cv_on_sf = dynamic_cast<const CurveOnSurface*>(&curve); 00409 if (cv_on_sf->parPref()) { 00410 spline_cv = dynamic_cast<const SplineCurve*>((cv_on_sf->parameterCurve()).get()); 00411 } else { 00412 spline_cv = dynamic_cast<const SplineCurve*>((cv_on_sf->spaceCurve()).get()); 00413 } 00414 } else { 00415 THROW("Unexpected curve type!"); 00416 } 00417 ASSERT(spline_cv != 0); 00418 int order = spline_cv->order(); 00419 vector<double>::const_iterator iter = spline_cv->basis().begin() + order; 00420 int mult = order - n; // If mult equal knots, we split. 00421 while ((iter < spline_cv->basis().end()) && (iter[0] != spline_cv->endparam())) { 00422 if (iter[mult-1] == iter[0]) { 00423 poss_disc.push_back(iter[0]); 00424 iter += mult; 00425 } else { 00426 ++iter; 00427 } 00428 } 00429 00430 // We loop through all possible discontinuities, checking the value. 00431 gn_joints.push_back(spline_cv->startparam()); 00432 int pds = poss_disc.size(); 00433 for (ki = 0; ki < pds; ++ki) { 00434 vector<Point> from_left = spline_cv->ParamCurve::point(poss_disc[ki], n, false); 00435 vector<Point> from_right = spline_cv->ParamCurve::point(poss_disc[ki], n); 00436 ASSERT(int(from_left.size()) == n+1); 00437 double dist = from_left[0].dist(from_right[0]); 00438 if (dist > cont[0]) // Testing for G0 cont 00439 { 00440 gn_joints.push_back(poss_disc[ki]); 00441 continue; 00442 } 00443 00444 if (n > 0) { // Testing for G1 cont (direction of tangents). 00445 from_left[1].normalize(); 00446 from_right[1].normalize(); 00447 dist = from_left[1].dist(from_right[1]); 00448 if (dist > cont[1]) 00449 { 00450 gn_joints.push_back(poss_disc[ki]); 00451 continue; 00452 } 00453 00454 if (n > 1) { // Testing for G2 cont 00455 // (We may not need to split into segments, but as the algorithm expects 00456 // it we do anyway. 00457 // Would be smarter to save segments as we proceed, but since when was 00458 // speed an issue ...) 00459 shared_ptr<SplineCurve> left_seg 00460 (spline_cv->subCurve(spline_cv->startparam(), poss_disc[ki])); 00461 shared_ptr<SplineCurve> right_seg 00462 (spline_cv->subCurve(poss_disc[ki], spline_cv->endparam())); 00463 00464 // Let b1, b2 & b3 be the last 3 ctrl pts on left seg, and c0, c1, c2 the 00465 // first 3 ctrl pts 00466 // on the right seg. Since we are guaranteed G0 cont we know that b0 = c0. 00467 // Assuming they are coplanar, we define d as the intersection point 00468 // between the lines given by (b1, b2) & (c1, c2) (i.e. passing through the pts). 00469 // If all pts are colinear we let d = b0 (= c0). 00470 // Defining 00471 // r_- = ratio(b1, b2, d) 00472 // r = ratio(b2, b3, c1) (= ratio(b2, c0, c1) 00473 // r_+ = ratio(d, c1, c2), 00474 // where ratio(a, b, c) = |b-a|/|c-b| for the colinear pts a, b & c. 00475 // By [Gerald Farin: Curves and Surfaces for CAGD, 12.2 (p.182)] G2 continuity is 00476 // given by the formula 00477 // r^2 = r_- * r_+. 00478 // Using the sinus sentence we calculate the unknown |d - b2| & |c1 - d|. 00479 int dim = left_seg->dimension(); 00480 Point b1(left_seg->coefs_end() - 3*dim, left_seg->coefs_end() - 2*dim); 00481 Point b2(left_seg->coefs_end() - 2*dim, left_seg->coefs_end() - dim); 00482 Point b3(left_seg->coefs_end() - dim, left_seg->coefs_end()); 00483 Point c0(right_seg->coefs_begin(), right_seg->coefs_begin() + dim); 00484 Point c1(right_seg->coefs_begin() + dim, right_seg->coefs_begin() + 2*dim); 00485 Point c2(right_seg->coefs_begin() + 2*dim, right_seg->coefs_begin() + 3*dim); 00486 00487 Point left_dir = b2 - b1; 00488 Point mid_dir = c1 - b2; 00489 Point right_dir = c1 - c2; 00490 double ang_left, ang_right; 00491 try { 00492 ang_left = left_dir.angle_smallest(mid_dir); 00493 ang_right = right_dir.angle_smallest(mid_dir); 00494 } 00495 catch ( ... ) { 00496 MESSAGE("Failed computing angle between joints, skipping."); 00497 continue; 00498 } 00499 double ang_mid = M_PI - ang_left - ang_right; 00500 double sin_left = sin(ang_left); 00501 double sin_right = sin(ang_right); 00502 double sin_mid = sin(ang_mid); 00503 double ratio_left = left_dir.length()*sin_mid/(mid_dir.length()*sin_right); 00504 double ratio_mid = b2.dist(b3)/c0.dist(c1); 00505 double ratio_right = mid_dir.length()*sin_left/(right_dir.length()*sin_mid); 00506 00507 double error = ratio_mid*ratio_mid - ratio_left*ratio_right; 00508 if (error > cont[2]) // @@sbr Not sure what estimate to apply. 00509 { 00510 gn_joints.push_back(poss_disc[ki]); 00511 continue; 00512 } 00513 } 00514 } 00515 // Since we got here all tests passed! This is NOT a segment 00516 // gn_joints.push_back(poss_disc[ki]); 00517 } 00518 gn_joints.push_back(spline_cv->endparam()); 00519 00520 // We run through gn_joints checking length of segments. 00521 if (gn_joints.size() > 2) { 00522 for (ki = 0; ki < int(gn_joints.size()) - 1; ++ki) { 00523 double segment_length = 00524 curve.ParamCurve::estimatedCurveLength(gn_joints[ki], gn_joints[ki+1], 1000); 00525 if (segment_length < cont[0]) { 00526 if (ki == 0) { 00527 gn_joints.erase(gn_joints.begin() + ki + 1); 00528 } else { 00529 gn_joints.erase(gn_joints.begin() + ki); 00530 } 00531 --ki; 00532 } 00533 if (gn_joints.size() == 2) { 00534 break; 00535 } 00536 } 00537 } 00538 }
void Go::getHermiteData | ( | const std::vector< Point > & | der1, | |
const std::vector< Point > & | der2, | |||
double & | parint, | |||
double & | len1, | |||
double & | len2 | |||
) |
Given position, first and second derivative in both ends of an Hermite segment, compute parameter interval and tangent lengths in order to stay close to a circular segment.
Definition at line 146 of file CurvatureUtils.C.
References curvatureRadius(), ltol, and tanLenFromRadius().
00153 { 00154 // First compute unit tangent, curvature and curvature radius 00155 vector<Point> unitder1, unitder2; 00156 double crad1, crad2; 00157 crad1 = curvatureRadius(der1, unitder1); 00158 crad2 = curvatureRadius(der2, unitder2); 00159 00160 // Compute the angle between the unit tangents 00161 double angle = unitder1[1].angle(unitder2[1]); 00162 angle = fabs(angle); 00163 00164 // Compute distance between endpoints 00165 parint = der1[0].dist(der2[0]); 00166 00167 // Compute tangent lengths 00168 if (angle < ltol || crad1 < 0.0) 00169 len1 = parint/3.0; 00170 else 00171 len1 = tanLenFromRadius(crad1, angle); 00172 00173 if (angle < ltol || crad2 < 0.0) 00174 len2 = parint/3.0; 00175 else 00176 len2 = tanLenFromRadius(crad2, angle); 00177 00178 // Make sure that the tangent does not explode due to numeric errors, 00179 // and make a controlled tangent when the radius is zero or almost zero 00180 double max_dist; 00181 if (angle < 0.1) 00182 max_dist = (double)0.35*parint; 00183 else if (angle < 0.35) 00184 max_dist = (double)0.40*parint; 00185 else if (angle < 0.75) 00186 max_dist = (double)0.50*parint; 00187 else 00188 max_dist = (double)0.70*parint; 00189 00190 if ( len1 > max_dist) 00191 len1 = max_dist; 00192 if ( len2 > max_dist) 00193 len2 = max_dist; 00194 00195 }
double Go::getKnotAtLargestInterval | ( | const BsplineBasis & | basis | ) |
Definition at line 1183 of file GeometryTools.C.
References getLargestParameterInterval(), and interval().
Referenced by insertKnotsEvenly().
01185 { 01186 const pair<double, double> interval = 01187 getLargestParameterInterval(basis); 01188 double new_knot = 0.5*(interval.first+interval.second); 01189 01190 return new_knot; 01191 }
pair< double, double > Go::getLargestParameterInterval | ( | const BsplineBasis & | basis | ) |
Definition at line 1196 of file GeometryTools.C.
References Go::BsplineBasis::begin(), and Go::BsplineBasis::end().
Referenced by getKnotAtLargestInterval().
01198 { 01199 double largest = 0.0; 01200 std::vector<double>::const_iterator index; 01201 for (std::vector<double>::const_iterator knot = basis.begin(); 01202 knot != basis.end()-1; ++knot) { 01203 if ( (*(knot+1) - *knot) > largest) { 01204 largest = *(knot+1) - *knot; 01205 index = knot; 01206 } 01207 } 01208 01209 return pair<double, double>(*index, *(index+1)); 01210 }
std::vector< double > Go::getRotationMatrix | ( | const Point & | unit_axis_dir, | |
double | alpha | |||
) |
Compute the elements of the matrix describing a rotation or a given number of radians around a given axis going through the origin.
unit_axis_dir | this vector defines the axis of rotation. It must be of unit length, although this is not checked by the function. | |
alpha | the angle of rotation, in radians |
Definition at line 1127 of file GeometryTools.C.
References ASSERT, and Go::Point::dimension().
Referenced by rotatePoint().
01129 { 01130 ASSERT(unit_rot_axis.dimension() == 3); // We're working in 3D space. 01131 std::vector<double> return_matrix(9); 01132 // Using the notation in 'Computational Gemoetry for Design and Manufacture'. 01133 double u1 = unit_rot_axis[0]; 01134 double u2 = unit_rot_axis[1]; 01135 double u3 = unit_rot_axis[2]; 01136 double cos_a = cos(alpha); 01137 double sin_a = sin(alpha); 01138 01139 return_matrix[0] = u1*u1 + cos_a*(1 - u1*u1); 01140 return_matrix[1] = u1*u2*(1 - cos_a) - u3*sin_a; 01141 return_matrix[2] = u3*u1*(1 - cos_a) + u2*sin_a; 01142 return_matrix[3] = u1*u2*(1 - cos_a) + u3*sin_a; 01143 return_matrix[4] = u2*u2 + cos_a*(1 - u2*u2); 01144 return_matrix[5] = u2*u3*(1 - cos_a) - u1*sin_a; 01145 return_matrix[6] = u3*u1*(1 - cos_a) - u2*sin_a; 01146 return_matrix[7] = u2*u3*(1 - cos_a) + u1*sin_a; 01147 return_matrix[8] = u3*u3 + cos_a*(1 - u3*u3); 01148 01149 return return_matrix; 01150 }
bool Go::getSfAdjacencyInfo | ( | shared_ptr< ParamSurface > | sf1, | |
shared_ptr< CurveOnSurface > | sf_cv1, | |||
shared_ptr< ParamSurface > | sf2, | |||
shared_ptr< CurveOnSurface > | sf_cv2, | |||
double | tol, | |||
int & | bd1, | |||
int & | bd2, | |||
bool & | same_orient | |||
) |
Definition at line 343 of file SurfaceTools.C.
00350 { 00351 // bd1, bd2: 00352 // 0 = umin, 1 = umax, 2 = vmin, 3 = vmax 00353 bool same_orient1, same_orient2; 00354 bd1 = sf_cv1->whichBoundary(tol, same_orient1); 00355 bd2 = sf_cv2->whichBoundary(tol, same_orient2); 00356 if (bd1 < 0 || bd2 < 0) 00357 return false; // Adjacency not along boundary 00358 00359 Point f1_p1 = sf_cv1->faceParameter(sf_cv1->startparam()); 00360 Point f1_p2 = sf_cv1->faceParameter(sf_cv1->endparam()); 00361 Point f2_p1 = sf_cv2->faceParameter(sf_cv2->startparam()); 00362 Point f2_p2 = sf_cv2->faceParameter(sf_cv2->endparam()); 00363 bool opposite = false; 00364 Point p1 = sf1->ParamSurface::point(f1_p1[0], f1_p1[1]); 00365 Point p2 = sf1->ParamSurface::point(f1_p2[0], f1_p2[1]); 00366 Point p3 = sf2->ParamSurface::point(f2_p1[0], f2_p1[1]); 00367 Point p4 = sf2->ParamSurface::point(f2_p2[0], f2_p2[1]); 00368 if ((p2 - p1)*(p4 -p3) < 0.0) 00369 opposite = true; 00370 if ((same_orient1 && !same_orient2) || (!same_orient1 && same_orient2)) 00371 opposite = !opposite; 00372 same_orient = !opposite; 00373 return true; 00374 }
bool Go::getSfAdjacencyInfo | ( | boost::shared_ptr< ParamSurface > | sf1, | |
boost::shared_ptr< CurveOnSurface > | sf_cv1, | |||
boost::shared_ptr< ParamSurface > | sf2, | |||
boost::shared_ptr< CurveOnSurface > | sf_cv2, | |||
double | tol, | |||
int & | bd1, | |||
int & | bd2, | |||
bool & | same_orient | |||
) |
SISLSurf * Go::GoSurf2SISL | ( | const SplineSurface & | sf, | |
bool | copy = true | |||
) |
Convert a SplineSurface to a SISLSurface.
sf | the SplineSurface to convert | |
copy | if 'true', then the generated SISLSurf will have its own copy of the coefficient information contained in 'sf'. Otherwise, it will share this information with 'sf' (ie. it will only contain a pointer into the corresponding storage array in 'sf'. |
Definition at line 91 of file SISLconversion.C.
References Go::SplineSurface::basis_u(), Go::SplineSurface::basis_v(), Go::BsplineBasis::begin(), Go::SplineSurface::coefs_begin(), Go::SplineSurface::dimension(), Go::SplineSurface::numCoefs_u(), Go::SplineSurface::numCoefs_v(), Go::SplineSurface::order_u(), Go::SplineSurface::order_v(), Go::SplineSurface::rational(), and Go::SplineSurface::rcoefs_begin().
Referenced by main(), and sisleval().
00092 { 00093 std::vector<double>::const_iterator coefsstart; 00094 int ikind; 00095 if (sf.rational()) { 00096 coefsstart = sf.rcoefs_begin(); 00097 ikind = 2; 00098 } else { 00099 coefsstart = sf.coefs_begin(); 00100 ikind = 1; 00101 } 00102 return newSurf(sf.numCoefs_u(), sf.numCoefs_v(), 00103 sf.order_u(), sf.order_v(), 00104 const_cast<double*>(&(*(sf.basis_u().begin()))), 00105 const_cast<double*>(&(*(sf.basis_v().begin()))), 00106 const_cast<double*>(&(*coefsstart)), 00107 ikind, sf.dimension(), copy); 00108 }
go_iterator_traits<ForwardIterator>::value_type Go::inner | ( | ForwardIterator | first, | |
ForwardIterator | last, | |||
ForwardIterator | second | |||
) | [inline] |
inner product
Definition at line 162 of file Utils.h.
Referenced by Go::CoonsPatchGen::blendcoef(), Go::MatrixXD< double, Dim >::mult(), Go::MatrixXD< double, Dim >::operator*(), Go::ParamCurve::s1771_s9del(), Go::SplineSurface::s1773(), Go::SplineSurface::s1773_s9dir(), and Go::SolveBCG::solve().
00165 { 00166 typename go_iterator_traits<ForwardIterator>::value_type sum = 0; 00167 for (; first != last; ++first, ++second) 00168 sum += (*first)*(*second); 00169 return sum; 00170 }
void Go::insertKnotsEvenly | ( | BsplineBasis & | basis, | |
double | tmin, | |||
double | tmax, | |||
int | num_knots, | |||
double | knot_diff_tol = 1e-05 | |||
) |
Definition at line 1166 of file GeometryTools.C.
References getKnotAtLargestInterval(), Go::BsplineBasis::insertKnot(), and Go::BsplineBasis::subBasis().
01169 { 01170 BsplineBasis sub_basis = basis.subBasis(tmin, tmax, knot_diff_tol); 01171 vector<double> new_knots; 01172 for (int i=0; i<num_knots; ++i) { 01173 double new_knot = getKnotAtLargestInterval(sub_basis); 01174 sub_basis.insertKnot(new_knot); 01175 new_knots.push_back(new_knot); 01176 } 01177 01178 basis.insertKnot(new_knots); 01179 }
void Go::insertKnotsEvenly | ( | BsplineBasis & | basis, | |
int | num_knots | |||
) |
Definition at line 1155 of file GeometryTools.C.
References getKnotAtLargestInterval(), and Go::BsplineBasis::insertKnot().
01157 { 01158 for (int i=0; i<num_knots; ++i) { 01159 double new_knot = getKnotAtLargestInterval(basis); 01160 basis.insertKnot(new_knot); 01161 } 01162 }
void Go::insideParamDomain | ( | double & | delta, | |
double | acoef, | |||
double | astart, | |||
double | aend | |||
) |
Adjust delta to satisfy:
Ported from the sisl function s1770_s9corr.
Definition at line 384 of file closestPtCurves.C.
Referenced by closestPtCurveSurf(), and extremalPtSurfSurf().
void Go::intersect2Dcurves | ( | const ParamCurve * | cv1, | |
const ParamCurve * | cv2, | |||
double | epsge, | |||
vector< pair< double, double > > & | intersections, | |||
vector< int > & | pretopology, | |||
vector< pair< pair< double, double >, pair< double, double > > > & | int_crvs | |||
) |
Definition at line 65 of file intersect2Dcurves.C.
References ALWAYS_ERROR_IF, Class_SplineCurve, Curve2SISL(), Go::GeomObject::dimension(), Go::GeomObject::instanceType(), and MESSAGE_IF.
00075 { 00076 00077 // First make sure that the curves are spline curves. 00078 ALWAYS_ERROR_IF(cv1->instanceType() != Class_SplineCurve || 00079 cv2->instanceType() != Class_SplineCurve, 00080 " Intersection between general parametric curves is not implemented."); 00081 00082 MESSAGE_IF(cv1->dimension() != 2, 00083 "Dimension different from 2, pretopology not reliable."); 00084 00085 // Make sisl curves and call sisl. 00086 SISLCurve *pc1 = Curve2SISL(*(dynamic_cast<const SplineCurve*>(cv1)), false); 00087 SISLCurve *pc2 = Curve2SISL(*(dynamic_cast<const SplineCurve*>(cv2)), false); 00088 00089 int kntrack = 0; 00090 int trackflag = 0; // Do not make tracks. 00091 SISLTrack **track =0; 00092 int knpt=0, kncrv=0; 00093 double *par1=0, *par2=0; 00094 int *pretop = 0; 00095 SISLIntcurve **vcrv = 0; 00096 int stat = 0; 00097 sh1857(pc1, pc2, 0.0, epsge, trackflag, &kntrack, &track, 00098 &knpt, &par1, &par2, &pretop, &kncrv, &vcrv, &stat); 00099 00100 ALWAYS_ERROR_IF(stat<0,"Error in intersection, code: " << stat); 00101 00102 00103 // Remember intersections points. 00104 int ki; 00105 for (ki=0; ki<knpt; ki++) 00106 { 00107 intersections.push_back(std::make_pair(par1[ki],par2[ki])); 00108 pretopology.insert(pretopology.end(), pretop+4*ki, pretop+4*(ki+1)); 00109 } 00110 00111 // Remember intersection curves 00112 for (ki=0; ki<kncrv; ++ki) 00113 int_crvs.push_back(std::make_pair(std::make_pair(vcrv[ki]->epar1[0], vcrv[ki]->epar2[0]), 00114 std::make_pair(vcrv[ki]->epar1[vcrv[ki]->ipoint-1], 00115 vcrv[ki]->epar2[vcrv[ki]->ipoint-1]))); 00116 00117 if (kncrv > 0) 00118 freeIntcrvlist(vcrv, kncrv); 00119 00120 if (par1 != 0) free(par1); 00121 if (par2 != 0) free(par2); 00122 if (pc1 != 0) freeCurve(pc1); 00123 if (pc2 != 0) freeCurve(pc2); 00124 if (pretop != 0) free(pretop); 00125 }
void Go::intersect2Dcurves | ( | const ParamCurve * | cv1, | |
const ParamCurve * | cv2, | |||
double | epsge, | |||
std::vector< std::pair< double, double > > & | intersections, | |||
std::vector< int > & | pretopology, | |||
std::vector< std::pair< std::pair< double, double >, std::pair< double, double > > > & | int_crvs | |||
) |
Intersect two 2D spline curves.
Collect intersection parameters and pretopology information.
cv1 | pointer to the first 2D curve | |
cv2 | pointer to the second 2D curve | |
epsge | geometrical tolerance |
intersections | this vector will contain the parameter pairs of the found intersections (one vector entry per intersection. The two parameters in the pair<> correspond to the parameter value in 'cv1' and 'cv2' for a particular intersection. | |
pretopology | vector containing a pretopology indicator for each detected intersection point. There is one entry per intersection point. |
Referenced by Go::CurveBoundedDomain::findPcurveInsideSegments(), and Go::BoundedUtils::intersectWithSurface().
void Go::intersectCurvePoint | ( | const ParamCurve * | crv, | |
Point | pnt, | |||
double | epsge, | |||
vector< double > & | intersections, | |||
vector< pair< double, double > > & | int_crvs | |||
) |
Definition at line 26 of file intersect2Dcurves.C.
References ALWAYS_ERROR_IF, Go::Point::begin(), Class_SplineCurve, Curve2SISL(), Go::GeomObject::instanceType(), and Go::Point::size().
00034 { 00035 // First make sure that the curve is a spline curve 00036 ALWAYS_ERROR_IF(crv->instanceType() != Class_SplineCurve, 00037 " Intersection involving general parametric curves is not implemented."); 00038 00039 // Make sisl curve and call sisl. 00040 SISLCurve *pc = Curve2SISL(*(dynamic_cast<const SplineCurve*>(crv)), false); 00041 00042 int knpt=0, kncrv=0; 00043 double *par=0; 00044 SISLIntcurve **vcrv = 0; 00045 int stat = 0; 00046 s1871(pc, pnt.begin(), pnt.size(), epsge, &knpt, &par, &kncrv, &vcrv, &stat); 00047 ALWAYS_ERROR_IF(stat<0,"Error in intersection, code: " << stat); 00048 00049 00050 // Remember intersections points. 00051 if (knpt > 0) 00052 intersections.insert(intersections.end(), par, par+knpt); 00053 00054 // Remember intersection curves 00055 for (int ki=0; ki<kncrv; ++ki) 00056 int_crvs.push_back(std::make_pair(vcrv[ki]->epar1[0], vcrv[ki]->epar1[vcrv[ki]->ipoint-1])); 00057 00058 if (kncrv > 0) 00059 freeIntcrvlist(vcrv, kncrv); 00060 00061 if (par != 0) free(par); 00062 if (pc) freeCurve(pc); 00063 }
void Go::intersectCurvePoint | ( | const ParamCurve * | crv, | |
Point | pnt, | |||
double | epsge, | |||
std::vector< double > & | intersections, | |||
std::vector< std::pair< double, double > > & | int_crvs | |||
) |
Referenced by Go::CurveBoundedDomain::isOnBoundary().
void Go::intersectcurves | ( | SplineCurve * | cv1, | |
SplineCurve * | cv2, | |||
double | epsge, | |||
std::vector< std::pair< double, double > > & | intersections | |||
) |
Intersect two spline curves.
Collect intersection parameters.
cv1 | pointer to the first spline curve | |
cv2 | pointer to the second spline curve | |
epsge | geometrical tolerance |
intersections | this vector will contain the parameter pairs of the found intersections (one vector entry per intersection. The two parameters in the pair<> correspond to the parameter value in 'cv1' and 'cv2' for a particular intersection. |
Definition at line 19 of file intersectcurves.C.
References ALWAYS_ERROR_IF, and Curve2SISL().
00026 { 00027 00028 // Make sisl curves and call sisl. 00029 SISLCurve *pc1 = Curve2SISL(*cv1, false); 00030 SISLCurve *pc2 = Curve2SISL(*cv2, false); 00031 00032 int kntrack = 0; 00033 int trackflag = 0; // Do not make tracks. 00034 SISLTrack **track =0; 00035 int knpt=0, kncrv=0; 00036 double *par1=0, *par2=0; 00037 int *pretop = 0; 00038 SISLIntcurve **intcrvs = 0; 00039 int stat = 0; 00040 sh1857(pc1, pc2, 0.0, epsge, trackflag, &kntrack, &track, 00041 &knpt, &par1, &par2, &pretop, &kncrv, &intcrvs, &stat); 00042 00043 ALWAYS_ERROR_IF(stat<0,"Error in intersection, code: " << stat); 00044 00045 00046 // Remember intersections points. The intersection curves are 00047 // skipped. 00048 int ki; 00049 for (ki=0; ki<knpt; ki++) 00050 { 00051 intersections.push_back(std::make_pair(par1[ki],par2[ki])); 00052 } 00053 00054 if (kncrv > 0) 00055 freeIntcrvlist(intcrvs, kncrv); 00056 00057 if (par1 != 0) free(par1); 00058 if (par2 != 0) free(par2); 00059 if (pc1 != 0) freeCurve(pc1); 00060 if (pc2 != 0) freeCurve(pc2); 00061 }
int Go::is_inside | ( | const std::vector< Vector3D > & | trim_curve_p, | |
const std::vector< int > & | contour, | |||
const double | u, | |||
const double | v | |||
) |
Definition at line 1065 of file 2dpoly_for_s2m.C.
References DBG_FLAG, and point_inside_contour().
Referenced by make_trimmed_mesh(), and trim_a_triangle().
01072 { 01073 #ifndef DBG 01074 // const bool dbg=false; // This way, all tests on 'dbg' is removed compile-time when DBG is not defined. 01075 #endif 01076 01077 01078 // test 100212 01079 01080 if (contour.size()==0) 01081 return 0; 01082 01083 #if 0 // 021012 01084 01085 const double * const vertices = &trim_curve_p[0][0]; 01086 01087 01088 vector<int> cont; 01089 cont.push_back(contour[0]); 01090 for (int i=0; i<int(contour.size()); i++) 01091 { 01092 const int j = (i+1)%int(contour.size()); 01093 const double &a=vertices[contour[i]], &b=vertices[contour[i]+1]; 01094 const double &c=vertices[contour[j]], &d=vertices[contour[j]+1]; 01095 const double len_squared = (a-c)*(a-c) + (b-d)*(b-d); 01096 const double eps = 1e-8; 01097 if ( len_squared < eps*eps ) 01098 { 01099 if (dbg) 01100 printf("is_inside preprocessing: HUH?! Segment with length %e, duplicate corner! REMOVING IT\n", 01101 sqrt(len_squared)); 01102 } 01103 else 01104 cont.push_back(contour[i]); 01105 } 01106 01107 01108 for (int s=2; s<=10; s++) 01109 { 01110 vector<int> cont2; 01111 cont2.push_back(cont[0]); 01112 for (int i=0; i<int(cont.size()); i++) 01113 { 01114 const int j = (i+1)%int(cont.size()); 01115 const double &a=vertices[cont[i]], &b=vertices[cont[i]+1]; 01116 const double &c=vertices[cont[j]], &d=vertices[cont[j]+1]; 01117 const double len_squared = (a-c)*(a-c) + (b-d)*(b-d); 01118 const double eps = 1e-8; 01119 if ( len_squared < eps*eps ) 01120 { 01121 if (dbg) 01122 printf("is_inside prep STAGE %d : HUH?! Segment %d with length %e, duplicate corner! REMOVING IT\n", 01123 s, i, sqrt(len_squared)); 01124 } 01125 else 01126 cont2.push_back(cont[i]); 01127 } 01128 cont=cont2; 01129 } 01130 01131 return point_inside_contour(u, v, &trim_curve_p[0][0], cont, dbg); 01132 #endif 01133 01134 01135 01136 01137 // 100212: The const_cast not needed any more. 01138 //return point_inside_contour(u, v, &trim_curve_p[0][0], const_cast<vector<int> &>(contour), dbg); 01139 return point_inside_contour(u, v, &trim_curve_p[0][0], contour DBG_FLAG); 01140 }
int Go::is_on_contour | ( | const std::vector< Vector3D > & | trim_curve_p, | |
const std::vector< int > & | contour, | |||
const double | u, | |||
const double | v | |||
) |
Definition at line 1170 of file 2dpoly_for_s2m.C.
References DBG_FLAG, and point_on_contour().
Referenced by make_trimmed_mesh(), split_quad(), and trim_a_triangle().
01175 { 01176 return point_on_contour(u, v, &trim_curve_p[0][0], const_cast<vector<int> &>(contour) DBG_FLAG); 01177 }
bool Go::is_on_corner | ( | const std::vector< Vector3D > & | trim_curve_p, | |
const std::vector< int > & | contour, | |||
const double | u, | |||
const double | v | |||
) |
Definition at line 1154 of file 2dpoly_for_s2m.C.
References point_on_contour_corner().
01155 { 01156 return point_on_contour_corner(u, v, &trim_curve_p[0][0], const_cast<vector<int> &>(contour)); 01157 }
bool Go::isCoincident | ( | const ParamCurve & | cv1, | |
const ParamCurve & | cv2, | |||
double | epsge | |||
) |
Returns true if the curves are approximately coincident (that is, they have the same parameter space and overlap in space).
The function uses a (possibly high) number of closest point calculations to check for spatial coincidence.
cv1 | the first curve to check for coincidence | |
cv2 | the second curve to check for coincidence | |
epsge | the tolerance for specifying what we mean by approximately coincident |
Definition at line 934 of file GeometryTools.C.
References Go::ParamCurve::closestPoint(), Go::Point::dist(), Go::ParamCurve::endparam(), Go::ParamCurve::estimatedCurveLength(), Go::ParamCurve::point(), and Go::ParamCurve::startparam().
00936 { 00937 // Check endpoints 00938 double ta1 = cv1.startparam(); 00939 double tb1 = cv1.endparam(); 00940 double ta2 = cv2.startparam(); 00941 double tb2 = cv2.endparam(); 00942 00943 Point pnt1 = cv1.point(ta1); 00944 Point pnt2 = cv1.point(tb1); 00945 Point pnt3 = cv2.point(ta2); 00946 Point pnt4 = cv2.point(tb2); 00947 00948 if (std::min(pnt1.dist(pnt3), pnt1.dist(pnt4)) > epsge || 00949 std::min(pnt2.dist(pnt3), pnt2.dist(pnt4)) > epsge) 00950 return false; 00951 00952 // Endpoints matching. Check the inner. 00953 bool same = (pnt1.dist(pnt3) < pnt1.dist(pnt4)); 00954 00955 double length = cv1.estimatedCurveLength(); 00956 int nmb_test = std::min(500, (int)(length/epsge)); 00957 double del = (tb1 - ta1)/(int)(nmb_test + 1); 00958 double del2 = (tb2 - ta2)/(int)(nmb_test + 1); 00959 double tpar, tpar2, seed, dist; 00960 int ki; 00961 for (ki=0, tpar=ta1+del; ki<nmb_test; ki++, tpar+=del) 00962 { 00963 seed = (same) ? ta2 + (ki+1)*del2 : tb2 - (ki+1)*del2; 00964 pnt1 = cv1.point(tpar); 00965 cv2.closestPoint(pnt1, ta2, tb2, tpar2, pnt2, dist, &seed); 00966 if (dist > epsge) 00967 return false; 00968 } 00969 00970 return true; 00971 }
void Go::iterateCornerPos | ( | Point & | vertex, | |
vector< pair< shared_ptr< ParamSurface >, Point > > | sfs, | |||
double | tol | |||
) |
Definition at line 217 of file SurfaceTools.C.
References Go::Point::dist(), and Go::Point::setValue().
00221 { 00222 Point prev, curr; 00223 curr = vertex; 00224 double wgt_fac = 10.0; 00225 double wgt = 1.0; 00226 double wgt_sum; 00227 int max_iter = 10; 00228 int kr = 0; 00229 00230 // Iterate until the vertex point doesn't move 00231 do 00232 { 00233 prev = curr; 00234 curr.setValue(0.0); 00235 wgt_sum = 0.0; 00236 00237 for (size_t ki=0; ki<sfs.size(); ++ki) 00238 { 00239 double seed[2]; 00240 double clo_u, clo_v, clo_dist; 00241 Point clo_pt; 00242 seed[0] = sfs[ki].second[0]; 00243 seed[1] = sfs[ki].second[1]; 00244 sfs[ki].first->closestPoint(prev, clo_u, clo_v, clo_pt, 00245 clo_dist, 0.001*tol, NULL, seed); 00246 00247 // Check if the surface is elementary 00248 shared_ptr<ElementarySurface> elemsf = 00249 shared_dynamic_cast<ElementarySurface, ParamSurface>(sfs[ki].first); 00250 double curr_wgt = (elemsf.get()) ? wgt*wgt_fac : wgt; 00251 curr += curr_wgt*clo_pt; 00252 wgt_sum += curr_wgt; 00253 00254 sfs[ki].second = Point(clo_u, clo_v); 00255 } 00256 curr /= wgt_sum; 00257 kr++; 00258 if (kr > max_iter) 00259 break; 00260 } 00261 while (prev.dist(curr) > tol); 00262 00263 vertex = curr; 00264 }
void Go::iterateCornerPos | ( | Point & | vertex, | |
std::vector< std::pair< boost::shared_ptr< ParamSurface >, Point > > | sfs, | |||
double | tol | |||
) |
boost::shared_ptr<SplineSurface> Go::joinPatches | ( | const vector< shared_ptr< SplineSurface > > & | patches, | |
const SplineSurface & | spline_space | |||
) |
Definition at line 663 of file GeometryTools.C.
References Go::SplineSurface::appendSurface(), Go::SplineSurface::basis_u(), Go::SplineSurface::basis_v(), Go::SplineSurface::clone(), Go::SplineSurface::endparam_u(), Go::SplineSurface::endparam_v(), Go::BsplineBasis::knotIntervalFuzzy(), Go::BsplineBasis::knotMultiplicity(), Go::SplineSurface::makeBernsteinKnotsU(), Go::SplineSurface::makeBernsteinKnotsV(), Go::BsplineBasis::numCoefs(), and Go::BsplineBasis::order().
00666 { 00667 // As we want to know how many patches there exist in u- and v-direction we 00668 // insert knots into copy of input sf. 00669 SplineSurface cp_spline_sf = spline_space; 00670 00671 cp_spline_sf.makeBernsteinKnotsU(); 00672 cp_spline_sf.makeBernsteinKnotsV(); 00673 00674 const BsplineBasis& orig_basis_u = spline_space.basis_u(); 00675 const BsplineBasis& orig_basis_v = spline_space.basis_v(); 00676 const BsplineBasis& basis_u = cp_spline_sf.basis_u(); 00677 const BsplineBasis& basis_v = cp_spline_sf.basis_v(); 00678 00679 // Assuming both input basises are represented with Bezier knots. 00680 // (i.e. all knots should have mult equal to degree). 00681 int num_u = basis_u.numCoefs(); 00682 int num_v = basis_v.numCoefs(); 00683 int order_u = basis_u.order(); 00684 int order_v = basis_v.order(); 00685 int numpat_u = num_u / order_u; //num_u + 1 - order_u 00686 int numpat_v = num_v / order_v;; //num_v + 1 - order_v; 00687 00688 bool repar = false; // @@sbr Alternatively we could update input knots (spline_space) as we append. 00689 double fuzzy_tol = 1e-06; 00690 SplineSurface* total_sf; 00691 for (int ki = 0; ki < numpat_v; ++ki) { 00692 SplineSurface sf_u = *patches[ki*numpat_u]; 00693 for (int kj = 1; kj <numpat_u; ++kj) { 00694 // @@sbr Perhaps make sure that we are not fooled by numerical noise? 00695 // suppose this could be done somewhat more efficient, but it'll do for now. 00696 double knot_u = sf_u.endparam_u(); 00697 orig_basis_u.knotIntervalFuzzy(knot_u, fuzzy_tol); 00698 int mult_u = orig_basis_u.knotMultiplicity(knot_u); 00699 int cont = order_u - mult_u - 1; 00700 double dist; 00701 sf_u.appendSurface(patches[ki*numpat_u+kj].get(), 1, cont, dist, repar); 00702 } 00703 00704 if (ki == 0) { 00705 total_sf = sf_u.clone(); 00706 } else { 00707 double knot_v = total_sf->endparam_v(); 00708 orig_basis_v.knotIntervalFuzzy(knot_v, fuzzy_tol); 00709 int mult_v = orig_basis_v.knotMultiplicity(knot_v); 00710 int cont = order_v - mult_v - 1; 00711 double dist; 00712 total_sf->appendSurface(&sf_u, 2, cont, dist, repar); 00713 } 00714 } 00715 00716 return boost::shared_ptr<SplineSurface>(total_sf); 00717 }
boost::shared_ptr<SplineSurface> GO_API Go::joinPatches | ( | const std::vector< boost::shared_ptr< SplineSurface > > & | patches, | |
const SplineSurface & | spline_space | |||
) |
Join patches with continuity according to input basis_u & basis_v.
The patches are assumed to be in Bezier form, and form a continuous set. There should be num_u x num_v patches, where num_u = numcoefs_u/order_u and num_v = numcoefs_v/order_v (as given by basis_u and basis_v).
Referenced by Go::SurfaceCreators::mult1DSurfaces().
void Go::LUDecomp | ( | SquareMatrix & | mat, | |
int | num_rows, | |||
int * | perm, | |||
bool & | parity | |||
) | [inline] |
LU decomposition algorithm, based on Crout's algorithm.
mat | The matrix to be decomposed. The actually used class must support the operation [][] and return 'double'. | |
num_rows | Number of rows (which is also equal to the number of columns). | |
perm | Should point to an n-sized array where the permutation is written. | |
parity | Value upon function completion is 'true' if the number of row interchanges was pair. 'false' otherwise. |
Definition at line 27 of file LUDecomp_implementation.h.
References sum().
Referenced by Go::SmoothCurve::equationSolve(), and LUsolveSystem().
00029 { 00030 parity = true; // as for now, number of row transpositions is 0, evidently 00031 const int num_cols = num_rows; // for clarity (should be optimized away by compiler...) 00032 00033 // filling out perm with sequence 0, 1,... 00034 for (int k = 0; k < num_rows; k++) 00035 perm[k] = k; 00036 00037 // determining scaling factor of each row 00038 std::vector<double> scaling(num_rows, 0); 00039 for (int i = 0; i < num_rows; ++i) { 00040 for (int j = 0; j < num_cols; ++j) { 00041 double temp = fabs(mat[i][j]); 00042 if (temp > scaling[i]) { 00043 scaling[i] = temp; // scaling[i] is max. absolute elem on row i. 00044 } 00045 } 00046 if (scaling[i] == 0) { 00047 throw std::runtime_error("Unable to LU decompose matrix. Null row detected."); 00048 } else { 00049 scaling[i] = double(1) / scaling[i]; 00050 } 00051 } 00052 00053 // executing Crout's algorithm 00054 for (int j = 0; j < num_cols; ++j) { 00055 // determining elements of UPPER matrix on this column 00056 for (int i = 0; i < j; ++i) { 00057 double sum = mat[i][j]; 00058 for (int k = 0; k <= i-1; ++k) { 00059 sum -= mat[i][k] * mat[k][j]; 00060 } 00061 mat[i][j] = sum; 00062 } 00063 00064 // compute rest of this column, before division by pivot 00065 double pivot_val = 0; 00066 int pivot_row = j; 00067 for (int i = j; i < num_rows; ++i) { 00068 double sum = mat[i][j]; 00069 for (int k = 0; k <= j-1; ++k) { 00070 sum -= mat[i][k] * mat[k][j]; 00071 } 00072 mat[i][j] = sum; 00073 double temp = std::fabs(sum * scaling[i]); 00074 if (temp > pivot_val) { 00075 pivot_val = temp; 00076 pivot_row = i; 00077 } 00078 } 00079 00080 if (mat[pivot_row][j] == 0) { 00081 throw std::runtime_error("Unable to LU decompose singular matrix."); 00082 } 00083 00084 // permute rows to position pivot correctly 00085 if (pivot_row != j) { 00086 for (int k = 0; k < num_cols; ++k) { 00087 std::swap(mat[pivot_row][k], mat[j][k]); 00088 } 00089 parity = !parity; 00090 std::swap(scaling[j], scaling[pivot_row]); 00091 std::swap(perm[j], perm[pivot_row]); 00092 } 00093 00094 if (j < num_rows - 1) { 00095 // dividing LOWER matrix elements by pivot 00096 pivot_val = double(1) / mat[j][j]; // inverse value, without scaling 00097 for (int i = j+1; i < num_rows; ++i) { 00098 mat[i][j] *= pivot_val; 00099 } 00100 } 00101 } 00102 }
void Go::LUsolveSystem | ( | SquareMatrix & | A, | |
int | num_unknowns, | |||
T * | vec | |||
) | [inline] |
Solve the system Ax = b for x, using LU decomposition of the matrix A.
Upon successful completion of the function, the matrix A will be LU decomposed, and the solution x will be computed and stored at the memory area pointed to by the last argument.
A | The system matrix A. The actually used class must support the operation [][] and return 'double'. | |
num_unknowns | Number of unknowns in the equation system. | |
vec | At function invocation, 'vec' should point to an array of T, containing the vector 'b'. On successful completion of the function, this array will contain the solution for x. |
Definition at line 107 of file LUDecomp_implementation.h.
References backwardSubstitution(), forwardSubstitution(), and LUDecomp().
Referenced by Go::SplineInterpolator::interpolate(), and Go::SplineApproximator::interpolate().
00109 { 00110 bool parity; 00111 std::vector<int> permutation(num_unknowns); 00112 00113 LUDecomp(A, num_unknowns, &permutation[0], parity); 00114 00115 // permuting b 00116 std::vector<T> vec_old(vec, vec + num_unknowns); 00117 for (int i = 0; i < num_unknowns; ++i) { 00118 swap(vec[i], vec_old[permutation[i]]); 00119 } 00120 forwardSubstitution(A, vec, num_unknowns); 00121 backwardSubstitution(A, vec, num_unknowns); 00122 }
void Go::make_coef_array_from_rational_coefs | ( | const double * | rationals, | |
double * | coefs, | |||
int | num_coefs, | |||
int | dim | |||
) |
convert an array of rational coefficients to an array of nonrational coefficients
rationals | pointer to the array of rational coefficients | |
coefs | pointer to the array where the nonrational coefficients are to be written | |
num_coefs | total number of coefficients | |
dim | dimension of coefficients (not counting the rational component). |
Definition at line 262 of file Utils.C.
Referenced by Go::SplineSurface::updateCoefsFromRcoefs(), and Go::SplineCurve::updateCoefsFromRcoefs().
00267 { 00268 for (int i = 0; i < num_coefs; ++i) { 00269 double w = from[dim]; 00270 if (w != 1.0) { 00271 for (int dd = 0; dd < dim; ++dd) { 00272 to[dd] = from[dd]/w; 00273 } 00274 } else { 00275 for (int dd = 0; dd < dim; ++dd) { 00276 to[dd] = from[dd]; 00277 } 00278 } 00279 from += dim+1; 00280 to += dim; 00281 } 00282 00283 }
void Go::make_trimmed_mesh | ( | boost::shared_ptr< SplineSurface > | srf, | |
std::vector< boost::shared_ptr< SplineCurve > > & | crv_set, | |||
std::vector< Vector3D > & | vert, | |||
std::vector< Vector2D > & | vert_p, | |||
std::vector< int > & | bd, | |||
std::vector< Vector3D > & | norm, | |||
std::vector< int > & | mesh, | |||
std::vector< Vector3D > & | trim_curve, | |||
std::vector< Vector3D > & | trim_curve_p, | |||
const int | dn, | |||
const int | dm, | |||
double | bd_res_ratio | |||
) |
Definition at line 1671 of file spline2mesh.C.
References add_triangle(), ASSERT2, Go::Point::begin(), construct_corner_lists(), Go::Point::cross(), is_inside(), is_on_contour(), Go::Point::length(), M_PI, MESSAGE, Go::Array< T, Dim >::normalize(), normalize(), pt_inside_tri(), s2m_with_boundary, Go::Point::setValue(), split_quad(), THROW, and trim_a_triangle_soup().
Referenced by Go::ParametricSurfaceTesselator::tesselate().
01677 : Not in use 01678 vector<int> &mesh, 01679 vector< Vector3D > &trim_curve_0, // Output 01680 vector< Vector3D > &trim_curve_p_0, // Output 01681 const int dn, // Initially dn+1 nodes in the u-direction 01682 const int dm, // Initially dm+1 nodes in the v-direction 01683 //vector< Vector3D > &extra_v, // 090130: Not in use 01684 double bd_res_ratio) 01685 { 01686 const double duplicate_tolerance = 1e-8; // 100210: Absolute number. Was 1e-12. 01687 01688 vert.resize((dn+1)*(dm+1)); 01689 vert_p.resize((dn+1)*(dm+1)); 01690 bd.resize((dn+1)*(dm+1)); 01691 norm.resize((dn+1)*(dm+1)); 01692 mesh.resize(0); 01693 01694 const double u0=srf->startparam_u(); 01695 const double u1=srf->endparam_u(); 01696 const double v0=srf->startparam_v(); 01697 const double v1=srf->endparam_v(); 01698 int i, j; 01699 const double ustep = (u1 - u0)/(dn-1); 01700 const double vstep = (v1 - v0)/(dm-1); 01701 01702 //-------------------------------------------------------------------------------------------------------------- 01703 // 01704 // Discretizing the trim curve... 01705 // 040621: We use the 'trim_curve_p' to store parameter pairs with z=0.0 in the form of triples for the 01706 // points in 'trim_curve'. 01707 // 081208: Now discretizing a set of curves. 01708 // 01709 //-------------------------------------------------------------------------------------------------------------- 01710 01711 vector< vector<Vector3D> > trim_curve_all(crv_set.size()), trim_curve_p_all(crv_set.size()); 01712 for (int c=0; c<int(crv_set.size()); c++) 01713 { 01714 vector<Vector3D> &trim_curve = trim_curve_all[c]; 01715 vector<Vector3D> &trim_curve_p = trim_curve_p_all[c]; 01716 01717 boost::shared_ptr<SplineCurve> crv = crv_set[c]; 01718 01719 vector<double> corner_pars; 01720 int kk = crv->order(); 01721 int kn = crv->numCoefs(); 01722 std::vector<double>::iterator st = crv->knotsBegin(); 01723 int kstat = 0; 01724 corner_pars.push_back(st[kk-1]); 01725 int knot_ind = kk; 01726 while (knot_ind < kn) 01727 { 01728 int knot_mult = 1; 01729 while (st[knot_ind] == st[knot_ind+knot_mult]) 01730 ++knot_mult; 01731 if (kstat < 0) 01732 { 01733 THROW("Unexpected incident."); 01734 } 01735 if (knot_mult > kk - 2) // A kink 01736 corner_pars.push_back(st[knot_ind]); 01737 01738 knot_ind += knot_mult; 01739 } 01740 01741 corner_pars.push_back(st[kn]); 01742 01743 int n2 = 200/(corner_pars.size() - 1); //200; //std::max(200, 4*n); @@sbr Should be const. 01744 01745 // 100212: For debugging/testing: 01746 // int n2 = 30/(corner_pars.size() - 1); //200; //std::max(200, 4*n); @@sbr Should be const. 01747 01748 for (i = 0; i < int(corner_pars.size()) - 1; ++i) 01749 { 01750 double t0=corner_pars[i]; 01751 double t1=corner_pars[i+1]; 01752 double tstep = (t1 - t0)/(n2-1); 01753 // for (i=0; i<n2; i++) 01754 double t = t0; 01755 double ref_step = tstep; 01756 01757 while (t <= t1) 01758 { 01759 // double t=i/double(n2); // Assuming the curve is closed, so we don't 01760 // need t==1.0... 01761 // t = ( crv->et[crv->ik-1] * (1.0-t) + 01762 // crv->et[crv->in] * t ); 01763 01764 Point result; 01765 Point result2; 01766 crv->point(result, t); 01767 01768 if ((bd_res_ratio > 0.0) && (trim_curve_p.size() > 0) && 01769 ((fabs(trim_curve_p[trim_curve_p.size()-1][0] - result[0]) > bd_res_ratio*ustep) || 01770 (fabs(trim_curve_p[trim_curve_p.size()-1][1] - result[1]) > bd_res_ratio*vstep))) 01771 { 01772 t -= ref_step; // Return to t of last approved parameter pt. 01773 ref_step *= 0.5; 01774 t += ref_step; 01775 } 01776 else 01777 // 090219: We only allow a point to be added if it is distinctly different from the last one 01778 // added! 01779 { 01780 // if ( (trim_curve_p.size()==0) || 01781 // ( ((result[0]-trim_curve_p[trim_curve_p.size()-1][0])* 01782 // (result[1]-trim_curve_p[trim_curve_p.size()-1][1]) ) > 1e-14*1e-14 ) ) 01783 { 01784 trim_curve_p.push_back(Vector3D(result[0], result[1], 0.0)); 01785 // printf("added %g %g\n", result[0], result[1]); 01786 srf->point(result2, result[0], result[1]); 01787 trim_curve.push_back(Vector3D(result2.begin())); 01788 } 01789 if (t == t1) 01790 break; 01791 t += tstep; 01792 if (t > t1) { 01793 tstep = t1 - (t - tstep); 01794 t = t1; 01795 } 01796 ref_step = tstep; 01797 } 01798 // printf("==================== t=%g\n", t); 01799 } 01800 } 01801 } // closing of loop over the curves 01802 01803 01804 01805 #ifdef DBG 01806 // 100222: Just to separate different runs from one another... 01807 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); 01808 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); 01809 printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); 01810 #endif 01811 01812 01813 01814 01815 #ifdef DBG 01816 puts("===================================================================================================="); 01817 printf("Weeding out duplicates from contours, tolerance=%e\n", duplicate_tolerance); 01818 #endif 01819 01820 //-------------------------------------------------------------------------------------------------------------- 01821 // 01822 // 090220: Weeding out duplicates. Note that we want the duplicates taken out for the lists used for the 01823 // insideness-testing routines, but we want them in for the corner construction! Hence... making two 01824 // sets of lists... 01825 // 100212: There was a bug here, when more than two points were equal, duplicates would survive. 01826 // 01827 //-------------------------------------------------------------------------------------------------------------- 01828 01829 vector< vector<Vector3D> > trim_curve_all_orig=trim_curve_all, trim_curve_p_all_orig=trim_curve_p_all; 01830 01831 for (int c=0; c<int(crv_set.size()); c++) 01832 { 01833 // printf("Length before: %d %d\n", int(trim_curve_all[c].size()), int(trim_curve_p_all[c].size())); 01834 01835 ASSERT2(trim_curve_all[c].size()>0, printf("Should not be here with degenerate curve.\n")); 01836 ASSERT2(trim_curve_p_all[c].size()>0, printf("Should not be here with degenerate curve.\n")); 01837 01838 vector<Vector3D> trim_curve, trim_curve_p; 01839 trim_curve.push_back(trim_curve_all[c][0]); 01840 trim_curve_p.push_back(trim_curve_p_all[c][0]); 01841 01842 for (int i=1; i<int(trim_curve_all[c].size()); i++) 01843 { 01844 const double last_u = trim_curve_p[trim_curve.size()-1][0]; 01845 const double last_v = trim_curve_p[trim_curve.size()-1][1]; 01846 const double dist_squared = ( (trim_curve_p_all[c][i][0]-last_u) * (trim_curve_p_all[c][i][0]-last_u) + 01847 (trim_curve_p_all[c][i][1]-last_v) * (trim_curve_p_all[c][i][1]-last_v) ); 01848 if ( dist_squared > duplicate_tolerance*duplicate_tolerance ) 01849 { 01850 // printf("%3d:%5d: prev point was (%f, %f), new is (%f, %f), dist=%e, pushing.\n", 01851 // c, i, last_u, last_v, trim_curve_p_all[c][i][0], trim_curve_p_all[c][i][1], sqrt(dist_squared)); 01852 trim_curve.push_back(trim_curve_all[c][i]); 01853 trim_curve_p.push_back(trim_curve_p_all[c][i]); 01854 } 01855 // else 01856 // printf("%3d:%5d: dist = %e, point skipped\n", c, i, sqrt(dist_squared)); 01857 } 01858 01859 // printf("Length after: %d %d\n", int(trim_curve.size()), int(trim_curve_p.size())); 01860 01861 // 100212: Must now handle the first point! It can still be coincident with the last one. 01862 const double last_u = trim_curve_p[trim_curve.size()-1][0]; 01863 const double last_v = trim_curve_p[trim_curve.size()-1][1]; 01864 const double dist_squared = ( (trim_curve_p[0][0]-last_u) * (trim_curve_p[0][0]-last_u) + 01865 (trim_curve_p[0][1]-last_v) * (trim_curve_p[0][1]-last_v) ); 01866 if ( dist_squared <= duplicate_tolerance*duplicate_tolerance ) 01867 { 01868 trim_curve.pop_back(); 01869 trim_curve_p.pop_back(); 01870 } 01871 01872 // Finally, we replace the original curves with the new ones. 01873 trim_curve_p_all[c] = trim_curve_p; 01874 trim_curve_all[c] = trim_curve; 01875 01876 // printf("Length after: %d %d\n", int(trim_curve.size()), int(trim_curve_p.size())); 01877 } 01878 01879 01880 01881 01882 //-------------------------------------------------------------------------------------------------------------- 01883 // 01884 // 100212: A check to make sure we have no duplicates. 01885 // 01886 //-------------------------------------------------------------------------------------------------------------- 01887 01888 { 01889 bool duplicates_found = false; 01890 for (int c=0; c<int(crv_set.size()); c++) 01891 { 01892 vector<Vector3D> &trim_curve = trim_curve_all[c]; 01893 vector<Vector3D> &trim_curve_p = trim_curve_p_all[c]; 01894 01895 for (int i=0; i<int(trim_curve.size()); i++) 01896 { 01897 const int im1 = (i-1+trim_curve.size())%trim_curve.size(); 01898 const double dist_to_previous = 01899 sqrt( (trim_curve_p[i][0]-trim_curve_p[im1][0])*(trim_curve_p[i][0]-trim_curve_p[im1][0]) + 01900 (trim_curve_p[i][1]-trim_curve_p[im1][1])*(trim_curve_p[i][1]-trim_curve_p[im1][1]) ); 01901 01902 // printf("%2d:%5d: dist = %e\n", c, i, dist_to_previous); 01903 if ( dist_to_previous <= duplicate_tolerance ) 01904 { 01905 #ifdef DBG 01906 printf("%2d:%5d: DUPLICATE POINT! dist_to_previous = %e\n", c, i, dist_to_previous); 01907 #endif 01908 duplicates_found = true; 01909 } 01910 } 01911 } 01912 if (duplicates_found) 01913 MESSAGE("\n\n WARNING: Something is fishy. At this point all duplicates should have been eliminated.\n" 01914 " This may lead to a funny mesh...\n\n"); 01915 } 01916 01917 01918 01919 01920 //-------------------------------------------------------------------------------------------------------------- 01921 // 01922 // Setting up the structure for fast inside-testing, and the 'contour' cursor array. 01923 // 081208: Again, extending to a set of contours... 01924 // 100212: The "fast inside-testing" stuff is long gone. 01925 // 01926 //-------------------------------------------------------------------------------------------------------------- 01927 01928 vector< vector<int> > contour_all(crv_set.size()); 01929 for (int c=0; c<int(crv_set.size()); c++) 01930 { 01931 vector<int> &contour = contour_all[c]; 01932 const vector<Vector3D> &trim_curve_p = trim_curve_p_all[c]; 01933 01934 contour.resize(trim_curve_p.size()); 01935 for (i=0; i<(int)trim_curve_p.size(); i++) 01936 contour[i]=3*i; 01937 } 01938 01939 #ifdef DBG 01940 // Just printing out matlab-code for rendering of all contours. 01941 if (1) 01942 for (int c=0; c<int(crv_set.size()); c++) 01943 { 01944 const vector<int> &contour = contour_all[c]; 01945 const vector<Vector3D> &trim_curve_p = trim_curve_p_all[c]; 01946 01947 char *tmp=new char[1000]; 01948 sprintf(tmp, "d%d.m", c); 01949 FILE *f=fopen(tmp, "w"); 01950 for (int i=0; i<int(trim_curve_p.size())-1; i++) 01951 { 01952 const double &x0 = trim_curve_p[contour[i]/3 ][0], &y0=trim_curve_p[contour[i]/3 ][1]; 01953 const double &x1 = trim_curve_p[contour[i]/3+1][0], &y1=trim_curve_p[contour[i]/3+1][1]; 01954 fprintf(f, "line([%f; %f], [%f; %f], 'color', 'b', 'linewidth', 3);\n", x0, x1, y0, y1); 01955 } 01956 fclose(f); 01957 } 01958 #endif 01959 01960 01961 01962 //-------------------------------------------------------------------------------------------------------------- 01963 // 01964 // Cache'ing all 'is_inside' results... 01965 // 081208: Again, extending to a set of contours... 01966 // 01967 // 100210: It seems like a (harmless) "bug" that the 'vert-arrays are filled once for every curve. 01968 // 01969 //-------------------------------------------------------------------------------------------------------------- 01970 01971 vector< vector<int> > inside_all(crv_set.size()); 01972 for (int c=0; c<int(crv_set.size()); c++) 01973 { 01974 const vector<int> &contour = contour_all[c]; 01975 const vector<Vector3D> &trim_curve_p = trim_curve_p_all[c]; 01976 vector<int> &inside = inside_all[c]; 01977 inside = vector<int>((dn+1)*(dm+1)); 01978 double uv[2], s; 01979 vector<Point> res(3); 01980 Point nrm; 01981 01982 ASSERT2(srf->dimension()==3, printf("Huh?! dim=%d\n", srf->dimension())); 01983 01984 for (i=0; i<=dm; i++) 01985 { 01986 double t=i/double(dm); 01987 uv[1]=v0*(1.0-t) + v1*t; 01988 for (j=0; j<=dn; j++) 01989 { 01990 s=j/double(dn); 01991 uv[0]=u0*(1.0-s) + u1*s; 01992 01993 inside[i*(dn+1)+j] = is_inside(trim_curve_p, contour, uv[0], uv[1]); 01994 01995 // 090115: 01996 if (s2m_with_boundary) 01997 inside[i*(dn+1)+j] |= is_on_contour(trim_curve_p, contour, uv[0], uv[1]); 01998 01999 // 090203: Enable this to see the trimming curve inside the untrimmed surface, for debugging purposes. 02000 // 100210: This does not work, or this enabling is not enough. 02001 // inside[i*(dn+1)+j] = 1; // !!! 02002 02003 srf->point(res, uv[0], uv[1], 1); 02004 nrm = res[1].cross(res[2]); 02005 02006 // 100210: Why on earth is this done for every curve?! 02007 vert[i*(dn+1)+j] = Vector3D(res[0].begin()); 02008 vert_p[i*(dn+1)+j] = Vector2D(uv); 02009 02010 bd[i*(dn+1)+j]= (i==0 || i==dm || j==0 || j==dn) ? 1 : 0; 02011 if (nrm.length() < 1.0e-12) 02012 nrm.setValue(0.0, 0.0, 1.0); 02013 norm[i*(dn+1)+j] = Vector3D(nrm.begin()); 02014 norm[i*(dn+1)+j].normalize(); 02015 } 02016 } 02017 } 02018 02019 02020 #ifdef DBG 02021 { 02022 FILE *f5=fopen("r1.m", "w"); // regular mesh 02023 fprintf(f5, "hold on\ngrid on\n"); 02024 for (int i=0; i<dm; i++) 02025 for (int j=0; j<=dn; j++) 02026 fprintf(f5, "line([%f; %f], [%f; %f], 'color', 'k');\n", 02027 vert_p[i*(dn+1)+j][0], vert_p[(i+1)*(dn+1)+j][0], 02028 vert_p[i*(dn+1)+j][1], vert_p[(i+1)*(dn+1)+j][1]); 02029 for (int i=0; i<=dm; i++) 02030 for (int j=0; j<dn; j++) 02031 fprintf(f5, "line([%f; %f], [%f; %f], 'color', 'k');\n", 02032 vert_p[i*(dn+1)+j][0], vert_p[i*(dn+1)+j+1][0], 02033 vert_p[i*(dn+1)+j][1], vert_p[i*(dn+1)+j+1][1]); 02034 fprintf(f5, "hold off\n"); 02035 fclose(f5); 02036 } 02037 #endif 02038 02039 02040 02041 //-------------------------------------------------------------------------------------------------------------- 02042 // 02043 // 090130: We want to preserve corner points on the contour. The idea: Identify all quads containing such 02044 // corners, then treat these quads separately: Split in the first corner, producing four new 02045 // triangles. These must then be processed further, until they contain no corner points. Then these 02046 // triangles must still be processed the "old way". 02047 // 02048 // 090203: Note that by checking that we do not make degenerate primitives, it does not become as important 02049 // to check for duplicate corner points any more. 02050 // 02051 //-------------------------------------------------------------------------------------------------------------- 02052 02053 02054 const double pt_edge_degen_limit=1e-6; // 090203: Should really be relative to the extent of the 02055 // geometry. Used to avoid constructing 02056 // almost-degenerate polygons. Applied in the 02057 // parameter domain. 02058 02059 // const double cosangle_limit= // 090203: The angle must be greater than this for a "corner" 02060 // cos(M_PI/180.0); 02061 const double cosangle_limit= // 090203: The angle must be greater than this for a "corner" 02062 cos(M_PI/180.0*0.1); // to be defined as a corner, i.e., for splitting to 02063 // be done. 02064 02065 const double pt_mult_def=1e-14; // 090203: In the parameter domain, two points closer than 02066 // this are identified. 02067 02068 const double eps=1e-13; // 090203: Used for zero-tests for distances in the parameter domain. 02069 02070 //const double tau=1e-12; // 090203: Used for zero-tests for distances in the geometric space. 02071 02072 const double max_corner_dist= // 090218: When corners are this far away, they are used no matter what 02073 100.0*std::max((u1-u0)/dn, (v1-v0)/dm); // the angle is. Must be larger than 'min_corner_dist'. 02074 02075 const double min_corner_dist= // 090219: When corners are this close, they are not used no 02076 0.5*std::min((u1-u0)/dn, (v1-v0)/dm); // matter what the angle is. 02077 02078 02079 02080 02081 02082 #ifdef DBG 02083 puts("===================================================================================================="); 02084 puts("Generating list of corners to force splitting in."); 02085 #endif 02086 02087 02088 02089 // 090218: Each of these will have dim nxn. 02090 vector<int> skip_quad; // Contains a 1 if quad is to be skipped, i.e., it is 02091 // replaced by custom list of triangles, since it did 02092 // contain corners or such. 02093 02094 vector< vector<Vector3D> > quad_corner_trim_curve; // The 3D corner point, fetched from the proper 02095 // trimming curve. Is this really used afterward? 02096 // Yes. Need it for updating 'vert'. 02097 02098 vector< vector<Vector2D> > quad_corner_trim_curve_p; // The 2D parameter corner point, constructed from a 02099 // 3D point by ignoring the third coordinate. Fetched 02100 // from the proper trimming curve. Not smart to call 02101 // it '...trim_curve...', should have been just 02102 // 'quad_corner_p' or something... 02103 02104 int quad_corners=0; 02105 construct_corner_lists(srf, crv_set, vert, vert_p, norm, mesh, 02106 trim_curve_all_orig, trim_curve_p_all_orig, 02107 dn, dm, bd_res_ratio, eps, cosangle_limit, pt_edge_degen_limit, pt_mult_def, min_corner_dist, 02108 max_corner_dist, skip_quad, quad_corner_trim_curve, quad_corner_trim_curve_p, quad_corners); 02109 02110 02111 02112 02113 02114 //-------------------------------------------------------------------------------------------------------------- 02115 // 02116 // 100210: Ok, in this stage, quads containing corners are split. They are initially split into four 02117 // triangles, which may again be further split in the innermost loop. This is to take care of cases 02118 // where quads contain more than just one "corner points". 02119 // 02120 //-------------------------------------------------------------------------------------------------------------- 02121 02122 #ifdef CORNER_SPLITTING 02123 02124 #ifdef DBG 02125 puts("===================================================================================================="); 02126 printf("\"Pre-splitting\" mesh, %d corners was found.\n", quad_corners); 02127 #endif 02128 02129 // 02130 // 090206: We build structures like 'quad_corner' for needed data. The problem with the "merged list" 02131 // approach is that information for each curve, like where it ends, must be preserved. This is 02132 // because the curves are closed. 02133 // 02134 02135 // Now splitting first quads, then triangles. 02136 02137 #ifdef DBG 02138 printf("dn=%d, dm=%d\n", dn, dm); 02139 #endif 02140 for (int i=0; i<dn*dm; i++) 02141 { 02142 // printf("i=%3d: corners: %d\n", i, int(quad_corner[i].size())); 02143 if (quad_corner_trim_curve_p[i].size()>0) 02144 { 02145 // First, split the quad. 02146 02147 const int p=i/dn, q=i%dn; 02148 02149 vert.push_back(quad_corner_trim_curve[i][0]); 02150 vert_p.push_back(quad_corner_trim_curve_p[i][0]); 02151 bd.push_back(1); 02152 // Unfortunately, we don't have any normals readily available. What we can do, is to just take the 02153 // average of the quad. What we *should* do, is to evaluate the surface... 02154 { 02155 Vector3D new_norm = norm[p*(dn+1)+q] + norm[p*(dn+1)+q+1] + norm[(p+1)*(dn+1)+q] + norm[(p+1)*(dn+1)+q+1]; 02156 new_norm.normalize(); 02157 norm.push_back(new_norm); 02158 } 02159 02160 int first_new_triangle=mesh.size()/3; 02161 02162 // printf("i=%d, p=%d, q=%d, ndx=%d: splitting this quad in %g, %g.\n", i, p, q, p*(n+1)+q, 02163 // vert_p[vert_p.size()-1][0], vert_p[vert_p.size()-1][1]); 02164 02165 add_triangle(vert_p, mesh, vert.size()-1, (p+1)*(dn+1)+q , p *(dn+1)+q ); 02166 add_triangle(vert_p, mesh, vert.size()-1, (p+1)*(dn+1)+q+1, (p+1)*(dn+1)+q ); 02167 add_triangle(vert_p, mesh, vert.size()-1, p *(dn+1)+q+1, (p+1)*(dn+1)+q+1); 02168 add_triangle(vert_p, mesh, vert.size()-1, p *(dn+1)+q , p *(dn+1)+q+1); 02169 02170 // Now, if there are more corners, we have to go through the triangles. And we have to do this again 02171 // for each new corner, and apply the split-testing and eventual splitting to all newly generated 02172 // triangles also. We assume that only one triangle can contain a given corner, so when a corner is 02173 // used, it does not need to be tested for again. 02174 02175 if (int(quad_corner_trim_curve_p[i].size())>1) 02176 { 02177 02178 //printf(" Corners in total: %d, continuing with triangle-splitting.\n", int(quad_corner[i].size())); 02179 02180 for (int j=1; j<int(quad_corner_trim_curve_p[i].size()); j++) 02181 { 02182 bool done_splitting=false; 02183 // 100210: Seems to be enough to enable this to skip the triangle-splitting stage. 02184 // done_splitting=true; 02185 02186 Vector2D &corner = quad_corner_trim_curve_p[i][j]; 02187 //printf(" j=%d, checking corner %f, %f.\n", j, corner[0], corner[1]); 02188 02189 // Ok, must now check, and possibly split triangles from 'first_new_triangle'. 02190 // Note that we quit after we split, since we want to start over again asap. 02191 for (int k=first_new_triangle; (k<int(mesh.size())/3) && (!done_splitting); k++) 02192 { 02193 //printf(" k=%d\n", k); 02194 if ( 02195 pt_inside_tri(corner, vert_p[mesh[3*k]], vert_p[mesh[3*k+1]], vert_p[mesh[3*k+2]]) 02196 // && (pt_dist_from_tri_edge(corner, vert_p[mesh[3*k]], 02197 // vert_p[mesh[3*k+1]], vert_p[mesh[3*k+2]]) 02198 // > pt_edge_degen_limit) 02199 // 090204: This test caused corners on the outer boundary not to trigger 02200 // splitting. Enabling this test is probably not a good idea, unless these 02201 // splitting causes other problems... 02202 ) 02203 // Splitting the triangle. 02204 { 02205 //printf(" splitting, i=%d, j=%d, k=%d.\n", i, j, k); 02206 vert.push_back(quad_corner_trim_curve[i][j]); 02207 vert_p.push_back(corner); 02208 bd.push_back(1); 02209 const int a=mesh[3*k], b=mesh[3*k+1], c=mesh[3*k+2]; 02210 // Unfortunately, we don't have any normals readily available. What we can do, is 02211 // to just take the average of the quad. What we should do, is to evaluate the 02212 // surface... 02213 { 02214 Vector3D tmp = norm[a] + norm[b] + norm[c]; 02215 tmp.normalize(); 02216 norm.push_back(tmp); 02217 } 02218 mesh.erase(mesh.begin()+3*k, mesh.begin()+3*k+3); 02219 add_triangle(vert_p, mesh, vert.size()-1, a, b); 02220 add_triangle(vert_p, mesh, vert.size()-1, b, c); 02221 add_triangle(vert_p, mesh, vert.size()-1, c, a); 02222 done_splitting=true; // No need to check more triangles for a corner already used. 02223 // 090204: Hmm... maybe not entirely true. If splitting was done on an edge, there may 02224 // be a triangle on the other side of that edge that also needs splitting...?! 02225 } 02226 } 02227 } 02228 } 02229 } 02230 } 02231 02232 #endif // end of #ifdef CORNER_SPLITTING 02233 02234 #ifdef DBG 02235 vector<char> col(mesh.size()/3, 'g'); 02236 #endif 02237 02238 02239 02240 02241 #ifdef SPLIT_NON_CORNER_QUADS 02242 02243 #ifdef DBG 02244 puts("===================================================================================================="); 02245 puts("Splitting remaining quads according to the first trimming curve."); 02246 #endif 02247 02248 for (i=0; i<dm; i++) 02249 for (j=0; j<dn; j++) 02250 if (!skip_quad[i*dn+j]) 02251 { 02252 // if ( (inside1[i*(n+1)+j]!=0) && (inside1[i*(n+1)+j]!=1) ) 02253 // MESSAGE("noe er muffens, inside1 er hverken 0 eller 1?!"); 02254 // if ( (inside[i*(n+1)+j]!=0) && (inside[i*(n+1)+j]!=1) ) 02255 // MESSAGE("noe er muffens, inside er hverken 0 eller 1?!"); 02256 02257 int s=((inside_all[0][ i *(dn+1)+j ] << 3) + // 8 02258 (inside_all[0][ i *(dn+1)+j+1] << 2) + // 4 02259 (inside_all[0][(i+1)*(dn+1)+j ] << 1) + // 2 02260 (inside_all[0][(i+1)*(dn+1)+j+1] << 0)); // 1 02261 // if (s!=0) // ((i==6) && (j==17)) 02262 // printf("s=%d, i=%d, j=%d\n", s, i, j); 02263 02264 // 090216: keeping all to test if the missing triangle was made at all. Ok, it was made, but then wrongly split here. 02265 //s=15; 02266 02267 // 090216: checking the lower right corner for debugging of problematic quad... 02268 //if ((fabs(vert_p[i*(n+1)+j+1][0]-.01)<1e-5) && (fabs(vert_p[i*(n+1)+j+1][1]-0.65)<1e-5)) 02269 // if ((i==12) && (j==3)) 02270 // printf("oooooooooooooooooooooooooooooooooooooooooooooooooo> s=%d\n", s), s=15; 02271 02272 // 100223: Shit! Didn't realize this override was here... This means that all the quad-splitting 02273 // code below is actually not used... Wonder when this was done... 02274 s=15; 02275 02276 switch (s) 02277 { 02278 case 15: 02279 // The whole rectangle is inside. 02280 { 02281 add_triangle(vert_p, mesh, (i+1)*(dn+1)+j, i*(dn+1)+j , i *(dn+1)+j+1); 02282 add_triangle(vert_p, mesh, (i+1)*(dn+1)+j, i*(dn+1)+j+1, (i+1)*(dn+1)+j+1); 02283 } 02284 break; 02285 //------------------------------------------------------------------- 02286 case 10: 02287 // The two left (smaller u, smaller j) points are inside. 02288 { 02289 // first segm this col 02290 vector<int> si0; si0.push_back(i ); si0.push_back(i+1); 02291 vector<int> sj0; sj0.push_back(j ); sj0.push_back(j ); 02292 vector<int> si1; si1.push_back(i ); si1.push_back(i+1); 02293 vector<int> sj1; sj1.push_back(j+1); sj1.push_back(j+1); 02294 // 02295 // s0[1] B s1[1] (Husk: i+1 er her!) 02296 // o----x------o 02297 // | | 02298 // | | 02299 // | | 02300 // o----x------o 02301 // s0[0] A s1[0] (Husk: i er her!) 02302 // 02303 split_quad(i+1, j, // s0[1] 02304 i, j, // s0[0] 02305 -1, -1, 02306 // Then the two intersection points are 02307 si0, sj0, si1, // somewhere on s0[0]-s1[0] (A) and 02308 sj1, // somewhere on s0[1]-s1[1] (B). 02309 srf, vert, vert_p, bd, norm, mesh, dn, dm, 02310 trim_curve_p_all[0], contour_all[0], s2m_with_boundary); 02311 } 02312 break; 02313 //------------------------------------------------------------------- 02314 case 5: 02315 // The two right (larger u, larger j) points are inside. 02316 { 02317 // first segm this col 02318 vector<int> si0; si0.push_back(i+1); si0.push_back(i ); 02319 vector<int> sj0; sj0.push_back(j ); sj0.push_back(j ); 02320 vector<int> si1; si1.push_back(i+1); si1.push_back(i ); 02321 vector<int> sj1; sj1.push_back(j+1); sj1.push_back(j+1); 02322 // 02323 // s0[0] A s1[0] (Husk: i+1 er her!) 02324 // o----x------o 02325 // | | 02326 // | | 02327 // | | 02328 // o----x------o 02329 // s0[1] B s1[1] (Husk: i er her!) 02330 // 02331 split_quad(i, j+1, // s1[1] 02332 i+1, j+1, // s1[0] 02333 -1, -1, 02334 // Then the two intersection points are 02335 si0, sj0, si1, // somewhere on s0[0]-s1[0] (A) and 02336 sj1, // somewhere on s0[1]-s1[1] (B). 02337 srf, vert, vert_p, bd, norm, mesh, dn, dm, 02338 trim_curve_p_all[0], contour_all[0], s2m_with_boundary); 02339 } 02340 break; 02341 //------------------------------------------------------------------- 02342 case 12: 02343 // The two lower (smaller v, smaller i) points are inside. 02344 { 02345 // (si0[0], sj0[0]) - (si1[0], sj1[0]) is the first segment, etc. 02346 // first segm this col 02347 vector<int> si0; si0.push_back(i ); si0.push_back(i+1); 02348 vector<int> sj0; sj0.push_back(j+1); sj0.push_back(j ); 02349 vector<int> si1; si1.push_back(i+1); si1.push_back(i ); 02350 vector<int> sj1; sj1.push_back(j+1); sj1.push_back(j ); 02351 // 02352 // s0[1] s1[0] (Husk: i+1 er her!) 02353 // o-----------o 02354 // | | 02355 // B x x A 02356 // | | 02357 // o-----------o 02358 // s1[1] s0[0] (Husk: i er her!) 02359 // 02360 split_quad(i, j, // s1[1] 02361 i, j+1, // s0[0] 02362 -1, -1, 02363 // Then the two intersection points are 02364 si0, sj0, si1, // somewhere on s0[0]-s1[0] (A) and 02365 sj1, // somewhere on s0[1]-s1[1] (B). 02366 srf, vert, vert_p, bd, norm, mesh, dn, dm, 02367 trim_curve_p_all[0], contour_all[0], s2m_with_boundary); 02368 } 02369 break; 02370 //------------------------------------------------------------------- 02371 case 1: 02372 // The upper, right (larger i, larger j) point is inside. 02373 { 02374 // first segm this col 02375 vector<int> si0; si0.push_back(i+1); si0.push_back(i+1); 02376 vector<int> sj0; sj0.push_back(j+1); sj0.push_back(j+1); 02377 vector<int> si1; si1.push_back(i+1); si1.push_back(i ); 02378 vector<int> sj1; sj1.push_back(j ); sj1.push_back(j+1); 02379 // 02380 // s1[0] A s0[0]=s0[1] 02381 // o-------x---o 02382 // | \ | 02383 // | \ x B 02384 // | | 02385 // o-----------o 02386 // s1[1] 02387 // 02388 split_quad(i+1, j+1, // s0[0] 02389 -1, -1, -1, -1, 02390 // Then the two intersection points are 02391 si0, sj0, si1, // somewhere on s0[0]-s1[0] (A) and 02392 sj1, // somewhere on s0[1]-s1[1] (B). 02393 srf, vert, vert_p, bd, norm, mesh, dn, dm, 02394 trim_curve_p_all[0], contour_all[0], s2m_with_boundary); 02395 } 02396 break; 02397 //------------------------------------------------------------------- 02398 case 4: 02399 // The lower, right (smaller i, larger j) point is inside. 02400 { 02401 // first segm this col 02402 vector<int> si0; si0.push_back(i+1); si0.push_back(i ); 02403 vector<int> sj0; sj0.push_back(j+1); sj0.push_back(j ); 02404 vector<int> si1; si1.push_back(i ); si1.push_back(i ); 02405 vector<int> sj1; sj1.push_back(j+1); sj1.push_back(j+1); 02406 split_quad(i, j+1, 02407 -1, -1, -1, -1, 02408 // Then the two intersection points are 02409 si0, sj0, si1, // somewhere on s0[0]-s1[0] (A) and 02410 sj1, // somewhere on s0[1]-s1[1] (B). 02411 srf, vert, vert_p, bd, norm, mesh, dn, dm, 02412 trim_curve_p_all[0], contour_all[0], s2m_with_boundary); 02413 } 02414 break; 02415 //------------------------------------------------------------------- 02416 case 8: 02417 // The lower, left (smaller i, smaller j) point is inside. 02418 { 02419 // first segm this col 02420 vector<int> si0; si0.push_back(i ); si0.push_back(i ); 02421 vector<int> sj0; sj0.push_back(j ); sj0.push_back(j ); 02422 vector<int> si1; si1.push_back(i ); si1.push_back(i+1); 02423 vector<int> sj1; sj1.push_back(j+1); sj1.push_back(j ); 02424 split_quad(i, j, 02425 -1, -1, -1, -1, 02426 // Then the two intersection points are 02427 si0, sj0, si1, // somewhere on s0[0]-s1[0] (A) and 02428 sj1, // somewhere on s0[1]-s1[1] (B). 02429 srf, vert, vert_p, bd, norm, mesh, dn, dm, 02430 trim_curve_p_all[0], contour_all[0], s2m_with_boundary); 02431 } 02432 break; 02433 //------------------------------------------------------------------- 02434 case 2: 02435 // The upper, left (larger i, smaller j) point is inside. 02436 { 02437 // first segm this col 02438 vector<int> si0; si0.push_back(i+1); si0.push_back(i+1); 02439 vector<int> sj0; sj0.push_back(j ); sj0.push_back(j ); 02440 vector<int> si1; si1.push_back(i ); si1.push_back(i+1); 02441 vector<int> sj1; sj1.push_back(j ); sj1.push_back(j+1); 02442 split_quad(i+1, j, 02443 -1, -1, -1, -1, 02444 // Then the two intersection points are 02445 si0, sj0, si1, // somewhere on s0[0]-s1[0] (A) and 02446 sj1, // somewhere on s0[1]-s1[1] (B). 02447 srf, vert, vert_p, bd, norm, mesh, dn, dm, 02448 trim_curve_p_all[0], contour_all[0], s2m_with_boundary); 02449 } 02450 break; 02451 //------------------------------------------------------------------- 02452 case 3: 02453 // The two upper points are inside. 02454 { 02455 // Same as for 12, but swapped the two segments. 02456 // Also using (i+1, j+1) and (i+1, j) as the inside points. 02457 vector<int> si0; si0.push_back(i+1); si0.push_back(i ); 02458 vector<int> sj0; sj0.push_back(j ); sj0.push_back(j+1); 02459 vector<int> si1; si1.push_back(i ); si1.push_back(i+1); 02460 vector<int> sj1; sj1.push_back(j ); sj1.push_back(j+1); 02461 split_quad(i+1, j+1, // s1[1] 02462 i+1, j, // s0[0] 02463 -1, -1, 02464 // Then the two intersection points are 02465 si0, sj0, si1, // somewhere on s0[0]-s1[0] (A) and 02466 sj1, // somewhere on s0[1]-s1[1] (B). 02467 srf, vert, vert_p, bd, norm, mesh, dn, dm, 02468 trim_curve_p_all[0], contour_all[0], s2m_with_boundary); 02469 } 02470 break; 02471 //------------------------------------------------------------------- 02472 case 14: 02473 // All except the upper right point are inside. 02474 { 02475 // first segm this col 02476 vector<int> si0; si0.push_back(i+1); si0.push_back(i+1); 02477 vector<int> sj0; sj0.push_back(j+1); sj0.push_back(j+1); 02478 vector<int> si1; si1.push_back(i ); si1.push_back(i+1); 02479 vector<int> sj1; sj1.push_back(j+1); sj1.push_back(j ); 02480 split_quad(i, j, // 02481 i+1, j, // 02482 i, j+1, // 02483 // Then the two intersection points are 02484 si0, sj0, // somewhere on s0[0]-s1[0] (A) and 02485 si1, sj1, // somewhere on s0[1]-s1[1] (B). 02486 srf, vert, vert_p, bd, norm, mesh, dn, dm, 02487 trim_curve_p_all[0], contour_all[0], s2m_with_boundary); 02488 } 02489 break; 02490 //------------------------------------------------------------------- 02491 case 11: 02492 // All except the lower right point are inside. 02493 { 02494 // first segm this col 02495 vector<int> si0; si0.push_back(i ); si0.push_back(i ); 02496 vector<int> sj0; sj0.push_back(j+1); sj0.push_back(j+1); 02497 vector<int> si1; si1.push_back(i ); si1.push_back(i+1); 02498 vector<int> sj1; sj1.push_back(j ); sj1.push_back(j+1); 02499 split_quad(i+1, j, // 02500 i+1, j+1, // 02501 i, j, // 02502 // Then the two intersection points are 02503 si0, sj0, // somewhere on s0[0]-s1[0] (A) and 02504 si1, sj1, // somewhere on s0[1]-s1[1] (B). 02505 srf, vert, vert_p, bd, norm, mesh, dn, dm, 02506 trim_curve_p_all[0], contour_all[0], s2m_with_boundary); 02507 } 02508 break; 02509 //------------------------------------------------------------------- 02510 case 7: 02511 // All except the lower left point are inside. 02512 { 02513 // first segm this col 02514 vector<int> si0; si0.push_back(i ); si0.push_back(i ); 02515 vector<int> sj0; sj0.push_back(j ); sj0.push_back(j ); 02516 vector<int> si1; si1.push_back(i+1); si1.push_back(i ); 02517 vector<int> sj1; sj1.push_back(j ); sj1.push_back(j+1); 02518 split_quad(i+1, j+1, // 02519 i, j+1, // 02520 i+1, j, // 02521 // Then the two intersection points are 02522 si0, sj0, // somewhere on s0[0]-s1[0] (A) and 02523 si1, sj1, // somewhere on s0[1]-s1[1] (B). 02524 srf, vert, vert_p, bd, norm, mesh, dn, dm, 02525 trim_curve_p_all[0], contour_all[0], s2m_with_boundary); 02526 } 02527 break; 02528 //------------------------------------------------------------------- 02529 case 13: 02530 // All except the upper left point are inside. 02531 { 02532 // first segm this col 02533 vector<int> si0; si0.push_back(i+1); si0.push_back(i+1); 02534 vector<int> sj0; sj0.push_back(j ); sj0.push_back(j ); 02535 vector<int> si1; si1.push_back(i+1); si1.push_back(i ); 02536 vector<int> sj1; sj1.push_back(j+1); sj1.push_back(j ); 02537 split_quad(i, j+1, // 02538 i, j, // 02539 i+1, j+1, // 02540 // Then the two intersection points are 02541 si0, sj0, // somewhere on s0[0]-s1[0] (A) and 02542 si1, sj1, // somewhere on s0[1]-s1[1] (B). 02543 srf, vert, vert_p, bd, norm, mesh, dn, dm, 02544 trim_curve_p_all[0], contour_all[0], s2m_with_boundary); 02545 } 02546 break; 02547 //------------------------------------------------------------------- 02548 } 02549 } 02550 02551 #ifdef DBG 02552 while (col.size()<mesh.size()/3) 02553 col.push_back('r'); 02554 #endif 02555 02556 #endif // end of #ifdef SPLIT_NON_CORNER_QUADS 02557 02558 02559 02560 02561 02562 #ifdef SPLIT_TRIANGLES_AT_OUTER_CURVE 02563 02564 # ifdef DBG 02565 puts("===================================================================================================="); 02566 puts("Splitting all triangles just generated, according to the first trimming curve."); 02567 # endif 02568 02569 // 02570 // 090203: Here we need a new pass to split triangles produced by the new "corner-stuff", and now we should 02571 // split according to the first trimming curve, only. (Note, this all is based on the assumption 02572 // that we should keep whatever is *inside* curve 0, and *outside* curves 1, 2, ...) 02573 // 02574 // 090203: Hmm... maybe this code can somehow be combined with the stage below, for more compact code?! 02575 // 02576 // 090203: Have a suspicion that h.g2 produces a denegerate triangle in this part of the code. 02577 // 02578 02579 for (int c=0; c<std::min(1, int(crv_set.size())); c++) 02580 trim_a_triangle_soup(srf, vert, vert_p, bd, norm, trim_curve_p_all[c], contour_all[c], mesh 02581 # ifdef DBG 02582 , col 02583 # endif 02584 ); 02585 02586 #endif // end of #ifdef SPLIT_TRIANGLES_AT_OUTER_CURVE 02587 02588 02589 02590 02591 02592 #ifdef SPLIT_TRIANGLES_AT_INNER_CURVES 02593 02594 #ifdef DBG 02595 puts("===================================================================================================="); 02596 puts("Splitting triangles according to the second and further trimming curves."); 02597 #endif 02598 02599 //printf("Triangles added in 'make_trimmed_mesh': %d\n", int(mesh.size())/3); 02600 02601 // 02602 // 081208: Adding a post-processing step in which we take into consideration further trimming curves. Now we 02603 // have a mesh consisting of a number of triangles. We loop through all of them, and split them 02604 // similarly to what was done with the first trimming curve above. 02605 // 02606 // (For max code reuse, clarity and orthogonality, we should really replace the above, older code, 02607 // with a pass similar to the one following below.) 02608 // 02609 // First a version without the cached inside-results, since these are kind of messed up now, when we 02610 // must free us from the regular grid... can be fixed later... 02611 // 02612 // 081210: What the h... did I mean by this? Shouldn't using the cached values be 02613 // straightforward?! 02614 // 02615 // 081210: Note that the number of vertices are not reduced, even when it could be. Should be relatively 02616 // easy to add a pass for doing such reduction later, if needed... 02617 // 02618 02619 #ifdef DBG 02620 printf("\n\n================================================== crv_set.size=%d\n\n\n", int(crv_set.size())); 02621 #endif 02622 02623 for (int c=1; c<int(crv_set.size()); c++) 02624 //for (int c=3; c<5; c++) 02625 { 02626 #ifdef DBG 02627 printf("----------==========########## trimming against inner curve %d (range=[%d, %d]) ##########==========----------\n", c, 1, int(crv_set.size())-1); 02628 #endif 02629 trim_a_triangle_soup(srf, vert, vert_p, bd, norm, trim_curve_p_all[c], contour_all[c], mesh, 02630 #ifdef DBG 02631 col, 02632 #endif 02633 true); 02634 } 02635 02636 #endif // end of #ifdef SPLIT_TRIANGLES_AT_INNER_CURVES 02637 02638 02639 02640 02641 #if 0 02642 02643 # if 1 02644 02645 // 100210: What was this?!?! probably some debugging... Seems to have been used for some hardcoded inner 02646 // trimming curves... (number 2 and 3..) 02647 02648 trim_a_triangle_soup(srf, vert, vert_p, bd, norm, trim_curve_p_all[2], contour_all[2], mesh, col, true); 02649 { 02650 FILE *f=fopen("e1.m", "w"); 02651 for (int i=0; i<int(trim_curve_p_all[2].size())-1; i++) 02652 { 02653 const double &x0=trim_curve_p_all[2][contour_all[2][i]/3 ][0]; 02654 const double &y0=trim_curve_p_all[2][contour_all[2][i]/3 ][1]; 02655 const double &x1=trim_curve_p_all[2][contour_all[2][i]/3+1][0]; 02656 const double &y1=trim_curve_p_all[2][contour_all[2][i]/3+1][1]; 02657 fprintf(f, "line([%f; %f], [%f; %f], 'color', 'r', 'linewidth', 3);\n", x0, x1, y0, y1); 02658 } 02659 fclose(f); 02660 } 02661 # endif 02662 02663 puts("####################################################################################################"); 02664 puts("####################################################################################################"); 02665 puts("####################################################################################################"); 02666 02667 02668 # if 0 02669 trim_a_triangle_soup(srf, vert, vert_p, bd, norm, trim_curve_p_all[3], contour_all[3], mesh, col, true); 02670 { 02671 FILE *f=fopen("e2.m", "w"); 02672 for (int i=0; i<int(trim_curve_p_all[3].size())-1; i++) 02673 { 02674 const double &x0=trim_curve_p_all[3][contour_all[3][i]/3 ][0]; 02675 const double &y0=trim_curve_p_all[3][contour_all[3][i]/3 ][1]; 02676 const double &x1=trim_curve_p_all[3][contour_all[3][i]/3+1][0]; 02677 const double &y1=trim_curve_p_all[3][contour_all[3][i]/3+1][1]; 02678 fprintf(f, "line([%f; %f], [%f; %f], 'color', 'r', 'linewidth', 3);\n", x0, x1, y0, y1); 02679 } 02680 fclose(f); 02681 } 02682 # endif 02683 02684 #endif 02685 02686 02687 02688 02689 02690 02691 #ifdef DBG 02692 02693 //-------------------------------------------------------------------------------------------------------------- 02694 // 02695 // 100210: Showing all remaining triangles. Colour coding: 02696 // 02697 // yellow: 02698 // green: 02699 // red: 02700 // cyan: 02701 // magenta: 02702 // 02703 //-------------------------------------------------------------------------------------------------------------- 02704 02705 FILE *f=fopen("vis.m", "w"); 02706 fprintf(f, "clf\n"); 02707 for (int i=0; i<int(mesh.size())/3; i++) 02708 { 02709 const int u=0, v=1; 02710 #if 0 02711 if ( (vert_p[mesh[3*i]][u] > -40) && 02712 (vert_p[mesh[3*i]][u] < -10) && 02713 (vert_p[mesh[3*i]][v] > 25) && 02714 (vert_p[mesh[3*i]][v] < 60) ) 02715 #endif 02716 { 02717 fprintf(f, "patch([%f; %f; %f], [%f; %f; %f], '%c');\n", 02718 vert_p[mesh[3*i]][u], vert_p[mesh[3*i+1]][u], vert_p[mesh[3*i+2]][u], 02719 vert_p[mesh[3*i]][v], vert_p[mesh[3*i+1]][v], vert_p[mesh[3*i+2]][v], col[i]); 02720 fprintf(f, "line([%f; %f; %f; %f], [%f; %f; %f; %f], 'color', 'k');\n", 02721 vert_p[mesh[3*i]][u], vert_p[mesh[3*i+1]][u], vert_p[mesh[3*i+2]][u], vert_p[mesh[3*i]][u], 02722 vert_p[mesh[3*i]][v], vert_p[mesh[3*i+1]][v], vert_p[mesh[3*i+2]][v], vert_p[mesh[3*i]][v]); 02723 } 02724 } 02725 fprintf(f, "zoom on\n"); 02726 fprintf(f, "grid on\n"); 02727 // fprintf(f, "axis('equal');\n"); 02728 fprintf(f, "xlabel('u');\n"); 02729 fprintf(f, "ylabel('v');\n"); 02730 fprintf(f, "title('" 02731 "green = post-corner-splitting\\newline" 02732 "red=post-first-curve-quad-splitting\\newline" 02733 "cyan = post-outer-curve-triangle-splitting, first iteration\\newline" 02734 "magenta = post-inner-curve-triangle-splitting, first iteration\\newline" 02735 "yellow = post-inner-curve-triangle-splitting\\newline" 02736 "blue = post-outer-curve-triangle-splitting');\n"); 02737 // fprintf(f, "set(gca, 'ydir', 'reverse');\n"); // 100210: To get the same view as default 'goview'. 02738 fclose(f); 02739 02740 #endif 02741 02742 02743 02744 02745 // 02746 // 081210: Note that it does not make as much sense as before to return these now, if we have more than one 02747 // trimming curve. But the caller is probably not using them... As it is, we return only for the 02748 // outer trimming curve. 02749 // 02750 trim_curve_0 = trim_curve_all[0]; 02751 trim_curve_p_0 = trim_curve_p_all[0]; 02752 02753 return; 02754 }
void Go::makeBdDegenerate | ( | SplineSurface & | srf, | |
int | bd_idx | |||
) |
Make a specified surface boundary exactly degenerate.
Definition at line 261 of file GeometryTools.C.
References Go::SplineSurface::coefs_begin(), Go::SplineSurface::dimension(), Go::SplineSurface::numCoefs_u(), and Go::SplineSurface::numCoefs_v().
00263 { 00264 bool dir_u = (bd_idx == 2 || bd_idx == 3); 00265 int nmb1 = (dir_u) ? srf.numCoefs_u() : srf.numCoefs_v(); 00266 int nmb2 = (dir_u) ? srf.numCoefs_v() : srf.numCoefs_u(); 00267 int dim = srf.dimension(); 00268 vector<double>::iterator coefs = srf.coefs_begin(); 00269 int kr1 = (dir_u) ? dim : nmb1*dim; 00270 00271 // First compute mean coefficient 00272 vector<double>::iterator c1 = coefs; 00273 if (bd_idx == 3) 00274 c1 += (nmb2-1)*nmb1*dim; 00275 if (bd_idx == 1) 00276 c1 += (nmb2-1)*dim; 00277 00278 vector<double> deg_pt(dim, 0.0); 00279 for (int ki=0; ki<nmb1; ki++, c1+=kr1) 00280 { 00281 vector<double>::iterator d1 = c1; 00282 for (int kj=0; kj<dim; kj++, d1++) 00283 deg_pt[kj] += c1[kj]; 00284 } 00285 for (int kj=0; kj<dim; kj++) 00286 deg_pt[kj] /= (double)nmb1; 00287 00288 c1 = coefs; 00289 if (bd_idx == 3) 00290 c1 += (nmb2-1)*nmb1*dim; 00291 if (bd_idx == 1) 00292 c1 += (nmb2-1)*dim; 00293 00294 for (int ki=0; ki<nmb1; ki++, c1+=kr1) 00295 { 00296 vector<double>::iterator d1 = c1; 00297 for (int kj=0; kj<dim; kj++, d1++) 00298 c1[kj] = deg_pt[kj]; 00299 } 00300 }
void Go::makeUnionKnots | ( | std::vector< BsplineBasis > & | bbasis, | |
double | tol, | |||
std::vector< double > & | union_knots | |||
) |
Compute the union of a set of knot vectors.
Definition at line 138 of file unifyCurveSplineSpace.C.
Referenced by unifyCurveSplineSpace().
00140 { 00141 union_knots.clear(); 00142 00143 vector< std::vector<double>::const_iterator > c_ptr; 00144 vector< std::vector<double>::const_iterator > c_end; 00145 int nmb_crv = bbasis.size(); 00146 c_ptr.resize(nmb_crv); 00147 c_end.resize(nmb_crv); 00148 int ki; 00149 for (ki=0; ki<nmb_crv; ki++) 00150 { 00151 c_ptr[ki] = bbasis[ki].begin(); 00152 c_end[ki] = bbasis[ki].end(); 00153 } 00154 00155 double min_knot, knot; 00156 int max_mult, mult; 00157 while (true) 00158 { 00159 // More knots? 00160 for (ki=0; ki<nmb_crv; ki++) 00161 if (c_ptr[ki] < c_end[ki]) 00162 break; 00163 00164 if (ki == nmb_crv) 00165 break; // All knots collected 00166 00167 min_knot = c_ptr[ki][0]; 00168 for (ki=1; ki<nmb_crv; ki++) 00169 { 00170 if (c_ptr[ki] != c_end[ki]) { 00171 knot = c_ptr[ki][0]; 00172 min_knot = std::min(min_knot, knot); 00173 } 00174 } 00175 00176 mult = 0; 00177 max_mult = 1; 00178 for (ki=0; ki<nmb_crv; ki++) 00179 { 00180 knot = c_ptr[ki][0]; 00181 if (knot < min_knot + tol) 00182 for (mult=0; c_ptr[ki]<c_end[ki] && c_ptr[ki][0]==knot; 00183 mult++, c_ptr[ki]++); 00184 max_mult = std::max(max_mult, mult); 00185 } 00186 00187 for (ki=0; ki<max_mult; ki++) 00188 union_knots.push_back(min_knot); 00189 } 00190 }
void Go::minimalCurvatureRadius | ( | const ParamSurface & | sf, | |
double | tolerance, | |||
double & | mincurv, | |||
double & | pos_u, | |||
double & | pos_v, | |||
double | degenerate_eps, | |||
double | curv_tol = 1.0e-3 | |||
) |
Definition at line 215 of file CurvatureAnalysis.C.
References Go::ParamSurface::containingDomain(), evaluateMinCurvatureRadius(), Go::ParamSurface::isDegenerate(), Go::RectDomain::umax(), Go::RectDomain::umin(), Go::RectDomain::vmax(), and Go::RectDomain::vmin().
00223 { 00224 const RectDomain& dom = sf.containingDomain(); 00225 double start_u = dom.umin(); 00226 double end_u = dom.umax(); 00227 double start_v = dom.vmin(); 00228 double end_v = dom.vmax(); 00229 00230 // Modify domain at degenerate boundaries 00231 bool b, r, t, l; 00232 bool is_degen = sf.isDegenerate(b, r, t, l, degenerate_eps); 00233 if (is_degen) 00234 { 00235 double par_eps = 1.0e-4; // @@@ VSK, dec 08. Rather arbitrary 00236 double fac = 1.0e-3; 00237 if (b) 00238 start_v += std::min(par_eps, fac*(end_v-start_v)); 00239 if (r) 00240 end_u -= std::min(par_eps, fac*(end_u-start_u)); 00241 if (t) 00242 end_v -= std::min(par_eps, fac*(end_v-start_v)); 00243 if (l) 00244 start_u += std::min(par_eps, fac*(end_u-start_u)); 00245 } 00246 00247 vector<double> param_u; 00248 vector<double> param_v; 00249 vector<vector<double> > curvs; 00250 00251 evaluateMinCurvatureRadius(sf, 00252 start_u, end_u, start_v, end_v, 00253 tolerance, 00254 param_u, param_v, curvs, 00255 mincurv, pos_u, pos_v, 00256 true); 00257 00258 /* 00259 // Make an interpolated surface interpolated_surf over the curvatures 00260 00261 // Intersect by level plane defined by mincurv 00262 vector<shared_ptr<SplineCurve> > level_curve = 00263 intersect( aPlane, interpolated_surf); 00264 00265 // Group curves into a set level_curves in two dimensions, answering to "boundingbox" 00266 00267 for (int i = 0; i < level_curve.size() ++i) 00268 { 00269 BoundingBox b = level_curve[i].boundingBox(); 00270 double box_start_u = max(start_u, b.low()[0] - tol); 00271 double box_end_u = min(end_u, b.high()[0] - tol); 00272 double box_start_v = max(start_v, b.low()[1] - tol); 00273 double box_end_v = min(end_v, b.high()[1] - tol); 00274 00275 param_u.resize(0); 00276 param_v.resize(0); 00277 curvs.resize(0); 00278 00279 local_tol = tolerance * min ((box_end_u - box_start_u) / (start_u-end_u), 00280 (box_end_v - box_start_v) / (start_v-end_v)); 00281 local_tol = max(local_tol, 0.1*tolerance); 00282 00283 evaluateMinCurvatureRadius(sf, 00284 box_start_u, box_end_u, box_start_v, box_end_v, 00285 local_tol, 00286 param_u, param_v, curvs, 00287 mincurv, pos_u, pos_v, 00288 false); 00289 } 00290 */ 00291 00292 // Rerun and make a finer evaluation round local minima 00293 vector<double> dummy_u; 00294 vector<double> dummy_v; 00295 vector<vector<double> > dummy_curvs; 00296 00297 //double local_tol = 2.0 * tolerance * tolerance / max(end_u-start_u, end_v-start_v); 00298 double local_tol = tolerance/(double)(std::max(param_u.size(), param_v.size())); 00299 local_tol = min(local_tol, tolerance); 00300 double step_u = (end_u-start_u) / (param_u.size() - 1); 00301 double step_v = (end_v-start_v) / (param_v.size() - 1); 00302 00303 for (int i = 0; i < (int)param_u.size(); ++i) 00304 { 00305 int i_prev = i - (i>0); 00306 int i_next = i + (i < (int)param_u.size()-1); 00307 for (int j = 0; j < (int)param_v.size(); ++j) 00308 { 00309 int j_prev = j - (j>0); 00310 int j_next = j + (j < (int)param_v.size()-1); 00311 double local_curv = curvs[i][j]; 00312 if (local_curv > curvs[i_next][j] || 00313 local_curv > curvs[i_prev][j] || 00314 local_curv > curvs[i][j_next] || 00315 local_curv > curvs[i][j_prev] || 00316 local_curv > curvs[i_next][j_next] || 00317 local_curv > curvs[i_next][j_prev] || 00318 local_curv > curvs[i_prev][j_next] || 00319 local_curv > curvs[i_prev][j_prev]) 00320 continue; 00321 double limit = 2.0 * local_curv - mincurv + curv_tol*mincurv; 00322 bool rand_i = i==i_next || i == i_prev; 00323 bool rand_j = j==j_next || j == j_prev; 00324 if (!rand_i && curvs[i_prev][j]<limit && curvs[i_next][j]<limit) continue; 00325 if (!rand_j && curvs[i][j_prev]<limit && curvs[i][j_next]<limit) continue; 00326 if (!rand_i && !rand_j && curvs[i_prev][j_prev]<limit && curvs[i_next][j_next]<limit) continue; 00327 if (!rand_i && !rand_j && curvs[i_prev][j_next]<limit && curvs[i_next][j_prev]<limit) continue; 00328 00329 dummy_u.resize(0); 00330 dummy_v.resize(0); 00331 dummy_curvs.resize(0); 00332 evaluateMinCurvatureRadius(sf, 00333 start_u+double(i_prev)*step_u, 00334 start_u+double(i_next)*step_u, 00335 start_v+double(j_prev)*step_v, 00336 start_v+double(j_next)*step_v, 00337 local_tol, 00338 dummy_u, dummy_v, dummy_curvs, 00339 mincurv, pos_u, pos_v, 00340 false); 00341 } 00342 } 00343 00344 }
void Go::minimalCurvatureRadius | ( | const SplineCurve & | curve, | |
double & | mincurv, | |||
double & | pos | |||
) |
Definition at line 140 of file Curvature.C.
References Go::SplineInterpolator::basis(), Go::SplineCurve::basis(), Go::BsplineBasis::begin(), curvatureRadius(), Curve2SISL(), Go::SplineCurve::derivCurve(), Go::BsplineBasis::endparam(), Go::SplineInterpolator::interpolate(), Go::BsplineBasis::knotMultiplicity(), Go::BsplineBasis::knotsSimple(), Go::Point::length(), MAXDOUBLE, Go::BsplineBasis::order(), Go::SplineInterpolator::setBasis(), and Go::BsplineBasis::startparam().
Referenced by main().
00144 { 00145 // Find the spline function for the numerator in the derivate of the square of the curvature 00146 00147 BsplineBasis basis = curve.basis(); 00148 int order = basis.order(); 00149 int new_order = 6 * order - 14; 00150 00151 if (new_order < 0) // Straight line 00152 { 00153 mincurv = MAXDOUBLE; 00154 pos = (basis.startparam() + basis.endparam()) / 2.0; 00155 return; 00156 } 00157 00158 vector<double> knots_simple; 00159 vector<double> new_knots; 00160 basis.knotsSimple(knots_simple); 00161 00162 for (size_t i = 0; i < knots_simple.size(); ++i) 00163 { 00164 int old_mult = basis.knotMultiplicity(knots_simple[i]); 00165 int new_mult = 5 * order - 11 + old_mult; 00166 if (old_mult >= order-2) new_mult -= 3 - order + old_mult; 00167 for (int j = 0; j < new_mult; ++j) new_knots.push_back(knots_simple[i]); 00168 } 00169 00170 int num_coefs = new_knots.size() - new_order; 00171 00172 BsplineBasis new_basis(new_order, new_knots.begin(), new_knots.end()); 00173 00174 vector<double> coefs_par; // Parameter values for the coefs (Greville) 00175 vector<double> coefs; 00176 00177 shared_ptr<SplineCurve> d_curve(curve.derivCurve(1)); 00178 shared_ptr<SplineCurve> dd_curve(d_curve->derivCurve(1)); 00179 shared_ptr<SplineCurve> ddd_curve(dd_curve->derivCurve(1)); 00180 00181 for (int i = 0; i < num_coefs; ) 00182 { 00183 int knot_pos = i + 1; 00184 while (knot_pos < int(new_knots.size()) && new_knots[knot_pos-1] == new_knots[knot_pos]) 00185 ++knot_pos; 00186 double step = (new_knots[knot_pos] - new_knots[knot_pos-1]) / double(knot_pos - i); 00187 double tpar = new_knots[knot_pos-1] + step/2.0; 00188 for (;i < knot_pos; ++i) 00189 { 00190 coefs_par.push_back(tpar); 00191 tpar += step; 00192 } 00193 } 00194 00195 for (int i = 0; i < num_coefs; ++i) 00196 { 00197 double tpar = coefs_par[i]; 00198 Point d_p, dd_p, ddd_p; 00199 d_curve->point(d_p, tpar); 00200 dd_curve->point(dd_p, tpar); 00201 ddd_curve->point(ddd_p, tpar); 00202 00203 coefs.push_back( (d_p % dd_p) * (d_p % (ddd_p * (d_p * d_p) - dd_p * 3 * (d_p * dd_p))) ); 00204 } 00205 00206 vector<double> numerator_coefs; 00207 vector<double> dummy_tangents; 00208 vector<int> dummy_index; 00209 SplineInterpolator interpolator; 00210 interpolator.setBasis(new_basis); 00211 interpolator.interpolate(coefs_par, coefs, dummy_index, 00212 dummy_tangents, numerator_coefs); 00213 00214 shared_ptr<SplineCurve> numerator_curve( 00215 new SplineCurve(num_coefs, new_order, 00216 interpolator.basis().begin(), 00217 numerator_coefs.begin(), 1)); 00218 00219 SISLCurve *num_sisl = Curve2SISL(*(numerator_curve.get()), false); 00220 SISLObject *qo1 = 0; 00221 SISLObject *qo2 = 0; 00222 SISLPoint *qp = 0; 00223 double spoint[1]; 00224 spoint[0] = 0.0; 00225 int kstat = 0; 00226 SISLIntdat *qintdat = 0; 00227 double aepsge = 1.0e-9; 00228 00229 bool mincurvFound = false; 00230 vector<double> extremalParametervalues; 00231 00232 if (!(qo1 = newObject(SISLCURVE))) goto error101; 00233 qo1 -> c1 = num_sisl; 00234 qo1 -> o1 = qo1; 00235 00236 if (!(qo2 = newObject(SISLPOINT))) goto error101; 00237 spoint[0] = 0.0; 00238 if(!(qp = newPoint(spoint,1,1))) goto error101; 00239 qo2 -> p1 = qp; 00240 00241 sh1761(qo1,qo2,aepsge,&qintdat,&kstat); 00242 if (kstat < 0) goto error101; 00243 00244 00245 if (qintdat) 00246 { 00247 for (int i = 0; i < qintdat->ipoint; ++i) 00248 extremalParametervalues.push_back(qintdat->vpoint[i]->epar[0]); 00249 } 00250 00251 for (size_t i = 0; i < knots_simple.size(); ++i) 00252 extremalParametervalues.push_back(knots_simple[i]); 00253 00254 for (size_t i = 0; i < extremalParametervalues.size(); ++i) 00255 { 00256 Point d_p, dd_p; 00257 d_curve->point(d_p, extremalParametervalues[i]); 00258 dd_curve->point(dd_p, extremalParametervalues[i]); 00259 double curv_numerator = (d_p % dd_p).length(); 00260 double curv_denominator = d_p.length(); 00261 curv_denominator = curv_denominator * curv_denominator * curv_denominator; 00262 if (curv_numerator <= curv_denominator * 1.0e-9) continue; 00263 00264 double curvatureRadius = curv_denominator/curv_numerator; // Same as 1/curvature 00265 if (!mincurvFound || curvatureRadius < mincurv) 00266 { 00267 mincurvFound = true; 00268 mincurv = curvatureRadius; 00269 pos = extremalParametervalues[i]; 00270 00271 } 00272 } 00273 00274 error101: 00275 if (qo1) freeObject(qo1); 00276 if (qo2) freeObject(qo2); 00277 if (qintdat) freeIntdat(qintdat); 00278 00279 00280 }
void Go::minimise_conjugated_gradient | ( | FunctionMinimizer< Functor > & | dfmin | ) | [inline] |
This is the algorithm for minimising a function taking multiple parameters, using the conjugated gradient method.
It is used in conjunction with the FunctionMinimizer class. Documentation for both can be found here: FunctionMinimizer
Definition at line 53 of file GeneralFunctionMinimizer_implementation.h.
References Go::FunctionMinimizer< Functor >::atMax(), Go::FunctionMinimizer< Functor >::atMin(), Go::FunctionMinimizer< Functor >::fval(), Go::FunctionMinimizer< Functor >::grad(), Go::Point::length2(), Go::FunctionMinimizer< Functor >::minimize(), and Go::FunctionMinimizer< Functor >::numPars().
Referenced by Go::SplineSurface::closestPoint(), closestPtCurves(), closestPtCurveSurf(), closestPtSurfSurfPlaneFunctional(), and Go::ParamSurface::singularity().
00055 { 00056 const double TOL = std::numeric_limits<double>::epsilon(); //1.0e-8; 00057 const double EPS = 1.0e-10; 00058 // minimising the 'dfmin' function using conjugated gradients. 00059 const int N = dfmin.numPars(); 00060 Point gradient(N), old_gradient(N), dir(N); 00061 dfmin.grad(old_gradient); 00062 dir = -old_gradient; 00063 double old_val = dfmin.fval(); 00064 while(true) { 00065 00066 // make sure direction is not uphill (is this already guaranteed??) 00067 // and truncating it if we are at the border of the domain 00068 if (dir * old_gradient > 0) { 00069 dir *= -1; 00070 } 00071 for (int i = 0; i < N; ++i) { 00072 if ((dfmin.atMin(i) && dir[i] < 0) || (dfmin.atMax(i) && dir[i] > 0)) { 00073 dir[i] = 0; 00074 // conjugate gradient value is broken since we modified dir. 00075 // Restarting cycle. 00076 } 00077 } 00078 00079 // minimize along this direction 00080 bool hit_domain_edge = false; 00081 double new_val = dfmin.minimize(dir, hit_domain_edge); 00082 if (2.0 * fabs(new_val - old_val) <= TOL * (fabs(new_val) + fabs(old_val)+ EPS)) { 00083 // we have reached a minimum 00084 break; 00085 } else { 00086 old_val = new_val; 00087 } 00088 00089 // choose new direction 00090 dfmin.grad(gradient); 00091 if (!hit_domain_edge) { 00092 // we are still in a conjugated gradient cycle. Choose new direction 00093 // using conjugated gradients (Polak-Ribiere variant) 00094 00095 Point diff = gradient - old_gradient; 00096 double factor = gradient * diff / old_gradient.length2(); 00097 Point dir_saved = dir; 00098 dir *= factor; 00099 dir -= gradient; 00100 00101 if (dir * old_gradient > 0) { 00102 dir *= -1; 00103 } 00104 00105 bool on_boundary = false; 00106 for (int i = 0; i != N; ++i) { 00107 if ((dfmin.atMin(i) && dir[i] < 0) || (dfmin.atMax(i) && dir[i] > 0)) { 00108 on_boundary = true; 00109 gradient[i] = old_gradient[i] = 0; 00110 dir_saved[i] = 0; // we will have to recalculated 'dir' based on this vector 00111 } 00112 } 00113 00114 if (on_boundary) { 00115 // the direction we choose will take us out of the domain. Reduce problem 00116 // to conjugated gradient in a lower dimension. 00117 dir = dir_saved; 00118 diff = gradient - old_gradient; 00119 factor = gradient * diff / old_gradient.length2(); 00120 dir *= factor; 00121 dir -= gradient; 00122 } 00123 old_gradient = gradient; 00124 } else { 00125 // We ran into an edge of the domain. Re-initialising conjugate 00126 // gradient method using steepest descent. 00127 dir = - gradient; 00128 for (int i = 0; i != N; ++i) { 00129 if ((dfmin.atMin(i) && dir[i] < 0) || (dfmin.atMax(i) && dir[i] > 0)) { 00130 dir[i] = 0; 00131 gradient[i] = 0; 00132 } 00133 } 00134 old_gradient = gradient; 00135 } 00136 } 00137 }
bool Go::negativeProj | ( | const SplineSurface & | surface, | |
const Array< Vector3D, 2 > & | refvector, | |||
const double | eps = 0.0 | |||
) |
Returns true if any vector difference between neighboring control points in the u- or v-directions has negative projection on the given reference vector.
surface | the SplineSurface containing the control points | |
refvector | the vector onto which we carry out the projection | |
eps | toleance used when defining whether a vector has a negative projection onto 'refvector' (the scalar product must be less than -eps). |
Definition at line 58 of file GGUdominant.C.
References Go::SplineSurface::coefs_begin(), Go::SplineSurface::numCoefs_u(), and Go::SplineSurface::numCoefs_v().
00062 { 00063 int num_u = surface.numCoefs_u(); 00064 int num_v = surface.numCoefs_v(); 00065 Vector3D temp; 00066 int i = 0, j = 0; 00067 while (i < num_u-1) { 00068 j = 0; 00069 while (j < num_v) { 00070 temp[0] = *(surface.coefs_begin() + 3*(num_u*j + i+1)) 00071 - *(surface.coefs_begin() + 3*(num_u*j + i)); 00072 temp[1] = *(surface.coefs_begin() + 3*(num_u*j + i+1) + 1) 00073 - *(surface.coefs_begin() + 3*(num_u*j + i) + 1); 00074 temp[2] = *(surface.coefs_begin() + 3*(num_u*j + i+1) + 2) 00075 - *(surface.coefs_begin() + 3*(num_u*j + i) + 2); 00076 // Positive tolerance means that there must be a small 00077 // _nonzero_ negative projection before it is reported as 00078 // negative! 00079 if (temp * refvector[0] < -eps) 00080 return true; 00081 ++j; 00082 } 00083 ++i; 00084 } 00085 i = 0; 00086 while (i < num_u) { 00087 j = 0; 00088 while (j < num_v-1) { 00089 temp[0] = *(surface.coefs_begin() + 3*(num_u*(j+1) + i)) 00090 - *(surface.coefs_begin() + 3*(num_u*j + i)); 00091 temp[1] = *(surface.coefs_begin() + 3*(num_u*(j+1) + i) + 1) 00092 - *(surface.coefs_begin() + 3*(num_u*j + i) +1); 00093 temp[2] = *(surface.coefs_begin() + 3*(num_u*(j+1) + i) + 2) 00094 - *(surface.coefs_begin() + 3*(num_u*j + i) + 2); 00095 // Positive tolerance means that there must be a small 00096 // _nonzero_ negative projection before it is reported as 00097 // negative! 00098 if (temp * refvector[1] < -eps) 00099 return true; 00100 ++j; 00101 } 00102 ++i; 00103 } 00104 00105 return false; 00106 }
void Go::nextStep | ( | double & | cdist, | |
double & | cdiff1, | |||
double & | cdiff2, | |||
std::vector< Point > & | eval1, | |||
std::vector< Point > & | eval2 | |||
) |
Computes the distance vector and value beetween a point on the first curve and a point on the second curve.
And computes a next step on both curves. This is equivalent to the nearest way to the parameter plane in the tangent plane from a point in the distance surface between two curves. Ported from the sisl function s1770_s9dir. METHOD : The method is to compute the parameter distance to the points on both tangents which is closest to each other. The difference vector beetween these points are orthogonal to both tangents. If the distance vector beetween the two points on the curve is "diff" and the two derivative vectors are "der1" and "der2", and the two wanted parameter distances are "dt1" and "dt2", then we get the following system of equations:
<dt1*der1+dist-dt2*der2,der2> = 0 <dt1*der1+dist-dt2*der2,der1> = 0 This is further: | -<der1,der2> <der2,der2> | | dt1 | | <diff,der2> | | | | | = | | | -<der1,der1> <der1,der2> | | dt2 | | <diff,der1> |
The solution of this matrix equation dt1,dt2 are returned in the parameters cdiff1,cdiff2.
Definition at line 400 of file closestPtCurves.C.
References Go::Point::length().
Referenced by closestPtCurveSurf(), closestPtSurfSurfPlaneGeometrical(), and extremalPtSurfSurf().
00403 { 00404 const double TOL = 1.0e-12; 00405 00406 Point& p1 = eval1[0]; // Value 00407 Point& d1 = eval1[1]; // 1. derivative 00408 00409 Point& p2 = eval2[0]; 00410 Point& d2 = eval2[1]; 00411 00412 Point gdiff = p1 - p2; // Distance vector 00413 cdist = gdiff.length(); // Length of distance vector 00414 00415 double t1,t2,t3,t4,t5; // Variables in equation system 00416 // scalar products 00417 t1 = d1*d1; 00418 t2 = d1*d2; 00419 t3 = d2*d2; 00420 t4 = gdiff*d1; 00421 t5 = gdiff*d2; 00422 00423 double tdet = t2*t2 - t1*t3; // Determinant 00424 00425 // double delta_t1, delta_t2; 00426 if (fabs(tdet) < TOL) { 00427 cdiff1 = 0.0; 00428 cdiff2 = 0.0; 00429 } 00430 else { // Using Cramer's rule to find the solution of the system 00431 cdiff1 = (t4*t3 - t5*t2)/tdet; 00432 cdiff2 = (t2*t4 - t1*t5)/tdet; 00433 } 00434 }
void Go::normalize | ( | ForwardIterator | first, | |
ForwardIterator | last | |||
) | [inline] |
normalize makes the length of a vector 1.0
Definition at line 149 of file Utils.h.
References sum_squared().
Referenced by make_trimmed_mesh().
00151 { 00152 typename go_iterator_traits<ForwardIterator>::value_type d 00153 = sqrt(sum_squared(first, last)); 00154 d = 1.0/d; 00155 for (; first != last; ++first) 00156 (*first) *= d; 00157 }
void Go::normalNoise | ( | double * | res, | |
double | mean_err, | |||
int | num_samples | |||
) |
Gives a certain number of random samples drawn from the normal distribution.
res | a pointer to the array where the resulting samples should be written. | |
mean_err | the sigma parameter to the normal distribution. | |
num_samples | the desired number of samples (should also be the size of the array pointed to by res. |
Definition at line 25 of file randomnoise.C.
00027 { 00028 double scale_factor = double(2) / double(RAND_MAX); 00029 double v1, v2, r2, fact; 00030 for (int i = 0; i < num_samples; i+=2) { 00031 do { 00032 v1 = double(rand()) * scale_factor - 1; 00033 v2 = double(rand()) * scale_factor - 1; 00034 r2 = v1 * v1 + v2 * v2; 00035 } while (r2 > 1 || r2 == double(0) || false); 00036 // we now know that the point (v1, v2) is within the unit circle, away from 0 00037 fact = sqrt(- 2 * log(r2)/r2); 00038 fact *= mean_err; 00039 res[i] = v1 * fact; 00040 if (i+1 < num_samples) { 00041 res[i+1] = v2 * fact; 00042 } 00043 } 00044 }
void Go::objsToFile | ( | vector< shared_ptr< GeomObject > > & | geom_objs, | |
char * | to_file | |||
) |
Definition at line 103 of file SplineDebugUtils.C.
void GO_API Go::objsToFile | ( | std::vector< boost::shared_ptr< GeomObject > > & | geom_objs, | |
char * | to_file | |||
) |
writes the geometric objects (with header) to the specified file name.
geom_objs | the objects to write to file. | |
to_file | the file name to which the objects will be written. |
void Go::objToFile | ( | GeomObject * | geom_obj, | |
char * | to_file | |||
) |
writes the geometric object (with header) to the specified file name.
geom_obj | the object to write to file. | |
to_file | the file name to which the object will be written. |
Definition at line 91 of file SplineDebugUtils.C.
References Go::Streamable::write(), and Go::GeomObject::writeStandardHeader().
Rational Go::operator* | ( | const Rational & | r1, | |
const Rational | r2 | |||
) |
Definition at line 132 of file Rational.h.
Point Go::operator* | ( | double | d, | |
const Point & | p | |||
) | [inline] |
Array<T, Dim> Go::operator* | ( | const Array< double, Dim > & | a, | |
const T | b | |||
) | [inline] |
Definition at line 145 of file BaryCoordSystem.h.
Rational Go::operator+ | ( | const Rational & | r1, | |
const Rational | r2 | |||
) |
Definition at line 118 of file Rational.h.
Rational Go::operator- | ( | const Rational & | r1, | |
const Rational | r2 | |||
) |
Definition at line 125 of file Rational.h.
Rational Go::operator/ | ( | const Rational & | r1, | |
const Rational | r2 | |||
) |
Definition at line 139 of file Rational.h.
bool Go::operator< | ( | const Point & | p1, | |
const Point & | p2 | |||
) | [inline] |
Definition at line 509 of file Point.h.
References DEBUG_ERROR_IF, and Go::Point::dimension().
00510 { 00511 const int dim = p1.dimension(); 00512 DEBUG_ERROR_IF(p2.dimension() != dim, "Dimension Mismatch"); 00513 for (int i = dim-1; i >= 0; --i) { 00514 if (p1[i] > p2[i]) return false; 00515 if (p1[i] < p2[i]) return true; 00516 } 00517 return false; 00518 }
std::ostream& Go::operator<< | ( | std::ostream & | os, | |
const Rational & | p | |||
) |
Definition at line 146 of file Rational.h.
References Go::Rational::write().
std::ostream& Go::operator<< | ( | std::ostream & | os, | |
const Go::Point & | v | |||
) | [inline] |
Stream insertion for Point.
Definition at line 505 of file Point.h.
References Go::Point::write().
00506 { v.write(os); return os; }
std::ostream& Go::operator<< | ( | std::ostream & | os, | |
const MatrixXD< T, Dim > & | m | |||
) | [inline] |
Specialization of the determinant function for the 1x1 case.
Terminates the det() template recursion. output operator
Definition at line 432 of file MatrixXD.h.
std::ostream& Go::operator<< | ( | std::ostream & | os, | |
const Go::Array< T, Dim > & | v | |||
) | [inline] |
std::ostream& Go::operator<< | ( | std::ostream & | os, | |
const Go::Streamable & | obj | |||
) | [inline] |
Definition at line 54 of file Streamable.h.
References Go::Streamable::write().
00056 { 00057 obj.write(os); 00058 return os; 00059 }
std::istream& Go::operator>> | ( | std::istream & | is, | |
Go::Point & | v | |||
) | [inline] |
Stream extraction for Point.
Definition at line 501 of file Point.h.
References Go::Point::read().
00502 { v.read(is); return is; }
std::istream& Go::operator>> | ( | std::istream & | is, | |
Go::Array< T, Dim > & | v | |||
) | [inline] |
Stream extraction for Array.
Definition at line 419 of file Array.h.
References Go::Array< T, Dim >::read().
00420 { v.read(is); return is; }
std::istream& Go::operator>> | ( | std::istream & | is, | |
Go::Streamable & | obj | |||
) | [inline] |
Definition at line 47 of file Streamable.h.
References ALWAYS_ERROR_IF, and Go::Streamable::read().
00048 { 00049 ALWAYS_ERROR_IF(is.eof(), "End of file reached. Cannot read."); 00050 obj.read(is); 00051 return is; 00052 }
void Go::orientCurves | ( | const std::vector< PtrToCurveType > & | curves, | |
std::vector< int > & | permutation, | |||
std::vector< bool > & | reversed, | |||
double | neighbour_tol, | |||
bool | assume_manifold = true | |||
) | [inline] |
This function sorts and orients a set of curves so that curves whose endpoints coincide will be ordered consecutively, and eventually 'reversed' so that startpoints meet endpoints.
It is assumed that the set of curves given constitute one or several manifolds, ie., that there will not be cases where three or more endpoints meet at a common point (this would make the above mentionned ordering impossible).
curves | a vector containing the set of (pointers to) curves to be analysed. It is expected that they constitute one or more 1-manifolds. | |
permutation | upon return, this vector will contain a permutation of the indices to the input curves such that after this permutation, curves whose endpoints are connected will become 'consecutive'. | |
reversed | upon return, this vector, whose length will be equal to that of 'curves' and 'permutation', will contain bool values. If curve at position 'i' in the 'curves' vector needs to be reversed in order to connect startpoint-to-endpoint with its neighbours, then the corresponding value in 'reversed' will be 'true', and 'false' if no reversal is necessary. | |
neighbour_tol | the tolerance used when checking for coincident points. | |
assume_manifold | if the user specifies 'true', then the manifold property will be assumed, but will not be explicitly checked. If 'false' is specified, then the input will be checked for consistency with respect to this, and an exception will be cast if the manifold condition is violated. |
Definition at line 43 of file orientCurves.h.
References Go::Point::dist(), and THROW.
Referenced by Go::CurveLoop::fixInvalidLoop().
00049 { 00050 // registering all points 00051 int i, num_seg = curves.size(); 00052 std::vector<Point> endpoints(2 * num_seg); 00053 for (i = 0; i < num_seg; ++i) { 00054 curves[i]->point(endpoints[2 * i + 0], curves[i]->startparam()); 00055 curves[i]->point(endpoints[2 * i + 1], curves[i]->endparam()); 00056 } 00057 00058 // detecting connections 00059 std::vector<int> connected_to(2 * num_seg, -1); 00060 for (i = 0; i < 2 * num_seg; ++i) { 00061 if (connected_to[i] == -1 || !assume_manifold) { 00062 Point& p1 = endpoints[i]; 00063 bool found = (connected_to[i] != -1); 00064 // this point has not been checked for connections yet 00065 for (int j = i+1; j < 2 * num_seg; ++j) { 00066 if (connected_to[j] == -1) { 00067 if (p1.dist(endpoints[j]) < neighbour_tol) { 00068 // we consider these points to be connected 00069 connected_to[i] = j; 00070 connected_to[j] = i; 00071 if (assume_manifold) { 00072 break; 00073 } else if (found == true) { 00074 THROW("Multiple connected points detected in " 00075 " orientCurves(). Not a 1-manifold!" ); 00076 } else { 00077 found = true; 00078 } 00079 } 00080 } 00081 } 00082 } 00083 } 00084 00085 // Making the permutation std::vector 00086 permutation.clear(); 00087 permutation.reserve(num_seg); 00088 reversed.clear(); 00089 reversed.reserve(num_seg); 00090 std::vector<bool> visited(2*num_seg, false); 00091 // First handle all open chains 00092 for (i = 0; i < 2*num_seg; ++i) { 00093 if (!visited[i] && connected_to[i] == -1) { 00094 int current = i; 00095 do { 00096 permutation.push_back(current/2); 00097 bool current_parity = (current%2 == 0); 00098 int partner = current_parity ? current + 1 : current - 1; 00099 reversed.push_back(!current_parity); 00100 visited[current] = true; 00101 visited[partner] = true; 00102 current = connected_to[partner]; 00103 } while (current != -1); 00104 } 00105 } 00106 // Then all closed chains (loops) 00107 for (i = 0; i < 2*num_seg; ++i) { 00108 if (!visited[i]) { 00109 int current = i; 00110 do { 00111 permutation.push_back(current/2); 00112 bool current_parity = (current%2 == 0); 00113 int partner = current_parity ? current + 1 : current - 1; 00114 reversed.push_back(!current_parity); 00115 visited[current] = true; 00116 visited[partner] = true; 00117 current = connected_to[partner]; 00118 } while (current != i); 00119 } 00120 } 00121 }
void Go::osloalg | ( | int | ij, | |
int | imy, | |||
int | ik, | |||
int | in, | |||
int * | jpl, | |||
int * | jfi, | |||
int * | jla, | |||
double * | et, | |||
double * | etau, | |||
double * | galfa | |||
) |
Corresponds to s1701 in SISL This function computes in a compact format a line in the discrete B-spline matrix converting between an orginal basis "etau" and a new basis "et".
ij | The index of the new vertice | |
imy | An index on etau, where the input value are to be etau(imy) <= et(ij) < etau(imy + 1). | |
ik | The order of the B-spline. | |
in | The number of the orginal vertices. | |
et | The new knot vector. | |
etau | The old knot vector. | |
et | An array ep(ik) to local use. Such that we do not need to allocate the array locally after each call. | |
jpl | The negativ difference between the index in galfa and the real knot inserten matrix. | |
jfi | The index of the first element in the line j in the the real knot inserten matrix whice is not zero. The element with the index (jfi+jpl) in galfa is the same as the element with index jfi in the real line j in the knot inserten matrix. | |
jla | The index of the last element in the line j in the real knot inserten matrix whice is not zero. The element with the index (jla+jpl) in galfa is the same as the element with index jla in the real line j in the knot inserten matrix. | |
galfa | A compressed line in the knot inserten matrix. |
Definition at line 20 of file osloalg.C.
Referenced by Go::SplineCurve::insertKnot(), and refmatrix().
00028 : To compute in a compact format a line in the discrete 00029 * B-spline matrix converting between an orginal basis 00030 * "etau" and a new basis "et". 00031 * 00032 * 00033 * 00034 * INPUT : ij - The index of the new vertice 00035 * imy - An index on etau, where the input value are to be 00036 * etau(imy) <= et(ij) < etau(imy + 1). 00037 * ik - The order of the B-spline. 00038 * in - The number of the orginal vertices. 00039 * et - The new knot vector. 00040 * etau - The old knot vector. 00041 * ep - An array ep(ik) to local use. Such that we 00042 * do not need to allocate the array locally after 00043 * each call. 00044 * 00045 * 00046 * 00047 * OUTPUT : jpl - The negativ difference between the index in galfa 00048 * and the real knot inserten matrix. 00049 * jfi - The index of the first element in the line j in the 00050 * the real knot inserten matrix whice is not zero. 00051 * The element with the index (jfi+jpl) in galfa 00052 * is the same as the element with index jfi in 00053 * the real line j in the knot inserten matrix. 00054 * jla - The index of the last element in the line j in the 00055 * real knot inserten matrix whice is not zero. 00056 * The element with the index (jla+jpl) in galfa 00057 * is the same as the element with index jla in 00058 * the real line j in the knot inserten matrix. 00059 * galfa - A compressed line in the knot inserten matrix. 00060 * jstat - status messages 00061 * > 0 : warning 00062 * = 0 : ok 00063 * < 0 : error 00064 * 00065 * 00066 * METHOD : Using the Oslo-algorithm 00067 * 00068 * 00069 * REFERENCES : Making The Oslo algorithm more efficient. 00070 * by T.Lyche and K.Moerken. 00071 * SIAM J.NUMER.ANAL Vol. 23, No. 3, June 1986. 00072 * 00073 *- 00074 * CALLS : 00075 * 00076 * WRITTEN BY : Arne Laksaa, SI, 88-11. 00077 * REVISED BY : Atgeirr F Rasmussen, Sintef, 06/04/2001. Go-ified. 00078 * 00079 **********************************************************************/ 00080 { 00081 int kp; /* Control variable in loop. */ 00082 int kv,kkv; /* Help variables. */ 00083 double *ah; /* Help pointer to galfa. */ 00084 double tbeta,tbeta1; /* Help variables. */ 00085 double td1,td2; /* Help variables. */ 00086 double *tu; /* Pointer to the knot vector. */ 00087 00088 std::vector<double> epvec(ik); 00089 double* ep = &epvec[0]; 00090 00091 /* Correction of imy to be sure that the the old knot etau(imy) 00092 is not passing the new knot et(ij). */ 00093 00094 kp=ij+1; kkv=ij+ik; in--; 00095 while ((et[kp] == etau[imy]) && kp<kkv) {kp++; imy--;} 00096 00097 00098 /* Counting the old and the new knot and copying the new knots 00099 in the area between et(ij) and et(ij+ik) in the array ep. */ 00100 00101 for (kp=imy+1,kv=0,ij++; ij<kkv; ij++) 00102 if (et[ij] == etau[kp]) kp++; 00103 else ep[kv++] = et[ij]; 00104 00105 00106 /* Compute the negativ difference between the index in galfa and 00107 the real knot inserten matrix. */ 00108 00109 *jpl=ik-imy-1; 00110 00111 00112 /* Changing the galfa so we may use the index in the real matrix. */ 00113 00114 galfa += *jpl; 00115 00116 00117 /* Initialise the last element. */ 00118 00119 galfa[imy] = 1; 00120 00121 00122 /* Here we go one time for each new knot from et(j+1) 00123 until et(j+k) we insert. */ 00124 00125 for (kp=0,kkv=ik-kv,ij=in+kv-1,in +=ik; kp<kv; kp++,kkv++,ep++) 00126 { 00127 /* The initialising: The two first are not changing. 00128 kkv = ik-kv , the nuber of old knots in the field. 00129 This variabel is counting up to ik 00130 (the order) during the loops. 00131 ij = in+kv-1, minus the maximum of kp it 00132 gives the index of the last 00133 orginal vertices. 00134 in = in+kv-1, the index of the last element in et. */ 00135 00136 00137 /* Here we note the special case where we are at the 00138 start of the matrix and we does not have a k-touple 00139 knot at this end. */ 00140 00141 if (kp>=imy) tbeta1=(*ep - *etau)*(*galfa)/(etau[kkv] - *etau); 00142 else tbeta1=0; 00143 00144 *jfi=(1>imy-kp) ? 1 : imy-kp; 00145 *jla=(imy < ij-kp) ? imy : ij-kp; 00146 00147 00148 /* For details about this loop look in the reference. */ 00149 00150 for (et=etau+ *jfi,tu=etau+ *jla,ah=galfa+ *jfi; et<=tu; et++,ah++) 00151 { 00152 td1 = *ep - *et; 00153 td2 = et[kkv] - *ep; 00154 tbeta = *ah/(td1+td2); 00155 *(ah-1) = td2*tbeta + tbeta1; 00156 tbeta1 = td1*tbeta; 00157 } 00158 00159 00160 /* Here we note the special case where we are at the 00161 end of the matrix and we does not have a k-touple 00162 knot at this end. */ 00163 00164 if (*jla<imy) 00165 { 00166 et = etau + in; 00167 *(ah-1) = tbeta1+(*et-*ep)*(*ah)/(*et - *(tu+1)); 00168 } else *(ah-1) = tbeta1; 00169 } 00170 00171 00172 /* Adjusting the index of first and last in galfa. */ 00173 00174 if (kv) (*jfi)--; 00175 else *jfi = *jla = imy; 00176 00177 if ((*jfi)<0) *jfi = 0; 00178 if ((*jla)>in-ik) *jla = in-ik; 00179 00180 }
CurveLoop Go::outerBoundarySfLoop | ( | boost::shared_ptr< ParamSurface > | surf, | |
double | degenerate_epsilon | |||
) |
Definition at line 12 of file SurfaceTools.C.
References Go::CurveLoop::size().
Referenced by allBoundarySfLoops().
00015 { 00016 // It is convenient to let boundary loops be described as CurveOnSurface 00017 // to store as much information as possible. Due to problems with shared_ptr, 00018 // this is not possible from within SplineSurface. 00019 // This function is implemented to get around this problem 00020 00021 boost::shared_ptr<SplineSurface> spline_sf = 00022 boost::shared_dynamic_cast<SplineSurface, ParamSurface>(surf); 00023 00024 if (spline_sf.get()) 00025 { 00026 // Spline surface 00027 // Test for degeneracy. 00028 bool deg[4]; 00029 spline_sf->isDegenerate(deg[0], deg[1], deg[2], deg[3], degenerate_epsilon); 00030 std::vector< shared_ptr< ParamCurve > > vec; 00031 for (int edgenum = 0; edgenum < 4; ++edgenum) { 00032 if (!deg[edgenum]) { 00033 // Fetch geometry curve 00034 shared_ptr<ParamCurve> edgecurve (spline_sf->edgeCurve(edgenum)); 00035 00036 // Construct curve on surface with knowledge about what it is 00037 int pardir = (edgenum == 1 || edgenum == 3) ? 1 : 2; 00038 double parval; 00039 int boundary; 00040 if (edgenum == 0) 00041 { 00042 parval = spline_sf->startparam_v(); 00043 boundary = 2; 00044 } 00045 else if (edgenum == 1) 00046 { 00047 parval = spline_sf->endparam_u(); 00048 boundary = 1; 00049 } 00050 else if (edgenum == 2) 00051 { 00052 parval = spline_sf->endparam_v(); 00053 boundary = 3; 00054 } 00055 else 00056 { 00057 parval = spline_sf->startparam_u(); 00058 boundary = 0; 00059 } 00060 shared_ptr<ParamCurve> sfcv = 00061 shared_ptr<ParamCurve>(new CurveOnSurface(surf, edgecurve, pardir, 00062 parval, boundary)); 00063 if (edgenum == 2 || edgenum == 3) 00064 sfcv->reverseParameterDirection(); 00065 vec.push_back(sfcv); 00066 } 00067 } 00068 00069 return CurveLoop(vec, degenerate_epsilon); 00070 } 00071 else 00072 { 00073 // VSK, 1109. A similar problem as for spline surface occurs for 00074 // elementary surfaces, but it is currently not handled 00075 // VSK, 0510. Add the surface back pointer 00076 CurveLoop cv_loop = surf->outerBoundaryLoop(degenerate_epsilon); 00077 int nmb_cvs = cv_loop.size(); 00078 if (nmb_cvs == 0) 00079 return cv_loop; 00080 00081 shared_ptr<CurveOnSurface> cv = 00082 shared_dynamic_cast<CurveOnSurface,ParamCurve>(cv_loop[0]); 00083 if (cv.get()) 00084 return cv_loop; // Already curve on surface curves 00085 00086 // Make new loop with curve-on-surface curves 00087 vector< shared_ptr< ParamCurve > > vec; 00088 for (int ki=0; ki<nmb_cvs; ++ki) 00089 { 00090 shared_ptr<ParamCurve> sfcv = 00091 shared_ptr<ParamCurve>(new CurveOnSurface(surf, cv_loop[ki], false)); 00092 vec.push_back(sfcv); 00093 } 00094 return CurveLoop(vec, degenerate_epsilon); 00095 } 00096 }
bool Go::point_inside_contour | ( | const double | x0, | |
const double | y0, | |||
const double *const | vertices, | |||
const std::vector< int > & | contour | |||
) | [inline] |
Definition at line 274 of file 2dpoly_for_s2m.C.
Referenced by is_inside().
00281 { 00282 #ifndef DBG 00283 const bool dbg=false; // This way, all tests on 'dbg' is removed compile-time when DBG is not defined. 00284 #endif 00285 00286 // 00287 // At last we enter the old loop for counting intersections. 00288 // 00289 // 090117: Note that the rest of the code is very similar to 'segment_contour_intersection_for_s2m'. In 00290 // fact, we could have called that one. (Maybe we should have?) The difference is that now we know 00291 // that the segment is horizontal, (the ray,) and hence the code here can be made (slightly) simpler 00292 // and faster. One disadvantage is that the two functions (this and 00293 // 'segment_contour_intersection_for_s2m') must agree on how to handle degenerate cases and so 00294 // on. Otherwise strange problems will occur. 00295 00296 int crossings=0; 00297 00298 // const double eps=1e-8; // 100210: Increasing from 1e-12 to 1e-10. 00299 00300 const double abs_eps = 1e-8; // 100223: Trying to convert to these 00301 // const double snap_eps = 1e-5; 00302 00303 const int n=contour.size(); 00304 00305 if (dbg) 00306 printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ n=%d\n", n); 00307 00308 for (int i=0; i<n; i++) 00309 { 00310 const int j=(i+1)%n, pre_i=(i+n-1)%n; 00311 const double &preb=vertices[contour[pre_i]+1]; 00312 const double &prea=vertices[contour[pre_i]]; 00313 const double &a=vertices[contour[i]], &b=vertices[contour[i]+1]; 00314 const double &c=vertices[contour[j]], &d=vertices[contour[j]+1]; 00315 00316 const double len_squared = (a-c)*(a-c) + (b-d)*(b-d); 00317 if ( (len_squared<abs_eps*abs_eps) && (dbg) ) 00318 printf("\n\n HUH?! Segment with length %e, duplicate corner!\n\n\n", sqrt(len_squared)); 00319 00320 // if (dbg) 00321 // printf(" i=%3d: a=%g b=%g c=%g d=%g y0=%g abs_eps=%g !horiz=%d y0-inrange=%d(%d)\n", 00322 // i, a, b, c, d, y0, abs_eps, 00323 // (fabs(b-d)>abs_eps), 00324 // ((b-abs_eps<=y0) && (y0<d-abs_eps)), 00325 // ((d+abs_eps<y0) && (y0<b+abs_eps))); 00326 // if ( dbg && ((i==77) || (i==79)) ) 00327 // { 00328 // printf("\n\n\nhold on; plot(%f, %f, 'md', 'markersize', 10, 'linewidth', 3); hold off;\n", x0, y0); 00329 // printf("line([%f; %f], [%f; %f], 'color', 'm', 'linewidth', 5);\n\n\n", a, c, b, d); 00330 // } 00331 00332 // 00333 // 100223: Remember, crossings are counted when occuring at the *start* of segments, not the ends, 00334 // *except* when the curve has a vertical turn in this "start", i.e., there is a corner 00335 // "pointing" upward or downward. 00336 // 00337 00338 const bool not_horizontal_segment = fabs(b-d) > abs_eps; 00339 const bool y0_in_range_1 = (b-y0<=abs_eps) && (abs_eps<d-y0); // y0 in [b-eps, d-eps) 00340 const bool y0_in_range_2 = (abs_eps<y0-d) && (y0-b<=abs_eps); // y0 in (d+eps, b+eps] 00341 const bool y0_in_range = y0_in_range_1 || y0_in_range_2; 00342 00343 if ( not_horizontal_segment && y0_in_range ) 00344 { 00345 const double t=(y0-b)/(d-b); // Where on the segment does the ray cross? t=0 for b, and t=1 for d. 00346 00347 if (dbg) 00348 printf(" i=%3d: a=%g b=%g c=%g d=%g y0=%g abs_eps=%g !horiz=%d y0-inrange=%d %d\n", 00349 i, a, b, c, d, y0, abs_eps, 00350 not_horizontal_segment, y0_in_range_1, y0_in_range_2); 00351 00352 const bool interior = ((t>=abs_eps) && (t<=(1.0-abs_eps))); 00353 const bool start = (fabs(t)<=abs_eps); 00354 const bool going_up = ((preb<b) && (b<d)); 00355 const bool going_down = ((preb>b) && (b>d)); 00356 const bool not_turning_vertically = going_up || going_down; 00357 const bool actually_crossing = (interior || (start && not_turning_vertically)); 00358 const double intersection_x = a+t*(c-a); 00359 if (dbg) 00360 printf("\n\n t=%g, interior: %d, start: %d, going_up: %d, going_down: %d, " 00361 "actually_crossing: %d, inters_x: %g", 00362 t, interior, start, going_up, going_down, actually_crossing, intersection_x); 00363 if (dbg) 00364 printf("\n preb=%g, b=%g, d=%g x-values: %g %g %g", preb, b, d, prea, a, c); 00365 if ( actually_crossing && (intersection_x > x0+abs_eps) ) 00366 { 00367 crossings++; 00368 if (dbg) printf(", CROSSES "); 00369 if (dbg) 00370 { 00371 printf("\n\n\nhold on; plot(%f, %f, 'md', 'markersize', 10, 'linewidth', 3); hold off;\n", x0, y0); 00372 printf("line([%f; %f], [%f; %f], 'color', 'm', 'linewidth', 5);\n\n\n", a, c, b, d); 00373 } 00374 } 00375 else 00376 if (dbg) 00377 { 00378 if (actually_crossing) 00379 printf("\n intersection_x too small: %e vs. x0=%e, inters_x-x0=%e", 00380 intersection_x, x0, intersection_x-x0); 00381 printf("\n\n\nhold on; plot(%f, %f, 'bd', 'markersize', 10, 'linewidth', 3); hold off;\n", x0, y0); 00382 printf("line([%f; %f], [%f; %f], 'color', 'b', 'linewidth', 5);\n\n\n", a, c, b, d); 00383 } 00384 if (dbg) printf("\n"); 00385 } 00386 00387 } 00388 if (dbg) printf(" Crossings in total: %d, i.e., %s\n", crossings, ((crossings & 1)==1) ? "INSIDE" : "OUTSIDE"); 00389 00390 return ((crossings & 1)==1); 00391 }
bool Go::point_on_contour | ( | const double | x0, | |
const double | y0, | |||
const double *const | vertices, | |||
const vector< int > & | contour | |||
) | [inline] |
Definition at line 438 of file 2dpoly_for_s2m.C.
Referenced by is_on_contour().
00444 { 00445 #ifndef DBG 00446 const bool dbg=false; // This way, all tests on 'dbg' is removed compile-time when DBG is not defined. 00447 #endif 00448 00449 //const double eps=1e-12; // 090115: Used for zero-tests for degeneracy and parallellity tests. 00450 // 090203: Here it is also used for testing if a point is on a curve segment. 00451 //const double eps=1e-8; // 090203: Need 1e-8 for proper meshing of 'bin_p1_3.g2'. 00452 //const double eps=1e-6; // 100213: See comments below. 00453 const double eps=1e-5; // 100214: Reverting to 1e-8, think the need to have 1e-6 is really another problem 00454 // 100218: Keeping 1e-5 after discussion with Vibeke. 00455 00456 const double tau=1e-12; // 090115: Used for zero-tests for distances in the parameter domain. 00457 // 100214: Changed from 1e-14 to 1e-12, not needed right now, but 1e-14 seems small. 00458 00459 const int n=contour.size(); 00460 if (dbg) printf(" point_on_contour for (%f, %f), %d segments.\n", x0, y0, n); 00461 for (int i=0; i<n; i++) 00462 { 00463 const int j=(i+1)%n; 00464 const double &x2=vertices[contour[i]], &y2=vertices[contour[i]+1]; 00465 const double &x3=vertices[contour[j]], &y3=vertices[contour[j]+1]; 00466 const double contour_segment_length_squared = (x3-x2)*(x3-x2) + (y3-y2)*(y3-y2); 00467 00468 if (contour_segment_length_squared>tau*tau) 00469 { 00470 // We project (x0, y0) onto the segment, and measure the distance. 00471 // The projection will be (x2, y2) + s*[(x3, y3)-(x2, y2)]. 00472 const double s = ( (x0-x2)*(x3-x2) + (y0-y2)*(y3-y2) ) / contour_segment_length_squared; 00473 00474 // 100213: Hmm... Checking for s in (-tau, 1+tau) is no good, if 1+tau==1. Better to use (-eps, 00475 // 1+eps) when eps is larger than tau, but this does not solve the problem! Which is that 00476 // 's' is not a measure of distance. Should rather use 00477 // s*sqrt(contour_segment_length_squared)! 00478 // 00479 // 100214: But, then, remember that the interval should be [0, 00480 // sqrt(contour_segment_length_squared)]. 00481 // 00482 // 100213: Hmm again. Seems that 1e-8 (and 1e-7!) for some reason is too restrictive. (How can this 00483 // be?!) Changing to 1e-6. 00484 // 00485 // 100214: Suspect that the reason for 1e-8 being to large is that something else is really wrong 00486 // with the contour of the test case. (Folding back onto itself or something strange?!) 00487 00488 const double s2 = s * sqrt(contour_segment_length_squared); 00489 00490 if ( (dbg) && (0) ) 00491 { 00492 printf(" %3d: (x2, y2) = (%f, %f), (x3, y3) = (%f, %f)\n", i, x2, y2, x3, y3); 00493 printf("line([%f; %f], [%f; %f], 'color', 'y', 'linewidth', 5);\n", x2, x3, y2, y3); 00494 printf(" s=%f, s2=%f\n", s, s2); 00495 } 00496 00497 // if ((s>-tau) && (s<1.0+tau)) 00498 // if ((s>=-eps) && (s<=1.0+eps)) 00499 // if ((s2>=-eps) && (s2<=1.0+eps)) 00500 if ( (s2>=-eps) && (s2<=sqrt(contour_segment_length_squared)+eps) ) 00501 { 00502 const double x = x2 + s*(x3-x2), y = y2 + s*(y3-y2); 00503 const double dist_squared = (x-x0)*(x-x0) + (y-y0)*(y-y0); 00504 if (dbg) printf("\t\t\t\t\t\t\t\t\t\tdist to segment = %e\n", sqrt(dist_squared)); 00505 00506 // 100214: That the tolerance required in the next test is as large as 1e-4 really shows that 00507 // the trimming curve is crappy, so by using 1-e4 we are really just hiding a symptom... 00508 00509 if (dist_squared<eps*eps) 00510 //if (dist_squared<1e-6*1e-6) 00511 //if (dist_squared<1e-4*1e-4) 00512 { 00513 if (dbg) printf("TRUE\n"); 00514 return true; 00515 } 00516 } 00517 } 00518 else 00519 { 00520 // 00521 // 090117: The contour segment is degenerate, and will be treated as a point. 00522 // 00523 // 100214: We should not get here, duplicate points should have been removed, but it's no harm in 00524 // keeping the branch I guess... 00525 // 00526 const double mx = 0.5*(x2+x3), my = 0.5*(y2+y3); 00527 const double dist_squared = (x0-mx)*(x0-mx) + (y0-my)*(y0-my); 00528 if (dist_squared<eps*eps) 00529 { 00530 if (dbg) printf("TRUE\n"); 00531 return true; 00532 } 00533 } 00534 } 00535 00536 if (dbg) printf("FALSE\n"); 00537 return false; 00538 }
bool Go::point_on_contour_corner | ( | const double | x0, | |
const double | y0, | |||
const double *const | vertices, | |||
const vector< int > & | contour | |||
) |
Definition at line 405 of file 2dpoly_for_s2m.C.
Referenced by is_on_corner().
00407 { 00408 const double eps=1e-13; // 090115: Used for zero-tests for distances in the parameter domain. 00409 // Hmm... these should *really*, *really* be taken from some global variable 00410 // or something 00411 for (int ilim=contour.size(), i=0; i<ilim; i++) 00412 { 00413 const double &corner_u=vertices[contour[i]], &corner_v=vertices[contour[i]+1]; 00414 const double dist_squared = (corner_u-x0)*(corner_u-x0) + (corner_v-y0)*(corner_v-y0); 00415 00416 if (dist_squared<eps*eps) 00417 return true; 00418 } 00419 return false; 00420 }
bool Go::point_on_segment | ( | const double | x0, | |
const double | y0, | |||
const double | x2, | |||
const double | y2, | |||
const double | x3, | |||
const double | y3, | |||
const double | zero_eps, | |||
const double | snap_eps | |||
) |
Definition at line 551 of file 2dpoly_for_s2m.C.
Referenced by segment_contour_intersection_for_s2m().
00560 { 00561 #ifndef DBG 00562 const bool dbg = false; // This way, all tests on 'dbg' is removed compile-time when DBG is not defined. 00563 #endif 00564 00565 const double t = ( (x0-x2)*(x3-x2) + (y0-y2)*(y3-y2) ) / ( (x3-x2)*(x3-x2) + (y3-y2)*(y3-y2) ); 00566 const double x = x2 + t*(x3-x2) - x0; 00567 const double y = y2 + t*(y3-y2) - y0; 00568 const double dist = sqrt( x*x+y*y ); 00569 if ( (dist<snap_eps) && (t>=-zero_eps) && (t-zero_eps<=1.0) ) 00570 { 00571 if (dbg) 00572 { 00573 printf(" END TESTS 2: t=%f, dist=%f\n", t, dist); 00574 // printf("\nline([%f; %f], [%f; %f], 'color', 'k', 'linewidth', 6);\n", x0, x1, y0, y1); 00575 printf("line([%f; %f], [%f; %f], 'color', 'y', 'linewidth', 6);\n", x2, x3, y2, y3); 00576 } 00577 return true; 00578 } 00579 00580 return false; 00581 }
void Go::principalCurvatures | ( | const ParamSurface & | sf, | |
double | u, | |||
double | v, | |||
double & | k1, | |||
Point & | d1, | |||
double & | k2, | |||
Point & | d2 | |||
) |
Definition at line 94 of file CurvatureAnalysis.C.
References computeSecondFundamentalForm(), Go::ParamSurface::point(), and Go::Point::setValue().
Referenced by evaluateMinCurvatureRadius().
00099 { 00100 double resolution = 1.0e-15; 00101 00102 // Compute surface derivatives 00103 int derivs = 1; 00104 std::vector<Point> pts(3); 00105 sf.point(pts, u, v, derivs); 00106 Point Su = pts[1]; 00107 Point Sv = pts[2]; 00108 00109 // Compute 1. and 2. fundamental form 00110 double I[3]; 00111 double II[3]; 00112 computeSecondFundamentalForm(sf, u, v, I, II); 00113 double denom = I[0]*I[2]-I[1]*I[1]; 00114 00115 // Calculate the transformation matrix 00116 double transform[4]; // The sequence is a11, a12, a21, a22. 00117 transform[0] = (I[1]*II[1] - I[2]*II[0])/denom; 00118 transform[1] = (I[1]*II[2] - I[2]*II[1])/denom; 00119 transform[2] = (I[1]*II[0] - I[0]*II[1])/denom; 00120 transform[3] = (I[1]*II[1] - I[0]*II[2])/denom; 00121 00122 // Initialize the principal directions to the parameter directions 00123 d1.setValue(1.0, 0.0); 00124 d2.setValue(0.0, 1.0); 00125 00126 // Calculate the principal curvatures 00127 double a = 1.; 00128 double b = transform[0] + transform[3]; 00129 double c = transform[0]*transform[3] - transform[1]*transform[2]; 00130 00131 double sqrt_arg = b*b - 4.*a*c; 00132 if (sqrt_arg < resolution) 00133 { 00134 k1 = - b/(2.*a); 00135 k2 = k1; 00136 return; 00137 } 00138 00139 k1 = (- b + sqrt(sqrt_arg))/(2.*a); 00140 k2 = (- b - sqrt(sqrt_arg))/(2.*a); 00141 00142 // Calculate the curvature directions. 00143 double ratio, length; 00144 00145 // Direction corresponding to the maximal curvature 00146 if (fabs(transform[0] + k1) < resolution && 00147 fabs(transform[1]) < resolution) 00148 { 00149 // Parallel to u direction 00150 length = 1./sqrt(Su[0]*Su[0] + Su[1]*Su[1] + Su[2]*Su[2]); 00151 d1.setValue(length, 0.0); 00152 } 00153 else if (fabs(transform[3] + k1) < resolution && 00154 fabs(transform[2]) < resolution) 00155 { 00156 // Parallel to v direction 00157 length = 1./sqrt(Sv[0]*Sv[0] + Sv[1]*Sv[1] + Sv[2]*Sv[2]); 00158 d1.setValue(0.0, length); 00159 } 00160 else if (fabs(transform[0] + k1) < fabs(transform[1])) 00161 { 00162 ratio = (transform[0] + k1)/transform[1]; 00163 length = 1./sqrt((Su[0] - ratio*Sv[0])*(Su[0] - ratio*Sv[0]) + 00164 (Su[1] - ratio*Sv[1])*(Su[1] - ratio*Sv[1]) + 00165 (Su[2] - ratio*Sv[2])*(Su[2] - ratio*Sv[2])); 00166 d1.setValue(length, -ratio*length); 00167 } 00168 else 00169 { 00170 ratio = transform[1]/(transform[0] + k1); 00171 length = 1./sqrt((Sv[0] - ratio*Su[0])*(Sv[0] - ratio*Su[0]) + 00172 (Sv[1] - ratio*Su[1])*(Sv[1] - ratio*Su[1]) + 00173 (Sv[2] - ratio*Su[2])*(Sv[2] - ratio*Su[2])); 00174 d1.setValue(-ratio*length, length); 00175 } 00176 00177 // Minimal curvature direction 00178 if (fabs(transform[0] + k2) < resolution && 00179 fabs(transform[1]) < resolution) 00180 { 00181 // Parallel to u direction 00182 length = 1./sqrt(Su[0]*Su[0] + Su[1]*Su[1] + Su[2]*Su[2]); 00183 d2.setValue(length, 0.0); 00184 } 00185 else if (fabs(transform[3] + k2) < resolution && 00186 fabs(transform[2]) < resolution) 00187 { 00188 // Parallel to v direction 00189 length = 1./sqrt(Sv[0]*Sv[0] + Sv[1]*Sv[1] + Sv[2]*Sv[2]); 00190 d2.setValue(0.0, length); 00191 } 00192 else if (fabs(transform[0] + k2) < fabs(transform[1])) 00193 { 00194 ratio = (transform[0] + k2)/transform[1]; 00195 length = 1./sqrt((Su[0] - ratio*Sv[0])*(Su[0] - ratio*Sv[0]) + 00196 (Su[1] - ratio*Sv[1])*(Su[1] - ratio*Sv[1]) + 00197 (Su[2] - ratio*Sv[2])*(Su[2] - ratio*Sv[2])); 00198 d2.setValue(length, -ratio*length); 00199 } 00200 else 00201 { 00202 ratio = transform[1]/(transform[0] + k2); 00203 length = 1./sqrt((Sv[0] - ratio*Su[0])*(Sv[0] - ratio*Su[0]) + 00204 (Sv[1] - ratio*Su[1])*(Sv[1] - ratio*Su[1]) + 00205 (Sv[2] - ratio*Su[2])*(Sv[2] - ratio*Su[2])); 00206 d2.setValue(-ratio*length, length); 00207 } 00208 00209 00210 00211 }
shared_ptr<ParamCurve> Go::projectCurve | ( | shared_ptr< ParamCurve > | incurve, | |
const Point & | normal, | |||
bool | planar | |||
) |
Definition at line 18 of file projectCurve.C.
References ALWAYS_ERROR_IF, Class_Line, Class_SplineCurve, Go::Point::dimension(), MESSAGE, MESSAGE_IF, and projectCurve().
00021 { 00022 int dim = incurve->dimension(); 00023 ALWAYS_ERROR_IF(dim != 2 && dim != 3, "Dimension must be 2 or 3"); 00024 ALWAYS_ERROR_IF(dim!=2 && dim!=normal.dimension(), 00025 "Error in dimension."); 00026 00027 if (incurve->instanceType() == Class_Line) 00028 { 00029 shared_ptr<Line> line = shared_dynamic_cast<Line, ParamCurve>(incurve); 00030 MESSAGE_IF(!line->isBounded(), "Line not bounded."); 00031 00032 shared_ptr<SplineCurve> spline_cv(line->geometryCurve()); 00033 shared_ptr<SplineCurve> proj_cv = 00034 projectCurve(*spline_cv, normal, planar); 00035 00036 Point from_pt = proj_cv->ParamCurve::point(line->startparam()); 00037 Point to_pt = proj_cv->ParamCurve::point(line->endparam()); 00038 Point dir_vec = to_pt - from_pt; 00039 shared_ptr<ParamCurve> proj_line = 00040 shared_ptr<Line>(new Line(from_pt, dir_vec)); 00041 proj_line->setParameterInterval(line->startparam(), line->endparam()); 00042 return proj_line; 00043 } 00044 else if (incurve->instanceType() == Class_SplineCurve) 00045 { 00046 shared_ptr<SplineCurve> spline_cv = 00047 shared_dynamic_cast<SplineCurve, ParamCurve>(incurve); 00048 return projectCurve(*spline_cv, normal, planar); 00049 } 00050 else { 00051 shared_ptr<SplineCurve> spline_cv(incurve->geometryCurve()); 00052 if (spline_cv.get() == NULL) { 00053 MESSAGE("Unexpected curve type!"); 00054 } else { 00055 return projectCurve(*spline_cv, normal, planar); 00056 } 00057 } 00058 00059 return shared_ptr<ParamCurve>(); 00060 }
shared_ptr< SplineCurve > Go::projectCurve | ( | const SplineCurve & | incurve, | |
const Point & | normal, | |||
bool | planar | |||
) |
Project a 3D SplineCurve into a given plane.
The curve can be returned either as a 3D curve lying in the plane or as a 2D curve. In the latter case, the coordinate system is rotated such that the given plane normal coincides with the z-axis.
incurve | the curve to project | |
normal | the normal to the plane of projection | |
planar | 'true' if we want the returned curve to be a 2D curve. |
Definition at line 63 of file projectCurve.C.
References ALWAYS_ERROR_IF, Go::SplineCurve::basis(), Go::BsplineBasis::begin(), Go::SplineCurve::coefs_begin(), Go::Point::dimension(), Go::SplineCurve::dimension(), Go::Point::normalize(), Go::SplineCurve::numCoefs(), Go::SplineCurve::order(), Go::SplineCurve::rational(), and Go::SplineCurve::rcoefs_begin().
00075 { 00076 int dim = incurve.dimension(); 00077 ALWAYS_ERROR_IF(dim != 2 && dim != 3, "Dimension must be 2 or 3"); 00078 ALWAYS_ERROR_IF(dim!=2 && dim!=normal.dimension(), 00079 "Error in dimension."); 00080 00081 // Make sure that the given normal is normalized. 00082 Point norm = normal; 00083 norm.normalize(); 00084 00085 // Fetch the coefficients of the input curve 00086 int nmbcoef = incurve.numCoefs(); 00087 bool rational = incurve.rational(); 00088 std::vector<double>::const_iterator coefs; 00089 if (rational) 00090 coefs = incurve.rcoefs_begin(); 00091 else 00092 coefs = incurve.coefs_begin(); 00093 int dim1 = dim + (rational); 00094 00095 // Find the position of the plane which approximates 00096 // the input curve best. First compute the mean distance 00097 // from the curve coefficients to the plane with the given 00098 // normal passing through origo. 00099 double meandist = 0.0, dist; 00100 int ki, kj; 00101 std::vector<double>::const_iterator co; 00102 std::vector<double>::iterator co2, co3; 00103 for (ki=0, co=coefs; ki<nmbcoef; ki++, co+=dim1) 00104 { 00105 for (kj=0, dist=0.0; kj<dim; kj++) 00106 dist += co[kj]*norm[kj]; 00107 meandist += dist; 00108 } 00109 meandist /= (double)nmbcoef; 00110 00111 // The point in the plane 00112 Point point(meandist*norm); 00113 00114 // Project the coefficients into the found plane 00115 std::vector<double> coef2(dim1*nmbcoef); 00116 for (ki=0, co=coefs, co2=coef2.begin(); ki<nmbcoef; ki++, co+=dim1, co2+=dim1) 00117 { 00118 Point pp(co[0],co[1],co[2]); 00119 double td = (point - pp)*norm; 00120 for (kj=0; kj<dim; kj++) 00121 co2[kj] = co[kj] - td*norm[kj]; 00122 if (rational) 00123 co2[dim] = co[dim]; // Keep the weight 00124 } 00125 00126 SplineCurve *planecrv; 00127 if (planar) 00128 { 00129 // Rotate coordinate system such that the z-axis coincides 00130 // with the given plane normal, and express the coefficients in 00131 // this coordinate system. Remove z in each coefficient. 00132 std::vector<double> coef3((dim1-1)*nmbcoef); 00133 double tdum; 00134 for (co3=coef3.begin(), co2=coef2.begin(), ki=0; ki<nmbcoef; 00135 ki++, co3+=(dim1-1), co2+=dim1) 00136 { 00137 co3[0] = norm[2]*co2[0] + norm[0]*co2[1] + norm[1]*co2[2]; 00138 co3[1] = norm[1]*co2[0] + norm[2]*co2[1] + norm[0]*co2[2]; 00139 tdum = norm[0]*co2[0]+norm[1]*co2[1]+norm[2]*co2[2]; 00140 if (rational) 00141 co3[2] = co2[dim]; 00142 } 00143 00144 planecrv = new SplineCurve(nmbcoef, incurve.order(), 00145 incurve.basis().begin(), 00146 coef3.begin(), 2, rational); 00147 } 00148 else 00149 planecrv = new SplineCurve(nmbcoef, incurve.order(), 00150 incurve.basis().begin(), 00151 coef2.begin(), 3, rational); 00152 00153 return shared_ptr<SplineCurve>(planecrv); 00154 }
boost::shared_ptr<ParamCurve> GO_API Go::projectCurve | ( | boost::shared_ptr< ParamCurve > | incurve, | |
const Point & | normal, | |||
bool | planar | |||
) |
Referenced by projectCurve().
double Go::pt_dist_from_line | ( | const Vector2D & | p, | |
const Vector2D & | A, | |||
const Vector2D & | B | |||
) | [inline] |
Definition at line 998 of file spline2mesh.C.
Referenced by pt_dist_from_tri_edge().
00999 { 01000 const double t = ((p-A)*(B-A))/((B-A)*(B-A)); 01001 const Vector2D proj = A+t*(B-A); 01002 return sqrt((proj-p)*(proj-p)); 01003 }
double Go::pt_dist_from_tri_edge | ( | const Vector2D & | p, | |
const Vector2D & | c1, | |||
const Vector2D & | c2, | |||
const Vector2D & | c3 | |||
) | [inline] |
Definition at line 1005 of file spline2mesh.C.
References pt_dist_from_line().
01006 { 01007 return std::min(pt_dist_from_line(p, c1, c2), 01008 std::min(pt_dist_from_line(p, c2, c3), pt_dist_from_line(p, c3, c1))); 01009 }
bool Go::pt_inside_tri | ( | const Vector3D & | p, | |
const Vector3D & | c1, | |||
const Vector3D & | c2, | |||
const Vector3D & | c3 | |||
) | [inline] |
Definition at line 971 of file spline2mesh.C.
Referenced by make_trimmed_mesh().
00972 { 00973 const Vector2D e=c2-c1, f=c3-c1, pc=p-c1; 00974 const double ee=e*e, ff=f*f, ef=e*f; 00975 #if 0 00976 // This is faster on x86 than allocating new variables for pc*e and pc*f, it seems... 00977 const double u = ff*(pc*e) - ef*(pc*f); 00978 const double v = ee*(pc*f) - ef*(pc*e); 00979 #else 00980 // Not on core2 is seems... 00981 const double pce=pc*e, pcf=pc*f; 00982 const double u = ff*pce - ef*pcf; 00983 const double v = ee*pcf - ef*pce; 00984 #endif 00985 00986 return ((u>=0.0) && (v>=0.0) && (u+v<=ee*ff-ef*ef)); 00987 }
void Go::push_an_intersection | ( | const boost::shared_ptr< SplineSurface > | srf, | |
const Vector3D & | c1, | |||
const Vector3D & | c2, | |||
const Vector2D & | c1_p, | |||
const Vector2D & | c2_p, | |||
const Vector3D & | n1, | |||
const Vector3D & | n2, | |||
const double & | s, | |||
vector< Vector3D > & | vert, | |||
vector< Vector2D > & | vert_p, | |||
vector< Vector3D > & | norm, | |||
vector< int > & | bd | |||
) | [inline] |
Definition at line 505 of file spline2mesh.C.
References Go::Array< T, Dim >::normalize().
Referenced by split_triangle().
00513 { 00514 vert_p.push_back( (1.0-s)*c1_p + s*c2_p ); 00515 00516 #ifndef EVAL_SRF_NOT_INTERP 00517 vert .push_back( (1.0-s)*c1 + s*c2 ); 00518 Vector3D tmp = (1.0-s)*n1 + s*n2; 00519 tmp.normalize(); 00520 norm.push_back(tmp); 00521 bd.push_back(1); 00522 #else 00523 vector<Point> res(3); 00524 srf->point(res, vert_p.back()[0], vert_p.back()[1], 1); // Could we have used 0 here? 00525 00526 // The point on the surface: 00527 vert.push_back( Vector3D(res[0].begin()) ); 00528 00529 // The normal in the same point: 00530 const Point nrm = res[1].cross(res[2]); 00531 Vector3D tmp = Vector3D(nrm); 00532 tmp.normalize(); 00533 norm.push_back(tmp); 00534 00535 // This is Vibeke's, don't know what it's for... 00536 bd.push_back(1); 00537 #endif 00538 00539 }
double Go::quadrinomial | ( | int | n, | |
int | i, | |||
int | j, | |||
int | k | |||
) | [inline] |
void Go::refmatrix | ( | double * | et, | |
int | im, | |||
int | ik, | |||
double * | etau, | |||
int | in, | |||
double * | ea, | |||
int * | nfirst, | |||
int * | nlast | |||
) |
Corresponds to sh1922 in SISL Computes the B-spline refinement transformation matrix from the spline space generated by the knot vector etau to the refined spline space generated by the refined knot vector et.
et | Real array of length (im+ik) containing the refined knot vector. | |
im | The dimension of the spline space corresponding to et. | |
ik | The order of the spline space. | |
etau | Real array of length (in+ik) containing the original knot vector. | |
in | The dimension of the spline space corresponding to etau. | |
ea | Real array of dimension (im*ik) containing the B-spline refinement matrix from the knot vector etau to the knot vector et. This matrix has dimension im*in but since at most ik entries are nonzero in each row, it can be stored in a im*ik array together with two integer arrays indicating the position of the first and last nonzero elements in each row. | |
nfirst | Integer array of dimension (im) containing pointers to the first nonzero element of each row of the B-spline refinement matrix from etau to et. | |
nlast | Integer array of dimension (im) containing pointers to the last nonzero element of each row of the B-spline refinement matrix from etau to et. |
Definition at line 20 of file refmatrix.C.
References osloalg().
00027 : To compute the B-spline refinement transformation matrix 00028 * from the spline space generated by the knot vector etau 00029 * to the refined spline space generated by the refined knot 00030 * vector et. 00031 * 00032 * INPUT : et - Real array of length (im+ik) containing the refined 00033 * knot vector. 00034 * im - The dimension of the spline space corresponding to et. 00035 * ik - The order of the spline space. 00036 * etau - Real array of length (in+ik) containing the original 00037 * knot vector. 00038 * in - The dimension of the spline space corresponding 00039 * to etau. 00040 * 00041 * 00042 * OUTPUT : ea - Real array of dimension (im*ik) containing 00043 * the B-spline refinement matrix from the knot vector 00044 * etau to the knot vector et. This matrix has 00045 * dimension im*in but since at most 00046 * ik entries are nonzero in each row, it can 00047 * be stored in a im*ik array together 00048 * with two integer arrays indicating the position 00049 * of the first and last nonzero elements in each 00050 * row. 00051 * nfirst - Integer array of dimension (im) containing 00052 * pointers to the first nonzero element of each row 00053 * of the B-spline refinement matrix from etau to et. 00054 * nlast - Integer array of dimension (im) containing 00055 * pointers to the last nonzero element of each row 00056 * of the B-spline refinement matrix from etau to et. 00057 * jstat - status messages 00058 * > 0 : warning 00059 * = 0 : ok 00060 * < 0 : error 00061 * 00062 * 00063 * METHOD : 00064 * 00065 * 00066 * REFERENCES : 00067 * 00068 * 00069 * USE : 00070 * 00071 *- 00072 * CALLS : 00073 * 00074 * WRITTEN BY : Vibeke Skytt, SI, 05.92, on the basis of a routine 00075 * written by Tom Lyche and Knut Moerken, 12.85. 00076 * REVISED BY : Vibeke Skytt, Sintef, 19/04/2002. Go-ified. 00077 * 00078 ********************************************************************* 00079 */ 00080 { 00081 int kj1,kj2; 00082 int kih1,kih2; 00083 int ki,kj,kjh,kkj; 00084 int kmu; 00085 int kpl, kfi, kla; 00086 00087 std::vector<double> sahvec(2*ik, 0.0); 00088 double *sah = &sahvec[0]; 00089 00090 /* The first and last few rows of the refinement matrix ea may contain 00091 only zeroes. The first task is to find the first and the last 00092 nonzero rows (pointed at by kj1 and kj2). First kj2 are determined. */ 00093 00094 for (kmu=in+ik-1; etau[kmu-1] == etau[kmu]; kmu--); 00095 00096 for (kjh=im-1; et[kjh+ik]>etau[kmu]; kjh--); 00097 00098 ki = kjh; 00099 if (et[kjh+ik] == etau[kmu]) 00100 { 00101 for (; et[ki-1+ik] == et[kjh+ik]; ki--); 00102 } 00103 00104 kj2 = std::min(im-1,ki+in+ik-kmu-1); 00105 00106 /* Determine kj1. */ 00107 00108 for (kmu=0; etau[kmu+1] == etau[kmu]; kmu++); 00109 00110 for (kjh=0; et[kjh]<etau[kmu]; kjh++); 00111 00112 ki = kjh; 00113 if (et[kjh] == etau[kmu]) 00114 { 00115 for (; et[ki+1] == et[kjh]; ki++); 00116 } 00117 kj1 = std::max(0,ki-kmu); 00118 00119 // /* Set all elements of ea to zero. */ 00120 00121 // memzero(ea,im*ik,DOUBLE); 00122 00123 /* Determine the refinement transformation. */ 00124 /* Indicate that rows 1,2,..,kj1 of ea are zero by setting nfirst>nlast 00125 for these rows. */ 00126 00127 for (kj=0; kj<kj1; kj++) 00128 { 00129 nfirst[kj] = ik; 00130 nlast[kj] = 0; 00131 } 00132 00133 /* Similarily for rows kj2+1, ... im-1 of ea. */ 00134 00135 for (kj=kj2+1; kj<im; kj++) 00136 { 00137 nfirst[kj] = ik; 00138 nlast[kj] = 0; 00139 } 00140 00141 /* Compute rows kj1 to kj2 of ea. */ 00142 00143 for (kj=kj1; kj<=kj2; kj++) 00144 { 00145 for (; etau[kmu+1] <= et[kj]; kmu++); 00146 kkj = kj; 00147 Go::osloalg(kkj, kmu, ik, in, &kpl, &kfi, &kla, 00148 et, etau, sah); 00149 // sh1929(etau,in,ik,kmu,et,im,kkj,sah,&kmuprm,&knu,&kstat); 00150 // if (kstat < 0) goto error; 00151 00152 /* Get the pointers right. */ 00153 00154 // nfirst[kj] = MAX(kmuprm-knu,0); 00155 // nlast[kj] = MIN(kmuprm,in-1); 00156 // kih1 = nfirst[kj] + ik - kmuprm - 1; 00157 // kih2 = nlast[kj] + ik - kmuprm - 1; 00158 nfirst[kj] = std::max(kfi, 0); 00159 nlast[kj] = std::min(kla, in-1); 00160 kih1 = kfi + kpl; 00161 kih2 = kpl + kla; 00162 for (ki=kih1; ki<=kih2; ki++) 00163 ea[kj*ik+ki] = sah[ki]; 00164 } 00165 00166 /* Refinement transformation matrix computed. */ 00167 00168 00169 }
void Go::Register | ( | ) | [inline] |
This function is used to register a class derived from GeomObject with the global Factory.
By using this function rather than Factory::registerClass(), the user does not have to worry about the details of the Creator class. To register a class
DerivedClass
, it should be sufficient to run:
Register<DerivedClass>()
.
Definition at line 128 of file Factory.h.
References f(), Go::Factory::globalFactory(), and Go::Factory::registerClass().
00129 { 00130 Factory* f = Factory::globalFactory(); 00131 ConcreteCreator<T>* c = new ConcreteCreator<T>; 00132 f->registerClass(T::classType(), c); 00133 delete c; 00134 }
boost::shared_ptr< SplineSurface > Go::representCurveAsSurface | ( | const SplineCurve & | curve, | |
int | cv_dir, | |||
const BsplineBasis & | other_bas, | |||
bool | rational | |||
) |
Describe a curve as surface in a given direction.
The surface output is rational if the argument rational is set to 'true'. In that case the curve is supposed to live in homogenous space. Describe a curve as a lower-dimensional surface in a given direction.
curve | the curve that we want to express as a surface | |
cv_dir | If this variable is set to '1', then the curve's parameter will become the first parameter in the generated surface. If it is set to '2', the curve's parameter will become the second parameter in the generated surface. Other values are illegal. | |
other_bas | the BsplineBasis for the additional parameter direction. | |
rational | define whether the generated surface shall be specified as rational or not. |
Definition at line 625 of file GeometryTools.C.
References Go::SplineCurve::basis(), Go::SplineCurve::coefs_begin(), Go::SplineCurve::dimension(), Go::SplineCurve::numCoefs(), Go::BsplineBasis::numCoefs(), Go::SplineCurve::rational(), and THROW.
Referenced by Go::SplineSurface::appendSurface(), Go::SplineSurface::subSurface(), and unifySurfaceSplineSpaceOneDir().
00630 { 00631 if (curve.rational()) { 00632 THROW("It does not make sense to have a rational hypercurve."); 00633 } 00634 int kdim = curve.dimension()/other_bas.numCoefs(); 00635 std::vector<double>::const_iterator co 00636 = curve.coefs_begin(); 00637 std::vector<double> surf_coefs; 00638 std::vector<double>::const_iterator coefstart; 00639 const BsplineBasis& bas = curve.basis(); 00640 if (cv_dir!=2) { 00641 // We must flip the curve coefficients 00642 int nu = curve.numCoefs(); 00643 int nv = other_bas.numCoefs(); 00644 surf_coefs.reserve(nu*nv*kdim); 00645 for (int i = 0; i < nv; ++i) 00646 for (int j = 0; j < nu; ++j) 00647 for (int k = 0; k < kdim; ++k) 00648 surf_coefs.push_back(co[(j*nv+i)*kdim + k]); 00649 coefstart = surf_coefs.begin(); 00650 } else { 00651 coefstart = co; 00652 } 00653 int dim = rational ? kdim - 1 : kdim; 00654 boost::shared_ptr<SplineSurface> surface 00655 (new SplineSurface((cv_dir==1) ? bas : other_bas, 00656 (cv_dir==1) ? other_bas : bas, 00657 coefstart, dim, rational)); 00658 return surface; 00659 }
boost::shared_ptr< SplineCurve > Go::representSurfaceAsCurve | ( | const SplineSurface & | surface, | |
int | cv_dir | |||
) |
Describe a surface as a high-dimensional curve in a given direction.
If the surface is rational, the curve will be non-rational and living in the homogenous space.
surface | the surface to express as a curve | |
cv_dir | the parameter direction that will be kept when defining the curve (the other one will disappear, as the control points in this direction will be lumped together and expressed as single control points in a higher-dimensional space. 'cv_dir' takes either the value '1' (keep the first parameter direction) or '2' (keep the second parameter direction). |
Definition at line 584 of file GeometryTools.C.
References Go::SplineSurface::basis(), Go::BsplineBasis::begin(), Go::SplineSurface::coefs_begin(), Go::SplineSurface::dimension(), Go::BsplineBasis::numCoefs(), Go::SplineSurface::numCoefs_u(), Go::SplineSurface::numCoefs_v(), Go::BsplineBasis::order(), Go::SplineSurface::rational(), and Go::SplineSurface::rcoefs_begin().
Referenced by analyzePeriodicity(), analyzePeriodicityDerivs(), Go::SplineSurface::appendSurface(), Go::SplineSurface::subSurface(), and unifySurfaceSplineSpaceOneDir().
00586 { 00587 int dim = surface.dimension(); 00588 int kdim = dim + (surface.rational() ? 1 : 0); 00589 const std::vector<double>::const_iterator co = (surface.rational()) ? 00590 surface.rcoefs_begin() : surface.coefs_begin(); 00591 std::vector<double> huge_curve_coefs; 00592 std::vector<double>::const_iterator coefstart; 00593 if (cv_dir != 2) { 00594 // We must flip the surface coefficients 00595 int nu = surface.numCoefs_u(); 00596 int nv = surface.numCoefs_v(); 00597 huge_curve_coefs.reserve(nu*nv*kdim); 00598 for (int i = 0; i < nu; ++i) 00599 for (int j = 0; j < nv; ++j) 00600 for (int k = 0; k < kdim; ++k) 00601 huge_curve_coefs.push_back(co[(j*nu+i)*kdim + k]); 00602 coefstart = huge_curve_coefs.begin(); 00603 } else { 00604 coefstart = co; 00605 } 00606 00607 const BsplineBasis& bas = surface.basis(2-cv_dir); 00608 const BsplineBasis& other_bas = surface.basis(cv_dir-1); 00609 00610 int num = other_bas.numCoefs(); 00611 int order = other_bas.order(); 00612 std::vector<double>::const_iterator knotstart = other_bas.begin(); 00613 00614 int dim2 = bas.numCoefs() * kdim; 00615 shared_ptr<SplineCurve> curve(new SplineCurve(num, order, 00616 knotstart, coefstart, 00617 dim2, 00618 false)); 00619 return curve; 00620 }
void Go::rotateLineCloud | ( | Point | rot_axis, | |
double | alpha, | |||
LineCloud & | lc | |||
) |
Rotate the given LineCloud a certain angle around a given axis.
rot_axis | the axis of rotation. It does not have to be normalized, but must of course be nonzero. | |
alpha | the angle of rotation, given in radians | |
lc | reference to the LineCloud that is to be rotated |
Definition at line 1083 of file GeometryTools.C.
References ASSERT, Go::Point::begin(), Go::Array< T, Dim >::begin(), Go::Point::dimension(), Go::Array< T, Dim >::end(), Go::Point::normalize(), Go::LineCloud::numLines(), Go::LineCloud::point(), Go::LineCloud::rawData(), and rotatePoint().
01085 { 01086 rot_axis.normalize(); 01087 ASSERT(rot_axis.dimension() == 3); // We're working in 3D space. 01088 int ki; 01089 int nmb_pts = lc.numLines()*2; 01090 int dim = 3; 01091 for (ki = 0; ki < nmb_pts; ++ki) { 01092 Vector3D vec = lc.point(ki); 01093 Point pt(vec.begin(), vec.end()); 01094 rotatePoint(rot_axis, alpha, pt.begin()); 01095 copy(pt.begin(), pt.end(), lc.rawData() + ki*dim); 01096 } 01097 }
void Go::rotatePoint | ( | Point | rot_axis, | |
double | alpha, | |||
Point & | space_pt | |||
) |
Rotate the given 3D point a certain angle around a certain axis.
rot_axis | the axis of rotation. It does not have to be normalized, but must of course be nonzero. | |
alpha | the angle of rotation, given in radians | |
space_pt | reference to teh point to be rotated. This will be overwritten with the rotated coordinates. |
Definition at line 1119 of file GeometryTools.C.
References Go::Point::begin(), and rotatePoint().
01121 { 01122 rotatePoint(rot_axis, alpha, space_pt.begin()); 01123 }
void Go::rotatePoint | ( | Point | rot_axis, | |
double | alpha, | |||
double * | space_pt | |||
) |
Rotate the given 3D point a certain angle around a certain axis.
rot_axis | the axis of rotation. It does not have to be normalized, but must of course be nonzero. | |
alpha | the angle of rotation, given in radians | |
space_pt | pointer to the memory location where the 3D coordinates of the point are stored. These will be overwritten with the rotated coordinates. |
Definition at line 1101 of file GeometryTools.C.
References ASSERT, Go::Point::dimension(), getRotationMatrix(), and Go::Point::normalize().
Referenced by Go::CreatorsUtils::createCrossTangent(), Go::CreatorsUtils::projectCurvePoint(), Go::Parabola::reverseParameterDirection(), Go::Hyperbola::reverseParameterDirection(), Go::Ellipse::reverseParameterDirection(), Go::Circle::reverseParameterDirection(), rotateLineCloud(), rotatePoint(), rotateSplineCurve(), and rotateSplineSurf().
01103 { 01104 rot_axis.normalize(); 01105 ASSERT(rot_axis.dimension() == 3); // We're working in 3D space. 01106 std::vector<double> rot_mat = getRotationMatrix(rot_axis, alpha); 01107 int ki, kj; 01108 Point rotated_pt(0.0, 0.0, 0.0); 01109 for (ki = 0; ki < 3; ++ki) 01110 for (kj = 0; kj < 3; ++kj) 01111 rotated_pt[ki] += rot_mat[ki*3+kj]*space_pt[kj]; 01112 01113 for (ki = 0; ki < 3; ++ki) 01114 space_pt[ki] = rotated_pt[ki]; 01115 }
void Go::rotateSplineCurve | ( | Point | rot_axis, | |
double | alpha, | |||
SplineCurve & | cv | |||
) |
Rotate the given SplineCurve a certain angle around a given axis.
rot_axis | the axis of rotation. It does not have to be normalized, but must of course be nonzero. | |
alpha | the angle of rotation, given in radians | |
cv | reference to the curve that is to be rotated |
Definition at line 1061 of file GeometryTools.C.
References ASSERT, Go::SplineCurve::coefs_begin(), Go::SplineCurve::coefs_end(), Go::Point::dimension(), Go::Point::normalize(), Go::SplineCurve::rational(), Go::SplineCurve::rcoefs_begin(), Go::SplineCurve::rcoefs_end(), and rotatePoint().
Referenced by Go::Circle::geometryCurve(), and Go::BoundedUtils::rotateBoundedSurf().
01063 { 01064 rot_axis.normalize(); 01065 ASSERT(rot_axis.dimension() == 3); // We're working in 3D space. 01066 int dim = 3 + cv.rational(); 01067 std::vector<double>::iterator iter = cv.rational() ? cv.rcoefs_begin() : cv.coefs_begin(); 01068 std::vector<double>::iterator end_iter = cv.rational() ? cv.rcoefs_end() : cv.coefs_end(); 01069 std::vector<double>::iterator coef_iter = cv.coefs_begin(); 01070 while (iter != end_iter) { // @@ A faster approach would be to use rotation matrix directly. 01071 rotatePoint(rot_axis, alpha, &*iter); 01072 if (cv.rational()) { 01073 for (int ki = 0; ki < 3; ++ki) 01074 coef_iter[ki] = iter[ki]/iter[3]; 01075 coef_iter += dim - 1; 01076 } 01077 iter += dim; 01078 } 01079 }
void Go::rotateSplineSurf | ( | Point | rot_axis, | |
double | alpha, | |||
SplineSurface & | sf | |||
) |
Rotate the given SplineSurface a certain angle around a given axis.
rot_axis | the axis of rotation. It does not have to be normalized, but must of course be nonzero. | |
alpha | the angle of rotation, given in radians | |
sf | reference to the surface that is to be rotated. |
Definition at line 1039 of file GeometryTools.C.
References ASSERT, Go::SplineSurface::coefs_begin(), Go::SplineSurface::coefs_end(), Go::Point::dimension(), Go::Point::normalize(), Go::SplineSurface::rational(), Go::SplineSurface::rcoefs_begin(), Go::SplineSurface::rcoefs_end(), and rotatePoint().
Referenced by Go::Sphere::geometrySurface(), Go::Cylinder::geometrySurface(), Go::Cone::geometrySurface(), and Go::BoundedUtils::rotateBoundedSurf().
01041 { 01042 rot_axis.normalize(); 01043 ASSERT(rot_axis.dimension() == 3); // We're working in 3D space. 01044 int dim = 3 + sf.rational(); 01045 std::vector<double>::iterator iter = sf.rational() ? sf.rcoefs_begin() : sf.coefs_begin(); 01046 std::vector<double>::iterator end_iter = sf.rational() ? sf.rcoefs_end() : sf.coefs_end(); 01047 std::vector<double>::iterator coef_iter = sf.coefs_begin(); 01048 while (iter != end_iter) { // @@ A faster approach would be to use rotation matrix directly. 01049 rotatePoint(rot_axis, alpha, &*iter); 01050 if (sf.rational()) { 01051 for (int ki = 0; ki < 3; ++ki) 01052 coef_iter[ki] = iter[ki]/iter[3]; 01053 coef_iter += dim - 1; 01054 } 01055 iter += dim; 01056 } 01057 }
bool Go::segment_contour_intersection_for_s2m | ( | const double | x0, | |
const double | y0, | |||
const double | x1, | |||
const double | y1, | |||
const double *const | vertices, | |||
const std::vector< int > & | contour, | |||
double & | x, | |||
double & | y, | |||
double & | s, | |||
const bool | snap_ends = false | |||
) |
Definition at line 654 of file 2dpoly_for_s2m.C.
References DBG_FLAG, and point_on_segment().
Referenced by split_quad(), and split_triangle().
00665 { 00666 #ifndef DBG 00667 const bool dbg=false; // This way, all tests on 'dbg' is removed compile-time when DBG is not defined. 00668 #endif 00669 00670 if (dbg) puts("\n\n # Entering segment_contour_intersection_for_s2m ########################################\n"); 00671 00672 // 00673 // Now we search for the (actually, just "a") piece of the contour which intersects the segment. Maybe it is 00674 // faster to just do this without the previous test, if we can use the 'sorted_segments' information. 00675 // 00676 00677 int i; 00678 //const double tau=1e-14; // 090115: Used for zero-tests for degeneracy and parallellity tests. 00679 const double tau=1e-12; // 100218: 00680 00681 const double parallellity_eps = 1e-10; // 100219 00682 00683 const double eps=1e-13; // 090115: Used for zero-tests for distances in the parameter domain. 00684 //const double eps2=1e-8; // 090203: This is used to determine whether or not an intersection is at one of the ends 00685 const double eps2=1e-5; // 100218: 00686 // of an edge. (In which case we continue to look for an "interior" intersection, 00687 // which will be favoured. Is this always sensible? Or is it possible to make a 00688 // case in which the opposite behaviour should be preferred? 00689 // 090204: We need this as large as 1e-8 for bin_p1_3.g2 to be meshed properly. 00690 bool intersection_found_at_the_end_of_the_segment = false; 00691 double x_saved=1e99, y_saved=1e99, s_saved=1e99; // Initial values to help spot unforeseen problems... 00692 const int n=contour.size(); 00693 for (i=0; i<n; i++) 00694 { 00695 const int ii=i, jj=(ii+1)%n; 00696 const double &x2=vertices[contour[ii]], &y2=vertices[contour[ii]+1]; 00697 const double &x3=vertices[contour[jj]], &y3=vertices[contour[jj]+1]; 00698 double t; 00699 00700 #if 0 00701 if (dbg) 00702 { 00703 const double d02 = sqrt( (x2-x0)*(x2-x0) + (y2-y0)*(y2-y0) ); 00704 const double d03 = sqrt( (x3-x0)*(x3-x0) + (y3-y0)*(y3-y0) ); 00705 const double d12 = sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) ); 00706 const double d13 = sqrt( (x3-x1)*(x3-x1) + (y3-y1)*(y3-y1) ); 00707 00708 const double eps3 = 1e-3; 00709 00710 if ( (d02<eps3) || (d03<eps3) || (d12<eps3) || (d13<eps3) || (i==111169) ) 00711 { 00712 printf(" i=%4d: END TESTS: d02=%f, d03=%f, d12=%f, d13=%f\n", i, d02, d03, d12, d13); 00713 printf("\nline([%f; %f], [%f; %f], 'color', 'k', 'linewidth', 6);\n", x0, x1, y0, y1); 00714 printf("line([%f; %f], [%f; %f], 'color', 'y', 'linewidth', 6);\n", x2, x3, y2, y3); 00715 } 00716 00717 // testing if ends of first segment is in the other. 00718 00719 const double t0 = ( (x0-x2)*(x3-x2) + (y0-y2)*(y3-y2) ) / ( (x3-x2)*(x3-x2) + (y3-y2)*(y3-y2) ); 00720 double p = x2+t0*(x3-x2) - x0; 00721 double q = y2+t0*(y3-y2) - y0; 00722 const double dist0 = sqrt(p*p+q*q); 00723 //if ( (dist0<1e-5) && (t0>=-eps) && (t0<=1.0+eps) ) 00724 if (i==69) 00725 { 00726 printf(" i=%4d: END TESTS 2: t0=%f, dist=%f\n", i, t0, dist0); 00727 printf("\nline([%f; %f], [%f; %f], 'color', 'k', 'linewidth', 6);\n", x0, x1, y0, y1); 00728 printf("line([%f; %f], [%f; %f], 'color', 'y', 'linewidth', 6);\n", x2, x3, y2, y3); 00729 } 00730 00731 p = x2+t0*(x3-x2) - x1; 00732 q = y2+t0*(y3-y2) - y1; 00733 const double dist1 = sqrt(p*p+q*q); 00734 if (i==69) 00735 //if ( (dist1<1e-5) && (t0>=-eps) && (t0<=1.0+eps) ) 00736 { 00737 printf(" i=%4d: END TESTS 3: t0=%f, dist=%f\n", i, t0, dist0); 00738 printf("\nline([%f; %f], [%f; %f], 'color', 'k', 'linewidth', 6);\n", x0, x1, y0, y1); 00739 printf("line([%f; %f], [%f; %f], 'color', 'y', 'linewidth', 6);\n", x2, x3, y2, y3); 00740 } 00741 00742 } 00743 #endif 00744 00745 // 081209: Adding this test... 00746 const double contour_segment_length_squared = (x2-x3)*(x2-x3)+(y2-y3)*(y2-y3); 00747 // if (dbg2) printf("i=%3d cont segm len=%f ", i, sqrt(contour_segment_length_squared)); 00748 00749 if (contour_segment_length_squared>tau*tau) 00750 { 00751 00752 if (snap_ends) 00753 { 00754 // 00755 // 100219: We check if the ends of the segment (the one given as input to the function) are 00756 // close to the contour piece in question. If 'snap_ends' is true, we could have that 00757 // situation even if the pieces are (close to) parallel. We do this testing now, 00758 // before the parallellity-test, since that test is too strict to determine if this 00759 // 'snap_ends'-test should be performed. (It is too strict because it is meant to trap 00760 // division with zero before they happen, mainly.) 00761 // 00762 // Note also that if one of the ends is on the contour, this is an "end intersection", 00763 // and this 'intersection_found_at_the_end_of_the_segment' is set and the search 00764 // continued, in case there is also some inner intersection. 00765 // 00766 00767 if (point_on_segment(x0, y0, x2, y2, x3, y3, eps, eps2)) // , prøve med true her og nedenfor, se om det alltid blir bra da.)) 00768 { 00769 intersection_found_at_the_end_of_the_segment = true; 00770 x_saved = x0; 00771 y_saved = y0; 00772 s_saved = 0.0; 00773 } 00774 else 00775 if (point_on_segment(x1, y1, x2, y2, x3, y3, eps, eps2 DBG_FLAG)) 00776 { 00777 intersection_found_at_the_end_of_the_segment = true; 00778 x_saved = x1; 00779 y_saved = y1; 00780 s_saved = 1.0; 00781 } 00782 } 00783 00784 // 090115: The next one should be zero for contour segment and segment parallel. If so, no intersection... 00785 const double parallellity = (x3-x2)*(y1-y0)-(y3-y2)*(x1-x0); 00786 if ( fabs(parallellity) > parallellity_eps ) // i.e., not parallel... 00787 { 00788 // 00789 // 100219: Let the (triangle) segment has ends A=(x0, y0) and B=(x1, y1), and the contour 00790 // piece has ends C=(x2, y2) and D=(x3, y3). With intersection S = A+s(B-A) = 00791 // C+t(D-C), we get the following: 00792 // 00793 t = ((x0-x2)*(y1-y0)-(y0-y2)*(x1-x0)) / parallellity; 00794 if ((t>=-eps) && (t<=1.0+eps)) 00795 { 00796 if (fabs(x1-x0)>fabs(y1-y0)) 00797 s = ((x2-x0)+t*(x3-x2))/(x1-x0); 00798 else 00799 s = ((y2-y0)+t*(y3-y2))/(y1-y0); 00800 // if (dbg2) printf("s=%f ", s); 00801 if ((s>=-eps) && (s<=1.0+eps)) 00802 { 00803 if (dbg) 00804 { 00805 const double ss = ((x0-x2)*(y3-y2)-(y0-y2)*(x3-x2)) / parallellity; 00806 printf(" i=%4d: s=%f (%f), t=%f, parallellity=%f\n", i, s, ss, t, parallellity); 00807 printf("\nline([%f; %f], [%f; %f], 'color', 'k', 'linewidth', 6);\n", x0, x1, y0, y1); 00808 printf("line([%f; %f], [%f; %f], 'color', 'y', 'linewidth', 6);\n", x2, x3, y2, y3); 00809 const double px = x0 + s*(x1-x0), py = y0 + s*(y1-y0); 00810 const double qx = x2 + t*(x3-x2), qy = y2 + t*(y3-y2); 00811 printf("hold on; plot(%f, %f, 'gs', 'markersize', 15, 'linewidth', 2);\n", px, py); 00812 printf("plot(%f, %f, 'ks', 'markersize', 15, 'linewidth', 2); hold off;\n\n", qx, qy); 00813 } 00814 s = std::max(std::min(s, 1.0), 0.0); 00815 x = x2+t*(x3-x2); 00816 y = y2+t*(y3-y2); 00817 //printf("***** s=%f t=%f x=%f y=%f\n", s, t, x, y); 00818 //printf("returning true from %s:%d...\n", __FILE__, __LINE__); 00819 if ((fabs(s)<eps2) || (fabs(s-1.0)<eps2)) 00820 { 00821 intersection_found_at_the_end_of_the_segment=true; 00822 if (dbg) printf("Intersection is at and end.\n"); 00823 x_saved=x; 00824 y_saved=y; 00825 s_saved=s; 00826 } 00827 else 00828 { 00829 if (dbg) puts(" # Returning true from segment_contour_intersection_for_s2m # (a) #####\n"); 00830 return true; 00831 } 00832 } 00833 else 00834 if (dbg) printf(" i=%4d: NO INTERS, s OUT OF RANGE s=%f, t=%f, p=%g\n", i, s, t, parallellity); 00835 } 00836 else 00837 if (dbg) printf(" i=%4d: no inters, t out of range s=%f, t=%f, p=%g\n", i, s, t, parallellity); 00838 } 00839 else 00840 if (dbg) 00841 { 00842 printf(" i=%4d: PARALLEL parallellity=%e\n", i, parallellity); 00843 // The egde of the triangle ("segment") and the piece of the contour: 00844 printf("\nline([%f; %f], [%f; %f], 'color', 'k', 'linewidth', 6);\n", x0, x1, y0, y1); 00845 printf("line([%f; %f], [%f; %f], 'color', 'y', 'linewidth', 6);\n\n", x2, x3, y2, y3); 00846 } 00847 } 00848 else 00849 { 00850 if (dbg) printf(" Hmm... degen contour segment... should that still be possible?!\n"); 00851 // 090117: The contour segment is degenerate, and will be treated as a point. 00852 const double mx = 0.5*(x2+x3), my = 0.5*(y2+y3); 00853 00854 // The projection will be (x0, y0) + s*[(x1, y1)-(x0, y0)]. 00855 s = ( (mx-x0)*(x1-x0)+(my-y0)*(y1-y0) ) / ( (x1-x0)*(x1-x0)+(y1-y0)*(y1-y0) ); 00856 // if (dbg2) printf("s=%f ", s); 00857 00858 if ((s>-eps) && (s<1.0+eps)) 00859 { 00860 x = x0 + s*(x1-x0); 00861 y = y0 + s*(y1-y0); 00862 00863 const double dist_squared = (x-mx)*(x-mx) + (y-my)*(y-my); 00864 if (dist_squared<eps*eps) 00865 { 00866 intersection_found_at_the_end_of_the_segment=true; 00867 x_saved=x; 00868 y_saved=y; 00869 s_saved=s; 00870 } 00871 } 00872 } 00873 // if (dbg2) printf("\n"); 00874 } 00875 00876 if (intersection_found_at_the_end_of_the_segment) 00877 { 00878 x=x_saved; 00879 y=y_saved; 00880 s=s_saved; 00881 if (dbg) puts(" # Returning true from segment_contour_intersection_for_s2m # (b) #######################\n"); 00882 return true; 00883 } 00884 00885 // 090205: This message is not longer as relevant (or correct!) Now (also before?) it is perfectly 00886 // acceptable that this returns 'false' for the "second intersection, first try". The problem is 00887 // that it should not happen in the "second try" done by 'split_triangle'... But the proper place to 00888 // catch that problem is most likely in 'split_triangle' itself, so I'll disable this old message... 00889 // MESSAGE("\nCouldn't find proper intersection between segment\n" 00890 // "and contour, while the segment's ends\n" 00891 // "are determined to be on opposite sides of the contour!!!\n" 00892 // "If you see this, the results are very likely going to look like crap, unfortunately.\n" 00893 // "It is currently unknown how this could happen.\n"); 00894 // printf("Segment length in the parameter domain: %g\n\n\n", sqrt((x0-x1)*(x0-x1) + (y0-y1)*(y0-y1))); 00895 00896 if (dbg) puts(" # Returning false from segment_contour_intersection_for_s2m # (c) ##########################\n"); 00897 00898 return false; 00899 }
void Go::setSfBdCoefToConst | ( | SplineSurface & | srf, | |
int | bd_idx, | |||
int | idx_d, | |||
double | val, | |||
double | deg_tol | |||
) |
Modify surface along specified boundary to match a specific constant in one direction.
Currently only non-rational surfaces
Definition at line 330 of file GeometryTools.C.
References Go::SplineSurface::coefs_begin(), Go::SplineSurface::dimension(), Go::SplineSurface::numCoefs_u(), and Go::SplineSurface::numCoefs_v().
00336 { 00337 bool dir_u = (bd_idx == 2 || bd_idx == 3); 00338 int nmb1 = (dir_u) ? srf.numCoefs_u() : srf.numCoefs_v(); 00339 int nmb2 = (dir_u) ? srf.numCoefs_v() : srf.numCoefs_u(); 00340 int dim = srf.dimension(); 00341 vector<double>::iterator coefs = srf.coefs_begin(); 00342 int kr1 = (dir_u) ? dim : nmb1*dim; 00343 int kr2 = (dir_u) ? nmb2*dim : dim; 00344 00345 if (idx_d >= dim) 00346 return; // Does not make sense 00347 00348 // Check degeneracy 00349 bool bd[] = { false, false, false, false }; // left, right, bottom, top 00350 // bool deg = srf.isDegenerate(bd[2], bd[1], bd[3], bd[0], deg_tol); 00351 bool start_deg = ((bd_idx <=1 && bd[2]) || (bd_idx > 1 && bd[0])); 00352 bool end_deg = ((bd_idx <=1 && bd[3]) || (bd_idx > 1 && bd[1])); 00353 00354 // Modify coefficients 00355 vector<double>::iterator c1 = coefs; 00356 if (bd_idx == 3) 00357 c1 += (nmb2-1)*nmb1*dim; 00358 if (bd_idx == 1) 00359 c1 += (nmb2-1)*dim; 00360 00361 for (int ki=0; ki<nmb1; ki++, c1+=kr1) 00362 { 00363 c1[idx_d] = val; 00364 } 00365 00366 if (start_deg) 00367 { 00368 // Make sure that the degeneracy is maintained 00369 vector<double>::iterator d1 = coefs; 00370 for (int ki=0; ki<nmb2; ki++, d1+=kr2) 00371 { 00372 d1[idx_d] = val; 00373 } 00374 } 00375 00376 if (end_deg) 00377 { 00378 // Make sure that the degeneracy is maintained 00379 vector<double>::iterator d1 = coefs; 00380 if (bd_idx <= 1) 00381 d1 += (nmb1-1)*nmb2*dim; 00382 else 00383 d1 += (nmb1-1)*dim; 00384 for (int ki=0; ki<nmb2; ki++, d1+=kr2) 00385 { 00386 d1[idx_d] = val; 00387 } 00388 } 00389 00390 }
T Go::signed_area | ( | const Array< T, 3 > * | c, | |
const Array< T, 3 > & | normal | |||
) | [inline] |
Computes the signed area of a triangle embedded in 3D space.
Input is an array of corner points and a normal to determine the sign.
Definition at line 92 of file Volumes.h.
References Go::Array< T, Dim >::cross(), and Go::Array< T, Dim >::length().
Referenced by Go::BaryCoordSystemTriangle3D::cartToBary().
00093 { 00094 // Using the one-half cross product rule 00095 Array<T, 3> d0 = c[1] - c[0]; 00096 Array<T, 3> d1 = c[2] - c[0]; 00097 Array<T, 3> crossprod = d0.cross(d1); 00098 if (crossprod*normal > 0) { 00099 return 0.5 * crossprod.length(); 00100 } else { 00101 return -0.5 * crossprod.length(); 00102 } 00103 }
T Go::simplex_volume | ( | const Array< T, Dim > * | a | ) | [inline] |
Computes the volume of a simplex consisting of (Dim+1) vertices embedded in Euclidean space of dimension (Dim).
Definition at line 52 of file Volumes.h.
References determinantOf(), and Go::InverseFactorial< T, N >::val().
Referenced by area(), Go::BaryCoordSystem< Dim >::BaryCoordSystem(), Go::BaryCoordSystem< Dim >::cartToBary(), Go::BaryCoordSystem< Dim >::read(), Go::BaryCoordSystem< Dim >::setCorners(), and volume().
00053 { 00054 Array<T, Dim> tmp[Dim]; 00055 for (int i = 0; i < Dim; ++i) { 00056 tmp[i] = a[i] - a[i+1]; 00057 } 00058 return determinantOf(tmp) * InverseFactorial<double, Dim>::val(); 00059 // determinant / factorial 00060 }
double Go::simpsons_rule | ( | Functor & | f, | |
double | a, | |||
double | b, | |||
const double | eps = 1.0e-6 , |
|||
const int | max_iter = 20 | |||
) | [inline] |
Routine to calculate the integral of the functor f from a to b using Simpson's rule.
Definition at line 59 of file Integration.h.
References MESSAGE, and trapezoidal().
Referenced by main(), and simpsons_rule2D().
00061 { 00062 const double one_third = double(1) / double(3); 00063 double result = 0; 00064 double tz = 0; 00065 double last_tz = std::numeric_limits<double>::min(); 00066 double last_result = std::numeric_limits<double>::min(); 00067 00068 for (int j = 1; j <= max_iter; ++j) { 00069 trapezoidal(f, a, b, tz, j); 00070 result = (4.0 * tz - last_tz) * one_third; 00071 if ((fabs(result - last_result) < eps * fabs(last_result)) || 00072 (fabs(result) < eps && fabs(last_result) < eps && j > 6)) { 00073 return result; 00074 } 00075 last_result = result; 00076 last_tz = tz; 00077 } 00078 MESSAGE("Too many steps in simpsons_rule."); 00079 throw std::runtime_error("Too many steps in simpsons_rule."); 00080 } //
double Go::simpsons_rule2D | ( | Functor2D & | f, | |
double | ax, | |||
double | bx, | |||
double | ay, | |||
double | by, | |||
const double | eps = 1.0e-6 , |
|||
const int | max_iter = 20 | |||
) | [inline] |
Routine to integrate the two-dimensional functor f over the rectangle defined by ax, bx, ay and by.
Uses Simpson's rule.
Definition at line 136 of file Integration.h.
References simpsons_rule().
00139 { 00140 Integrate2ndFunctor<Functor2D> fu(f, ay, by); 00141 return simpsons_rule(fu, ax, bx, eps, max_iter); 00142 }
SplineCurve * Go::SISLCurve2Go | ( | const SISLCurve *const | cv | ) |
Convert a SISLCurve to a SplineCurve.
cv | the SISLcurve to convert |
delete
function. Definition at line 74 of file SISLconversion.C.
References THROW.
Referenced by main().
00075 { 00076 double* coefsstart; 00077 bool rational; 00078 if (cv->ikind == 2) { 00079 coefsstart = cv->rcoef; 00080 rational = true; 00081 } else if (cv->ikind == 1) { 00082 coefsstart = cv->ecoef; 00083 rational = false; 00084 } else { 00085 THROW("ikind must be 1 or 2."); 00086 } 00087 return new SplineCurve(cv->in, cv->ik, cv->et, 00088 coefsstart, cv->idim, rational); 00089 }
SplineSurface * Go::SISLSurf2Go | ( | SISLSurf * | sf | ) |
Convert a SISLSurface to a SplineSurface.
sf | the SISLSurf to convert |
delete
function. Definition at line 110 of file SISLconversion.C.
References THROW.
Referenced by main().
00111 { 00112 double* coefsstart; 00113 bool rational; 00114 if (sf->ikind == 2) { 00115 coefsstart = sf->rcoef; 00116 rational = true; 00117 } else if (sf->ikind == 1) { 00118 coefsstart = sf->ecoef; 00119 rational = false; 00120 } else { 00121 THROW("ikind must be 1 or 2."); 00122 } 00123 return new SplineSurface(sf->in1, sf->in2, sf->ik1, sf->ik2, 00124 sf->et1, sf->et2, 00125 coefsstart, sf->idim, rational); 00126 }
vector< short_list_short_list > Go::sort_2dpoly_segments | ( | const double *const | vertices, | |
const std::vector< int > & | contour, | |||
const bool | transposed = false | |||
) |
Definition at line 910 of file 2dpoly_for_s2m.C.
References THROW.
00913 { 00914 vector< short_list_short_list > sorted_segments; 00915 const int n=contour.size(); 00916 00917 const int debug=0; 00918 00919 // 020615: Introducing the 'transposed' for making a version in which x and y swap roles. 00920 00921 // 00922 // We cannot choose, it must contain indices into the 'contour' vector, if we were to copy that vector's 00923 // indices directly into 'vertices', we would lose information about one of the ends of all segments, as 00924 // soon as we started reordering the segments. Hence, initializing with 'contour[i]' was wrong. It must be 00925 // 'i'. 00926 sorted_segments.resize(n); 00927 for (int i=0; i<n; i++) 00928 sorted_segments[i].first=i; 00929 00930 // Now we sort this "outer" list wrt. largest x-value of the segments. 00931 { 00932 less_largest_x compare_functor(contour, vertices, 0.0, transposed); 00933 std::sort(sorted_segments.begin(), sorted_segments.end(), compare_functor); 00934 } 00935 00936 if ((debug) && (!transposed)) 00937 { 00938 //short_list_short_list *first_cut; 00939 vector<short_list_short_list>::iterator first_cut; 00940 00941 printf("\n"); 00942 for (first_cut=sorted_segments.begin(); first_cut<sorted_segments.end(); first_cut++) 00943 { 00944 const int a=contour[first_cut->first], b=contour[(first_cut->first+1)%n]; 00945 printf("%3d: %5d-%5d: (%10.3f, %10.3f, %10.3f)-" 00946 "(%10.3f, %10.3f, %10.3f) maxx: %10.3f\n", 00947 int(first_cut-sorted_segments.begin()), 00948 a, b, 00949 vertices[a+0], vertices[a+1], vertices[a+2], 00950 vertices[b+0], vertices[b+1], vertices[b+2], 00951 std::max(vertices[a+0], vertices[b+0])); 00952 } 00953 } 00954 00955 // Next, we fill inn all the lists of each pair of this "outer" list, i.e., the "middle" lists. 00956 if (transposed) 00957 { 00958 THROW("Huh?! This should not be in use, I think... J.O. 090129"); 00959 exit(0); 00960 } 00961 less_smallest_y lsy_comp(contour, vertices, 0.0); // , transposed); 00962 less_largest_y lly_comp(contour, vertices, 0.0); // , transposed); 00963 00964 for (int i=0; i<n; i++) 00965 { 00966 sorted_segments[i].second=new vector<short_list>; 00967 sorted_segments[i].second->resize(n-i); 00968 for (int j=0; j<n-i; j++) 00969 (*sorted_segments[i].second)[j].first=sorted_segments[i+j].first; 00970 00971 // Now we sort this "middle" list wrt. largest y-value of the segments. 00972 std::sort(sorted_segments[i].second->begin(), sorted_segments[i].second->end(), lly_comp); 00973 00974 if ((debug) && (!transposed)) 00975 { 00976 vector<short_list>::iterator second_cut; 00977 00978 printf("\n"); 00979 for (second_cut=sorted_segments[i].second->begin(); second_cut<sorted_segments[i].second->end(); second_cut++) 00980 { 00981 const int a=contour[second_cut->first], b=contour[(second_cut->first+1)%n]; 00982 printf(" %3d: %5d-%5d: (%10.3f, %10.3f, %10.3f)-" 00983 "(%10.3f, %10.3f, %10.3f) maxy: %10.3f\n", 00984 int(second_cut-sorted_segments[i].second->begin()), 00985 a, b, 00986 vertices[a+0], vertices[a+1], vertices[a+2], 00987 vertices[b+0], vertices[b+1], vertices[b+2], 00988 std::max(vertices[a+1], vertices[b+1])); 00989 } 00990 } 00991 00992 // Next, we fill inn all the lists of each pair of this "middle" list, i.e., the "inner" lists. 00993 for (int j=0; j<n-i; j++) 00994 { 00995 (*sorted_segments[i].second)[j].second=new vector<short>; 00996 (*sorted_segments[i].second)[j].second->resize(n-i-j); 00997 for (int k=0; k<n-i-j; k++) 00998 (*(*sorted_segments[i].second)[j].second)[k] = (*sorted_segments[i].second)[j+k].first; 00999 01000 // Now we sort this "inner" list wrt. smallest y-value of the segments. Default 'compare' should be 01001 // 'less'. 01002 // 01003 // 020614: Don't know why such a default comparison functor is mentioned. How could it ever work 01004 // with these compounded lists with the "strange" comparisons that are to be done?! 01005 // 020615: Probably I thought that as the inner list's entries consist of just an integer, there is 01006 // no need for the complex compare_functor, but then I forgot that it's not the integers (or 01007 // shorts) that are to be used as key in the sorting, but that which they point to! 01008 std::sort((*sorted_segments[i].second)[j].second->begin(), 01009 (*sorted_segments[i].second)[j].second->end(), 01010 lsy_comp); 01011 01012 if ((debug) && (!transposed)) 01013 { 01014 vector<short>::iterator third_cut; 01015 01016 printf("\n"); 01017 for (third_cut=(*sorted_segments[i].second)[j].second->begin(); 01018 third_cut<(*sorted_segments[i].second)[j].second->end(); 01019 third_cut++) 01020 { 01021 const int a=contour[*third_cut], b=contour[(*third_cut+1)%n]; 01022 printf(" %3d: %5d-%5d: (%10.3f, %10.3f, %10.3f)-" 01023 "(%10.3f, %10.3f, %10.3f) miny: %10.3f\n", 01024 int(third_cut- 01025 (*sorted_segments[i].second)[j].second->begin()), 01026 a, b, 01027 vertices[a+0], vertices[a+1], vertices[a+2], 01028 vertices[b+0], vertices[b+1], vertices[b+2], 01029 std::min(vertices[a+1], vertices[b+1])); 01030 } 01031 } 01032 01033 } 01034 } 01035 01036 // if (transposed) 01037 // { 01038 // printf("\n"); 01039 // print_sorted_segments2(sorted_segments, contour, vertices); 01040 // } 01041 01042 return sorted_segments; 01043 }
void Go::split_quad | ( | const int | i0, | |
const int | j0, | |||
const int | i1, | |||
const int | j1, | |||
const int | i2, | |||
const int | j2, | |||
const vector< int > & | si0, | |||
const vector< int > & | sj0, | |||
const vector< int > & | si1, | |||
const vector< int > & | sj1, | |||
boost::shared_ptr< SplineSurface > | srf, | |||
vector< Vector3D > & | vert, | |||
vector< Vector2D > & | vert_p, | |||
vector< int > & | bd, | |||
vector< Vector3D > & | norm, | |||
vector< int > & | mesh, | |||
const int | dn, | |||
const int | dm, | |||
const vector< Vector3D > & | trim_curve_p, | |||
const vector< int > & | contour, | |||
const bool | with_boundary, | |||
const bool | dbg = false | |||
) |
Definition at line 186 of file spline2mesh.C.
References add_triangle(), ASSERT2, DBG_FLAG, is_on_contour(), MESSAGE, Go::Array< T, Dim >::normalize(), and segment_contour_intersection_for_s2m().
Referenced by make_trimmed_mesh().
00192 : All the vectors above have two elements each, s?0[i] and s?1[i] are the two end 00193 // points of two of the sides of some quad, that the contour is assumed to intersect. 00194 // (The contour is given in 'contour', and 'vert', together. I think.) 00195 // (i?, j?) (actually, it makes more sense to say (j?, i?)...) specifies corners of 00196 // the quad. Which corners, is dependent on the configuration in question... (sigh.) 00197 00198 boost::shared_ptr<SplineSurface> srf, 00199 vector< Vector3D > &vert, vector<Vector2D> &vert_p, 00200 vector< int > &bd, vector< Vector3D > &norm, 00201 //vector< Vector3D > &col, 00202 vector<int> &mesh, const int dn, const int dm, 00203 //vector< Vector3D > &extra_v, 00204 const vector< Vector3D > &trim_curve_p, 00205 const vector<int> &contour, 00206 const bool with_boundary, const bool dbg=false) 00207 { 00208 // 00209 // This one always get two existing points and two segments between two pairs of points in, and intersect 00210 // the trimming curve twice against these segments for the two remaining points. The triangles are not 00211 // always oriented the same way, but that shouldn't matter too much. [Could easily be fixed by a switch 00212 // among the arguments...] 00213 // 00214 00215 int i; 00216 00217 // 00218 // Do the intersections. 00219 // 00220 00221 const double u0=srf->startparam_u(); 00222 const double u1=srf->endparam_u(); 00223 const double v0=srf->startparam_v(); 00224 const double v1=srf->endparam_v(); 00225 for (i=0; i<2; i++) 00226 { 00227 double x, y, s; 00228 if (dbg) 00229 printf("%f %f %f %f\n", u0*(1.0-sj0[i]/double(dn)) + u1*sj0[i]/double(dn), 00230 v0*(1.0-si0[i]/double(dm)) + v1*si0[i]/double(dm), 00231 u0*(1.0-sj1[i]/double(dn)) + u1*sj1[i]/double(dn), 00232 v0*(1.0-si1[i]/double(dm)) + v1*si1[i]/double(dm)); 00233 bool inters_found = segment_contour_intersection_for_s2m(u0*(1.0-sj0[i]/double(dn)) + u1*sj0[i]/double(dn), 00234 v0*(1.0-si0[i]/double(dm)) + v1*si0[i]/double(dm), 00235 u0*(1.0-sj1[i]/double(dn)) + u1*sj1[i]/double(dn), 00236 v0*(1.0-si1[i]/double(dm)) + v1*si1[i]/double(dm), 00237 &trim_curve_p[0][0], contour, 00238 x, y, s, 00239 false // 100222: New 'snap_ends' flag. 00240 DBG_FLAG); 00241 if (dbg) 00242 printf("=1===> i=%d, inters=%d\n", i, inters_found?1:0); 00243 00244 if ((!inters_found) && (with_boundary)) 00245 { 00246 // 090117: Didn't find intersection, even though one should be here. Checking if the segment's ends 00247 // are on the contour. 00248 if (is_on_contour(trim_curve_p, contour, 00249 u0*(1.0-sj0[i]/double(dn)) + u1*sj0[i]/double(dn), 00250 v0*(1.0-si0[i]/double(dm)) + v1*si0[i]/double(dm))) 00251 { 00252 x=u0*(1.0-sj0[i]/double(dn)) + u1*sj0[i]/double(dn); 00253 y=v0*(1.0-si0[i]/double(dm)) + v1*si0[i]/double(dm); 00254 s=0.0; 00255 inters_found=true; 00256 if (dbg) 00257 printf("=2===> i=%d, inters=%d\n", i, inters_found?1:0); 00258 } 00259 else 00260 if (is_on_contour(trim_curve_p, contour, 00261 u0*(1.0-sj1[i]/double(dn)) + u1*sj1[i]/double(dn), 00262 v0*(1.0-si1[i]/double(dm)) + v1*si1[i]/double(dm))) 00263 { 00264 x=u0*(1.0-sj1[i]/double(dn)) + u1*sj1[i]/double(dn); 00265 y=v0*(1.0-si1[i]/double(dm)) + v1*si1[i]/double(dm); 00266 s=1.0; 00267 inters_found=true; 00268 if (dbg) 00269 printf("=3===> i=%d, inters=%d\n", i, inters_found?1:0); 00270 } 00271 } 00272 00273 if (!inters_found) 00274 { 00275 MESSAGE("Failed finding intersection. Expected one."); 00276 fflush(stderr); 00277 } 00278 else 00279 { 00280 const double eps=1e-13; // 090115: Used for zero-tests for distances in the parameter domain. 00281 // Hmm... these should *really*, *really* be taken from some global 00282 // variable or something 00283 // 090117: Anyway... s will never be out of range here... 00284 ASSERT2((s>=-eps) && (s<=1.0+eps), printf("Huh?! s=%f\n", s)); 00285 } 00286 // eval surf i x og y for aa faa vert og norm, evt. returnere param 00287 // for skjaering mellom punktene s.a. vi igjen kan danne lin komb. 00288 if (inters_found) 00289 { 00290 vert.push_back((1.0-s)*vert[si0[i]*(dn+1)+sj0[i]] + 00291 s*vert[si1[i]*(dn+1)+sj1[i]] ); 00292 vert_p.push_back((1.0-s)*vert_p[si0[i]*(dn+1)+sj0[i]] + 00293 s*vert_p[si1[i]*(dn+1)+sj1[i]] ); 00294 if (dbg) 00295 printf("=4===> inters: %f %f\n", vert_p[vert_p.size()-1][0], vert_p[vert_p.size()-1][1]); 00296 bd.push_back(1); 00297 Vector3D new_norm = (1.0-s)*norm[si0[i]*(dn+1)+sj0[i]] + 00298 s*norm[si1[i]*(dn+1)+sj1[i]]; 00299 new_norm.normalize(); 00300 norm.push_back(new_norm); 00301 } 00302 //extra_v.push_back(vert[vert.size()-1]); // for debugging 00303 } 00304 00305 // 00306 // Add triangles to the mesh. 00307 // 00308 // Adding three triangles: (A, B, 0), (B, 1, 0), (0, 2, A). 00309 // 00310 // (i1, j1) B 00311 // o------x----o 00312 // | \ | 00313 // | \ x A 00314 // | | 00315 // o-----------o 00316 // (i0, j0) (i2, j2) 00317 // 00318 // 00319 // Adding two triangles: 00320 // 00321 // "-1" -----o "-2" Note that we want the triangles 00322 // o-----/ | oriented ccw., i.e., 00323 // | | (-2, -1, 0), and (-2, 0, 1). 00324 // | | 00325 // o-----------o 00326 // (i0, j0) (i1, j1) 00327 // 00328 00329 // This triangle can be used in all three modes. 00330 add_triangle(vert_p, mesh, vert.size()-2, vert.size()-1, i0*(dn+1)+j0); 00331 //col.push_back(Vector3D(1.0, 0.6, 0.6)); 00332 00333 if ((i1==-1) || (j1==-1)) 00334 // Only one triangle to add. 00335 return; 00336 00337 if ((i2==-1) || (j2==-1)) 00338 { 00339 // Two triangles to add, i.e., one more. 00340 add_triangle(vert_p, mesh, vert.size()-2, i0*(dn+1)+j0, i1*(dn+1)+j1); 00341 //col.push_back(Vector3D(0.0, 0.0, 1.0)); 00342 } 00343 else 00344 { 00345 // Three triangles to add, i.e., two more. 00346 add_triangle(vert_p, mesh, i0*(dn+1)+j0, vert.size()-1, i1*(dn+1)+j1); 00347 //col.push_back(Vector3D(0.6, 1.0, 0.6)); 00348 00349 add_triangle(vert_p, mesh, vert.size()-2, i0*(dn+1)+j0, i2*(dn+1)+j2); 00350 //col.push_back(Vector3D(0.6, 0.6, 1.0)); 00351 } 00352 }
bool Go::split_triangle | ( | const int | c1_indx, | |
const int | c2_indx, | |||
const int | c3_indx, | |||
boost::shared_ptr< SplineSurface > | srf, | |||
vector< Vector3D > & | vert, | |||
vector< Vector2D > & | vert_p, | |||
vector< int > & | bd, | |||
vector< Vector3D > & | norm, | |||
vector< int > & | newmesh, | |||
const vector< Vector3D > & | trim_curve_p, | |||
const vector< int > & | contour, | |||
const bool | dbg = false , |
|||
bool | forced_skipping_of_second_edge = false , |
|||
const bool | inner_trimming_curve = false | |||
) |
Definition at line 544 of file spline2mesh.C.
References add_triangle(), DBG_FLAG, degenerate_triangle(), MESSAGE, push_an_intersection(), and segment_contour_intersection_for_s2m().
Referenced by trim_a_triangle().
00553 : See above. 00554 { 00555 const double abs_eps = 1e-12; // 100218: Used for distance between two intersections in the param domain. 00556 00557 // 100223: Testing a new approach. Want to get rid of 'forced_skipping_of_second_edge', but trying to do 00558 // it one step at a time, through these temporary switches... 00559 00560 const bool try_without_forced_stuff = true; 00561 00562 if (try_without_forced_stuff) 00563 forced_skipping_of_second_edge = false; 00564 00565 // 090129: Not using references in fear of what 'push_back' will do... 00566 const Vector2D c1_p=vert_p[c1_indx], c2_p=vert_p[c2_indx], c3_p=vert_p[c3_indx]; 00567 const Vector3D c1=vert[c1_indx], c2=vert[c2_indx], c3=vert[c3_indx]; 00568 const Vector3D n1=norm[c1_indx], n2=norm[c2_indx], n3=norm[c3_indx]; 00569 00570 if (dbg) 00571 { 00572 puts("\n\n ----- split_triangle starting -----------------------------------------------------------------"); 00573 printf("\n The corners:\n\n"); 00574 printf("hold on; plot(%f, %f, 'rd', 'markersize', %d, 'linewidth', 2); hold off\n", c1_p[0], c1_p[1], 14); 00575 printf("hold on; plot(%f, %f, 'gd', 'markersize', %d, 'linewidth', 2); hold off\n", c2_p[0], c2_p[1], 14); 00576 printf("hold on; plot(%f, %f, 'bd', 'markersize', %d, 'linewidth', 2); hold off\n\n", c3_p[0], c3_p[1], 14); 00577 } 00578 00579 double x1, y1, s1, x2, y2, s2; 00580 00581 if (dbg) printf(" Looking for intersection on edge 1-2...\n"); 00582 const bool first_inters = 00583 segment_contour_intersection_for_s2m(c1_p[0], c1_p[1], c2_p[0], c2_p[1], 00584 &trim_curve_p[0][0], // Pointer to vertices is enough, size not needed 00585 contour, x1, y1, s1, 00586 true // 100222: New 'snap_ends' flag. 00587 DBG_FLAG); 00588 if (!first_inters) 00589 { 00590 if (!inner_trimming_curve) 00591 { 00592 // 100223: Disabling this warning, for with the new branch depending on "innerness" of contour, 00593 // the situation will probably (hopefully) be correctly treated in all cases now. 00594 if ( (dbg) && (0) ) 00595 puts(" Warning:\n It is likely that the 'inside'-test gave a false positive for a corner of a\n" 00596 " triangle that is really fully outside a trimming curve. We continue with this\n" 00597 " assumption, and discard the triangle in question, without attempting to clip it.\n"); 00598 } 00599 else 00600 // 100223: The new and alternate branch, which should be more likely to be correct for inner curves. 00601 add_triangle(vert_p, newmesh, c1_indx, c2_indx, c3_indx); 00602 if (dbg) puts(" ----- split_triangle done, no new triangles produced ---------------------------------\n\n"); 00603 return false; 00604 } 00605 00606 // 00607 // The first intersection is now between corner c1 and c2. The second may be between c2 and c3, or between 00608 // c3 and c1. Per assumption, c1 is *inside* the contour. (And c2 outside, c3 unknown.) 00609 // 00610 // 100223: But remember, now, that there may in fact be a lot more than the anticipated/assumed two 00611 // intersections... trying to cope better with such situations from now on. 00612 // 00613 00614 // Pushing inters1. 00615 push_an_intersection(srf, c1, c2, c1_p, c2_p, n1, n2, s1, vert, vert_p, norm, bd); 00616 if (dbg) 00617 printf(" First intersection found: s1=%f\n\n hold on; plot(%f, %f, 'm*', 'markersize', " 00618 "7, 'linewidth', 2); hold off\n\n", s1, vert_p.back()[0], vert_p.back()[1]); 00619 00620 // 100218: Note that we only have to *test* for a 2-3 intersection, since if there is none, we should have a 3-1. 00621 if (dbg) printf(" Looking for intersection on edge 2-3...\n"); 00622 const bool second_inters = 00623 segment_contour_intersection_for_s2m(c2_p[0], c2_p[1], c3_p[0], c3_p[1], &trim_curve_p[0][0], contour, x2, y2, s2, 00624 true // 100222: New 'snap_ends'-flag 00625 DBG_FLAG); 00626 00627 const double i1_i2_dist_squared = second_inters ? (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) : 0.0; 00628 if (dbg) printf(" second_inters (2-3) =%d, s2=%f, dist=%g\n", second_inters, s2, sqrt(i1_i2_dist_squared)); 00629 const bool inters1_and_inters2_distinct = i1_i2_dist_squared > abs_eps*abs_eps; 00630 00631 00632 //-------------------------------------------------------------------------------------------------------------- 00633 // 00634 // 100223: When three intersections between triangle edges and the contour are detected, the triangle is 00635 // split in four, and flagged for further trimming in a new iteration. This should take care of a 00636 // lot of previously unsolved cases with minimal new code! 00637 // 00638 //-------------------------------------------------------------------------------------------------------------- 00639 00640 bool third_inters; 00641 const bool look_for_a_third_inters = first_inters && second_inters && inters1_and_inters2_distinct; 00642 if (dbg) printf(" look_for_a_third_inters = %d\n", look_for_a_third_inters); 00643 double x3, y3, s3; 00644 if ( look_for_a_third_inters ) 00645 { 00646 if (dbg) printf(" PRE_SPLITTING_3_INTERS: Looking for intersection on edge 3-1...\n"); 00647 third_inters = segment_contour_intersection_for_s2m(c3_p[0], c3_p[1], c1_p[0], c1_p[1], 00648 &trim_curve_p[0][0], contour, x3, y3, s3, 00649 true // 100222: New 'snap_ends'-flag 00650 DBG_FLAG); 00651 if (third_inters) 00652 { 00653 const double i1_i3_dist_squared = (x3-x1)*(x3-x1) + (y3-y1)*(y3-y1); 00654 const bool inters1_and_inters3_distinct = i1_i3_dist_squared > abs_eps*abs_eps; 00655 const double i2_i3_dist_squared = (x3-x2)*(x3-x2) + (y3-y2)*(y3-y2); 00656 const bool inters2_and_inters3_distinct = i2_i3_dist_squared > abs_eps*abs_eps; 00657 00658 if (inters1_and_inters3_distinct && inters2_and_inters3_distinct) 00659 { 00660 // puts("JEPP, FANT ET KJIPT LITE TRIANGEL..."); 00661 00662 // Pushing inters2. 00663 push_an_intersection(srf, c2, c3, c2_p, c3_p, n2, n3, s2, vert, vert_p, norm, bd); 00664 // Pushing inters3. 00665 push_an_intersection(srf, c3, c1, c3_p, c1_p, n3, n1, s3, vert, vert_p, norm, bd); 00666 00667 // Triangles... 00668 add_triangle(vert_p, newmesh, c1_indx, vert.size()-3, vert.size()-1 DBG_FLAG); 00669 add_triangle(vert_p, newmesh, c2_indx, vert.size()-2, vert.size()-3 DBG_FLAG); 00670 add_triangle(vert_p, newmesh, c3_indx, vert.size()-1, vert.size()-2 DBG_FLAG); 00671 add_triangle(vert_p, newmesh, vert.size()-3, vert.size()-2, vert.size()-1 DBG_FLAG); 00672 00673 return true; 00674 } 00675 } 00676 } 00677 00678 if ( second_inters && inters1_and_inters2_distinct && (!forced_skipping_of_second_edge) ) 00679 { 00680 //---------------------------------------------------------------------------------------------------- 00681 // 00682 // The second intersection is between corners c2 and c3, and it is distinct from the first 00683 // intersection. We can try to make the triangles as round as possible... 00684 // 00685 // 100223: What happens when 'forced_skipping_of_second_edge=true', is that this branch is not taken, 00686 // although a perfectly fine intersection distinct from inters1 was found on 2-3. That will 00687 // cause an intersection on 3-1 to be searched for, and used instead. (And who knows what will 00688 // happen if that 3-1 intersection does not exist...) If we were to enter this branch, it 00689 // seems a lot of triangles will be wrongly discarded, for some reasone. Cannot actually see 00690 // how that will happen in this branch, right now, though... Could be that one of the four 00691 // 'add_triangle' calls below try to add a degenerate triangle. Hmm... seems not so unlikely. 00692 // 00693 //---------------------------------------------------------------------------------------------------- 00694 00695 // Pushing inters2. 00696 push_an_intersection(srf, c2, c3, c2_p, c3_p, n2, n3, s2, vert, vert_p, norm, bd); 00697 if (dbg) 00698 printf(" branch 1:\n\n hold on; plot(%f, %f, 'g*', 'markersize', 7, 'linewidth', 2); hold off\n\n", 00699 vert_p.back()[0], vert_p.back()[1]); 00700 00701 if ( (x2-c1_p[0])*(x2-c1_p[0])+(y2-c1_p[1])*(y2-c1_p[1]) < (x1-c3_p[0])*(x1-c3_p[0])+(y1-c3_p[1])*(y1-c3_p[1]) ) 00702 // Splitting between c1 and inters2. 00703 { 00704 if (dbg) printf(" branch 2: Adding triangles (c1, i1, i2) and (c1, i2, c3).\n"); 00705 if (dbg) printf(" adding the first:\n"); 00706 add_triangle(vert_p, newmesh, c1_indx, vert.size()-2, vert.size()-1 DBG_FLAG); 00707 if (dbg) printf(" adding the second:\n"); 00708 add_triangle(vert_p, newmesh, c1_indx, vert.size()-1, c3_indx DBG_FLAG); 00709 } 00710 else 00711 // Splitting between c3 and inters1. 00712 { 00713 if (dbg) printf(" branch 3: Adding triangles (c1, i1, c3) and (i1, i2, c3).\n"); 00714 add_triangle(vert_p, newmesh, c1_indx, vert.size()-2, c3_indx DBG_FLAG); 00715 add_triangle(vert_p, newmesh, vert.size()-2, vert.size()-1, c3_indx DBG_FLAG); 00716 } 00717 } 00718 else 00719 { 00720 //---------------------------------------------------------------------------------------------------- 00721 // 00722 // Ok, no second intersection 2-3, then it should be on 3-1. If not, that's an error... (There should 00723 // always be exactly two intersections!) (100223: Yeah... well... not entirely true, really...) 00724 // 00725 //---------------------------------------------------------------------------------------------------- 00726 00727 if (dbg) printf(" branch 4:\n Looking for intersection on edge 3-1...\n"); 00728 bool tmp; 00729 if (look_for_a_third_inters) // If so, we have already called 'segment_contour_intersection_for_s2m'... 00730 tmp = third_inters, x2 = x3, y2 = y3, s2 = s3; 00731 else 00732 tmp = segment_contour_intersection_for_s2m(c3_p[0], c3_p[1], c1_p[0], c1_p[1], 00733 &trim_curve_p[0][0], contour, x2, y2, s2, 00734 true); // 100222: New 'snap_ends'-flag 00735 00736 // 100224: Hmm... tmp only used for debugging output? (Hence the name 'tmp'?!) 00737 00738 if (dbg) 00739 printf(" 2nd try: 3-1-inters=%d, dist=%g\n forced_skipping_of_second_edge=%d\n\n" 00740 " hold on; plot(%f, %f, 'g*', 'markersize', 8, 'linewidth', 2); hold off\n\n", 00741 tmp?1:0, sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)), forced_skipping_of_second_edge, x2, y2); 00742 00743 // 00744 // 100224: Ok, before, we had 'if (!forced...) { ... }' here, because it would be detected as a 00745 // problem if we got here, i.e., one 1-2-intersection and no 2-3-intersection *without* the 00746 // caller expecting this and therefore using 'forced...'. 00747 // 00748 // If we now want to get rid of the 'forced...' flag, we cannot trap this as a potential 00749 // problem, since we have no way of knowing if the caller expected it. If we get here, we must 00750 // simply assume that it is correct, and continue with the splitting... Therefore: We wrap the 00751 // test in the new 'do_ignore_forced_skipping'-test: 00752 // 00753 00754 if (!try_without_forced_stuff) 00755 if (!forced_skipping_of_second_edge) 00756 { 00757 MESSAGE(" Warning:\nShould not happen 2 ! Where did the second intersection go?!" 00758 //"\nJust keeping the full triangle...\n"); 00759 "\n Discarding the full triangle...\n"); 00760 fflush(stdout); 00761 fflush(stderr); 00762 //add_triangle(vert_p, newmesh, c1_indx, c2_indx, c3_indx); 00763 00764 if (dbg) 00765 { 00766 if (degenerate_triangle(vert_p[c1_indx], vert_p[c2_indx], vert_p[c3_indx] DBG_FLAG)) 00767 puts("Hmm... triangle is degenerate, so maybe appropriate to discard it then..."); 00768 int m=5*(c1_indx%4+1); 00769 printf("\n\nwwwwwwwwwwww\n\n\n" 00770 "hold on; plot(%f, %f, 'rs', 'markersize', %d, 'linewidth', 2); hold off\n" 00771 "hold on; plot(%f, %f, 'gs', 'markersize', %d, 'linewidth', 2); hold off\n" 00772 "hold on; plot(%f, %f, 'bs', 'markersize', %d, 'linewidth', 2); hold off\n\n", 00773 c1_p[0], c1_p[1], m, c2_p[0], c2_p[1], m, c3_p[0], c3_p[1], m); 00774 puts(" ----- split_triangle done ------------------------------------------------------------\n\n"); 00775 } 00776 return false; 00777 } 00778 00779 //============================================================================================================== 00780 // 090217: Now, if the first intersection is through the first corner, and there is another "non-corner" 00781 // intersection in the "middle" edge (and 'forced_skipping_of_second_edge' is true) we do some 00782 // special treatment: We split the triangle in two new ones covering the old. Note that these 00783 // must then be recursively re-processed by the caller! To make this simpler, we introduce a 00784 // boolean return value, which will be true when further processing may be required. 00785 00786 if ( ((fabs(s1)<1e-12) || (fabs(s2-1.0)<1e-12)) && forced_skipping_of_second_edge ) 00787 { 00788 double x3, y3, s3; 00789 if (dbg) printf(" Looking for intersection on edge 2-3 again...\n"); 00790 const bool tmp2= 00791 segment_contour_intersection_for_s2m(c2_p[0], c2_p[1], c3_p[0], c3_p[1], 00792 &trim_curve_p[0][0], contour, x3, y3, s3, 00793 true); // 100222: New 'snap_ends' flag. 00794 if ( tmp2 && (fabs(s3)>1e-12) && (fabs(s3-1.0)<1-1e-12) ) 00795 { 00796 // Pushing inters3. 00797 push_an_intersection(srf, c2, c3, c2_p, c3_p, n2, n3, s3, vert, vert_p, norm, bd); 00798 // Hmm... now we have added a totally unneeded point, for intersection 1... 00799 add_triangle(vert_p, newmesh, c1_indx, vert.size()-1, c3_indx); 00800 add_triangle(vert_p, newmesh, c1_indx, c2_indx, vert.size()-1); 00801 00802 if (dbg) puts(" ----- split_triangle done -----------------------------------------------------\n\n"); 00803 return true; 00804 } 00805 } 00806 00807 // Pushing inters2. 00808 push_an_intersection(srf, c3, c1, c3_p, c1_p, n3, n1, s2, vert, vert_p, norm, bd); 00809 if (dbg) 00810 printf(" s2=%g\n hold on; plot(%f, %f, 'b*', 'markersize', 7, 'linewidth', 2); hold off\n", 00811 s2, vert_p[vert_p.size()-1][0], vert_p[vert_p.size()-1][1]); 00812 00813 // There is only one triangle to push on the list in this case. 00814 if (dbg) printf(" adding the only triangle...\n"); 00815 add_triangle(vert_p, newmesh, c1_indx, vert.size()-2, vert.size()-1); 00816 00817 } // end of the block for the second intersection being of 3-1 kind instead of 2-3... 00818 00819 if (dbg) puts(" ----- split_triangle done ----------- xxx ------------------------------------------------\n\n"); 00820 return false; 00821 }
void Go::splitCurveIntoSegments | ( | const SplineCurve & | cv, | |
std::vector< SplineCurve > & | seg | |||
) |
Split a spline curve into Bezier segments.
Definition at line 28 of file GGUsplit.C.
References Go::SplineCurve::basis(), Go::BsplineBasis::begin(), Go::SplineCurve::makeBernsteinKnots(), Go::SplineCurve::numCoefs(), Go::SplineCurve::order(), and Go::SplineCurve::subCurve().
Referenced by main().
00031 { 00032 SplineCurve orig = cv; 00033 orig.makeBernsteinKnots(); 00034 00035 int n = orig.numCoefs(); 00036 int order = orig.order(); 00037 int numseg = n / order; 00038 00039 seg.resize(numseg); 00040 vector<double>::const_iterator it = orig.basis().begin(); 00041 for (int i = 0; i < numseg; ++i) { 00042 shared_ptr<ParamCurve> new_cv(orig.subCurve(*it, *(it+order))); 00043 seg[i] = dynamic_cast<SplineCurve&>(*new_cv); 00044 it += order; 00045 } 00046 00047 return; 00048 }
std::vector< boost::shared_ptr< SplineSurface > > Go::splitInKinks | ( | const SplineSurface & | sf, | |
const std::vector< double > & | u_kinks, | |||
const std::vector< double > & | v_kinks | |||
) |
Extract sub patches from the surface given by input parameters.
Definition at line 871 of file GeometryTools.C.
References Go::SplineSurface::endparam_u(), Go::SplineSurface::endparam_v(), Go::SplineSurface::startparam_u(), Go::SplineSurface::startparam_v(), and Go::SplineSurface::subSurface().
00875 { 00876 std::vector<shared_ptr<SplineSurface> > return_sfs; 00877 00878 std::vector<double> split_params_u; 00879 std::vector<double> split_params_v; 00880 split_params_u.push_back(sf.startparam_u()); 00881 split_params_u.insert(split_params_u.end(), u_kinks.begin(), u_kinks.end()); 00882 split_params_u.push_back(sf.endparam_u()); 00883 split_params_v.push_back(sf.startparam_v()); 00884 split_params_v.insert(split_params_v.end(), v_kinks.begin(), v_kinks.end()); 00885 split_params_v.push_back(sf.endparam_v()); 00886 int num_u = split_params_u.size(); 00887 int num_v = split_params_v.size(); 00888 for (int ki = 0; ki < num_u - 1; ++ki) 00889 for (int kj = 0; kj < num_v - 1; ++kj) 00890 { 00891 // #if _MSC_VER > 0 && _MSC_VER < 1300 00892 // return_sfs.push_back(shared_ptr<SplineSurface> 00893 // (dynamic_cast<SplineSurface*> 00894 // (sf.subSurface(split_params_u[ki], split_params_v[kj], 00895 // split_params_u[ki+1], split_params_v[kj+1])))); 00896 // #else 00897 return_sfs.push_back(shared_ptr<SplineSurface> 00898 (sf.subSurface(split_params_u[ki], split_params_v[kj], 00899 split_params_u[ki+1], split_params_v[kj+1]))); 00900 // #endif 00901 } 00902 00903 return return_sfs; 00904 }
void Go::splitSurfaceIntoPatches | ( | const SplineSurface & | sf, | |
std::vector< SplineSurface > & | pat | |||
) |
Splits a spline surface into Bezier patches.
Definition at line 52 of file GGUsplit.C.
References Go::SplineSurface::basis_u(), Go::SplineSurface::basis_v(), Go::BsplineBasis::begin(), Go::SplineSurface::makeBernsteinKnotsU(), Go::SplineSurface::makeBernsteinKnotsV(), Go::SplineSurface::numCoefs_u(), Go::SplineSurface::numCoefs_v(), Go::SplineSurface::order_u(), Go::SplineSurface::order_v(), and Go::SplineSurface::subSurface().
Referenced by main(), Go::SurfaceCreators::mult1DSurfaces(), and Go::SplineSurface::normalSurface().
00055 { 00056 SplineSurface orig = sf; 00057 orig.makeBernsteinKnotsU(); 00058 orig.makeBernsteinKnotsV(); 00059 00060 int num_u = orig.numCoefs_u(); 00061 int num_v = orig.numCoefs_v(); 00062 int order_u = orig.order_u(); 00063 int order_v = orig.order_v(); 00064 int numpat_u = num_u / order_u; 00065 int numpat_v = num_v / order_v; 00066 00067 pat.resize(numpat_u * numpat_v); 00068 typedef vector<double>::const_iterator const_iter; 00069 const_iter itu = orig.basis_u().begin(); 00070 const_iter itv; 00071 for (int i = 0; i < numpat_u; ++i) { 00072 itv = orig.basis_v().begin(); 00073 for (int j = 0; j < numpat_v; ++j) { 00074 shared_ptr<SplineSurface> 00075 new_sf(orig.subSurface(*itu, *itv, 00076 *(itu+order_u), *(itv+order_v))); 00077 pat[numpat_u*j + i] = *new_sf; 00078 itv += order_v; 00079 } 00080 itu += order_u; 00081 } 00082 00083 return; 00084 }
double Go::stepLenFromRadius | ( | double | radius, | |
double | aepsge | |||
) |
Computes the step length along a curve based on radius of curvature at a point on the curve, and an absolute tolerance.
Definition at line 89 of file CurvatureUtils.C.
00094 { 00095 double tstep; 00096 00097 if (radius > ltol) { 00098 // Estimate the opening angle of the segments based on the error formula. 00099 double talpha = M_PI/0.4879*pow(aepsge/radius,1.0/6.0); 00100 00101 // Estimate step length equal to curve length of this circular arc, 00102 // We limit the step length to half the radius of curvature. 00103 tstep = std::min(talpha,0.5)*radius; 00104 } 00105 00106 else if (radius >= 0.0) // Radius of curvature is zero 00107 tstep = 100.0*aepsge; 00108 00109 else // Infinite radius of curvature 00110 tstep = 1.e4*aepsge; // @@ ???? tstep = amax in s1311 00111 00112 return tstep; 00113 }
go_iterator_traits<ForwardIterator>::value_type Go::sum | ( | ForwardIterator | first, | |
ForwardIterator | last | |||
) | [inline] |
sum finds the sum of the elements
Definition at line 112 of file Utils.h.
Referenced by Go::SplineSurface::accumulateBasis(), Go::SplineCurve::appendCurve(), Go::CreatorsUtils::createCrossTangent(), curve_ratder(), LUDecomp(), Go::SmoothSurfSet::removeKnownCoefs(), Go::SmoothSurf::setSideConstraints(), Go::SmoothCurve::setSideConstraints(), and trapezoidal().
00114 { 00115 typename go_iterator_traits<ForwardIterator>::value_type sum = 0; 00116 for (; first != last; ++first) 00117 sum += *first; 00118 return sum; 00119 }
go_iterator_traits<ForwardIterator>::value_type Go::sum_squared | ( | ForwardIterator | first, | |
ForwardIterator | last | |||
) | [inline] |
sum_squared finds the squared sum of the elements
Definition at line 124 of file Utils.h.
Referenced by Go::CoonsPatchGen::blendcoef(), and normalize().
00126 { 00127 typename go_iterator_traits<ForwardIterator>::value_type sum = 0; 00128 for (; first != last; ++first) 00129 sum += (*first)*(*first); 00130 return sum; 00131 }
void Go::surface_ratder | ( | double const | eder[], | |
int | idim, | |||
int | ider, | |||
double | gder[] | |||
) |
This function takes as input the position and a certain number of derivatives in homogenous space of a point on a rational surface.
It outputs the positioin and derivatives of this point in non-homogenous ("ordinary") space. (Corresponds to s6strider in SISL)
eder | pointer to double array of dimenson [(ider+1)*(ider+2)*(idim+1)/2] containing the position and the derivative vectors of the homogeneous surface at the point with parameter value (epar[0],epar[1]). (idim+1 is the number of components of each B-spline coefficient, i.e. the dimension of the homogemous space in which the surface lies.) These vectors are stored in the following order: First the idim+1 components of the position vector, then the idim+1 components of the D(1,0) vector, then the idim+1 components of the D(0,1) vector, then the idim+1 components of the D(2,0) vector, followed by D(1,1), D(0,2) and so on up to the idim+1 components of the D(0,ider). | |
idim | The dimension of the non homogenous space | |
ider | The number of input derivatives with respect to both parameter directions. | |
gder | pointer to the array where the result will be written (in same order as 'eder'). |
Definition at line 166 of file ratder.C.
References ALWAYS_ERROR_IF, and binom().
Referenced by Go::SplineSurface::point(), Go::SplineSurface::pointsGrid(), and surfaceKinks().
00170 : To calculate the value and ider*ider derivatives of 00171 * a rational B-spline surface. 00172 * 00173 * INPUT : eder - Double array of dimenson [(ider+1)*(ider+2)*(idim+1)/2] 00174 * containing the position and the derivative vectors 00175 * of the homogeneous surface at the point with parameter value 00176 * (epar[0],epar[1]). 00177 * (idim+1 is the number of components of each B-spline 00178 * coefficient, i.e. the dimension of the homogemous 00179 * space in which the surface lies.) 00180 * These vectors are stored in the following order: 00181 * First the idim+1 components of the position vector, 00182 * then the idim+1 components of the D(1,0) vector, 00183 * then the idim+1 components of the D(0,1) vector, 00184 * then the idim+1 components of the D(2,0) vector, 00185 * followed by D(1,1), D(0,2) 00186 * and so on up to the idim+1 components of the D(0,ider). 00187 * idim - The dimension of the non homogenous space 00188 * ider - The number of input derivatives with respect 00189 * to both parameter directions. 00190 * 00191 * 00192 * OUTPUT : jstat - Status message 00193 * >0 : Warning 00194 * =0 : ok 00195 * <0 : Error 00196 * gder - Double array of dimension [(ider+1)*(ider+2)*idim/2] 00197 * containing the position and the derivative vectors 00198 * of the surface at the point with parameter value 00199 * (epar[0],epar[1]). 00200 * (idim is the number of components of each B-spline 00201 * coefficient, i.e. the dimension of the Euclidean 00202 * space in which the surface lies.) 00203 * These vectors are stored in the following order: 00204 * First the idim components of the position vector, 00205 * then the idim components of the D(1,0) vector, 00206 * then the idim components of the D(0,1) vector, 00207 * then the idim components of the D(2,0) vector, 00208 * followed by D(1,1), D(0,2) 00209 * and so on up to the idim components of the D(0,ider). 00210 * 00211 * 00212 * METHOD : The surface P(u,v) can be written as the quotient 00213 * P(u,v) = T(u,v) / w(u,v) where T and w are ordinary splines. 00214 * The dimensions of T and w are idim and 1 00215 * respectively. The array eder contains position 00216 * and derivatives of the idim+1 dimensional surface 00217 * (T(u,v),w(u,v)). 00218 * 00219 * Now, since wP = T, we find, by the Leibnitz formula, 00220 * 00221 * k l 00222 * k! l! (k-i,l-j) (i,j) (k,l) 00223 * sum sum -------- -------- w P = T . 00224 * i!(k-i)! j!(l-j)! 00225 * i=0 j=0 00226 * 00227 * Therefore 00228 * 00229 * 00230 * -- k l -- 00231 * (k,l) | (k,l) k! l! (k-i,l-j) (i,j) | 00232 * P = | T - sum sum -------- -------- w P | / w . 00233 * | i!(k-i)! j!(l-j)! | 00234 * -- i=0 j=0 -- 00235 * i+j<k+l 00236 * 00237 * This formula is applied recursively to evaluate P's derivatives. 00238 * 00239 * MF. 00240 * 00241 * 00242 * 00243 * CALLS : 00244 * 00245 * WRITTEN BY : Michael Floater, SI, 3.9.92. 00246 * Essentially the same as s6sratder 00247 * except that we work with triangular matrices 00248 * ((0,0), (1,0), (0,1), (2,0), (1,1), ...) 00249 * instead of rectangular ones. 00250 * Revised by : Christophe Rene Birkeland, SINTEF Oslo, May 1993. 00251 * Error message corrected 00252 * Revised by : Atgeirr F Rasmussen, SINTEF, 06/04/2001. Go and C++-ified. 00253 * 00254 ********************************************************************* 00255 */ 00256 { 00257 double w0; /* The denominator. */ 00258 int ki; /* Count through dimensions. */ 00259 int idu; /* Count through derivatives in u. */ 00260 int idv; /* Count through derivatives in v. */ 00261 int* binom; 00262 std::vector<int> binomvec; 00263 int *binomu=0; /* Pointer to binomial coefficients in u. */ 00264 int *binomv=0; /* Pointer to binomial coefficients in v. */ 00265 double *sum1=0; /* Leibnitz expansion in u */ 00266 double *sum2=0; /* Leibnitz expansion in u and v. */ 00267 std::vector<double> sum1v; 00268 std::vector<double> sum2v; 00269 double sumdum1[4]; /* Fixed space for sum1. */ 00270 double sumdum2[4]; /* Fixed space for sum2. */ 00271 int idimp1; /* idim + 1. */ 00272 int iw; /* Pointer to a weight. */ 00273 int igder; /* Pointer to already calculated derivs. */ 00274 int i,iu,iv,j,k; /* Counters. */ 00275 int iderp1; /* ider + 1. */ 00276 int igrow; /* (ider+1) * idim. */ 00277 int iwrow; /* (ider+1) * idimp1. */ 00278 int iutemp,ivtemp; /* Used to find next weight in the sum. */ 00279 int tot,temp1; /* Temporary variables. */ 00280 int bidum[10]; /* Array for storing binomial coeffs. */ 00281 double temp; /* Temporary multiple. */ 00282 00283 ALWAYS_ERROR_IF(ider<0, "Less than zero derivatives ?!?"); 00284 ALWAYS_ERROR_IF(idim<1, "Less than zero derivatives ?!?"); 00285 00286 /* Find denominator. */ 00287 00288 w0 = eder[idim]; 00289 if (fabs(w0)<1e-13) w0 = (double)1.0; // Maybe we should throw instead? 00290 00291 /* If we're only asked for position, we'll do it 00292 now and exit for the sake of speed. */ 00293 00294 if(ider == 0) 00295 { 00296 for(ki=0; ki<idim; ki++) 00297 gder[ki] = eder[ki] / w0; 00298 00299 return; 00300 } 00301 00302 /* Set up some constants. */ 00303 00304 idimp1 = idim + 1; 00305 iderp1 = ider + 1; 00306 igrow = iderp1 * idim; 00307 iwrow = igrow + iderp1; /* = iderp1 * idimp1 */ 00308 00309 /* Set up binomial coefficients. 00310 Use new array only when ider > 3. */ 00311 00312 if (ider > 3) 00313 { 00314 binomvec.resize((iderp1*(iderp1+1))/2); 00315 binom = &binomvec[0]; 00316 } 00317 else 00318 { 00319 binom = bidum; 00320 } 00321 00322 for(j=0,k=0; j<=ider; j++,k+=j) 00323 { 00324 /* Calculate the new row of binomial coefficients. */ 00325 00326 binom[k] = 1; 00327 00328 for(i=k+1; i<k+j; i++) 00329 { 00330 binom[i] = binom[i-j-1] + binom[i-j]; 00331 } 00332 00333 binom[k+j] = 1; 00334 } 00335 00336 /* Set up space for sum1 and sum2 if necessary. 00337 Use new arrays only when idim > 4. */ 00338 00339 if (idim > 4) 00340 { 00341 sum1v.resize(idim); 00342 sum1 = &sum1v[0]; 00343 sum2v.resize(idim); 00344 sum2 = &sum2v[0]; 00345 } 00346 else 00347 { 00348 sum1=sumdum1; 00349 sum2=sumdum2; 00350 } 00351 00352 /* Loop through derivatives in u and v. */ 00353 00354 for(idv=0,binomv=binom; idv<=ider; idv++,binomv+=idv) 00355 { 00356 for(idu=0,binomu=binom; idu<=ider-idv; idu++,binomu+=idu) 00357 { 00358 if(idu == 0 && idv == 0) 00359 { 00360 /* Position is a special case. */ 00361 00362 for(ki=0; ki<idim; ki++) 00363 gder[ki] = eder[ki] / w0; 00364 } 00365 else 00366 { 00367 /* Calculate indices in eder and gder. */ 00368 00369 tot = idu + idv; 00370 temp1 = ((tot * (tot+1)) >> 1) + idv; 00371 00372 j = temp1 * idim; 00373 k = j + temp1; 00374 00375 /* Calculating each coefficient of the (idu,idv)'th 00376 derivative of the rational surface (in gder). 00377 00378 This requires calculating the Liebnitz sum from 00379 the subarray of gder (0,..,idu, 0,...,idv) and 00380 the subarray of eder (0,..,idu, 0,...,idv). */ 00381 00382 /* Calculate the Leibnitz sum. */ 00383 00384 for(ki=0; ki<idim; ki++) 00385 sum2[ki] = (double)0.0; 00386 00387 for(iv=0; iv<=idv; iv++) 00388 { 00389 for(ki=0; ki<idim; ki++) 00390 sum1[ki] = (double)0.0; 00391 ivtemp = idv-iv; 00392 00393 for(iu=0; iu<=idu; iu++) 00394 { 00395 tot = iu + iv; 00396 temp1 = ((tot * (tot+1)) >> 1) + iv; 00397 00398 igder = temp1 * idim; 00399 iutemp = idu-iu; 00400 00401 tot = iutemp + ivtemp; 00402 temp1 = ((tot * (tot+1)) >> 1) + ivtemp; 00403 00404 iw = temp1 * idimp1 + idim; 00405 00406 /* Add the next Leibnitz term unless we 00407 have reached the last one (the unknown). */ 00408 00409 if(iu<idu || iv<idv) 00410 { 00411 /* If iu=0 or iu=idu, the u binomial 00412 coefficient is 1 so don't multiply. */ 00413 00414 if(iu>0 && iu<idu) 00415 { 00416 temp = (double)binomu[iu] * eder[iw]; 00417 for(ki=0; ki<idim; ki++,igder++) 00418 sum1[ki] += temp * gder[igder]; 00419 } 00420 else 00421 for(ki=0; ki<idim; ki++,igder++) 00422 sum1[ki] += eder[iw] * gder[igder]; 00423 } 00424 } 00425 00426 /* If iv=0 or iv=idv, the v binomial 00427 coefficient is 1 so don't multiply. */ 00428 00429 if(iv>0 && iv<idv) 00430 for(ki=0; ki<idim; ki++) 00431 sum2[ki] += (double)binomv[iv] * sum1[ki]; 00432 else 00433 for(ki=0; ki<idim; ki++) 00434 sum2[ki] += sum1[ki]; 00435 } 00436 for(ki=0; ki<idim; ki++,j++,k++) 00437 gder[j] = (eder[k] - sum2[ki]) / w0; 00438 } 00439 } 00440 } 00441 00442 return; 00443 }
void Go::surfaceKinks | ( | const SplineSurface & | sf, | |
double | max_normal_angle, | |||
std::vector< double > & | g1_disc_u, | |||
std::vector< double > & | g1_disc_v, | |||
bool | compute_g1_disc = true | |||
) |
Surface assumed to be continuous.
Return parameter values failing to achieve G1-continuity.
Definition at line 720 of file GeometryTools.C.
References ALWAYS_ERROR_IF, Go::Point::angle(), Go::SplineSurface::basis(), Go::Point::begin(), Go::BsplineBasis::begin(), Go::SplineSurface::coefs_begin(), Go::SplineSurface::coefs_end(), Go::BsplineBasis::computeBasisValues(), Go::BsplineBasis::computeBasisValuesLeft(), Go::SplineSurface::dimension(), Go::Point::dist(), Go::Point::end(), Go::BsplineBasis::end(), Go::BsplineBasis::knotIntervalFuzzy(), Go::BsplineBasis::knotMultiplicity(), Go::BsplineBasis::numCoefs(), Go::BsplineBasis::order(), Go::SplineSurface::rational(), Go::SplineSurface::rcoefs_begin(), Go::SplineSurface::rcoefs_end(), Go::Point::resize(), Go::Point::setValue(), Go::BsplineBasis::startparam(), surface_ratder(), and transpose_array().
Referenced by Go::BoundedUtils::trimSurfaceKinks().
00724 { 00725 int dim = sf.dimension(); 00726 bool rational = sf.rational(); 00727 int kdim = dim + (rational); 00728 ALWAYS_ERROR_IF(dim != 3, 00729 "Expecting surface to be of dimension 3."); 00730 g1_disc_u.clear(); 00731 g1_disc_v.clear(); 00732 00733 bool dir_is_u = true; // We traverse dir given by dir_is_u, looking for kinks. 00734 for (int ki = 0; ki < 2; ++ki) { // We perform calculations in both parameter directions. 00735 const BsplineBasis& basis = sf.basis(!dir_is_u); 00736 const BsplineBasis& other_basis = sf.basis(dir_is_u); 00737 std::vector<double> disc_candidates; 00738 int order = basis.order(); 00739 int other_order = other_basis.order(); 00740 int num_coefs = basis.numCoefs(); 00741 int other_num_coefs = other_basis.numCoefs(); 00742 std::vector<double> coefs(rational ? sf.rcoefs_begin() : sf.coefs_begin(), 00743 rational ? sf.rcoefs_end() : sf.coefs_end()); 00744 if (!dir_is_u) // We may now assume that direction is u. 00745 transpose_array(kdim, num_coefs, other_num_coefs, &coefs[0]); 00746 00747 int nmb_int_samples = (rational) ? 00748 9*other_order - 11 : 4*other_order - 5; // # of evaluations for each knot interval 00749 00750 if (!compute_g1_disc) 00751 { 00752 // Check for parametric continuity. Fewer evaluations are required 00753 nmb_int_samples = (rational) ? 4*other_order - 1 : other_order-1; 00754 } 00755 00756 int g1_mult = order - 2; // Multiplicity for which g1 is assured. 00757 std::vector<double>::const_iterator iter = basis.begin() + order; 00758 std::vector<double>::const_iterator end_iter = basis.end() - order; 00759 for (; iter != end_iter; ++iter) 00760 if (iter[0] == iter[g1_mult]) { 00761 disc_candidates.push_back(*iter); 00762 while (iter[0] == iter[1]) 00763 ++iter; 00764 } 00765 00766 // For each possible discontinuity we calculate angles between normals. 00767 for (size_t kj = 0; kj < disc_candidates.size(); ++kj) { 00768 double tpar = disc_candidates[kj]; 00769 int derivs = 1; 00770 std::vector<double> basis_vals_left = // Computing from the left. 00771 basis.computeBasisValuesLeft(tpar, derivs); 00772 std::vector<double> basis_vals_right = // Computing from the right. 00773 basis.computeBasisValues(tpar, derivs); 00774 int coef_li = basis.knotIntervalFuzzy(tpar) - order + 1; 00775 int mult = basis.knotMultiplicity(tpar); 00776 int coef_left_li = coef_li - mult; 00777 00778 // To increase performance we avoid recalculating basis values when next 00779 // knots is in the same interval. 00780 std::vector<double>::const_iterator iter = other_basis.begin(); 00781 while (iter != other_basis.end()) { 00782 std::vector<double>::const_iterator next_iter = iter + 1; 00783 while ((next_iter < other_basis.end()) && (*next_iter == *iter)) 00784 ++next_iter; 00785 if (next_iter == other_basis.end()) { 00786 break; 00787 } 00788 double tstep = (*next_iter - *iter)/(nmb_int_samples - 1); 00789 double tmin = other_basis.startparam(); 00790 int kh; 00791 for (kh = 0; kh < nmb_int_samples; ++kh) { 00792 double other_tpar = tmin + kh*tstep; 00793 // We must calculate normals from both sides of the iso-curve. 00794 std::vector<double> other_basis_vals = 00795 other_basis.computeBasisValues(other_tpar, derivs); 00796 int other_coef_li = other_basis.knotIntervalFuzzy(other_tpar) - other_order + 1; 00797 00798 Point part_left(kdim); 00799 part_left.setValue(0.0); 00800 Point part_right = part_left; 00801 Point other_part = part_left; 00802 Point pt = part_left; 00803 // We compute the partial derivatives in both dirs, assuming surface is cont. 00804 for (int ii = 0; ii < order; ++ii) 00805 for (int jj = 0; jj < other_order; ++jj) 00806 for (int kk = 0; kk < kdim; ++kk) { 00807 double coef = 00808 coefs[kdim*((other_coef_li+jj)*num_coefs+coef_li+ii)+kk]; 00809 double coef_l = 00810 coefs[kdim*((other_coef_li+jj)*num_coefs+coef_left_li+ii)+kk]; 00811 pt[kk] += 00812 coef*basis_vals_right[2*ii]*other_basis_vals[2*jj]; 00813 part_left[kk] += 00814 coef_l*basis_vals_left[2*ii+1]*other_basis_vals[2*jj]; 00815 part_right[kk] += 00816 coef*basis_vals_right[2*ii+1]*other_basis_vals[2*jj]; 00817 other_part[kk] += 00818 coef*basis_vals_left[2*ii]*other_basis_vals[2*jj+1]; 00819 } 00820 if (rational) { 00821 std::vector<double> restemp(3*kdim); 00822 std::copy(pt.begin(), pt.end(), restemp.begin()); 00823 std::copy(part_left.begin(), part_left.end(), restemp.begin() + kdim); 00824 std::copy(other_part.begin(), other_part.end(), restemp.begin() + 2*kdim); 00825 std::vector<double> restemp2(3*dim); 00826 surface_ratder(&restemp[0], dim, 1, &restemp2[0]); 00827 part_left.resize(dim); 00828 part_left.setValue(&restemp2[dim]); 00829 std::copy(part_right.begin(), part_right.end(), restemp.begin() + kdim); 00830 surface_ratder(&restemp[0], dim, 1, &restemp2[0]); 00831 part_right.resize(dim); 00832 part_right.setValue(&restemp2[dim]); 00833 other_part.resize(dim); 00834 other_part.setValue(&restemp2[2*dim]); 00835 } 00836 00837 double angle; 00838 if (compute_g1_disc) 00839 { 00840 // Compute angle between surface normals 00841 Point left_normal = part_left%other_part; 00842 Point right_normal = part_right%other_part; 00843 angle = left_normal.angle(right_normal); 00844 } 00845 else 00846 { 00847 // Compute difference between partial derivatives 00848 angle = part_left.dist(part_right); 00849 } 00850 00851 if (angle > max_normal_angle) { 00852 if (dir_is_u) 00853 g1_disc_u.push_back(tpar); 00854 else 00855 g1_disc_v.push_back(tpar); 00856 break; 00857 } 00858 } 00859 if (kh < nmb_int_samples) 00860 break; 00861 else 00862 iter = next_iter; 00863 } 00864 } 00865 dir_is_u = false; 00866 } 00867 }
boost::shared_ptr< SplineSurface > Go::surfaceSum | ( | const SplineSurface & | sf1, | |
double | fac1, | |||
const SplineSurface & | sf2, | |||
double | fac2, | |||
double | num_tol = 1e-05 | |||
) |
Definition at line 25 of file surfaceSum.C.
References ALWAYS_ERROR_IF, Go::SplineSurface::clone(), Go::SplineSurface::endparam_u(), Go::SplineSurface::endparam_v(), Go::SplineSurface::rational(), Go::SplineSurface::startparam_u(), Go::SplineSurface::startparam_v(), THROW, and unifySurfaceSplineSpace().
00033 { 00034 // Check input 00035 ALWAYS_ERROR_IF(fabs(sf1.startparam_u() - sf2.startparam_u()) > num_tol || 00036 fabs(sf1.endparam_u() - sf2.endparam_u()) > num_tol || 00037 fabs(sf1.startparam_v() - sf2.startparam_v()) > num_tol || 00038 fabs(sf1.endparam_v() - sf2.endparam_v()) > num_tol, 00039 "Inconsistent parameter domain."); 00040 00041 // For the time being 00042 if (sf1.rational() || sf2.rational()) { 00043 THROW("Sum of rational surfaces is not implemented"); 00044 } 00045 00046 // Make copy of surfaces 00047 vector<shared_ptr<SplineSurface> > surfaces; 00048 surfaces.reserve(2); 00049 shared_ptr<SplineSurface> sf; 00050 // #ifdef _MSC_VER 00051 // sf = shared_ptr<SplineSurface>(dynamic_cast<SplineSurface*>(sf1.clone())); 00052 // #else 00053 sf = shared_ptr<SplineSurface>(sf1.clone()); 00054 // #endif 00055 surfaces.push_back(sf); 00056 // #ifdef _MSC_VER 00057 // sf = shared_ptr<SplineSurface>(dynamic_cast<SplineSurface*>(sf2.clone())); 00058 // #else 00059 sf = shared_ptr<SplineSurface>(sf2.clone()); 00060 // #endif 00061 surfaces.push_back(sf); 00062 00063 // Make sure that the surfaces live on the same knot vector 00064 unifySurfaceSplineSpace(surfaces, num_tol); 00065 00066 // Add signed coefficients 00067 vector<double> coefs; 00068 int nmb_coefs_u = surfaces[0]->numCoefs_u(); 00069 int nmb_coefs_v = surfaces[0]->numCoefs_v(); 00070 int dim = surfaces[0]->dimension(); 00071 coefs.resize(dim*nmb_coefs_u*nmb_coefs_v); 00072 int ki; 00073 std::vector<double>::iterator s1 = surfaces[0]->coefs_begin(); 00074 std::vector<double>::iterator s2 = surfaces[1]->coefs_begin(); 00075 for (ki=0; ki<dim*nmb_coefs_u*nmb_coefs_v; ki++) 00076 coefs[ki] = fac1*s1[ki] + fac2*s2[ki]; 00077 00078 // Create output curve 00079 boost::shared_ptr<SplineSurface> 00080 surfacesum(new SplineSurface(nmb_coefs_u, nmb_coefs_v, 00081 surfaces[0]->order_u(), 00082 surfaces[0]->order_v(), 00083 surfaces[0]->basis_u().begin(), 00084 surfaces[0]->basis_v().begin(), 00085 &coefs[0], dim, false)); 00086 00087 return surfacesum; 00088 }
void Go::systemSleep | ( | double | sleep_time | ) |
Sleep for sleep_time seconds.
Definition at line 127 of file timeutils.C.
00129 { 00130 // Sleep if sleep time is positive 00131 if( sleep_time > 0 ) 00132 { 00133 #ifdef WIN32 00134 #ifndef _WIN32_WCE 00135 Sleep((unsigned long)(sleep_time*1000)); 00136 #else 00137 // Do not sleep... 00138 #endif 00139 #else 00140 #ifdef __GNUC__ 00141 usleep((long)(sleep_time*1e6)); 00142 #else 00143 usleep(sleep_time*1e6); 00144 #endif 00145 #endif 00146 } 00147 }
double Go::tanLenFromRadius | ( | double | radius, | |
double | angle | |||
) |
To create the tangent length for interpolating a circular arc with an almost equi-oscillating Hermit qubic.
Definition at line 116 of file CurvatureUtils.C.
Referenced by getHermiteData().
00121 { 00122 double tcos,tsin; /* Dummy variables */ 00123 double ta,tb,tc,tl; /* Dummy variables */ 00124 double tconst = (double)1.85530139760811990992528773586425; 00125 /* Constant used in the calculation */ 00126 00127 00128 00129 tcos = cos(angle); 00130 tsin = sin(angle); 00131 00132 /* Calculate length of tangents 00133 * tconst = (3-2sqrt(2))**1/3 + (3+2sqrt(2))**1/3 - 0.5 */ 00134 00135 ta = (double)0.6*tconst - (double)0.9*tcos; 00136 tb = ((double)0.4*tconst+(double)1.8)*tsin; 00137 tc = ((double)0.4*tconst+(double)1.0) 00138 * tcos - (double)0.4*tconst - (double)1.0; 00139 tl = radius*(-tb+sqrt(tb*tb-4*ta*tc))/((double)2.0*ta); 00140 00141 return(tl); 00142 }
void Go::translateLineCloud | ( | const Point & | trans_vec, | |
LineCloud & | lc | |||
) |
Translate the given LineCloud by trans_vec.
Definition at line 1023 of file GeometryTools.C.
References Go::Array< T, Dim >::begin(), Go::Array< T, Dim >::end(), Go::LineCloud::numLines(), Go::LineCloud::point(), and Go::LineCloud::rawData().
01025 { 01026 int ki; 01027 int nmb_pts = lc.numLines()*2; 01028 int dim = 3; 01029 for (ki = 0; ki < nmb_pts; ++ki) { 01030 Vector3D vec = lc.point(ki); 01031 Point pt(vec.begin(), vec.end()); 01032 pt += trans_vec; 01033 copy(pt.begin(), pt.end(), lc.rawData() + ki*dim); 01034 } 01035 }
void Go::translateSplineCurve | ( | const Point & | trans_vec, | |
SplineCurve & | cv | |||
) |
Translate the given SplineCurve by trans_vec.
Definition at line 999 of file GeometryTools.C.
References ASSERT, Go::SplineCurve::coefs_begin(), Go::SplineCurve::coefs_end(), Go::Point::dimension(), Go::SplineCurve::rational(), Go::SplineCurve::rcoefs_begin(), and Go::SplineCurve::rcoefs_end().
Referenced by Go::Circle::geometryCurve(), and Go::BoundedUtils::translateBoundedSurf().
01001 { 01002 int ki; 01003 ASSERT(trans_vec.dimension() == 3); // We're working in 3D space. 01004 int dim = 3 + cv.rational(); 01005 std::vector<double>::iterator iter = cv.rational() ? cv.rcoefs_begin() : cv.coefs_begin(); 01006 std::vector<double>::iterator end_iter = cv.rational() ? cv.rcoefs_end() : cv.coefs_end(); 01007 std::vector<double>::iterator coef_iter = cv.coefs_begin(); 01008 while (iter != end_iter) { // @@ A faster approach would be to use rotation matrix directly. 01009 double weight = cv.rational() ? iter[3] : 1.0; 01010 for (ki = 0; ki < 3; ++ki) 01011 iter[ki] = (iter[ki]/weight + trans_vec[ki])*weight; 01012 if (cv.rational()) { 01013 for (ki = 0; ki < 3; ++ki) 01014 coef_iter[ki] = iter[ki]/weight; 01015 coef_iter += dim - 1; 01016 } 01017 iter += dim; 01018 } 01019 }
void Go::translateSplineSurf | ( | const Point & | trans_vec, | |
SplineSurface & | sf | |||
) |
Translate the given SplineSurface by trans_vec.
Definition at line 976 of file GeometryTools.C.
References ASSERT, Go::SplineSurface::coefs_begin(), Go::SplineSurface::coefs_end(), Go::Point::dimension(), Go::SplineSurface::rational(), Go::SplineSurface::rcoefs_begin(), and Go::SplineSurface::rcoefs_end().
Referenced by Go::Sphere::geometrySurface(), Go::Cylinder::geometrySurface(), Go::Cone::geometrySurface(), and Go::BoundedUtils::translateBoundedSurf().
00978 { 00979 int ki; 00980 ASSERT(trans_vec.dimension() == 3); // We're working in 3D space. 00981 int dim = 3 + sf.rational(); 00982 std::vector<double>::iterator iter = sf.rational() ? sf.rcoefs_begin() : sf.coefs_begin(); 00983 std::vector<double>::iterator end_iter = sf.rational() ? sf.rcoefs_end() : sf.coefs_end(); 00984 std::vector<double>::iterator coef_iter = sf.coefs_begin(); 00985 while (iter != end_iter) { 00986 double weight = sf.rational() ? iter[3] : 1.0; 00987 for (ki = 0; ki < 3; ++ki) 00988 iter[ki] = (iter[ki]/weight + trans_vec[ki])*weight; 00989 if (sf.rational()) { 00990 for (ki = 0; ki < 3; ++ki) 00991 coef_iter[ki] = iter[ki]/weight; 00992 coef_iter += dim - 1; 00993 } 00994 iter += dim; 00995 } 00996 }
void Go::transpose_array | ( | int | dim, | |
int | m, | |||
int | n, | |||
double * | array_start | |||
) |
Transpose an (m x n) matrix of dim-dimensional points stored as an array in row-major order (i.e.
all elements of a single row are stored together).
dim | the dimension of each of the points in the array | |
m | number of lines in the matrix | |
n | number of columns in the matrix | |
array_start | pointer to the start of array where matrix is stored |
Definition at line 29 of file Utils.C.
Referenced by Go::SplineSurface::interpolate(), main(), surfaceKinks(), Go::RectGrid::swapDirections(), and Go::SplineSurface::swapParameterDirection().
00032 { 00033 std::vector<double> c(array_start, 00034 array_start + dim*num_old_cols*num_old_rows); 00035 for (int new_row = 0; new_row < num_old_cols; ++new_row) { 00036 for (int new_col = 0; new_col < num_old_rows; ++new_col) { 00037 for (int dd = 0; dd < dim; ++dd) { 00038 array_start[new_row*num_old_rows*dim + new_col*dim + dd] 00039 = c[new_col*num_old_cols*dim + new_row*dim + dd]; 00040 } 00041 } 00042 } 00043 }
void Go::trapezoidal | ( | Functor & | f, | |
double | a, | |||
double | b, | |||
double & | s, | |||
int | n | |||
) | [inline] |
This routine computes the n'th stage of refinement of an extended trapezoidal rule.
Used as a help routine for 'simpsons_rule', found further down in this file. NB: It only carries out the computation for ONE stage of the procedure, so if you want to use it to integrate a function, you must call it successively for n = 1, n = 2, ....
Definition at line 35 of file Integration.h.
References DEBUG_ERROR_IF, f(), and sum().
Referenced by simpsons_rule().
00036 { 00037 DEBUG_ERROR_IF(n < 1, "Bad function argument to trapezoidal()."); 00038 if (n == 1) { 00039 s = 0.5 * (b - a) * (f(a) + f(b)); 00040 } else { 00041 int num_int_pts = 1 << (n-2); 00042 //int num_int_pts = std::power(2, n-2); 00043 double spacing = (b - a) / num_int_pts; 00044 double x = a + 0.5 * spacing; 00045 double sum = 0.0; 00046 for (int i = 0; i < num_int_pts; ++i) { 00047 sum += f(x); 00048 x += spacing; 00049 } 00050 s += (b - a) * sum / num_int_pts; 00051 s *= 0.5; 00052 } 00053 }
bool Go::trim_a_triangle | ( | boost::shared_ptr< SplineSurface > | srf, | |
vector< Vector3D > & | vert, | |||
vector< Vector2D > & | vert_p, | |||
vector< int > & | bd, | |||
vector< Vector3D > & | norm, | |||
const vector< Vector3D > & | trim_curve_p, | |||
const vector< int > & | contour, | |||
const int | c1_indx, | |||
const int | c2_indx, | |||
const int | c3_indx, | |||
vector< int > & | mesh, | |||
const bool | inner_trimming_curve = false | |||
) |
Definition at line 1022 of file spline2mesh.C.
References add_triangle(), DBG_FLAG, degenerate_triangle(), is_inside(), is_on_contour(), and split_triangle().
Referenced by trim_a_triangle_soup().
01035 { 01036 #ifndef DBG 01037 const bool dbg=false; 01038 #endif 01039 if (dbg) 01040 printf("\n\n= trim_a_triangle starting =====================================================================\n"); 01041 01042 vector<int> new_mesh; 01043 01044 const Vector3D c1=vert[c1_indx], c2=vert[c2_indx], c3=vert[c3_indx]; 01045 const Vector3D n1=norm[c1_indx], n2=norm[c2_indx], n3=norm[c3_indx]; 01046 const Vector2D c1_p=vert_p[c1_indx], c2_p=vert_p[c2_indx], c3_p=vert_p[c3_indx]; 01047 int s0, s, s3; 01048 01049 if (dbg) 01050 { 01051 printf("\n The corners:\n\n"); 01052 printf("hold on; plot(%f, %f, 'rx', 'markersize', %d, 'linewidth', 2); hold off\n", c1_p[0], c1_p[1], 14); 01053 printf("hold on; plot(%f, %f, 'gx', 'markersize', %d, 'linewidth', 2); hold off\n", c2_p[0], c2_p[1], 14); 01054 printf("hold on; plot(%f, %f, 'bx', 'markersize', %d, 'linewidth', 2); hold off\n\n", c3_p[0], c3_p[1], 14); 01055 } 01056 01057 if (dbg) printf(" = Calling is_inside (point_inside_contour) for corner c1... ============================\n"); 01058 const int c1_inside = is_inside(trim_curve_p, contour, c1_p[0], c1_p[1] DBG_FLAG); 01059 if (dbg) printf(" = Calling is_inside (point_inside_contour) for corner c2... ============================\n"); 01060 const int c2_inside = is_inside(trim_curve_p, contour, c2_p[0], c2_p[1] DBG_FLAG); 01061 if (dbg) printf(" = Calling is_inside (point_inside_contour) for corner c3... ============================\n"); 01062 const int c3_inside = is_inside(trim_curve_p, contour, c3_p[0], c3_p[1] DBG_FLAG); 01063 01064 if (dbg) printf(" = Calling is_on_contour (point_on_contour) for corner c1... ============================\n"); 01065 const int c1_on = is_on_contour(trim_curve_p, contour, c1_p[0], c1_p[1] DBG_FLAG); 01066 if (dbg) printf(" = Calling is_on_contour (point_on_contour) for corner c2... ============================\n"); 01067 const int c2_on = is_on_contour(trim_curve_p, contour, c2_p[0], c2_p[1] DBG_FLAG); 01068 if (dbg) printf(" = Calling is_on_contour (point_on_contour) for corner c3... ============================\n"); 01069 const int c3_on = is_on_contour(trim_curve_p, contour, c3_p[0], c3_p[1] DBG_FLAG); 01070 01071 if (dbg) 01072 printf("----------------------------------------------------------------------------------------------------\n" 01073 "IN/ON-tests before considering whether curve is outer or inner:\n" 01074 "c1_inside=%d, c2_inside=%d, c3_inside=%d, c1_on=%d, c2_on=%d, c3_on=%d\n" 01075 "----------------------------------------------------------------------------------------------------\n", 01076 c1_inside, c2_inside, c3_inside, c1_on, c2_on, c3_on); 01077 01078 // 100211: s2==0 <=> no corner on curve itself. 01079 const int s2 = (c1_on << 0) + (c2_on << 1) + (c3_on << 2); 01080 01081 const Vector2D centroid = (1.0/3.0)*(c1_p+c2_p+c3_p); 01082 const int c_inside = is_inside(trim_curve_p, contour, centroid[0], centroid[1]); 01083 01084 if (inner_trimming_curve) 01085 { 01086 // 100211: s0==0 <=> all corners are not inside. (Is "on edge" included in "inside"?) 01087 s0 = ((!c1_inside) << 0) + ((!c2_inside) << 1) + ((!c3_inside) << 2); 01088 01089 // 100211: 01090 s = (((!c1_inside) | c1_on) << 0) + (((!c2_inside) | c2_on) << 1) + (((!c3_inside) | c3_on) << 2); 01091 01092 // 100211: s3==true <=> "centroid is not inside". 01093 s3 = !c_inside; 01094 01095 if (dbg) 01096 // if ((s0!=7) || (s2!=0) || (s!=7)) 01097 printf(" s0=%d, s2=%d, s=%d, s3=%d\n", s0, s2, s, s3); 01098 01099 if ( (s0==0) && ((s2==1) || (s2==2) || (s2==4)) ) 01100 { 01101 if (dbg) 01102 printf("No points on the inside, exactly one *on* the contour. Setting s=0 and skipping triangle. 1\n"); 01103 s=0; 01104 } 01105 if ( ((s0==1) && (s2==1)) || ((s0==2) && (s2==2)) || ((s0==4) && (s2==4)) ) 01106 { 01107 if (dbg) 01108 printf("Two points not on the inside, the remaining both inside and *on*. Skipping triangle. 2\n"); 01109 s=0; 01110 } 01111 01112 if (dbg) 01113 if ( (s==7) && (s3==0) ) 01114 { 01115 printf("All corners on the inside, mean not, skipping triangle.\n"); 01116 // 090220: This is not so straightforward... Not all these triangles are either fully inside or 01117 // outside. They should really be split, but then we should split neighbours also, if we 01118 // ever are to get a valid triangulation. (Which we are currently not getting, since we 01119 // produce lots of duplicate nodes and so on...) 01120 //s=0; 01121 } 01122 01123 if (dbg) 01124 if ( ((s2==3) && (s0==4)) || 01125 ((s2==5) && (s0==2)) || 01126 ((s2==6) && (s0==1)) ) 01127 { 01128 printf("Two points on the curve, one inside. Skipping triangle.\n"); 01129 // s=0; 01130 } 01131 01132 if (dbg) 01133 if (s2==7) 01134 { 01135 printf("All points on contour, guessing that the triangle should be excluded. \n"); 01136 printf(" s0=%d, s2=%d, s=%d, s3=%d\n", s0, s2, s, s3); 01137 // s=0; 01138 } 01139 01140 } 01141 else 01142 { 01143 s0 = (c1_inside << 0) + (c2_inside << 1) + (c3_inside << 2); 01144 s = ((c1_inside | c1_on) << 0) + ((c2_inside | c2_on) << 1) + ((c3_inside | c3_on) << 2); 01145 s3 = c_inside; 01146 01147 if (dbg) 01148 printf("---> s0=%d s2=%d s=%d s3=%d\n", s0, s2, s, s3), fflush(stdout); 01149 01150 if ( (s0==0) && ((s2==1) || (s2==2) || (s2==4)) ) 01151 { 01152 if (dbg) 01153 printf("No points on the inside, exactly one *on* the contour. Setting s=0 and skipping triangle. 4\n"); 01154 // s=0; 01155 } 01156 01157 if ( ((s0==1) && (s2==1)) || ((s0==2) && (s2==2)) || ((s0==4) && (s2==4)) ) 01158 { 01159 if (dbg) 01160 printf("Two points not inside, the remaining both inside and *on*. Skipping triangle. s=%d 5\n", s); 01161 //s=0; 01162 //s=7; 01163 } 01164 01165 if (dbg) 01166 if ((s==7) && (!s3)) 01167 { 01168 printf("====================> HUH?! s0=%d s2=%d s=%d s3=%d\n", s0, s2, s, s3); 01169 // s=0; 01170 } 01171 01172 if (dbg) 01173 printf("---> s0=%d s2=%d s=%d s3=%d\n", s0, s2, s, s3), fflush(stdout); 01174 01175 } 01176 01177 if (degenerate_triangle(c1_p, c2_p, c3_p)) 01178 { 01179 printf("Degenerate triangle! setting s=-1 and skipping triangle. 6\n"); 01180 s=-1; 01181 } 01182 01183 01184 // 01185 // 100223: Hmm... What is really the pattern with respect to the usage of 01186 // 'forced_skipping_of_second_edge'-values used below? 01187 // 01188 // Note that if s==0, the triangle will silently be forgotten... 01189 // 01190 // 100225: No, adding a stage for this situation too. 01191 // 01192 // Hmm... Maybe it's time to stop letting "on" imply "inside"...?! 01193 // 01194 01195 #ifdef SPLIT_LARGE_TRIANGLES 01196 if ( (!(c1_inside || c2_inside || c3_inside)) && (!inner_trimming_curve) && (c1_on || c2_on || c3_on) ) 01197 s=0; 01198 #endif 01199 01200 01201 01202 01203 bool redo=false; 01204 if (dbg) 01205 printf(" Going into the switch, s=%d\n", s); 01206 switch (s) 01207 { 01208 #ifdef SPLIT_LARGE_TRIANGLES 01209 case 0: 01210 if (dbg) printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); 01211 if (!inner_trimming_curve) 01212 redo = split_triangle_with_all_corners_outside(c1_indx, c2_indx, c3_indx, 01213 c1_inside, c2_inside, c3_inside, 01214 c1_on, c2_on, c3_on, 01215 srf, vert, vert_p, bd, norm, new_mesh, trim_curve_p, contour, 01216 dbg, inner_trimming_curve); 01217 if (dbg) printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); 01218 break; 01219 #endif 01220 case 5: // Corners 1 and 3 are inside, intersections must be on edges 1-2 and 2-3. Compatible with 1-case. 01221 // 090217: Not now, don't want the 'forced skip'. 01222 redo=split_triangle(c1_indx, c2_indx, c3_indx, srf, vert, vert_p, bd, norm, new_mesh, 01223 trim_curve_p, contour, dbg, false, inner_trimming_curve); 01224 break; 01225 case 1: // Only corner 1 is inside, so intersections must be on edges 1-2 and 3-1. 01226 redo=split_triangle(c1_indx, c2_indx, c3_indx, srf, vert, vert_p, bd, norm, new_mesh, 01227 trim_curve_p, contour, dbg, true, inner_trimming_curve); 01228 break; 01229 case 2: // Corner 2 is inside, intersections must be on edges 2-3 and 3-1. Can go straight into the 3-case. 01230 01231 // 090217: Huh?! Should be 2-3 and 1-2, shouldn't it?! Think maybe the comment was wrong, but 01232 // conclusion and code correct. Sadly, this will only work when the assumption about no 01233 // "spurious" intersections is met. I.e., that there are no "superfluous" 01234 // intersections. In many cases this does not hold. Trying to fix this by not combining 01235 // cases here, and at the same time, not letting split_triangle choose to continue on the 01236 // third edge if it does not find any intersection on the second edge. The problem seems 01237 // to be that such a spurious intersection can be on edge 2, causing split_triangle not to 01238 // look for the (correct and sought) intersection on edge 3... 01239 01240 redo=split_triangle(c2_indx, c3_indx, c1_indx, srf, vert, vert_p, bd, norm, new_mesh, 01241 trim_curve_p, contour, dbg, true, inner_trimming_curve); 01242 break; 01243 case 3: // Corners 1 and 2 are inside, so intersections must be on edges 2-3 and 3-1. 01244 redo=split_triangle(c2_indx, c3_indx, c1_indx, srf, vert, vert_p, bd, norm, new_mesh, 01245 trim_curve_p, contour, dbg, false, inner_trimming_curve); 01246 break; 01247 case 6: // Corners 2 and 3 are inside, intersections must be on edges 3-1 and 1-2. Compatible with 4-case. 01248 // 090217: Not now, don't want the 'forced skip'. 01249 redo=split_triangle(c3_indx, c1_indx, c2_indx, srf, vert, vert_p, bd, norm, new_mesh, 01250 trim_curve_p, contour, dbg, false, inner_trimming_curve); 01251 break; 01252 case 4: // Corner 3 is inside, so intersections must be on edges 3-1 and 2-3. 01253 redo=split_triangle(c3_indx, c1_indx, c2_indx, srf, vert, vert_p, bd, norm, new_mesh, 01254 trim_curve_p, contour, dbg, true, inner_trimming_curve); 01255 break; 01256 case 7: // All corners are inside, not splitting, just keeping it. 01257 add_triangle(vert_p, new_mesh, c1_indx, c2_indx, c3_indx); 01258 redo=false; 01259 break; 01260 } 01261 mesh=new_mesh; 01262 01263 if (dbg) 01264 printf(" redo=%d\n= trim_a_triangle done =======================================================" 01265 "==================\n\n\n", redo); 01266 01267 return redo; 01268 }
void Go::trim_a_triangle_soup | ( | boost::shared_ptr< SplineSurface > | srf, | |
vector< Vector3D > & | vert, | |||
vector< Vector2D > & | vert_p, | |||
vector< int > & | bd, | |||
vector< Vector3D > & | norm, | |||
const vector< Vector3D > & | trim_curve_p, | |||
const vector< int > & | contour, | |||
vector< int > & | mesh, | |||
const bool | inner_trimming_curve = false | |||
) |
Definition at line 1287 of file spline2mesh.C.
References trim_a_triangle().
Referenced by make_trimmed_mesh().
01298 { 01299 vector<int> new_mesh, mesh_to_reiterate, mesh_ok; 01300 const int maxiter=10; 01301 int iter=0; 01302 01303 #ifdef DBG 01304 system("rm tats*.m"); 01305 #endif 01306 01307 do 01308 { 01309 01310 for (int ilim=mesh.size()/3, i=0; i<ilim; i++) 01311 //for (int ilim=mesh.size()/3, i=0; i<1; i++) 01312 { 01313 const int c1_indx=mesh[3*i], c2_indx=mesh[3*i+1], c3_indx=mesh[3*i+2]; 01314 bool redo=trim_a_triangle(srf, vert, vert_p, bd, norm, trim_curve_p, contour, 01315 c1_indx, c2_indx, c3_indx, new_mesh, inner_trimming_curve 01316 #ifdef DBG 01317 // 100223: Remember that when having more trimming curves, this may be 01318 // triggered once for each of them... 01319 ,false // , i==423 // , false // , i==1069 // , false // , i==94 01320 #endif 01321 ); 01322 if (redo) 01323 mesh_to_reiterate.insert(mesh_to_reiterate.end(), new_mesh.begin(), new_mesh.end()); 01324 else 01325 mesh_ok.insert(mesh_ok.end(), new_mesh.begin(), new_mesh.end()); 01326 #ifdef DBG 01327 // 100210: Showing both the triangle being processed (magenta) and the ones being produced (red.) 01328 if ( (iter==0) || (iter==1) ) 01329 #if 0 01330 if ( 01331 01332 ( ((fabs(vert_p[mesh[3*i ]][0]-(-22.56))<1e-5) && (fabs(vert_p[mesh[3*i ]][1]-(30.888))<1e-5)) || 01333 ((fabs(vert_p[mesh[3*i+1]][0]-(-22.56))<1e-5) && (fabs(vert_p[mesh[3*i+1]][1]-(30.888))<1e-5)) || 01334 ((fabs(vert_p[mesh[3*i+2]][0]-(-22.56))<1e-5) && (fabs(vert_p[mesh[3*i+2]][1]-(30.888))<1e-5)) ) && 01335 01336 (vert_p[mesh[3*i]][0] > -26) && 01337 (vert_p[mesh[3*i]][0] < -17) && 01338 (vert_p[mesh[3*i]][1] > 28) && 01339 (vert_p[mesh[3*i]][1] < 36) ) 01340 #endif 01341 { 01342 char fname[1000]; 01343 if (iter==0) 01344 sprintf(fname, "tats%04d.m", i); 01345 else 01346 sprintf(fname, "xtats%04d.m", i); 01347 FILE *f = fopen(fname, "w"); 01348 fprintf(f, "hold on\ngrid on\n"); 01349 const int u=0, v=1; 01350 const char col1 = iter==0 ? 'm' : 'b'; 01351 const char col2 = iter==0 ? 'r' : 'g'; 01352 fprintf(f, "patch([%f; %f; %f], [%f; %f; %f], '%c');\n", 01353 vert_p[mesh[3*i]][u], vert_p[mesh[3*i+1]][u], vert_p[mesh[3*i+2]][u], 01354 vert_p[mesh[3*i]][v], vert_p[mesh[3*i+1]][v], vert_p[mesh[3*i+2]][v], col1); 01355 fprintf(f, "line([%f; %f; %f; %f], [%f; %f; %f; %f], 'color', 'k');\n", 01356 vert_p[mesh[3*i]][u], vert_p[mesh[3*i+1]][u], vert_p[mesh[3*i+2]][u], vert_p[mesh[3*i]][u], 01357 vert_p[mesh[3*i]][v], vert_p[mesh[3*i+1]][v], vert_p[mesh[3*i+2]][v], vert_p[mesh[3*i]][v]); 01358 for (int j=0; j<int(new_mesh.size())/3; j++) 01359 { 01360 fprintf(f, "patch([%f; %f; %f], [%f; %f; %f], '%c');\n", 01361 vert_p[new_mesh[3*j]][u], vert_p[new_mesh[3*j+1]][u], vert_p[new_mesh[3*j+2]][u], 01362 vert_p[new_mesh[3*j]][v], vert_p[new_mesh[3*j+1]][v], vert_p[new_mesh[3*j+2]][v], col2); 01363 fprintf(f, "line([%f; %f; %f; %f], [%f; %f; %f; %f], 'color', 'k');\n", 01364 vert_p[new_mesh[3*j ]][u], vert_p[new_mesh[3*j+1]][u], 01365 vert_p[new_mesh[3*j+2]][u], vert_p[new_mesh[3*j ]][u], 01366 vert_p[new_mesh[3*j ]][v], vert_p[new_mesh[3*j+1]][v], 01367 vert_p[new_mesh[3*j+2]][v], vert_p[new_mesh[3*j ]][v]); 01368 } 01369 fprintf(f, "xlabel('magenta/blue=old triangle, red/green=new ones');\n"); 01370 fprintf(f, "hold off\n"); 01371 fclose(f); 01372 } 01373 #endif 01374 } 01375 01376 #ifdef DBG 01377 if (iter==0) 01378 if (inner_trimming_curve) 01379 col=vector<char>(mesh_ok.size()/3, 'm'); 01380 else 01381 col=vector<char>(mesh_ok.size()/3, 'c'); 01382 #endif 01383 01384 mesh=mesh_to_reiterate; 01385 iter++; 01386 01387 } 01388 while ( (mesh.size()>0) && (iter<maxiter) ); 01389 01390 mesh=mesh_ok; 01391 #ifdef DBG 01392 while (col.size()<mesh.size()/3) 01393 if (inner_trimming_curve) 01394 col.push_back('y'); 01395 else 01396 col.push_back('b'); 01397 #endif 01398 }
double Go::trinomial | ( | int | n, | |
int | i, | |||
int | j | |||
) | [inline] |
void Go::uniformNoise | ( | double * | res, | |
double | lval, | |||
double | uval, | |||
int | num_samples | |||
) |
Gives a certain number of random samples drawn from the uniform distribution.
res | a pointer to the array where the resulting samples should be written. | |
lval | lower bound of the range from which the samples can take their values. | |
uval | upper bound of the range from which the samples can take their values. | |
num_samples | the desired number of samples (should also be the size of the array pointed to by res. |
Definition at line 47 of file randomnoise.C.
00049 { 00050 if (uval <= lval) { 00051 throw runtime_error("uniformNoise(...) : erroneous range."); 00052 } 00053 double range = uval - lval; 00054 double scale_factor = range / double(RAND_MAX); 00055 for (int i = 0; i < num_samples; ++i) { 00056 res[i] = double(rand()) * scale_factor + lval; 00057 } 00058 }
void Go::unifyCurveSplineSpace | ( | vector< shared_ptr< SplineCurve > > & | curves, | |
double | tol | |||
) |
Definition at line 20 of file unifyCurveSplineSpace.C.
References makeUnionKnots(), and THROW.
00026 { 00027 int ki; 00028 int num_curves = curves.size(); 00029 // Do not allow input curves to have inner knots with pos difference less than tol. 00030 for (ki = 0; ki < num_curves; ++ki) 00031 if (curves[ki].get() != 0) { 00032 vector<double>::iterator iter = curves[ki]->basis().begin(); 00033 vector<double>::iterator next_iter = iter + 1; 00034 while (next_iter != curves[ki]->basis().end()) { 00035 if ((*iter != *next_iter) && (*next_iter - *iter < tol)) 00036 THROW("Inner knot difference too small!"); 00037 iter = next_iter; 00038 next_iter = iter + 1; 00039 } 00040 } 00041 00042 // We allow members of curves to be NULL pointers. 00043 vector<shared_ptr<SplineCurve> > copy_curves; 00044 vector<bool> curve_exists(num_curves); 00045 for (ki = 0; ki < num_curves; ++ki) 00046 if (curves[ki].get() != 0) { 00047 copy_curves.push_back(curves[ki]); 00048 curve_exists[ki] = true; 00049 } else 00050 curve_exists[ki] = false; 00051 00052 if (copy_curves.size() <= 1) 00053 return; // Nothing to do 00054 00055 // Raise the order of each curve to the maximum order 00056 int nmb_crv = copy_curves.size(); 00057 int order_max = copy_curves[0]->order(); 00058 int order; 00059 for (ki=1; ki<nmb_crv; ki++) 00060 { 00061 order = copy_curves[ki]->order(); 00062 order_max = std::max(order_max, order); 00063 } 00064 00065 for (ki=0; ki<nmb_crv; ki++) 00066 { 00067 // Also make sure that the copy_curves have multiple knots in the ends 00068 copy_curves[ki]->makeKnotStartRegular(); 00069 copy_curves[ki]->makeKnotEndRegular(); 00070 order = copy_curves[ki]->order(); 00071 if (order < order_max) 00072 copy_curves[ki]->raiseOrder(order_max - order); 00073 } 00074 00075 // Unify knot vectors 00076 // First find the union of all knot vector 00077 vector<double> union_knots; 00078 vector<BsplineBasis> bbasis(nmb_crv); 00079 for (ki=0; ki<nmb_crv; ++ki) 00080 bbasis[ki] = copy_curves[ki]->basis(); 00081 00082 makeUnionKnots(bbasis, tol, union_knots); 00083 00084 // Insert missing knots into the copy_curves 00085 int num_union = union_knots.size() - order_max; 00086 for (ki=0; ki<nmb_crv; ki++) 00087 { 00088 vector<double> new_knots; 00089 double knot; 00090 int kj, kh; 00091 for (kj=order_max, kh=order_max; 00092 kj<copy_curves[ki]->numCoefs() || kh<num_union;) 00093 { 00094 knot = copy_curves[ki]->basis().begin()[kj]; 00095 if (fabs(knot - union_knots[kh]) < tol) 00096 { 00097 kj++; 00098 kh++; 00099 } 00100 else if (union_knots[kh] < knot) 00101 { 00102 new_knots.push_back(union_knots[kh]); 00103 kh++; 00104 } 00105 else 00106 kj++; 00107 } 00108 00109 // Insert new knots 00110 copy_curves[ki]->insertKnot(new_knots); 00111 // We test whether we must make a new spline curve in order to 00112 // alter tol-equal knots. 00113 vector<double> difference; 00114 std::set_difference(union_knots.begin(), union_knots.end(), 00115 copy_curves[ki]->basis().begin(), 00116 copy_curves[ki]->basis().end(), 00117 std::back_inserter(difference)); 00118 if (difference.size() != 0) 00119 { 00120 SplineCurve tmp(copy_curves[ki]->numCoefs(), 00121 copy_curves[ki]->order(), 00122 union_knots.begin(), 00123 copy_curves[ki]->coefs_begin(), 00124 copy_curves[ki]->dimension()); 00125 copy_curves[ki]->swap(tmp); 00126 } 00127 } 00128 00129 // We make sure the original curve is altered. 00130 int kj = 0; 00131 for (ki = 0; ki < num_curves; ++ki) 00132 if (curve_exists[ki]) { 00133 curves[ki] = copy_curves[kj]; 00134 ++kj; 00135 } 00136 }
void GO_API Go::unifyCurveSplineSpace | ( | std::vector< boost::shared_ptr< SplineCurve > > & | curves, | |
double | tol | |||
) |
Make sure that a set of curves live on the same knot vector tol-equal knots are set equal (i.e.
if they differ within tol).
Referenced by curveSum(), Go::CurveCreators::insertParamDomain(), and unifySurfaceSplineSpaceOneDir().
void Go::unifySurfaceSplineSpace | ( | vector< shared_ptr< SplineSurface > > & | surfaces, | |
double | tol, | |||
int | dir | |||
) |
Definition at line 30 of file unifySurfaceSplineSpace.C.
References MESSAGE.
00032 { 00033 00034 if (surfaces.size() <= 1) 00035 return; 00036 00037 int nmb_srfs = surfaces.size(); 00038 double startparam_u = surfaces[0]->startparam_u(); 00039 double endparam_u = surfaces[0]->endparam_u(); 00040 double startparam_v = surfaces[0]->startparam_v(); 00041 double endparam_v = surfaces[0]->endparam_v(); 00042 int i, j, h, g; 00043 // We first locate a joint parameter domain. 00044 for (i = 1; i < nmb_srfs; ++i) { 00045 startparam_u = std::max(startparam_u, surfaces[i]->startparam_u()); 00046 endparam_u = std::min(endparam_u, surfaces[i]->endparam_u()); 00047 startparam_v = std::max(startparam_v, surfaces[i]->startparam_v()); 00048 endparam_v = std::min(endparam_v, surfaces[i]->endparam_v()); 00049 } 00050 // We make sure the surfaces are k-regular, over tol-equal param domain. 00051 for (i = 0; i < nmb_srfs; ++i) { 00052 if (((dir != 2) && 00053 ((fabs(startparam_u - surfaces[i]->startparam_u()) > tol) || 00054 (fabs(endparam_u - surfaces[i]->endparam_u()) > tol))) || 00055 ((dir != 1) && 00056 ((fabs(startparam_v - surfaces[i]->startparam_v()) > tol) || 00057 (fabs(endparam_v - surfaces[i]->endparam_v()) > tol)))) { 00058 MESSAGE("Surfaces defined over different parameter domains, reparametrizing!"); 00059 double umin = (dir != 2) ? startparam_u : surfaces[i]->startparam_u(); 00060 double umax = (dir != 2) ? endparam_u : surfaces[i]->endparam_u(); 00061 double vmin = (dir != 1) ? startparam_v : surfaces[i]->startparam_v(); 00062 double vmax = (dir != 1) ? endparam_v : surfaces[i]->endparam_v(); 00063 surfaces[i]->setParameterDomain(umin, umax, vmin, vmax); 00064 } 00065 00066 // #ifdef _MSC_VER 00067 // surfaces[i] = shared_ptr<SplineSurface> 00068 // (dynamic_cast<SplineSurface*>(surfaces[i]->subSurface(surfaces[i]->startparam_u(), 00069 // surfaces[i]->startparam_v(), 00070 // surfaces[i]->endparam_u(), 00071 // surfaces[i]->endparam_v()))); 00072 // #else 00073 surfaces[i]->makeSurfaceKRegular(); 00074 // #endif 00075 } 00076 00077 int order_u_max = surfaces[0]->order_u(); 00078 int order_v_max = surfaces[0]->order_v(); 00079 // Raise the order of each surface to the maximum order 00080 for (i = 1; i < nmb_srfs; ++i) { 00081 order_u_max = std::max(order_u_max, surfaces[i]->order_u()); 00082 order_v_max = std::max(order_v_max, surfaces[i]->order_v()); 00083 } 00084 for (i = 0; i < nmb_srfs; ++i) 00085 if ((order_u_max > surfaces[i]->order_u()) || 00086 (order_v_max > surfaces[i]->order_v())) 00087 surfaces[i]->raiseOrder(order_u_max - surfaces[i]->order_u(), 00088 order_v_max - surfaces[i]->order_v()); 00089 00090 // This last section is cut and paste from unifyCurveSplineSpace.C... 00091 // Unify knot vectors 00092 // First find the union of all knot vectors 00093 vector<double> union_knots_u, union_knots_v; 00094 for (g = 0; g < 2; ++g) { 00095 if (((g == 0) && (dir == 2)) || ((g == 1) && (dir == 1))) 00096 continue; // We will not unify in that direction. 00097 00098 vector< std::vector<double>::const_iterator > c_ptr; 00099 vector< std::vector<double>::const_iterator > c_end; 00100 c_ptr.resize(nmb_srfs); 00101 c_end.resize(nmb_srfs); 00102 for (i = 0; i < nmb_srfs; ++i) 00103 { 00104 c_ptr[i] = (g == 0) ? surfaces[i]->basis_u().begin() : 00105 surfaces[i]->basis_v().begin(); 00106 c_end[i] = (g == 0) ? surfaces[i]->basis_u().end() : 00107 surfaces[i]->basis_v().end(); 00108 } 00109 00110 vector<double> union_knots; 00111 double min_knot, knot; 00112 int max_mult, mult; 00113 while (true) 00114 { 00115 // More knots? 00116 for (i = 0; i < nmb_srfs; ++i) 00117 if (c_ptr[i] < c_end[i]) 00118 break; 00119 00120 if (i == nmb_srfs) 00121 break; // All knots collected 00122 00123 min_knot = c_ptr[0][0]; 00124 for (i = 1; i < nmb_srfs; ++i) 00125 { 00126 knot = c_ptr[i][0]; 00127 min_knot = std::min(min_knot, knot); 00128 } 00129 00130 mult = 1; 00131 max_mult = 1; 00132 for (i = 0; i < nmb_srfs; ++i) 00133 { 00134 knot = c_ptr[i][0]; 00135 if (knot < min_knot + tol) 00136 for (mult=0; c_ptr[i]<c_end[i] && c_ptr[i][0]==knot; 00137 mult++, c_ptr[i]++); 00138 max_mult = std::max(max_mult, mult); 00139 } 00140 00141 for (i = 0; i < max_mult; ++i) 00142 union_knots.push_back(min_knot); 00143 } 00144 00145 // Extract the new knot vectors. 00146 if (g == 0) 00147 union_knots_u = union_knots; 00148 else union_knots_v = union_knots; 00149 } 00150 00151 // Insert missing knots into the surfaces 00152 for (i = 0; i < nmb_srfs; ++i) { 00153 for (g = 0; g < 2; ++g) { 00154 if (((g == 0) && (dir == 2)) || ((g == 1) && (dir == 1))) 00155 continue; // We will not unify in that direction. 00156 00157 vector<double> union_knots = (g == 0) ? union_knots_u : union_knots_v; 00158 double knot; 00159 int order_max = (g == 0) ? order_u_max : order_v_max; 00160 int num_union = union_knots.size() - order_max; 00161 int num_coefs = (g == 0) ? surfaces[i]->numCoefs_u() : 00162 surfaces[i]->numCoefs_v(); 00163 vector<double> new_knots; 00164 for (j = order_max, h = order_max; 00165 j < num_coefs || h < num_union;) 00166 { 00167 knot = (g == 0) ? surfaces[i]->basis_u().begin()[j] : 00168 surfaces[i]->basis_v().begin()[j]; 00169 if (fabs(knot - union_knots[h]) < tol) 00170 { 00171 ++j; 00172 ++h; 00173 } 00174 else if (union_knots[h] < knot) 00175 { 00176 new_knots.push_back(union_knots[h]); 00177 ++h; 00178 } 00179 else 00180 ++j; 00181 } 00182 00183 if (g == 0) 00184 surfaces[i]->insertKnot_u(new_knots); 00185 else surfaces[i]->insertKnot_v(new_knots); 00186 } 00187 00188 // We test whether we must make a new spline surface in order to 00189 // alter tol-equal knots. 00190 vector<double> difference_u, difference_v; 00191 if (dir == 1) 00192 union_knots_v.assign(surfaces[i]->basis_v().begin(), surfaces[i]->basis_v().end()); 00193 else if (dir == 2) 00194 union_knots_u.assign(surfaces[i]->basis_u().begin(), surfaces[i]->basis_u().end()); 00195 std::set_difference(union_knots_u.begin(), union_knots_u.end(), 00196 surfaces[i]->basis_u().begin(), 00197 surfaces[i]->basis_u().end(), 00198 std::back_inserter(difference_u)); 00199 std::set_difference(union_knots_v.begin(), union_knots_v.end(), 00200 surfaces[i]->basis_v().begin(), 00201 surfaces[i]->basis_v().end(), 00202 std::back_inserter(difference_v)); 00203 if ((difference_u.size() != 0) || (difference_v.size() != 0)) 00204 { 00205 SplineSurface tmp(surfaces[i]->numCoefs_u(), 00206 surfaces[i]->numCoefs_v(), 00207 surfaces[i]->order_u(), 00208 surfaces[i]->order_v(), 00209 union_knots_u.begin(), 00210 union_knots_v.begin(), 00211 surfaces[i]->coefs_begin(), 00212 surfaces[i]->dimension()); 00213 surfaces[i]->swap(tmp); 00214 } 00215 } 00216 }
void GO_API Go::unifySurfaceSplineSpace | ( | std::vector< boost::shared_ptr< SplineSurface > > & | surfaces, | |
double | tol, | |||
int | dir = 0 | |||
) |
Make sure that a set of surfaces live on the same knot vectors tol-equal knots are set equal (i.e.
if they differ within tol). dir 0 means both, 1 is u, 2 is v
Referenced by averageBoundaryCoefs(), Go::SurfaceCreators::mergeRationalParts(), and surfaceSum().
void Go::unifySurfaceSplineSpaceOneDir | ( | vector< shared_ptr< SplineSurface > > & | surfaces, | |
double | tol, | |||
bool | unify_u_dir | |||
) |
Definition at line 219 of file unifySurfaceSplineSpace.C.
References representCurveAsSurface(), representSurfaceAsCurve(), and unifyCurveSplineSpace().
00221 { 00222 int cv_dir = unify_u_dir ? 1 : 2; 00223 int nmb_sfs = surfaces.size(); 00224 00225 vector<shared_ptr<SplineCurve> > curves; 00226 for (int i = 0; i < nmb_sfs; ++i) 00227 { 00228 SplineSurface* sf = surfaces[i].get(); 00229 curves.push_back(representSurfaceAsCurve(*sf, cv_dir)); 00230 } 00231 unifyCurveSplineSpace(curves, tol); 00232 00233 if (unify_u_dir) 00234 for (int i = 0; i < nmb_sfs; ++i) 00235 { 00236 SplineCurve* cv = curves[i].get(); 00237 surfaces[i] = representCurveAsSurface(*cv, cv_dir, surfaces[i]->basis_v(), surfaces[i]->rational()); 00238 } 00239 else 00240 for (int i = 0; i < nmb_sfs; ++i) 00241 { 00242 SplineCurve* cv = curves[i].get(); 00243 surfaces[i] = representCurveAsSurface(*cv, cv_dir, surfaces[i]->basis_u(), surfaces[i]->rational()); 00244 } 00245 }
void GO_API Go::unifySurfaceSplineSpaceOneDir | ( | std::vector< boost::shared_ptr< SplineSurface > > & | surfaces, | |
double | tol, | |||
bool | unify_u_dir | |||
) |
Make sure that a set of surfaces live on the same knot vectors in one parameter direction.
tol-equal knots are set equal (i.e. if they differ within tol). Nothing is changed in the other parameter direction (as opposed to unifySurfaceSplineSpace() where orders are raised to same value for all surfaces in both directions) Warning! Objects being pointed to may be recreated inside function. Remember to update other shared pointers if needed.
surfaces | Surfaces to end up with common knot vectors | |
tol | tolerance for identifying equal knot values | |
unify_u_dir | if 'true', unify bases in first parameter direction if 'false', unify bases in second parameter direction |
T Go::volume | ( | const Array< T, 3 > * | c | ) | [inline] |
Computes the volume of a 3D simplex (embedded i 3D space).
Definition at line 85 of file Volumes.h.
References simplex_volume().
00086 { return simplex_volume(c); }
void Go::writeSISLFormat | ( | const SplineCurve & | spline_cv, | |
std::ostream & | os | |||
) |
Write a SplineCurve to a stream using the SISL file format (not the Go format).
spline_cv | the curve to write to a stream | |
os | the stream to which the curve will be written (in SISL format)x |
Definition at line 116 of file SplineDebugUtils.C.
References Go::SplineCurve::basis(), Go::BsplineBasis::begin(), Go::SplineCurve::coefs_begin(), Go::SplineCurve::dimension(), Go::SplineCurve::numCoefs(), Go::SplineCurve::order(), Go::SplineCurve::rational(), and Go::SplineCurve::rcoefs_begin().
00118 { 00119 int i,j; 00120 int linenum; 00121 00122 int dim = spline_cv.dimension(); 00123 int num_coefs = spline_cv.numCoefs(); 00124 int order = spline_cv.order(); 00125 00126 os << setprecision(15); 00127 00128 os << "$ This is a B-Spline curve" << std::endl; 00129 os << "$ type: 0 is usual, 5 point, 6 analytic\n" << std::endl; 00130 os << "0" << std::endl; 00131 /* order */ 00132 os << "$ order ik" << std::endl; 00133 os << order << std::endl; 00134 00135 /* number of control vertices */ 00136 os << "$ number of control vertices in" << std::endl; 00137 os << num_coefs << std::endl; 00138 00139 /* dimension of geometry space */ 00140 os << "$ dimension" << std::endl; 00141 os << dim << std::endl; 00142 00143 /* curve open/closed */ 00144 os << "$ curve open/closed" << std::endl; 00145 os << 1 << std::endl; 00146 00147 /* nonrational, i.e. polynomial */ 00148 os << "$ rational or not" << std::endl; 00149 os << spline_cv.rational() << std::endl; 00150 00151 /* knot vector */ 00152 linenum = (num_coefs + order)/4; 00153 os << "$ knot vector" << std::endl; 00154 for (j=0; j < linenum; j++){ 00155 for (i=0; i < 4; i++) 00156 os << spline_cv.basis().begin()[j * 4 + i] << " "; 00157 os << ""; 00158 } 00159 for (i = linenum * 4; i < (num_coefs + order); i++) 00160 os << spline_cv.basis().begin()[i] << " "; 00161 os << std::endl; 00162 00163 /* control vertices */ 00164 os << "$ control vertices" << std::endl; 00165 00166 if (!spline_cv.rational()) 00167 { 00168 for ( i = 0; i < num_coefs; i++ ) 00169 { 00170 for ( j = 0; j < dim; j++ ) 00171 os << spline_cv.coefs_begin()[i*dim+j] << " "; 00172 os << 1.0 << std::endl; 00173 } 00174 } 00175 else 00176 { 00177 for ( i = 0; i < num_coefs; i++ ) 00178 { 00179 for ( j = 0; j < dim+1; j++ ) 00180 os << spline_cv.rcoefs_begin()[i*(dim+1)+j] << " "; 00181 os << "" << std::endl; 00182 } 00183 } 00184 00185 /* instance matrix */ 00186 os << "$ instance matrix" << std::endl; 00187 if (dim == 3) 00188 { 00189 os << 1.0 << " " << 0.0 << " " << 0.0 << " " << 0.0 << std::endl; 00190 os << 0.0 << " " << 1.0 << " " << 0.0 << " " << 0.0 << std::endl; 00191 os << 0.0 << " " << 0.0 << " " << 1.0 << " " << 0.0 << std::endl; 00192 os << 0.0 << " " << 0.0 << " " << 0.0 << " " << 1.0 << std::endl; 00193 } 00194 else if (dim == 2) 00195 { 00196 os << 1.0 << " " << 0.0 << " " << 0.0 << " " << std::endl; 00197 os << 0.0 << " " << 1.0 << " " << 0.0 << " " << std::endl; 00198 os << 0.0 << " " << 0.0 << " " << 1.0 << " " << std::endl; 00199 } 00200 else 00201 { 00202 os << 1.0 << " " << 0.0 << std::endl; 00203 os << 0.0 << " " << 1.0 << std::endl; 00204 } 00205 00206 os << "$ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" << std::endl; 00207 00208 return; 00209 }
void Go::writeSpaceParamCurve | ( | const SplineCurve & | pcurve, | |
std::ostream & | os, | |||
double | z = 0.0 | |||
) |
For debugging.
Writes a parameter curve in the xy-plane. Remove when GoViewer handles 2D curves. For debugging. Writes a parameter curve (2D) in the xy-plane, for a given z-value. It will be written (with header) to the specified stream as a 3D curve.
pcurve | the parameter curve we want to write as a 3D curve | |
os | the stream to which we want to write the 3D curve | |
z | the constant z-value for the generated curve |
Definition at line 31 of file SplineDebugUtils.C.
References ALWAYS_ERROR_IF, Go::SplineCurve::basis(), Go::BsplineBasis::begin(), Go::SplineCurve::coefs_begin(), Go::SplineCurve::dimension(), Go::SplineCurve::numCoefs(), Go::SplineCurve::order(), Go::SplineCurve::write(), and Go::GeomObject::writeStandardHeader().
Referenced by Go::BoundedSurface::orderBoundaryLoops(), and writeTrimmedInfo().
00033 { 00034 ALWAYS_ERROR_IF(pcurve.dimension() != 2, 00035 "Expecting input of 2D-curve."); 00036 00037 std::vector<double> space_coefs; 00038 for (int i = 0; i < pcurve.numCoefs(); ++i) { 00039 space_coefs.insert(space_coefs.end(), 00040 pcurve.coefs_begin() + i*2, 00041 pcurve.coefs_begin() + (i + 1)*2); 00042 space_coefs.push_back(z); // Make param_curve live in plane parallell to the xy-plane. 00043 } 00044 00045 SplineCurve space_pcurve = 00046 SplineCurve(pcurve.numCoefs(), pcurve.order(), 00047 pcurve.basis().begin(), space_coefs.begin(), 3); 00048 space_pcurve.writeStandardHeader(os); 00049 space_pcurve.write(os); 00050 }
void Go::writeTrimmedInfo | ( | BoundedSurface & | bd_sf, | |
std::ostream & | os, | |||
double | z = 0.0 | |||
) |
Definition at line 54 of file SplineDebugUtils.C.
References Class_SplineCurve, Go::BoundedSurface::loop(), Go::BoundedSurface::numberOfLoops(), Go::BoundedSurface::underlyingSurface(), and writeSpaceParamCurve().
Referenced by Go::CreatorsUtils::fixTrimCurves().
00057 { 00058 shared_ptr<ParamSurface> under_sf = bd_sf.underlyingSurface(); 00059 under_sf->writeStandardHeader(os); 00060 under_sf->write(os); 00061 int nmb_loops = bd_sf.numberOfLoops(); 00062 for (int kj = 0; kj < nmb_loops; ++kj) { 00063 shared_ptr<CurveLoop> loop = bd_sf.loop(kj); 00064 for (int kk = 0; kk < loop->size(); ++kk) { 00065 shared_ptr<CurveOnSurface> cv_on_sf = 00066 shared_dynamic_cast<CurveOnSurface, ParamCurve> 00067 ((*loop)[kk]); 00068 shared_ptr<ParamCurve> par_cv = 00069 cv_on_sf->parameterCurve(); 00070 if (par_cv.get() != NULL) { 00071 if (par_cv->instanceType() == Class_SplineCurve) { 00072 shared_ptr<SplineCurve> spline_cv = 00073 shared_dynamic_cast<SplineCurve, ParamCurve> 00074 (par_cv); 00075 writeSpaceParamCurve(*spline_cv, 00076 os); 00077 } 00078 } 00079 shared_ptr<ParamCurve> space_cv = 00080 cv_on_sf->spaceCurve(); 00081 if (space_cv.get() != NULL) { 00082 space_cv->writeStandardHeader(os); 00083 space_cv->write(os); 00084 } 00085 } 00086 } 00087 }
double Go::ltol = 1.0e-11 |
Definition at line 25 of file CurvatureUtils.C.
Referenced by curvatureRadius(), getHermiteData(), and stepLenFromRadius().
const int Go::MAJOR_VERSION = 1 |
Definition at line 26 of file GeomObject.h.
Referenced by Go::GeomObject::writeStandardHeader().
const int Go::MINOR_VERSION = 0 |
Definition at line 27 of file GeomObject.h.
Referenced by Go::GeomObject::writeStandardHeader().
vector<vector<shared_ptr<CurveOnSurface> > > Go::new_loops |
Definition at line 937 of file BoundedUtils.C.
const bool Go::s2m_with_boundary = false |
Definition at line 77 of file spline2mesh.C.
Referenced by make_trimmed_mesh().