[Libreoffice-commits] libcdr.git: src/lib
Fridrich Å trba
fridrich.strba at bluewin.ch
Fri Jul 5 06:36:18 PDT 2013
src/lib/CDRPath.cpp | 111 ++++++++++++++++++++++++++++++++++++----------------
1 file changed, 77 insertions(+), 34 deletions(-)
New commits:
commit e5e26505e64487a1d292b3d59960456ee766830c
Author: Fridrich Å trba <fridrich.strba at bluewin.ch>
Date: Fri Jul 5 15:35:51 2013 +0200
Decompose Splines into a sequence of cubic beziers
diff --git a/src/lib/CDRPath.cpp b/src/lib/CDRPath.cpp
index 2d3e0b5..7f88933 100644
--- a/src/lib/CDRPath.cpp
+++ b/src/lib/CDRPath.cpp
@@ -28,6 +28,7 @@
*/
#include <math.h>
+#include <map>
#include "CDRPath.h"
#include "CDRTypes.h"
@@ -126,6 +127,7 @@ public:
CDRPathElement *clone();
private:
std::vector<std::pair<double, double> > m_points;
+ unsigned knot(unsigned i) const;
};
class CDRArcToElement : public CDRPathElement
@@ -265,56 +267,97 @@ libcdr::CDRPathElement *libcdr::CDRQuadraticBezierToElement::clone()
return new CDRQuadraticBezierToElement(m_x1, m_y1, m_x, m_y);
}
+#define CDR_SPLINE_DEGREE 3
+
+unsigned libcdr::CDRSplineToElement::knot(unsigned i) const
+{
+ /* Emulates knot vector of an uniform B-Spline of degree 3 */
+ if (i < CDR_SPLINE_DEGREE)
+ return 0;
+ if (i > m_points.size())
+ return (unsigned)(m_points.size() - CDR_SPLINE_DEGREE);
+ else
+ return i - CDR_SPLINE_DEGREE;
+}
+
void libcdr::CDRSplineToElement::writeOut(WPXPropertyListVector &vec) const
{
WPXPropertyList node;
-#if 0
node.insert("libwpg:path-action", "M");
node.insert("svg:x", m_points[0].first);
node.insert("svg:y", m_points[0].second);
vec.append(node);
- for (unsigned j = 0; j < m_points.size(); ++j)
+ /* Decomposition of a spline of 3rd degree into Bezier segments
+ * adapted from the algorithm DecomposeCurve (Les Piegl, Wayne Tiller:
+ * The NURBS Book, 2nd Edition, 1997
+ */
+
+ unsigned m = m_points.size() + CDR_SPLINE_DEGREE + 1;
+ unsigned a = CDR_SPLINE_DEGREE;
+ unsigned b = CDR_SPLINE_DEGREE + 1;
+ std::vector< std::pair<double, double> > Qw(CDR_SPLINE_DEGREE+1), NextQw(CDR_SPLINE_DEGREE+1);
+ unsigned i = 0;
+ for (; i <= CDR_SPLINE_DEGREE; i++)
+ Qw[i] = m_points[i];
+ while (b < m)
{
+ i = b;
+ while (b < m && knot(b+1) == knot(b))
+ b++;
+ unsigned mult = b - i + 1;
+ if (mult < CDR_SPLINE_DEGREE)
+ {
+ double numer = (double)(knot(b) - knot(a));
+ unsigned j = CDR_SPLINE_DEGREE;
+ std::map<unsigned, double> alphas;
+ for (; j >mult; j--)
+ alphas[j-mult-1] = numer/double(knot(a+j)-knot(a));
+ unsigned r = CDR_SPLINE_DEGREE - mult;
+ for (j=1; j<=r; j++)
+ {
+ unsigned save = r - j;
+ unsigned s = mult+j;
+ for (unsigned k = CDR_SPLINE_DEGREE; k>=s; k--)
+ {
+ double alpha = alphas[k-s];
+ Qw[k].first = alpha*Qw[k].first + (1.0-alpha)*Qw[k-1].first;
+ Qw[k].second = alpha*Qw[k].second + (1.0-alpha)*Qw[k-1].second;
+ }
+ if (b < m)
+ {
+ NextQw[save].first = Qw[CDR_SPLINE_DEGREE].first;
+ NextQw[save].second = Qw[CDR_SPLINE_DEGREE].second;
+ }
+ }
+ }
+ // Pass the segment to the path
+
node.clear();
- node.insert("libwpg:path-action", "L");
- node.insert("svg:x", m_points[j].first);
- node.insert("svg:y", m_points[j].second);
+ node.insert("libwpg:path-action", "C");
+ node.insert("svg:x1", Qw[1].first);
+ node.insert("svg:y1", Qw[1].second);
+ node.insert("svg:x2", Qw[2].first);
+ node.insert("svg:y2", Qw[2].second);
+ node.insert("svg:x", Qw[3].first);
+ node.insert("svg:y", Qw[3].second);
+
vec.append(node);
- }
- node.clear();
- node.insert("libwpg:path-action", "M");
- node.insert("svg:x", m_points[0].first);
- node.insert("svg:y", m_points[0].second);
- vec.append(node);
-#endif
- for (unsigned i = 1; i < m_points.size()-1; i++)
- {
- node.clear();
- node.insert("libwpg:path-action", "Q");
- node.insert("svg:x1", m_points[i].first);
- node.insert("svg:y1", m_points[i].second);
- if (i < m_points.size() - 2)
- {
- node.insert("svg:x", (m_points[i].first+m_points[i+1].first)/2.0);
- node.insert("svg:y", (m_points[i].second+m_points[i+1].second)/2.0);
- }
- else
+ std::swap(Qw, NextQw);
+
+ if (b < m)
{
- node.insert("svg:x", m_points[i+1].first);
- node.insert("svg:y", m_points[i+1].second);
+ for (i=CDR_SPLINE_DEGREE-mult; i <= CDR_SPLINE_DEGREE; i++)
+ {
+ Qw[i].first = m_points[b-CDR_SPLINE_DEGREE+i].first;
+ Qw[i].second = m_points[b-CDR_SPLINE_DEGREE+i].second;
+ }
+ a = b;
+ b++;
}
- vec.append(node);
}
-
- // For the while, just move to the end point
- node.clear();
- node.insert("libwpg:path-action", "L");
- node.insert("svg:x", m_points.back().first);
- node.insert("svg:y", m_points.back().second);
- vec.append(node);
}
void libcdr::CDRSplineToElement::transform(const CDRTransforms &trafos)
More information about the Libreoffice-commits
mailing list