void Path::DoButt(Shape *dest, double width, ButtType butt, Geom::Point pos, Geom::Point dir, int &leftNo, int &rightNo) { Geom::Point nor; nor = dir.ccw(); if (butt == butt_square) { Geom::Point x; x = pos + width * dir + width * nor; int bleftNo = dest->AddPoint (x); x = pos + width * dir - width * nor; int brightNo = dest->AddPoint (x); x = pos + width * nor; leftNo = dest->AddPoint (x); x = pos - width * nor; rightNo = dest->AddPoint (x); dest->AddEdge (rightNo, brightNo); dest->AddEdge (brightNo, bleftNo); dest->AddEdge (bleftNo, leftNo); } else if (butt == butt_pointy) { leftNo = dest->AddPoint (pos + width * nor); rightNo = dest->AddPoint (pos - width * nor); int mid = dest->AddPoint (pos + width * dir); dest->AddEdge (rightNo, mid); dest->AddEdge (mid, leftNo); } else if (butt == butt_round) { const Geom::Point sx = pos + width * nor; const Geom::Point ex = pos - width * nor; leftNo = dest->AddPoint (sx); rightNo = dest->AddPoint (ex); RecRound (dest, rightNo, leftNo, ex, sx, -nor, nor, pos, width); } else { leftNo = dest->AddPoint (pos + width * nor); rightNo = dest->AddPoint (pos - width * nor); dest->AddEdge (rightNo, leftNo); } }
// find the position at which node "newOne" should be inserted in the subtree rooted here // we want to order with respect to the order of intersections with the sweepline, currently // lying at y=px[1]. // px is the upper endpoint of newOne int SweepTree::Find(Geom::Point const &px, SweepTree *newOne, SweepTree *&insertL, SweepTree *&insertR, bool sweepSens) { // get the edge associated with this node: one point+one direction // since we're dealing with line, the direction (bNorm) is taken downwards Geom::Point bOrig, bNorm; bOrig = src->pData[src->getEdge(bord).st].rx; bNorm = src->eData[bord].rdx; if (src->getEdge(bord).st > src->getEdge(bord).en) { bNorm = -bNorm; } // rotate to get the normal to the edge bNorm=bNorm.ccw(); Geom::Point diff; diff = px - bOrig; // compute (px-orig)^dir to know on which side of this edge the point px lies double y = 0; //if ( startPoint == newOne->startPoint ) { // y=0; //} else { y = dot(bNorm, diff); //} //y*=invDirLength; if (fabs(y) < 0.000001) { // that damn point px lies on me, so i need to consider to direction of the edge in // newOne to know if it goes toward my left side or my right side // sweepSens is needed (actually only used by the Scan() functions) because if the sweepline goes upward, // signs change // prendre en compte les directions Geom::Point nNorm; nNorm = newOne->src->eData[newOne->bord].rdx; if (newOne->src->getEdge(newOne->bord).st > newOne->src->getEdge(newOne->bord).en) { nNorm = -nNorm; } nNorm=nNorm.ccw(); if (sweepSens) { y = cross(nNorm, bNorm); } else { y = cross(bNorm, nNorm); } if (y == 0) { y = dot(bNorm, nNorm); if (y == 0) { insertL = this; insertR = static_cast<SweepTree *>(elem[RIGHT]); return found_exact; } } } if (y < 0) { if (son[LEFT]) { return (static_cast<SweepTree *>(son[LEFT]))->Find(px, newOne, insertL, insertR, sweepSens); } else { insertR = this; insertL = static_cast<SweepTree *>(elem[LEFT]); if (insertL) { return found_between; } else { return found_on_left; } } } else { if (son[RIGHT]) { return (static_cast<SweepTree *>(son[RIGHT]))->Find(px, newOne, insertL, insertR, sweepSens); } else { insertL = this; insertR = static_cast<SweepTree *>(elem[RIGHT]); if (insertR) { return found_between; } else { return found_on_right; } } } return not_found; }
void Path::DoRightJoin (Shape * dest, double width, JoinType join, Geom::Point pos, Geom::Point prev, Geom::Point next, double miter, double /*prevL*/, double /*nextL*/, int &rightStNo, int &rightEnNo,int pathID,int pieceID,double tID) { const Geom::Point pnor=prev.ccw(); const Geom::Point nnor=next.ccw(); double angSi = cross (next,prev); if (angSi > -0.0001 && angSi < 0.0001) { double angCo = dot (prev, next); if (angCo > 0.9999) { // tout droit rightEnNo = rightStNo = dest->AddPoint (pos - width*pnor); } else { // demi-tour rightEnNo = dest->AddPoint (pos + width*pnor); rightStNo = dest->AddPoint (pos - width*pnor); int nEdge=dest->AddEdge (rightStNo, rightEnNo); if ( dest->hasBackData() ) { dest->ebData[nEdge].pathID=pathID; dest->ebData[nEdge].pieceID=pieceID; dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID; } } return; } if (angSi < 0) { if (join == join_pointy) { rightStNo = dest->AddPoint (pos - width*pnor); rightEnNo = dest->AddPoint (pos - width*nnor); const Geom::Point biss = StrokeNormalize (pnor + nnor); double c2 = dot (biss, nnor); double l = width / c2; double emiter = width * c2; if (emiter < miter) emiter = miter; if (l <= emiter) { int nrightStNo = dest->AddPoint (pos - l * biss); int nEdge=dest->AddEdge (rightStNo, nrightStNo); if ( dest->hasBackData() ) { dest->ebData[nEdge].pathID=pathID; dest->ebData[nEdge].pieceID=pieceID; dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID; } nEdge=dest->AddEdge (nrightStNo, rightEnNo); if ( dest->hasBackData() ) { dest->ebData[nEdge].pathID=pathID; dest->ebData[nEdge].pieceID=pieceID; dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID; } } else { double s2 = cross (biss, nnor); double dec = (l - emiter) * c2 / s2; const Geom::Point tbiss=biss.ccw(); int nrightStNo = dest->AddPoint (pos - emiter*biss - dec*tbiss); int nrightEnNo = dest->AddPoint (pos - emiter*biss + dec*tbiss); int nEdge=dest->AddEdge (rightStNo, nrightStNo); if ( dest->hasBackData() ) { dest->ebData[nEdge].pathID=pathID; dest->ebData[nEdge].pieceID=pieceID; dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID; } nEdge=dest->AddEdge (nrightStNo, nrightEnNo); if ( dest->hasBackData() ) { dest->ebData[nEdge].pathID=pathID; dest->ebData[nEdge].pieceID=pieceID; dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID; } nEdge=dest->AddEdge (nrightEnNo, rightEnNo); if ( dest->hasBackData() ) { dest->ebData[nEdge].pathID=pathID; dest->ebData[nEdge].pieceID=pieceID; dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID; } } } else if (join == join_round) { const Geom::Point sx = pos - width * pnor; rightStNo = dest->AddPoint (sx); const Geom::Point ex = pos - width * nnor; rightEnNo = dest->AddPoint (ex); RecRound(dest, rightStNo, rightEnNo, sx, ex, -pnor, -nnor ,pos, width); } else { rightStNo = dest->AddPoint (pos - width * pnor); rightEnNo = dest->AddPoint (pos - width * nnor); int nEdge=dest->AddEdge (rightStNo, rightEnNo); if ( dest->hasBackData() ) { dest->ebData[nEdge].pathID=pathID; dest->ebData[nEdge].pieceID=pieceID; dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID; } } } else { /* Geom::Point biss; biss=next.x-prev.x; biss.y=next.y-prev.y; double c2=cross(next,biss); double l=width/c2; double projn=l*(dot(biss,next)); double projp=-l*(dot(biss,prev)); if ( projp <= 0.5*prevL && projn <= 0.5*nextL ) { double x,y; x=pos.x+l*biss.x; y=pos.y+l*biss.y; rightEnNo=rightStNo=dest->AddPoint(x,y); } else {*/ rightStNo = dest->AddPoint (pos - width*pnor); rightEnNo = dest->AddPoint (pos - width*nnor); int midNo = dest->AddPoint (pos); int nEdge=dest->AddEdge (rightStNo, midNo); if ( dest->hasBackData() ) { dest->ebData[nEdge].pathID=pathID; dest->ebData[nEdge].pieceID=pieceID; dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID; } nEdge=dest->AddEdge (midNo, rightEnNo); if ( dest->hasBackData() ) { dest->ebData[nEdge].pathID=pathID; dest->ebData[nEdge].pieceID=pieceID; dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID; } // } } }
void Path::DoJoin (Shape *dest, double width, JoinType join, Geom::Point pos, Geom::Point prev, Geom::Point next, double miter, double /*prevL*/, double /*nextL*/, int *stNo, int *enNo) { Geom::Point pnor = prev.ccw(); Geom::Point nnor = next.ccw(); double angSi = cross(next, prev); /* FIXED: this special case caused bug 1028953 */ if (angSi > -0.0001 && angSi < 0.0001) { double angCo = dot (prev, next); if (angCo > 0.9999) { // tout droit stNo[LEFT] = enNo[LEFT] = dest->AddPoint(pos + width * pnor); stNo[RIGHT] = enNo[RIGHT] = dest->AddPoint(pos - width * pnor); } else { // demi-tour const Geom::Point sx = pos + width * pnor; const Geom::Point ex = pos - width * pnor; stNo[LEFT] = enNo[RIGHT] = dest->AddPoint (sx); stNo[RIGHT] = enNo[LEFT] = dest->AddPoint (ex); if (join == join_round) { RecRound (dest, enNo[LEFT], stNo[LEFT], ex, sx, -pnor, pnor, pos, width); dest->AddEdge(stNo[RIGHT], enNo[RIGHT]); } else { dest->AddEdge(enNo[LEFT], stNo[LEFT]); dest->AddEdge(stNo[RIGHT], enNo[RIGHT]); // two times because both are crossing each other } } return; } if (angSi < 0) { int midNo = dest->AddPoint(pos); stNo[LEFT] = dest->AddPoint(pos + width * pnor); enNo[LEFT] = dest->AddPoint(pos + width * nnor); dest->AddEdge(enNo[LEFT], midNo); dest->AddEdge(midNo, stNo[LEFT]); if (join == join_pointy) { stNo[RIGHT] = dest->AddPoint(pos - width * pnor); enNo[RIGHT] = dest->AddPoint(pos - width * nnor); const Geom::Point biss = StrokeNormalize(prev - next); double c2 = dot(biss, nnor); double l = width / c2; double emiter = width * c2; if (emiter < miter) { emiter = miter; } if (fabs(l) < miter) { int const n = dest->AddPoint(pos - l * biss); dest->AddEdge(stNo[RIGHT], n); dest->AddEdge(n, enNo[RIGHT]); } else { dest->AddEdge(stNo[RIGHT], enNo[RIGHT]); } } else if (join == join_round) { Geom::Point sx = pos - width * pnor; stNo[RIGHT] = dest->AddPoint(sx); Geom::Point ex = pos - width * nnor; enNo[RIGHT] = dest->AddPoint(ex); RecRound(dest, stNo[RIGHT], enNo[RIGHT], sx, ex, -pnor, -nnor, pos, width); } else { stNo[RIGHT] = dest->AddPoint(pos - width * pnor); enNo[RIGHT] = dest->AddPoint(pos - width * nnor); dest->AddEdge(stNo[RIGHT], enNo[RIGHT]); } } else { int midNo = dest->AddPoint(pos); stNo[RIGHT] = dest->AddPoint(pos - width * pnor); enNo[RIGHT] = dest->AddPoint(pos - width * nnor); dest->AddEdge(stNo[RIGHT], midNo); dest->AddEdge(midNo, enNo[RIGHT]); if (join == join_pointy) { stNo[LEFT] = dest->AddPoint(pos + width * pnor); enNo[LEFT] = dest->AddPoint(pos + width * nnor); const Geom::Point biss = StrokeNormalize(next - prev); double c2 = dot(biss, nnor); double l = width / c2; double emiter = width * c2; if (emiter < miter) { emiter = miter; } if ( fabs(l) < miter) { int const n = dest->AddPoint (pos + l * biss); dest->AddEdge (enNo[LEFT], n); dest->AddEdge (n, stNo[LEFT]); } else { dest->AddEdge (enNo[LEFT], stNo[LEFT]); } } else if (join == join_round) { Geom::Point sx = pos + width * pnor; stNo[LEFT] = dest->AddPoint(sx); Geom::Point ex = pos + width * nnor; enNo[LEFT] = dest->AddPoint(ex); RecRound(dest, enNo[LEFT], stNo[LEFT], ex, sx, nnor, pnor, pos, width); } else { stNo[LEFT] = dest->AddPoint(pos + width * pnor); enNo[LEFT] = dest->AddPoint(pos + width * nnor); dest->AddEdge(enNo[LEFT], stNo[LEFT]); } } }