Advertisement
Guest User

BSpline LPE Inkscape

a guest
Feb 25th, 2013
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.10 KB | None | 0 0
  1. static void bspline_doEffect(SPCurve * curve)
  2. {
  3.     if(curve->get_segment_count() < 2)
  4.     return;
  5.     // Make copy of old path as it is changed during processing
  6.     Geom::PathVector const original_pathv = curve->get_pathvector();
  7.     curve->reset();
  8.     //Sbasis
  9.     Geom::D2< Geom::SBasis > SBasisIn;
  10.     Geom::D2< Geom::SBasis > SBasisOut;
  11.     Geom::D2< Geom::SBasis > SBasisEnd;
  12.     Geom::D2< Geom::SBasis > SBasisHelper;
  13.     //curves
  14.     SPCurve * in = new SPCurve();
  15.     SPCurve * out = new SPCurve();
  16.     SPCurve * end = new SPCurve();
  17.     //Curvas temporales
  18.     SPCurve *lineHelper = new SPCurve();
  19.     SPCurve *curveHelper = new SPCurve();
  20.     SPCurve *nCurve = new SPCurve();
  21.     //Puntos a usar. Ponemos todos los posibles para hacer más inteligible el código
  22.     Geom::Point startNode(0,0);
  23.     Geom::Point previousNode(0,0);
  24.     Geom::Point node(0,0);
  25.     //Geom::Point previousPointAt3(0,0);
  26.     Geom::Point pointAt0(0,0);
  27.     Geom::Point pointAt1(0,0);
  28.     Geom::Point pointAt2(0,0);
  29.     Geom::Point pointAt3(0,0);
  30.     //Geom::Point nextPointAt0(0,0);
  31.     Geom::Point nextPointAt1(0,0);
  32.     Geom::Point nextPointAt2(0,0);
  33.     Geom::Point nextPointAt3(0,0);
  34.    
  35.     Geom::Point endPointAt2(0,0);
  36.     Geom::CubicBezier const *cubic;
  37.     //Recorremos todos los paths a los que queremos aplicar el efecto, hasta el penúltimo
  38.     for(Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
  39.         //Si está vacío...
  40.         if (path_it->empty())
  41.             continue;
  42.         //Itreadores
  43.        
  44.         Geom::Path::const_iterator curve_it1 = path_it->begin();      // incoming curve
  45.         Geom::Path::const_iterator curve_it2 = ++(path_it->begin());         // outgoing curve
  46.         Geom::Path::const_iterator curve_end = path_it->end_open(); // end curve
  47.         Geom::Path::const_iterator curve_endit = path_it->end_default(); // this determines when the loop has to stop
  48.  
  49.         //Creamos las lineas rectas que unen todos los puntos del trazado y donde se calcularán
  50.         //los puntos clave para los manejadores.
  51.         //Esto hace que la curva BSpline no pierda su condición aunque se trasladen
  52.         //dichos manejadores
  53.         in->moveto(curve_it1->initialPoint());
  54.         in->lineto(curve_it1->finalPoint());
  55.         out->moveto(curve_it2->initialPoint());
  56.         out->lineto(curve_it2->finalPoint());
  57.         //este no cambia.
  58.         end->moveto(curve_end->initialPoint());
  59.         end->lineto(curve_end->finalPoint());
  60.         //Si la curva está cerrada calculamos el punto donde
  61.         //deveria estar el nodo BSpline de cierre/inicio de la curva
  62.         //en posible caso de que se cierre con una linea recta creando un nodo BSPline
  63.  
  64.         if (path_it->closed()) {
  65.             // if the path is closed, maybe we have to stop a bit earlier because the closing line segment has zerolength.
  66.             const Geom::Curve &closingline = path_it->back_closed(); // the closing line segment is always of type Geom::LineSegment.
  67.             if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
  68.                 // closingline.isDegenerate() did not work, because it only checks for *exact* zero length, which goes wrong for relative coordinates and rounding errors...
  69.                 // the closing line segment has zero-length. So stop before that one!
  70.                 curve_endit = path_it->end_open();
  71.             }
  72.             SBasisIn = in->first_segment()->toSBasis();
  73.             SBasisEnd = end->first_segment()->toSBasis();
  74.             cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1);
  75.             if(cubic){
  76.                 pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1],*in->first_segment()));
  77.             }else{
  78.                 pointAt1 = in->first_segment()->initialPoint();
  79.             }
  80.             cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_end);
  81.             if(cubic){
  82.                 endPointAt2 = SBasisEnd.valueAt(Geom::nearest_point((*cubic)[2],*end->first_segment()));
  83.             }else{
  84.                 endPointAt2 = end->first_segment()->finalPoint();
  85.             }
  86.             lineHelper->moveto(pointAt1);
  87.             lineHelper->lineto(endPointAt2);
  88.             SBasisHelper = lineHelper->first_segment()->toSBasis();
  89.             lineHelper->reset();
  90.             //Guardamos el principio de la curva
  91.             startNode = SBasisHelper.valueAt(0.5);
  92.             //Definimos el punto de inicio original de la curva resultante
  93.             node = startNode;
  94.         }else{
  95.             //Guardamos el principio de la curva
  96.             startNode = in->first_segment()->initialPoint();
  97.             //Definimos el punto de inicio original de la curva resultante
  98.             node = startNode;
  99.         }
  100.         //Recorremos todos los segmentos menos el último
  101.         while ( curve_it2 != curve_endit )
  102.         {
  103.             //previousPointAt3 = pointAt3;
  104.             //Calculamos los puntos que dividirían en tres segmentos iguales el path recto de entrada y de salida
  105.             cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1);
  106.             if(cubic){
  107.                 SBasisIn = in->first_segment()->toSBasis();
  108.                 pointAt0 = (*cubic)[0];
  109.                 pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1],*in->first_segment()));
  110.                 pointAt2 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[2],*in->first_segment()));
  111.                 pointAt3 = (*cubic)[3];
  112.             }else{
  113.                 pointAt0 = in->first_segment()->initialPoint();
  114.                 pointAt1 = in->first_segment()->initialPoint();
  115.                 pointAt2 = in->first_segment()->finalPoint();
  116.                 pointAt3 = in->first_segment()->finalPoint();
  117.             }
  118.             //Y hacemos lo propio con el path de salida
  119.             //nextPointAt0 = curveOut.valueAt(0);
  120.             cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it2);
  121.             if(cubic){
  122.                 SBasisOut = out->first_segment()->toSBasis();
  123.                 nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1],*out->first_segment()));
  124.                 nextPointAt2 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[2],*out->first_segment()));;
  125.                 nextPointAt3 = (*cubic)[3];
  126.             }else{
  127.                 nextPointAt1 = out->first_segment()->initialPoint();
  128.                 nextPointAt2 = out->first_segment()->finalPoint();
  129.                 nextPointAt3 = out->first_segment()->finalPoint();
  130.             }
  131.             //La curva BSpline se forma calculando el centro del segmanto de unión
  132.             //de el punto situado en las 2/3 partes de el segmento de entrada
  133.             //con el punto situado en la posición 1/3 del segmento de salida
  134.             //Estos dos puntos ademas estan posicionados en el lugas correspondiente de
  135.             //los manejadores de la curva
  136.             lineHelper->moveto(pointAt2);
  137.             lineHelper->lineto(nextPointAt1);
  138.             SBasisHelper = lineHelper->first_segment()->toSBasis();
  139.             lineHelper->reset();
  140.             //almacenamos el punto del anterior bucle -o el de cierre- que nos hara de principio de curva
  141.             previousNode = node;
  142.             //Y este hará de final de curva
  143.             node = SBasisHelper.valueAt(0.5);
  144.             curveHelper->moveto(previousNode);
  145.             curveHelper->curveto(pointAt1, pointAt2, node);
  146.             //añadimos la curva generada a la curva pricipal
  147.             nCurve->append_continuous(curveHelper, 0.0625);
  148.             curveHelper->reset();
  149.             //aumentamos los valores para el siguiente paso en el bucle
  150.             ++curve_it1;
  151.             ++curve_it2;
  152.             //Damos valor a el objeto para el path de entrada y el de salida
  153.             in->reset();
  154.             in->moveto(curve_it1->initialPoint());
  155.             in->lineto(curve_it1->finalPoint());
  156.             out->reset();
  157.             if(curve_it1 != curve_end){
  158.                 out->moveto(curve_it2->initialPoint());
  159.                 out->lineto(curve_it2->finalPoint());
  160.             }
  161.         }
  162.         //Aberiguamos la ultima parte de la curva correspondiente al último segmento
  163.         curveHelper->moveto(node);
  164.         //Si está cerrada la curva, la cerramos sobre  el valor guardado previamente
  165.         //Si no finalizamos en el punto final
  166.         if (path_it->closed()) {
  167.             curveHelper->curveto(nextPointAt1, nextPointAt2, startNode);
  168.         }else{
  169.             curveHelper->curveto(nextPointAt1, nextPointAt2, nextPointAt3);
  170.         }
  171.         //añadimos este último segmento
  172.         nCurve->append_continuous(curveHelper, 0.0625);
  173.         //y cerramos la curva
  174.         if (path_it->closed()) {
  175.             nCurve->closepath_current();
  176.         }
  177.         curve->append(nCurve,false);
  178.         nCurve->reset();
  179.         //Limpiamos
  180.         in->reset();
  181.         out->reset();
  182.         end->reset();
  183.         lineHelper->reset();
  184.         curveHelper->reset();
  185.     }
  186.     delete in;
  187.     delete out;
  188.     delete end;
  189.     delete lineHelper;
  190.     delete curveHelper;
  191.     //Todo: remove?
  192.     //delete SBasisHelper;
  193. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement