/** * Takes two paths and time ranges on them, with the invariant that the * paths are monotonic on the range. Splits A when the linear intersection * doesn't exist or is inaccurate. Uses the fact that it is monotonic to * do very fast local bounds. */ void mono_pair(Path const &A, double Al, double Ah, Path const &B, double Bl, double Bh, Crossings &ret, double /*tol*/, unsigned depth = 0) { if( Al >= Ah || Bl >= Bh) return; std::cout << " " << depth << "[" << Al << ", " << Ah << "]" << "[" << Bl << ", " << Bh << "]"; Point A0 = A.pointAt(Al), A1 = A.pointAt(Ah), B0 = B.pointAt(Bl), B1 = B.pointAt(Bh); //inline code that this implies? (without rect/interval construction) if(!Rect(A0, A1).intersects(Rect(B0, B1)) || A0 == A1 || B0 == B1) return; //Checks the general linearity of the function //if((depth > 12) || (A.boundsLocal(Interval(Al, Ah), 1).maxExtent() < 0.1 // && B.boundsLocal(Interval(Bl, Bh), 1).maxExtent() < 0.1)) { double tA, tB, c; if(linear_intersect(A0, A1, B0, B1, tA, tB, c)) { tA = tA * (Ah - Al) + Al; tB = tB * (Bh - Bl) + Bl; if(depth % 2) ret.push_back(Crossing(tB, tA, c < 0)); else ret.push_back(Crossing(tA, tB, c > 0)); return; } //} if(depth > 12) return; double mid = (Bl + Bh)/2; mono_pair(B, Bl, mid, A, Al, Ah, ret, depth+1); mono_pair(B, mid, Bh, A, Al, Ah, ret, depth+1); }
Crossings reverse_ta(Crossings const &cr, std::vector<double> max) { Crossings ret; for(Crossings::const_iterator i = cr.begin(); i != cr.end(); ++i) { double mx = max[i->a]; ret.push_back(Crossing(i->ta > mx+0.01 ? (1 - (i->ta - mx) + mx) : mx - i->ta, i->tb, !i->dir)); } return ret; }
Crossings reverse_tb(Crossings const &cr, unsigned split, std::vector<double> max) { Crossings ret; for(Crossings::const_iterator i = cr.begin(); i != cr.end(); ++i) { double mx = max[i->b - split]; std::cout << i->b << "\n"; ret.push_back(Crossing(i->ta, i->tb > mx+0.01 ? (1 - (i->tb - mx) + mx) : mx - i->tb, !i->dir)); } return ret; }
void CLineCrossings::RemoveAll(void) { int nCrossings = Crossings(); for (int nCrossing = 0; nCrossing < nCrossings; nCrossing++) { delete Crossing(nCrossing); } CPtrArray::RemoveAll(); }
/** * This uses the local bounds functions of curves to generically intersect two. * It passes in the curves, time intervals, and keeps track of depth, while * returning the results through the Crossings parameter. */ void pair_intersect(Curve const & A, double Al, double Ah, Curve const & B, double Bl, double Bh, Crossings &ret, unsigned depth=0) { // std::cout << depth << "(" << Al << ", " << Ah << ")\n"; OptRect Ar = A.boundsLocal(Interval(Al, Ah)); if (!Ar) return; OptRect Br = B.boundsLocal(Interval(Bl, Bh)); if (!Br) return; if(! Ar->intersects(*Br)) return; //Checks the general linearity of the function if((depth > 12)) { // || (A.boundsLocal(Interval(Al, Ah), 1).maxExtent() < 0.1 //&& B.boundsLocal(Interval(Bl, Bh), 1).maxExtent() < 0.1)) { double tA, tB, c; if(linear_intersect(A.pointAt(Al), A.pointAt(Ah), B.pointAt(Bl), B.pointAt(Bh), tA, tB, c)) { tA = tA * (Ah - Al) + Al; tB = tB * (Bh - Bl) + Bl; intersect_polish_root(A, tA, B, tB); if(depth % 2) ret.push_back(Crossing(tB, tA, c < 0)); else ret.push_back(Crossing(tA, tB, c > 0)); return; } } if(depth > 12) return; double mid = (Bl + Bh)/2; pair_intersect(B, Bl, mid, A, Al, Ah, ret, depth+1); pair_intersect(B, mid, Bh, A, Al, Ah, ret, depth+1); }
//same as below but curves not paths void mono_intersect(Curve const &A, double Al, double Ah, Curve const &B, double Bl, double Bh, Crossings &ret, double tol = 0.1, unsigned depth = 0) { if( Al >= Ah || Bl >= Bh) return; //std::cout << " " << depth << "[" << Al << ", " << Ah << "]" << "[" << Bl << ", " << Bh << "]"; Point A0 = A.pointAt(Al), A1 = A.pointAt(Ah), B0 = B.pointAt(Bl), B1 = B.pointAt(Bh); //inline code that this implies? (without rect/interval construction) Rect Ar = Rect(A0, A1), Br = Rect(B0, B1); if(!Ar.intersects(Br) || A0 == A1 || B0 == B1) return; if(depth > 12 || (Ar.maxExtent() < tol && Ar.maxExtent() < tol)) { double tA, tB, c; if(linear_intersect(A.pointAt(Al), A.pointAt(Ah), B.pointAt(Bl), B.pointAt(Bh), tA, tB, c)) { tA = tA * (Ah - Al) + Al; tB = tB * (Bh - Bl) + Bl; intersect_polish_root(A, tA, B, tB); if(depth % 2) ret.push_back(Crossing(tB, tA, c < 0)); else ret.push_back(Crossing(tA, tB, c > 0)); return; } } if(depth > 12) return; double mid = (Bl + Bh)/2; mono_intersect(B, Bl, mid, A, Al, Ah, ret, tol, depth+1); mono_intersect(B, mid, Bh, A, Al, Ah, ret, tol, depth+1); }
void CLineCrossings::AddCrossing(CFixed lPosition, int nCount) { int nCrossings = Crossings(); int nCrossing; // Look for the crossing in the array. // This will also determine the place to insert if it is not found. for (nCrossing = 0; nCrossing < nCrossings; nCrossing++) { // Get the crossing to check where we are. CLineCrossing* pCrossing = Crossing(nCrossing); // If this crossing is at our position, merge the counts. if (pCrossing->m_lPosition == lPosition) { // Update the existing one. if ((pCrossing->m_nCount += nCount) == 0) { // The crossing went away! Get rid of it. delete pCrossing; RemoveAt(nCrossing); } return; } if (pCrossing->m_lPosition > lPosition) { // Insert here. break; } } // The crossing was not found. Create a new one. CLineCrossing* pCrossing = new CLineCrossing; // Fill in the values. pCrossing->m_lPosition = lPosition; pCrossing->m_nCount = nCount; // Insert it where we stopped searching. InsertAt(nCrossing, pCrossing); }
void flip_crossings(Crossings &crs) { for(unsigned i = 0; i < crs.size(); i++) crs[i] = Crossing(crs[i].tb, crs[i].ta, crs[i].b, crs[i].a, !crs[i].dir); }