bool MinimumIsBracketed(avtPoincareIC *poincare_ic) { Vector xzplane(0,1,0); FieldlineLib fieldlib; avtPoincareIC *_a = poincare_ic->a_IC; avtPoincareIC *_b = poincare_ic; avtPoincareIC *_c = poincare_ic->c_IC; std::vector<avtVector> a_puncturePoints; std::vector<avtVector> b_puncturePoints; std::vector<avtVector> c_puncturePoints; fieldlib.getPunctures(_a->points,xzplane,a_puncturePoints); fieldlib.getPunctures(_b->points,xzplane,b_puncturePoints); fieldlib.getPunctures(_c->points,xzplane,c_puncturePoints); // Need to get distances for each a, b & c double a_dist = FindMinimizationDistance(_a); double b_dist = FindMinimizationDistance(_b); double c_dist = FindMinimizationDistance(_c); if (3 <= RATIONAL_DEBUG) std::cerr << "LINE " << __LINE__ << " Checking if min is bracketed:\ta_dist, b_dist, c_dist:\n " << a_dist<<", "<<b_dist<<", "<<c_dist << std::endl; return (b_dist <= a_dist && b_dist <= c_dist); }
double FindMinimizationDistance( avtPoincareIC* ic) { if (4 <= RATIONAL_DEBUG) cerr << "Finding Minimization Distance...\n"; std::vector<avtVector> puncturePoints; FieldlineLib fieldlib; fieldlib.getPunctures(ic->points, avtVector(0, 1, 0), puncturePoints); if (puncturePoints.size() < 2*ic->properties.toroidalWinding) { cerr << "Not enough puncture points to find correct Rational Surface Minimization distance. Failing.\n"; cerr << "need "<<2*ic->properties.toroidalWinding<<" puncture pts at least.\n"; return -1; } int ix = FindMinimizationIndex(ic); avtVector puncture1 = puncturePoints[ix]; avtVector puncture2 = puncturePoints[ix + ic->properties.toroidalWinding]; double dist = (puncture1 - puncture2).length(); return dist; }
bool BracketIsValid(avtPoincareIC *poincare_ic) { Vector xzplane(0,1,0); FieldlineLib fieldlib; avtPoincareIC *_a = poincare_ic->a_IC; avtPoincareIC *_b = poincare_ic; avtPoincareIC *_c = poincare_ic->c_IC; std::vector<avtVector> a_puncturePoints; std::vector<avtVector> b_puncturePoints; std::vector<avtVector> c_puncturePoints; fieldlib.getPunctures(_a->points,xzplane,a_puncturePoints); fieldlib.getPunctures(_b->points,xzplane,b_puncturePoints); fieldlib.getPunctures(_c->points,xzplane,c_puncturePoints); // Need to get distances for each a, b & c int a_i = FindMinimizationIndex(_a); int b_i = FindMinimizationIndex(_b); int c_i = FindMinimizationIndex(_c); if (3 <= RATIONAL_DEBUG) { std::cerr << "LINE " << __LINE__ << " " << "a_i, b_i, c_i: " <<a_i; if (a_i > -1) std::cerr <<"\n"<< VectorToString(a_puncturePoints[a_i])<<",\n"<<b_i; if (b_i > -1) std::cerr << VectorToString(b_puncturePoints[b_i])<<",\n"<<c_i; if (c_i > -1) std::cerr << VectorToString(c_puncturePoints[c_i]); std::cerr << std::endl; } return !(a_i == -1 || b_i == -1 || c_i == -1); }
bool SetupRational(avtPoincareIC *rational) { if (2 <= RATIONAL_DEBUG) { std::vector<avtVector> puncturePoints; FieldlineLib fieldlib; fieldlib.getPunctures(rational->points, avtVector(0, 1, 0), puncturePoints); std::cerr << "LINE " << __LINE__ << " " << "Found an unsearched rational, ID: " << rational->id << ", " << puncturePoints[0] << std::endl; } // Update rational's properties // The analysis method is Rational_Search for most of the process. // The Original_Rational is kept around mainly to help with // organization. rational->properties.analysisMethod = FieldlineProperties::RATIONAL_SEARCH; rational->properties.searchState = FieldlineProperties::ORIGINAL_RATIONAL; // The Original_Rational has a list of each of the // seeds. These get swapped out with better curves over the // course of the minimization and this list is used to draw // the final curves rational->properties.children = new std::vector< avtPoincareIC* >(); return true; }
//******************* // To start the minimization, we need to define three points // If the middle point ('b) is already lower than the // other two we can go straight to // minimization. Otherwise, we have to bracket the // minimum. First things first, setup the two new // points (b & c) and send them off bool PrepareToBracket(avtPoincareIC *seed, avtVector &newA, avtVector &newB, avtVector &newC) { if (5 <= RATIONAL_DEBUG) std::cerr<< "Line: " << __LINE__ <<" Preparing to bracket the minimum"<<std::endl; Vector xzplane(0,1,0); FieldlineLib fieldlib; std::vector<avtVector> seed_puncture_points; fieldlib.getPunctures( seed->points, xzplane, seed_puncture_points); avtVector maxPuncture; avtVector origPt1 = seed->properties.rationalPt1; avtVector origPt2 = seed->properties.rationalPt2; int ix = FindMinimizationIndex(seed); if (1 <= RATIONAL_DEBUG) cerr <<"Line: "<<__LINE__<< " Bracketing inside Original Rational Pts:\n"<<VectorToString(origPt1)<<"\n"<<VectorToString(origPt2)<<std::endl; if (ix < 0) return false; maxPuncture = seed_puncture_points[ix]; avtVector origChord = origPt2 - origPt1; avtVector perpendicular = -origChord.cross(avtVector(0,1,0)); double xa = (origPt1 - maxPuncture).dot(perpendicular); perpendicular.normalize(); double minDist = 2 * MAX_SPACING; if (xa < minDist) xa = minDist; avtVector intersection = maxPuncture + xa * perpendicular; cerr << "Max Puncture: "<<VectorToString(maxPuncture)<<"\nxa: "<<xa<<"\nintersection: "<<VectorToString(intersection)<<"\n"; avtVector newPt1 = intersection; avtVector newPt2 = maxPuncture + GOLD * (newPt1 - maxPuncture); newPt1[1] = Z_OFFSET; newPt2[1] = Z_OFFSET; newA = maxPuncture; newB = newPt1; newC = newPt2; if (1 <= RATIONAL_DEBUG) cerr<<"LINE "<<__LINE__<<"New A,B,C:\n"<< VectorToString(newA) <<"\n"<< VectorToString(newB) <<"\n"<< VectorToString(newC) <<"\n"; seed->properties.analysisMethod = FieldlineProperties::RATIONAL_SEARCH; seed->properties.searchState = FieldlineProperties::MINIMIZING_A; return true; }
bool NeedToMinimize(avtPoincareIC *poincare_ic) { Vector xzplane(0,1,0); FieldlineLib fieldlib; std::vector<avtVector> seed_puncture_points; fieldlib.getPunctures( poincare_ic->points, xzplane, seed_puncture_points); std::vector<avtVector> orig_puncture_points; fieldlib.getPunctures( poincare_ic->src_rational_ic->points, xzplane, orig_puncture_points); // Need to get distances for each a, b & c int _i = FindMinimizationIndex(poincare_ic); // Find distance between puncture points double _dist = PythDist(seed_puncture_points[_i],seed_puncture_points[_i+poincare_ic->properties.toroidalWinding]); return (_dist > MAX_SPACING); }
/** * * Takes in a curve, returns the index of puncture point contained * between pt0 and pt1. * **/ int FindMinimizationIndex( avtPoincareIC *ic ) { if (4 <= RATIONAL_DEBUG) cerr << "Finding Minimization Index...\n"; std::vector<avtVector> puncturePoints; FieldlineLib fieldlib; fieldlib.getPunctures(ic->points, avtVector(0, 1, 0), puncturePoints); if (puncturePoints.size() < 2*ic->properties.toroidalWinding) { cerr << "Not enough puncture points to find correct Rational Surface Minimization index. Failing.\n"; cerr << "need "<<2*ic->properties.toroidalWinding<<" puncture pts at least.\n"; return -1; } avtVector seedPt = ic->properties.srcPt; double min = 99999999; int minix = -1; for (int i =0; i < ic->properties.toroidalWinding && i < puncturePoints.size(); i++) { avtVector puncture = puncturePoints[i]; double dist = (seedPt - puncture).length(); if (min > dist) { min = dist; minix = i; } } if (minix > -1 && 3 <= RATIONAL_DEBUG) cerr <<"LINE: "<<__LINE__<<"found " << minix <<", "<< min <<"\n"; return minix; if (puncturePoints.size() > 0) return 0; else return -1; }
double MinRationalDistance( avtPoincareIC *ic, unsigned int toroidalWinding, unsigned int &index ) { double delta = 9999999999999.0; std::vector<avtVector> puncturePoints; FieldlineLib fieldlib; fieldlib.getPunctures(ic->points, avtVector(0, 1, 0), puncturePoints); for (unsigned int i=0; i+toroidalWinding < puncturePoints.size() && i < toroidalWinding; ++i) { avtVector vec = puncturePoints[i] - puncturePoints[i+toroidalWinding]; if( delta > vec.length() ) { delta = vec.length(); index = i; } } return delta; }
/** * * return a vector of seed points for the given rational * **/ std::vector<avtVector> GetSeeds( avtPoincareIC *poincare_ic, avtVector &point1, avtVector &point2, double maxDistance ) { std::vector<avtVector> puncturePoints; FieldlineLib fieldlib; fieldlib.getPunctures(poincare_ic->points, avtVector(0, 1, 0), puncturePoints); unsigned int toroidalWinding = poincare_ic->properties.toroidalWinding; unsigned int windingGroupOffset = poincare_ic->properties.windingGroupOffset; // Calculate angle size for each puncture point and find the one // that forms the largest angle (i.e. flattest portion of the // surface). int nSeeds = 0; double maxAngle = 0; unsigned int best_index = 0; unsigned int best_one_less; unsigned int best_one_more; bool twoPts = false; for( int i=0; i<toroidalWinding; ++i ) { unsigned int one_less = (i-windingGroupOffset+toroidalWinding) % toroidalWinding; unsigned int one_more = (i+windingGroupOffset+toroidalWinding) % toroidalWinding; if (one_less == one_more) { best_index = i; best_one_more = one_more; twoPts = true; break; } if (3 <= RATIONAL_DEBUG) cerr << "Line: "<<__LINE__<<" wgo: "<<windingGroupOffset<<", ix-1: "<<one_less<<", ix: "<<i<<", ix+1: " <<one_more<<std::endl; avtVector pt0 = puncturePoints[one_less]; avtVector pt1 = puncturePoints[i]; avtVector pt2 = puncturePoints[one_more]; // Save the maximum angle angle and the index of the puncture point. double angle = GetAngle( pt0, pt1, pt2 ); if (maxAngle < angle) { maxAngle = angle; best_index = i; best_one_less = one_less; best_one_more = one_more; } } // Get circle equation avtVector pt0,pt1,pt2; if (twoPts) { pt0 = puncturePoints[best_index]; pt2 = puncturePoints[best_one_more]; if (1 <= RATIONAL_DEBUG) cerr <<"Line: "<<__LINE__<< " 2 Rational Pts:\n" <<VectorToString(pt0)<<"\n" <<VectorToString(pt2)<<"\n"; avtVector midpt = pt0 + 0.5 * (pt2-pt0); avtVector cx = (pt2-pt0).cross(avtVector(0,1,0)); avtVector newpt = midpt + .5*cx; if (1 <= RATIONAL_DEBUG) cerr <<"Line: "<<__LINE__<< " 2 New Pts:\n" <<VectorToString(midpt)<<"\n" <<VectorToString(newpt)<<"\n"; pt1 = newpt; } else { // Find the circle that intersects the three punctures points which // approximates the cross section of the surface. // Get circle equation pt0 = puncturePoints[best_one_less]; pt1 = puncturePoints[best_index]; pt2 = puncturePoints[best_one_more]; if (1 <= RATIONAL_DEBUG) cerr <<"Line: "<<__LINE__<< " Rational Pts:\n" <<VectorToString(pt0)<<"\n" <<VectorToString(pt1)<<"\n" <<VectorToString(pt2)<<"\n"; } point1 = pt1; //for future reference point2 = pt2; if (1 <= RATIONAL_DEBUG) cerr <<"Line: "<<__LINE__<< " New seeds between:\n" <<VectorToString(point1)<<"\n" <<VectorToString(point2)<<"\n"; // Center of the circle /////*********** Find The Circle Using Three Points******************/// double ax,ay,bx,by,cx,cy,x1,y11,dx1,dy1,x2,y2,dx2,dy2,ox,oy,dx,dy,radius; ax = pt0[0]; ay = pt0[2]; bx = pt1[0]; by = pt1[2]; cx = pt2[0]; cy = pt2[2]; x1 = (bx + ax) / 2; y11 = (by + ay) / 2; dy1 = bx - ax; dx1 = -(by - ay); x2 = (cx + bx) / 2; y2 = (cy + by) / 2; dy2 = cx - bx; dx2 = -(cy - by); ox = (y11 * dx1 * dx2 + x2 * dx1 * dy2 - x1 * dy1 * dx2 - y2 * dx1 * dx2)/ (dx1 * dy2 - dy1 * dx2); oy = (ox - x1) * dy1 / dx1 + y11; dx = ox - ax; dy = oy - ay; radius = sqrt(dx * dx + dy * dy); avtVector center(ox,0,oy); // Get the number of points needed to cover the range between the two // the puncture points. double dist = (pt2 - pt1).length(); nSeeds = dist / maxDistance; if( dist > (double) nSeeds * maxDistance ) ++nSeeds; double angle =GetAngle(point1, center, point2); // Add seeds stretching between two of the puncture points. std::vector<avtVector> seedPts; seedPts.resize( nSeeds ); if (1 <= RATIONAL_DEBUG) std::cerr <<"Line: "<<__LINE__ << " \ncenter: " << center << " \nradius: " << radius << " \nnSeeds: " << nSeeds << " \nAngle: " << angle << std::endl; for( double i=0; i<nSeeds; ++i) { double t = i / nSeeds; avtVector X = center + (std::sin((1-t) * angle ) * (point1-center) + std::sin(t * angle) * (point2-center)) / std::sin(angle); X[1] = Z_OFFSET; seedPts[i] = X; if (3 <= RATIONAL_DEBUG) cerr << "New Seed: "<<VectorToString(X) << std::endl; } return seedPts; }
bool PrepareToMinimize(avtPoincareIC *poincare_ic, avtVector &newPt, bool &cbGTba) { // Have bracketed the minimum Vector xzplane(0,1,0); FieldlineLib fieldlib; avtPoincareIC *_a = poincare_ic->a_IC; avtPoincareIC *_b = poincare_ic; avtPoincareIC *_c = poincare_ic->c_IC; std::vector<avtVector> a_puncturePoints; std::vector<avtVector> b_puncturePoints; std::vector<avtVector> c_puncturePoints; fieldlib.getPunctures(_a->points,xzplane,a_puncturePoints); fieldlib.getPunctures(_b->points,xzplane,b_puncturePoints); fieldlib.getPunctures(_c->points,xzplane,c_puncturePoints); // Need to get distances for each a, b & c int a_i = FindMinimizationIndex(_a); int b_i = FindMinimizationIndex(_b); int c_i = FindMinimizationIndex(_c); _a->properties.searchState = FieldlineProperties::MINIMIZING_X0; _c->properties.searchState = FieldlineProperties::MINIMIZING_X3; _a->properties.analysisMethod = FieldlineProperties::RATIONAL_MINIMIZE; _c->properties.analysisMethod = FieldlineProperties::RATIONAL_MINIMIZE; _a->properties.rationalPt1 =_b->properties.rationalPt1; _a->properties.rationalPt2 =_b->properties.rationalPt2; double bx_ax,cx_bx; double a_x,a_z,b_x,b_z,c_x,c_z; a_x = a_puncturePoints[a_i][0]; a_z = a_puncturePoints[a_i][2]; b_x = b_puncturePoints[b_i][0]; b_z = b_puncturePoints[b_i][2]; c_x = c_puncturePoints[c_i][0]; c_z = c_puncturePoints[c_i][2]; bx_ax = PythDist(a_puncturePoints[a_i],b_puncturePoints[b_i]); cx_bx = PythDist(b_puncturePoints[b_i],c_puncturePoints[c_i]); avtVector va = a_puncturePoints[a_i]; avtVector vb = b_puncturePoints[b_i]; avtVector vc = c_puncturePoints[c_i]; if (3 <= RATIONAL_DEBUG) { std::cerr<<"Line: "<<__LINE__<<"Prepare to minimize: "<<"\n\t"<<VectorToString(a_puncturePoints[a_i])<<"\n\t"<<VectorToString(b_puncturePoints[b_i])<<"\n\t"<<VectorToString(c_puncturePoints[c_i])<<"\n"; } double new_x,new_z; if (cx_bx > bx_ax) { cbGTba = true; _b->properties.searchState = FieldlineProperties::MINIMIZING_X1; _b->properties.analysisMethod = FieldlineProperties::RATIONAL_MINIMIZE; newPt = vb + golden_C * (vc-vb); if (2 <= RATIONAL_DEBUG) std::cerr << "LINE " << __LINE__ << " New Minimization pt:\t"<<VectorToString(newPt)<< std::endl; } else { cbGTba = false; _b->properties.searchState = FieldlineProperties::MINIMIZING_X2; _b->properties.analysisMethod = FieldlineProperties::RATIONAL_MINIMIZE; newPt = vb + golden_C * (va-vb); if (2 <= RATIONAL_DEBUG) std::cerr << "LINE " << __LINE__ << " New Minimization pt:\t"<< VectorToString(newPt) << std::endl; } newPt[1] = Z_OFFSET; return true; }
bool UpdateBracket(avtPoincareIC *poincare_ic, bool &swapped, avtVector &C) { if (4 <= RATIONAL_DEBUG) std::cerr << "LINE " << __LINE__ << " " << "Minimum needs to be bracketed" << std::endl; // Have bracketed the minimum Vector xzplane(0,1,0); FieldlineLib fieldlib; avtPoincareIC *_a = poincare_ic->a_IC; avtPoincareIC *_b = poincare_ic; avtPoincareIC *_c = poincare_ic->c_IC; std::vector<avtVector> a_puncturePoints; std::vector<avtVector> b_puncturePoints; std::vector<avtVector> c_puncturePoints; fieldlib.getPunctures(_a->points,xzplane,a_puncturePoints); fieldlib.getPunctures(_b->points,xzplane,b_puncturePoints); fieldlib.getPunctures(_c->points,xzplane,c_puncturePoints); // Need to get distances for each a, b & c double a_dist = FindMinimizationDistance(_a); double b_dist = FindMinimizationDistance(_b); double c_dist = FindMinimizationDistance(_c); // Need to swap so a > b if ( b_dist > a_dist ) { swapped = true; avtPoincareIC *temp = _a; _a = _b; _b = temp; std::vector<avtVector> vtemp = a_puncturePoints; a_puncturePoints = b_puncturePoints; b_puncturePoints = vtemp; int itemp = a_dist; a_dist = b_dist; b_dist = itemp; _a->properties.searchState = FieldlineProperties::MINIMIZING_A; _b->properties.searchState = FieldlineProperties::MINIMIZING_B; _b->a_IC = _a; } if (c_dist >= b_dist) return false; int a_i = FindMinimizationIndex(_a); int b_i = FindMinimizationIndex(_b); int c_i = FindMinimizationIndex(_c); // For Parabolic Bracketing, not actually implemented, too difficult // double rr = PythDist( _a, _b ) * (b_dist - c_dist); // double qq = PythDist( _c, _b ) * (b_dist - a_dist); avtVector va = a_puncturePoints[a_i]; avtVector vb = b_puncturePoints[b_i]; avtVector vc = c_puncturePoints[c_i]; if (swapped == true) { vc = vb + GOLD * (vb - va); } else { vc = vb + GOLD * (vc - vb); } C = vc; C[1] = Z_OFFSET; return true; }