summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohan B. C. Engelen <jbc.engelen@swissonline.ch>2011-02-02 21:24:36 +0000
committerJohan Engelen <goejendaagh@zonnet.nl>2011-02-02 21:24:36 +0000
commit53933f5fea9d07d1ba6304b88439fba257ee8c34 (patch)
tree21f94cd05346fc1236751bb1db3e0850e5aece54 /src
parentTranslations. French translation minor update. (diff)
downloadinkscape-53933f5fea9d07d1ba6304b88439fba257ee8c34.tar.gz
inkscape-53933f5fea9d07d1ba6304b88439fba257ee8c34.zip
update to latest 2geom !
(bzr r10025)
Diffstat (limited to 'src')
-rw-r--r--src/2geom/Makefile_insert2
-rw-r--r--src/2geom/angle.h208
-rw-r--r--src/2geom/basic-intersection.cpp2
-rw-r--r--src/2geom/bezier-curve.h390
-rw-r--r--src/2geom/bezier-utils.cpp20
-rw-r--r--src/2geom/bezier.h11
-rw-r--r--src/2geom/chebyshev.cpp2
-rw-r--r--src/2geom/choose.h56
-rw-r--r--src/2geom/circle.cpp3
-rw-r--r--src/2geom/circle.h8
-rw-r--r--src/2geom/convex-cover.cpp137
-rw-r--r--src/2geom/convex-cover.h3
-rw-r--r--src/2geom/coord.h11
-rw-r--r--src/2geom/curve.h328
-rw-r--r--src/2geom/curves.h13
-rw-r--r--src/2geom/d2-sbasis.cpp53
-rw-r--r--src/2geom/d2-sbasis.h9
-rw-r--r--src/2geom/d2.h4
-rw-r--r--src/2geom/ellipse.cpp26
-rw-r--r--src/2geom/ellipse.h13
-rw-r--r--src/2geom/elliptical-arc.cpp1601
-rw-r--r--src/2geom/elliptical-arc.h420
-rw-r--r--src/2geom/exception.h26
-rw-r--r--src/2geom/forward.h59
-rw-r--r--src/2geom/hvlinesegment.h536
-rw-r--r--src/2geom/interval.h414
-rw-r--r--src/2geom/line.cpp164
-rw-r--r--src/2geom/line.h471
-rw-r--r--src/2geom/matrix.cpp258
-rw-r--r--src/2geom/matrix.h165
-rw-r--r--src/2geom/numeric/fitting-model.h50
-rw-r--r--src/2geom/numeric/matrix.cpp43
-rw-r--r--src/2geom/numeric/matrix.h42
-rw-r--r--src/2geom/numeric/vector.h18
-rw-r--r--src/2geom/path-intersection.cpp130
-rw-r--r--src/2geom/path.cpp18
-rw-r--r--src/2geom/path.h4
-rw-r--r--src/2geom/pathvector.cpp2
-rw-r--r--src/2geom/pathvector.h7
-rw-r--r--src/2geom/piecewise.cpp74
-rw-r--r--src/2geom/piecewise.h135
-rw-r--r--src/2geom/point.cpp149
-rw-r--r--src/2geom/point.h410
-rw-r--r--src/2geom/poly.cpp1
-rw-r--r--src/2geom/poly.h3
-rw-r--r--src/2geom/ray.h32
-rw-r--r--src/2geom/rect.h252
-rw-r--r--src/2geom/recursive-bezier-intersection.cpp26
-rw-r--r--src/2geom/region.cpp4
-rw-r--r--src/2geom/region.h2
-rw-r--r--src/2geom/sbasis-curve.h127
-rw-r--r--src/2geom/sbasis-geometric.cpp41
-rw-r--r--src/2geom/sbasis-roots.cpp232
-rw-r--r--src/2geom/sbasis.h84
-rw-r--r--src/2geom/shape.cpp2
-rw-r--r--src/2geom/shape.h2
-rw-r--r--src/2geom/solve-bezier-one-d.cpp267
-rw-r--r--src/2geom/solver.h15
-rw-r--r--src/2geom/svg-elliptical-arc.cpp938
-rw-r--r--src/2geom/svg-elliptical-arc.h383
-rw-r--r--src/2geom/svg-path-parser.cpp47
-rw-r--r--src/2geom/svg-path.cpp4
-rw-r--r--src/2geom/sweep.h3
-rw-r--r--src/2geom/transforms.cpp199
-rw-r--r--src/2geom/transforms.h260
-rw-r--r--src/2geom/utils.h41
-rw-r--r--src/arc-context.cpp2
-rw-r--r--src/box3d.cpp12
-rw-r--r--src/conn-avoid-ref.cpp18
-rw-r--r--src/conn-avoid-ref.h2
-rw-r--r--src/connector-context.cpp10
-rw-r--r--src/desktop-style.cpp10
-rw-r--r--src/desktop.cpp8
-rw-r--r--src/desktop.h14
-rw-r--r--src/dialogs/clonetiler.cpp186
-rw-r--r--src/display/canvas-arena.cpp4
-rw-r--r--src/display/canvas-axonomgrid.cpp2
-rw-r--r--src/display/canvas-axonomgrid.h2
-rw-r--r--src/display/canvas-bpath.cpp4
-rw-r--r--src/display/canvas-bpath.h2
-rw-r--r--src/display/canvas-grid.cpp6
-rw-r--r--src/display/canvas-grid.h4
-rw-r--r--src/display/canvas-text.cpp4
-rw-r--r--src/display/canvas-text.h2
-rw-r--r--src/display/curve.cpp2
-rw-r--r--src/display/curve.h2
-rw-r--r--src/display/gnome-canvas-acetate.cpp4
-rw-r--r--src/display/guideline.cpp8
-rw-r--r--src/display/inkscape-cairo.cpp12
-rw-r--r--src/display/inkscape-cairo.h2
-rw-r--r--src/display/nr-3dutils.cpp2
-rw-r--r--src/display/nr-3dutils.h2
-rw-r--r--src/display/nr-arena-glyphs.cpp12
-rw-r--r--src/display/nr-arena-glyphs.h8
-rw-r--r--src/display/nr-arena-group.cpp6
-rw-r--r--src/display/nr-arena-group.h6
-rw-r--r--src/display/nr-arena-image.cpp4
-rw-r--r--src/display/nr-arena-image.h2
-rw-r--r--src/display/nr-arena-item.cpp12
-rw-r--r--src/display/nr-arena-item.h12
-rw-r--r--src/display/nr-arena-shape.cpp14
-rw-r--r--src/display/nr-arena-shape.h6
-rw-r--r--src/display/nr-filter-colormatrix.cpp2
-rw-r--r--src/display/nr-filter-colormatrix.h2
-rw-r--r--src/display/nr-filter-component-transfer.cpp2
-rw-r--r--src/display/nr-filter-component-transfer.h2
-rw-r--r--src/display/nr-filter-convolve-matrix.cpp2
-rw-r--r--src/display/nr-filter-convolve-matrix.h2
-rw-r--r--src/display/nr-filter-diffuselighting.cpp4
-rw-r--r--src/display/nr-filter-diffuselighting.h2
-rw-r--r--src/display/nr-filter-displacement-map.cpp4
-rw-r--r--src/display/nr-filter-displacement-map.h2
-rw-r--r--src/display/nr-filter-flood.cpp2
-rw-r--r--src/display/nr-filter-flood.h2
-rw-r--r--src/display/nr-filter-gaussian.cpp6
-rw-r--r--src/display/nr-filter-gaussian.h2
-rw-r--r--src/display/nr-filter-image.cpp8
-rw-r--r--src/display/nr-filter-morphology.cpp4
-rw-r--r--src/display/nr-filter-morphology.h2
-rw-r--r--src/display/nr-filter-offset.cpp4
-rw-r--r--src/display/nr-filter-offset.h2
-rw-r--r--src/display/nr-filter-primitive.cpp2
-rw-r--r--src/display/nr-filter-primitive.h2
-rw-r--r--src/display/nr-filter-slot.cpp4
-rw-r--r--src/display/nr-filter-specularlighting.cpp4
-rw-r--r--src/display/nr-filter-specularlighting.h2
-rw-r--r--src/display/nr-filter-tile.cpp2
-rw-r--r--src/display/nr-filter-tile.h2
-rw-r--r--src/display/nr-filter-turbulence.cpp2
-rw-r--r--src/display/nr-filter-units.cpp36
-rw-r--r--src/display/nr-filter-units.h24
-rw-r--r--src/display/nr-filter.cpp6
-rw-r--r--src/display/nr-filter.h2
-rw-r--r--src/display/nr-light.cpp4
-rw-r--r--src/display/nr-light.h4
-rw-r--r--src/display/nr-svgfonts.cpp2
-rw-r--r--src/display/pixblock-scaler.cpp6
-rw-r--r--src/display/pixblock-scaler.h2
-rw-r--r--src/display/pixblock-transform.cpp10
-rw-r--r--src/display/pixblock-transform.h4
-rw-r--r--src/display/sodipodi-ctrl.cpp6
-rw-r--r--src/display/sodipodi-ctrlrect.cpp6
-rw-r--r--src/display/sodipodi-ctrlrect.h2
-rw-r--r--src/display/sp-canvas-item.h8
-rw-r--r--src/display/sp-canvas-util.cpp8
-rw-r--r--src/display/sp-canvas-util.h6
-rw-r--r--src/display/sp-canvas.cpp18
-rw-r--r--src/display/sp-canvas.h2
-rw-r--r--src/display/sp-ctrlline.cpp4
-rw-r--r--src/display/sp-ctrlline.h2
-rw-r--r--src/display/sp-ctrlpoint.cpp4
-rw-r--r--src/display/sp-ctrlpoint.h2
-rw-r--r--src/display/sp-ctrlquadr.cpp6
-rw-r--r--src/draw-context.cpp2
-rw-r--r--src/dropper-context.cpp4
-rw-r--r--src/dyna-draw-context.cpp10
-rw-r--r--src/extension/implementation/implementation.cpp8
-rw-r--r--src/extension/implementation/implementation.h8
-rw-r--r--src/extension/internal/cairo-render-context.cpp28
-rw-r--r--src/extension/internal/cairo-render-context.h20
-rw-r--r--src/extension/internal/cairo-renderer-pdf-out.cpp2
-rw-r--r--src/extension/internal/cairo-renderer.cpp46
-rw-r--r--src/extension/internal/emf-win32-print.cpp22
-rw-r--r--src/extension/internal/emf-win32-print.h16
-rw-r--r--src/extension/internal/javafx-out.cpp4
-rw-r--r--src/extension/internal/latex-pstricks.cpp18
-rw-r--r--src/extension/internal/latex-pstricks.h10
-rw-r--r--src/extension/internal/latex-text-renderer.cpp16
-rw-r--r--src/extension/internal/latex-text-renderer.h8
-rw-r--r--src/extension/internal/odf.cpp38
-rw-r--r--src/extension/internal/odf.h2
-rw-r--r--src/extension/internal/pdfinput/svg-builder.cpp16
-rw-r--r--src/extension/internal/pdfinput/svg-builder.h4
-rw-r--r--src/extension/internal/pov-out.cpp2
-rw-r--r--src/extension/internal/win32.cpp2
-rw-r--r--src/extension/internal/win32.h4
-rw-r--r--src/extension/print.cpp8
-rw-r--r--src/extension/print.h8
-rw-r--r--src/file.cpp2
-rw-r--r--src/filter-chemistry.cpp4
-rw-r--r--src/flood-context.cpp10
-rw-r--r--src/gradient-chemistry.cpp44
-rw-r--r--src/gradient-chemistry.h2
-rw-r--r--src/helper/geom.cpp32
-rw-r--r--src/helper/geom.h14
-rw-r--r--src/helper/pixbuf-ops.cpp2
-rw-r--r--src/helper/png-write.cpp2
-rw-r--r--src/knot-holder-entity.cpp22
-rw-r--r--src/knotholder.cpp2
-rw-r--r--src/libnr/nr-convert2geom.h8
-rw-r--r--src/libnr/nr-matrix.h8
-rw-r--r--src/libnrtype/FontInstance.cpp2
-rw-r--r--src/libnrtype/Layout-TNG-OutIter.cpp4
-rw-r--r--src/libnrtype/Layout-TNG-Output.cpp28
-rw-r--r--src/libnrtype/Layout-TNG-Scanline-Makers.cpp6
-rw-r--r--src/libnrtype/Layout-TNG.h12
-rw-r--r--src/libnrtype/font-instance.h2
-rw-r--r--src/libnrtype/font-style.h4
-rw-r--r--src/livarot/Path.cpp2
-rw-r--r--src/livarot/Path.h6
-rw-r--r--src/livarot/PathCutting.cpp14
-rw-r--r--src/livarot/PathSimplify.cpp4
-rw-r--r--src/livarot/Shape.h6
-rw-r--r--src/livarot/ShapeMisc.cpp6
-rw-r--r--src/livarot/ShapeSweep.cpp2
-rw-r--r--src/livarot/path-description.cpp14
-rw-r--r--src/livarot/path-description.h14
-rw-r--r--src/live_effects/effect.cpp4
-rw-r--r--src/live_effects/effect.h2
-rw-r--r--src/live_effects/lpe-copy_rotate.cpp4
-rw-r--r--src/live_effects/lpe-curvestitch.cpp8
-rw-r--r--src/live_effects/lpe-curvestitch.h2
-rw-r--r--src/live_effects/lpe-dynastroke.cpp10
-rw-r--r--src/live_effects/lpe-knot.cpp4
-rw-r--r--src/live_effects/lpe-mirror_symmetry.cpp12
-rw-r--r--src/live_effects/lpe-patternalongpath.cpp2
-rw-r--r--src/live_effects/lpe-patternalongpath.h2
-rw-r--r--src/live_effects/lpe-rough-hatches.cpp8
-rw-r--r--src/live_effects/lpe-sketch.cpp2
-rw-r--r--src/live_effects/lpe-spiro.cpp2
-rw-r--r--src/live_effects/lpe-vonkoch.cpp28
-rw-r--r--src/live_effects/lpegroupbbox.cpp2
-rw-r--r--src/live_effects/parameter/parameter.h2
-rw-r--r--src/live_effects/parameter/path.cpp2
-rw-r--r--src/live_effects/parameter/path.h2
-rw-r--r--src/live_effects/parameter/point.cpp4
-rw-r--r--src/live_effects/parameter/point.h2
-rw-r--r--src/live_effects/parameter/powerstrokepointarray.cpp4
-rw-r--r--src/live_effects/parameter/powerstrokepointarray.h2
-rw-r--r--src/live_effects/parameter/vector.cpp4
-rw-r--r--src/live_effects/parameter/vector.h2
-rw-r--r--src/lpe-tool-context.cpp2
-rw-r--r--src/marker.cpp18
-rw-r--r--src/marker.h8
-rw-r--r--src/object-edit.cpp4
-rw-r--r--src/object-snapper.cpp6
-rw-r--r--src/object-snapper.h2
-rw-r--r--src/persp3d.cpp2
-rw-r--r--src/persp3d.h2
-rw-r--r--src/print.cpp12
-rw-r--r--src/print.h10
-rw-r--r--src/selection-chemistry.cpp66
-rw-r--r--src/selection-chemistry.h2
-rw-r--r--src/selection.cpp2
-rw-r--r--src/seltrans.cpp24
-rw-r--r--src/seltrans.h12
-rw-r--r--src/snap-candidate.h4
-rw-r--r--src/snapped-curve.cpp4
-rw-r--r--src/snapped-curve.h4
-rw-r--r--src/sp-clippath.cpp14
-rw-r--r--src/sp-clippath.h4
-rw-r--r--src/sp-conn-end-pair.cpp6
-rw-r--r--src/sp-conn-end.cpp10
-rw-r--r--src/sp-ellipse.cpp4
-rw-r--r--src/sp-flowregion.cpp2
-rw-r--r--src/sp-flowtext.cpp6
-rw-r--r--src/sp-gradient-fns.h8
-rw-r--r--src/sp-gradient-test.h30
-rw-r--r--src/sp-gradient.cpp60
-rw-r--r--src/sp-gradient.h2
-rw-r--r--src/sp-image.cpp16
-rw-r--r--src/sp-item-group.cpp12
-rw-r--r--src/sp-item-group.h2
-rw-r--r--src/sp-item-transform.cpp26
-rw-r--r--src/sp-item-transform.h4
-rw-r--r--src/sp-item.cpp68
-rw-r--r--src/sp-item.h52
-rw-r--r--src/sp-line.cpp4
-rw-r--r--src/sp-line.h2
-rw-r--r--src/sp-mask.cpp8
-rw-r--r--src/sp-mask.h2
-rw-r--r--src/sp-offset.cpp10
-rw-r--r--src/sp-paint-server.cpp4
-rw-r--r--src/sp-paint-server.h4
-rw-r--r--src/sp-path.cpp8
-rw-r--r--src/sp-pattern.cpp36
-rw-r--r--src/sp-pattern.h8
-rw-r--r--src/sp-rect.cpp16
-rw-r--r--src/sp-rect.h2
-rw-r--r--src/sp-root.cpp2
-rw-r--r--src/sp-root.h2
-rw-r--r--src/sp-shape.cpp50
-rw-r--r--src/sp-shape.h8
-rw-r--r--src/sp-spiral.cpp2
-rw-r--r--src/sp-star.cpp4
-rw-r--r--src/sp-symbol.cpp12
-rw-r--r--src/sp-symbol.h4
-rw-r--r--src/sp-text.cpp20
-rw-r--r--src/sp-text.h2
-rw-r--r--src/sp-tref.cpp4
-rw-r--r--src/sp-tspan.cpp4
-rw-r--r--src/sp-use-reference.cpp12
-rw-r--r--src/sp-use.cpp36
-rw-r--r--src/sp-use.h4
-rw-r--r--src/splivarot.cpp48
-rw-r--r--src/splivarot.h2
-rw-r--r--src/spray-context.cpp8
-rw-r--r--src/svg/svg-affine-test.h80
-rw-r--r--src/svg/svg-affine.cpp16
-rw-r--r--src/svg/svg-path.cpp6
-rw-r--r--src/svg/svg.h6
-rw-r--r--src/text-editing.cpp12
-rw-r--r--src/text-editing.h2
-rw-r--r--src/text-tag-attributes.h2
-rw-r--r--src/trace/trace.cpp2
-rw-r--r--src/transf_mat_3x4.cpp6
-rw-r--r--src/transf_mat_3x4.h4
-rw-r--r--src/tweak-context.cpp12
-rw-r--r--src/ui/cache/svg_preview_cache.cpp2
-rw-r--r--src/ui/clipboard.cpp2
-rw-r--r--src/ui/dialog/filedialogimpl-win32.cpp2
-rw-r--r--src/ui/dialog/svg-fonts-dialog.cpp4
-rw-r--r--src/ui/dialog/tile.cpp2
-rw-r--r--src/ui/dialog/transformation.cpp12
-rw-r--r--src/ui/tool/control-point-selection.cpp14
-rw-r--r--src/ui/tool/control-point-selection.h6
-rw-r--r--src/ui/tool/control-point.cpp2
-rw-r--r--src/ui/tool/control-point.h2
-rw-r--r--src/ui/tool/node.cpp34
-rw-r--r--src/ui/tool/node.h2
-rw-r--r--src/ui/tool/path-manipulator.cpp12
-rw-r--r--src/ui/tool/path-manipulator.h12
-rw-r--r--src/ui/tool/shape-record.h4
-rw-r--r--src/ui/tool/transform-handle-set.cpp28
-rw-r--r--src/ui/tool/transform-handle-set.h4
-rw-r--r--src/ui/widget/registered-widget.cpp2
-rw-r--r--src/ui/widget/registered-widget.h6
-rw-r--r--src/unclump.cpp4
-rw-r--r--src/widgets/font-selector.cpp2
-rw-r--r--src/widgets/icon.cpp6
-rw-r--r--src/widgets/select-toolbar.cpp2
-rw-r--r--src/widgets/stroke-style.cpp2
-rw-r--r--src/widgets/toolbox.cpp2
333 files changed, 5950 insertions, 6024 deletions
diff --git a/src/2geom/Makefile_insert b/src/2geom/Makefile_insert
index 7ded3a637..ead0e3517 100644
--- a/src/2geom/Makefile_insert
+++ b/src/2geom/Makefile_insert
@@ -22,7 +22,7 @@
2geom/elliptical-arc.cpp \
2geom/geom.cpp \
2geom/line.cpp \
- 2geom/matrix.cpp \
+ 2geom/affine.cpp \
2geom/nearest-point.cpp \
2geom/path-intersection.cpp \
2geom/path.cpp \
diff --git a/src/2geom/angle.h b/src/2geom/angle.h
index c950dd803..42e3531f3 100644
--- a/src/2geom/angle.h
+++ b/src/2geom/angle.h
@@ -1,11 +1,13 @@
/**
- * \file angle.h
+ * \file
* \brief Various trigoniometric helper functions
- *
+ *//*
* Authors:
* Johan Engelen <goejendaagh@zonnet.nl>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
*
- * Copyright (C) 2007 authors
+ * Copyright (C) 2007-2010 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -35,12 +37,177 @@
#ifndef LIB2GEOM_SEEN_ANGLE_H
#define LIB2GEOM_SEEN_ANGLE_H
+#include <cmath>
+#include <boost/operators.hpp>
+#include <2geom/exception.h>
+#include <2geom/coord.h>
+#include <2geom/point.h>
+
namespace Geom {
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
+/** @brief Wrapper for angular values.
+ *
+ * This class is a convenience wrapper that implements the behavior generally expected of angles,
+ * like addition modulo \f$2\pi\f$. The value returned from the default conversion
+ * to <tt>double</tt> is in the range \f$[-\pi, \pi)\f$ - the convention used by C's
+ * math library.
+ *
+ * @ingroup Primitives
+ */
+class Angle
+ : boost::additive< Angle
+ , boost::equality_comparable< Angle
+ > >
+{
+public:
+ Angle(Coord v) : _angle(v) { _normalize(); } // this can be called implicitly
+ explicit Angle(Point p) : _angle(atan2(p)) { _normalize(); }
+ Angle(Point a, Point b) : _angle(angle_between(a, b)) { _normalize(); }
+ operator Coord() const { return radians(); }
+ Angle &operator+=(Angle const &o) {
+ _angle += o._angle;
+ _normalize();
+ return *this;
+ }
+ Angle &operator-=(Angle const &o) {
+ _angle -= o._angle;
+ _normalize();
+ return *this;
+ }
+ bool operator==(Angle const &o) const {
+ return _angle == o._angle;
+ }
+
+ /** @brief Get the angle as radians.
+ * @return Number in range \f$[-\pi, \pi)\f$. */
+ Coord radians() const {
+ return _angle > M_PI ? _angle - 2*M_PI : _angle;
+ }
+ /** @brief Get the angle as positive radians.
+ * @return Number in range \f$[0, 2\pi)\f$. */
+ Coord radians0() const {
+ return _angle;
+ }
+ /** @brief Get the angle as degrees in math convention.
+ * @return Number in range [-180, 180) obtained by scaling the result of radians()
+ * by \f$180/\pi\f$. */
+ Coord degrees() const { return radians() / M_PI * 180.0; }
+ /** @brief Get the angle as degrees in clock convention.
+ * This method converts the angle to the "clock convention": angles start from the +Y axis
+ * and grow clockwise. This means that 0 corresponds to \f$\pi/2\f$ radians,
+ * 90 to 0 radians, 180 to \f$-\pi/2\f$ radians, and 270 to \f$\pi\f$ radians.
+ * @return A number in the range [0, 360).
+ */
+ Coord degreesClock() const {
+ Coord ret = 90.0 - _angle / M_PI * 180.0;
+ if (ret < 0) ret += 360;
+ return ret;
+ }
+
+ static Angle from_degrees(Coord d) {
+ Angle a(d * M_PI / 180);
+ return a;
+ }
+ static Angle from_degrees_clock(Coord d) {
+ // first make sure d is in [0, 360)
+ d = std::fmod(d, 360.0);
+ if (d < 0) d += 360.0;
+ Coord rad = M_PI/2 - d * M_PI / 180.0;
+ if (rad < 0) rad += 2*M_PI;
+ Angle a;
+ a._angle = rad;
+ return a;
+ }
+private:
+ Angle() {}
+ void _normalize() {
+ _angle -= floor(_angle / (2*M_PI)) * 2*M_PI;
+ }
+ Coord _angle; // this is always in [0, 2pi)
+ friend class AngleInterval;
+};
+
+/** @brief Directed angular interval.
+ *
+ * Wrapper for directed angles with defined start and end values. Useful e.g. for representing
+ * the portion of an ellipse in an elliptical arc. Both extreme angles are contained
+ * in the interval (it is a closed interval). Angular intervals can also be interptered
+ * as functions \f$f: [0, 1] \to [-\pi, \pi)\f$, which return the start angle for 0,
+ * the end angle for 1, and interpolate linearly for other values. Note that such functions
+ * are not continuous if the interval contains the zero angle.
+ *
+ * This class is immutable - you cannot change the values of start and end angles
+ * without creating a new instance of this class.
+ *
+ * @ingroup Primitives
+ */
+class AngleInterval {
+public:
+ AngleInterval(Angle const &s, Angle const &e, bool cw = false)
+ : _start_angle(s), _end_angle(e), _sweep(cw)
+ {}
+ AngleInterval(double s, double e, bool cw = false)
+ : _start_angle(s), _end_angle(e), _sweep(cw)
+ {}
+ /** @brief Get the angular coordinate of the interval's initial point
+ * @return Angle in range \f$[0,2\pi)\f$ corresponding to the start of arc */
+ Angle const &initialAngle() const { return _start_angle; }
+ /** @brief Get the angular coordinate of the interval's final point
+ * @return Angle in range \f$[0,2\pi)\f$ corresponding to the end of arc */
+ Angle const &finalAngle() const { return _end_angle; }
+ bool isDegenerate() const { return initialAngle() == finalAngle(); }
+ /** @brief Get an angle corresponding to the specified time value. */
+ Angle angleAt(Coord t) const {
+ Coord span = extent();
+ Angle ret = _start_angle.radians0() + span * (_sweep ? t : -t);
+ return ret;
+ }
+ Angle operator()(Coord t) const { return angleAt(t); }
+#if 0
+ /** @brief Find an angle nearest to the specified time value.
+ * @param a Query angle
+ * @return If the interval contains the query angle, a number from the range [0, 1]
+ * such that a = angleAt(t); otherwise, 0 or 1, depending on which extreme
+ * angle is nearer. */
+ Coord nearestAngle(Angle const &a) const {
+ Coord dist = distance(_start_angle, a, _sweep).radians0();
+ Coord span = distance(_start_angle, _end_angle, _sweep).radians0();
+ if (dist <= span) return dist / span;
+ else return distance_abs(_start_angle, a).radians0() > distance_abs(_end_angle, a).radians0() ? 1.0 : 0.0;
+ }
+#endif
+ /** @brief Check whether the interval includes the given angle. */
+ bool contains(Angle const &a) const {
+ Coord s = _start_angle.radians0();
+ Coord e = _end_angle.radians0();
+ Coord x = a.radians0();
+ if (_sweep) {
+ if (s < e) return x >= s && x <= e;
+ return x >= s || x <= e;
+ } else {
+ if (s > e) return x <= s && x >= e;
+ return x <= s || x >= e;
+ }
+ }
+ /** @brief Extent of the angle interval.
+ * @return Extent in range \f$[0, 2\pi)\f$ */
+ Coord extent() const {
+ Coord d = _end_angle - _start_angle;
+ if (!_sweep) d = -d;
+ if (d < 0) d += 2*M_PI;
+ return d;
+ }
+protected:
+ AngleInterval() {}
+ Angle _start_angle;
+ Angle _end_angle;
+ bool _sweep;
+};
+
inline double deg_to_rad(double deg) { return deg*M_PI/180.0;}
inline double rad_to_deg(double rad) { return rad*180.0/M_PI;}
@@ -89,9 +256,44 @@ Coord map_unit_interval_on_circular_arc(Coord t, double start_angle, double end_
return angle;
}
+/*
+ * Return true if the given angle is contained in the circular arc determined
+ * by the passed angles.
+ *
+ * a: the angle to be tested
+ * sa: the angle the arc start from
+ * ia: an angle strictly inner to the arc
+ * ea: the angle the arc end to
+ *
+ * prerequisite: the inner angle has to be not equal (mod 2PI) to the start
+ * or the end angle, except when they are equal each other, too.
+ * warning: when sa == ea (mod 2PI) they define a whole circle
+ * if ia != sa (mod 2PI), on the contrary if ia == sa == ea (mod 2PI)
+ * they define a single point.
+ */
+inline
+bool arc_contains (double a, double sa, double ia, double ea)
+{
+ a -= sa;
+ a = std::fmod(a, 2*M_PI);
+ if (a < 0) a += 2*M_PI;
+ ia -= sa;
+ ia = std::fmod(ia, 2*M_PI);
+ if (ia < 0) ia += 2*M_PI;
+ ea -= sa;
+ ea = std::fmod(ea, 2*M_PI);
+ if (ea < 0) ea += 2*M_PI;
+ if (ia == 0 && ea == 0) return (a == 0);
+ if (ia == 0 || ia == ea)
+ {
+ THROW_RANGEERROR ("arc_contains: passed angles do not define an arc");
+ }
+ return (ia < ea && a <= ea) || (ia > ea && (a >= ea || a == 0));
}
+} // end namespace Geom
+
#endif
diff --git a/src/2geom/basic-intersection.cpp b/src/2geom/basic-intersection.cpp
index 66f174da6..3be6792b9 100644
--- a/src/2geom/basic-intersection.cpp
+++ b/src/2geom/basic-intersection.cpp
@@ -202,7 +202,7 @@ static void intersect_polish_root (D2<SBasis> const &A, double &s,
// We're using the standard transformation matricies, which is numerically rather poor. Much better to solve the equation using elimination.
- Matrix jack(as[1][0], as[1][1],
+ Affine jack(as[1][0], as[1][1],
-bs[1][0], -bs[1][1],
0, 0);
Point soln = (F)*jack.inverse();
diff --git a/src/2geom/bezier-curve.h b/src/2geom/bezier-curve.h
index c943512c7..1014c79f0 100644
--- a/src/2geom/bezier-curve.h
+++ b/src/2geom/bezier-curve.h
@@ -1,12 +1,14 @@
/**
* \file
- * \brief Bezier-Curve
+ * \brief Bezier curve
*
+ *//*
* Authors:
- * MenTaLguY <mental@rydia.net>
- * Marco Cecchetti <mrcekets at gmail.com>
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
*
- * Copyright 2007-2008 authors
+ * Copyright 2007-2009 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -32,217 +34,225 @@
* the specific language governing rights and limitations.
*/
-
-
-
-#ifndef _2GEOM_BEZIER_CURVE_H_
-#define _2GEOM_BEZIER_CURVE_H_
-
+#ifndef SEEN_LIB2GEOM_BEZIER_CURVE_H
+#define SEEN_LIB2GEOM_BEZIER_CURVE_H
#include <2geom/curve.h>
#include <2geom/sbasis-curve.h> // for non-native winding method
#include <2geom/bezier.h>
-#include <algorithm>
-
-
namespace Geom
{
-
-
-template <unsigned order>
class BezierCurve : public Curve {
-
-private:
- D2<Bezier > inner;
-
-public:
- template <unsigned required_degree>
- static void assert_degree(BezierCurve<required_degree> const *) {}
-
- BezierCurve() : inner(Bezier::Order(order), Bezier::Order(order)) {
- }
-
- explicit BezierCurve(D2<Bezier > const &x) : inner(x) {}
-
- BezierCurve(Bezier x, Bezier y) : inner(x, y) {}
-
- // default copy
- // default assign
-
- BezierCurve(Point c0, Point c1) {
- assert_degree<1>(this);
- for(unsigned d = 0; d < 2; d++)
- inner[d] = Bezier(c0[d], c1[d]);
- }
-
- BezierCurve(Point c0, Point c1, Point c2) {
- assert_degree<2>(this);
- for(unsigned d = 0; d < 2; d++)
- inner[d] = Bezier(c0[d], c1[d], c2[d]);
- }
-
- BezierCurve(Point c0, Point c1, Point c2, Point c3) {
- assert_degree<3>(this);
- for(unsigned d = 0; d < 2; d++)
- inner[d] = Bezier(c0[d], c1[d], c2[d], c3[d]);
- }
-
- unsigned degree() const { return order; }
-
- Curve *duplicate() const { return new BezierCurve(*this); }
-
- Point initialPoint() const { return inner.at0(); }
- Point finalPoint() const { return inner.at1(); }
-
- bool isDegenerate() const { return inner.isConstant(); }
-
- void setInitial(Point v) { setPoint(0, v); }
- void setFinal(Point v) { setPoint(order, v); }
-
- void setPoint(unsigned ix, Point v) { inner[X].setPoint(ix, v[X]); inner[Y].setPoint(ix, v[Y]); }
- Point const operator[](unsigned ix) const { return Point(inner[X][ix], inner[Y][ix]); }
-
- virtual OptRect boundsFast() const { return bounds_fast(inner); }
- virtual OptRect boundsExact() const { return bounds_exact(inner); }
- virtual OptRect boundsLocal(OptInterval i, unsigned deg) const {
- if (!i) return OptRect();
- if(i->min() == 0 && i->max() == 1) return boundsFast();
- if(deg == 0) return bounds_local(inner, i);
- // TODO: UUUUUUGGGLLY
- if(deg == 1 && order > 1) return OptRect(bounds_local(Geom::derivative(inner[X]), i),
- bounds_local(Geom::derivative(inner[Y]), i));
- return OptRect();
- }
-//TODO: local
-
-//TODO: implement next 3 natively
- int winding(Point p) const {
- return SBasisCurve(toSBasis()).winding(p);
- }
-
- virtual int degreesOfFreedom() const {
- return 2*order;
- }
-
- std::vector<double>
- roots(double v, Dim2 d) const {
- return (inner[d] - v).roots();
- }
-
- double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
- {
- return Curve::nearestPoint(p, from, to);
- }
-
- void setPoints(std::vector<Point> ps) {
- for(unsigned i = 0; i <= order; i++) {
- setPoint(i, ps[i]);
- }
- }
- std::vector<Point> points() const { return bezier_points(inner); }
-
- std::pair<BezierCurve<order>, BezierCurve<order> > subdivide(Coord t) const {
- std::pair<Bezier, Bezier > sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t);
- return std::pair<BezierCurve<order>, BezierCurve<order> >(
- BezierCurve<order>(sx.first, sy.first),
- BezierCurve<order>(sx.second, sy.second));
- }
-
- Curve *portion(double f, double t) const {
- return new BezierCurve(Geom::portion(inner, f, t));
- }
-
- Curve *reverse() const {
- return new BezierCurve(Geom::reverse(inner));
- }
-
- Curve *transformed(Matrix const &m) const {
- BezierCurve *ret = new BezierCurve();
- std::vector<Point> ps = points();
- for(unsigned i = 0; i <= order; i++) ps[i] = ps[i] * m;
- ret->setPoints(ps);
- return ret;
- }
-
- Curve *derivative() const;
-
- Point pointAt(double t) const { return inner.valueAt(t); }
- std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const { return inner.valueAndDerivatives(t, n); }
-
- double valueAt(double t, Dim2 d) const { return inner[d].valueAt(t); }
-
- D2<SBasis> toSBasis() const {return inner.toSBasis(); }
-
protected:
- BezierCurve(Point c[]) {
- Coord x[order+1], y[order+1];
- for(unsigned i = 0; i <= order; i++) {
- x[i] = c[i][X]; y[i] = c[i][Y];
+ D2<Bezier> inner;
+
+public:
+ /// @name Construct the curve
+ /// @{
+ /** @brief Construct a Bezier curve of the specified order with all points zero. */
+ explicit BezierCurve(unsigned order)
+ : inner(Bezier::Order(order), Bezier::Order(order))
+ {}
+ /** @brief Construct from 2D Bezier polynomial. */
+ explicit BezierCurve(D2<Bezier > const &x)
+ : inner(x)
+ {
+ if (inner[X].order() != inner[Y].order())
+ THROW_LOGICALERROR("Beziers used to construct a BezierCurve "
+ "are not of the same order");
+ }
+ /** @brief Construct from two 1D Bezier polynomials of the same order. */
+ BezierCurve(Bezier x, Bezier y)
+ : inner(x, y)
+ {
+ // throw an error if the orders do not match
+ if (x.order() != y.order())
+ THROW_LOGICALERROR("Beziers used to construct a BezierCurve "
+ "are not of the same order");
+ }
+ /** @brief Construct a linear segment from its endpoints. */
+ BezierCurve(Point c0, Point c1) {
+ for(unsigned d = 0; d < 2; d++)
+ inner[d] = Bezier(c0[d], c1[d]);
+ }
+ /** @brief Construct a quadratic Bezier curve from its control points. */
+ BezierCurve(Point c0, Point c1, Point c2) {
+ for(unsigned d = 0; d < 2; d++)
+ inner[d] = Bezier(c0[d], c1[d], c2[d]);
+ }
+ /** @brief Construct a cubic Bezier curve from its control points. */
+ BezierCurve(Point c0, Point c1, Point c2, Point c3) {
+ for(unsigned d = 0; d < 2; d++)
+ inner[d] = Bezier(c0[d], c1[d], c2[d], c3[d]);
+ }
+ /** @brief Construct a Bezier curve from a vector of its control points. */
+ BezierCurve(std::vector<Point> const &points) {
+ unsigned ord = points.size() - 1;
+ if (ord < 1) THROW_LOGICALERROR("Not enough points to construct a Bezier curve");
+ for (unsigned d = 0; d < 2; ++d) {
+ inner[d] = Bezier(Bezier::Order(ord));
+ for(unsigned i = 0; i <= ord; i++)
+ inner[d][i] = points[i][d];
+ }
+ }
+ /// @}
+
+ // methods new to BezierCurve go here
+
+ /// @name Access and modify control points
+ /// @{
+ /** @brief Get the order of the Bezier curve.
+ * A Bezier curve has order() + 1 control points. */
+ unsigned order() const { return inner[X].order(); }
+ /** @brief Get the control points.
+ * @return Vector with order() + 1 control points. */
+ std::vector<Point> points() const { return bezier_points(inner); }
+ /** @brief Modify a control point.
+ * @param ix The zero-based index of the point to modify
+ * @param v The new value of the point */
+ void setPoint(unsigned ix, Point v) {
+ inner[X].setPoint(ix, v[X]);
+ inner[Y].setPoint(ix, v[Y]);
+ }
+ /** @brief Set new control points for this curve.
+ * @param ps Vector which must contain order() + 1 points. */
+ virtual void setPoints(std::vector<Point> const &ps) {
+ // must be virtual, because HLineSegment will need to redefine it
+ if (ps.size() != order() + 1)
+ THROW_LOGICALERROR("BezierCurve::setPoints: incorrect number of points in vector");
+ for(unsigned i = 0; i <= order(); i++) {
+ setPoint(i, ps[i]);
+ }
+ }
+ /** Access control points of the curve.
+ * @param ix Index of the control point
+ * @return The control point. No-reference return, use setPoint() to modify control points. */
+ Point const operator[](unsigned ix) const { return Point(inner[X][ix], inner[Y][ix]); }
+ /// @}
+
+ /** @brief Divide a Bezier curve into two curves
+ * @param t Time value
+ * @return Pair of Bezier curves \f$(\mathbf{D}, \mathbf{E})\f$ such that
+ * \f$\mathbf{D}[ [0,1] ] = \mathbf{C}[ [0,t] ]\f$ and
+ * \f$\mathbf{E}[ [0,1] ] = \mathbf{C}[ [t,1] ]\f$ */
+ std::pair<BezierCurve, BezierCurve> subdivide(Coord t) const {
+ std::pair<Bezier, Bezier> sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t);
+ return std::make_pair(
+ BezierCurve(sx.first, sy.first),
+ BezierCurve(sx.second, sy.second));
+ }
+ BezierCurve *optimize() const;
+
+ // implementation of virtual methods goes here
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ virtual Curve *duplicate() const;
+ virtual Point initialPoint() const { return inner.at0(); }
+ virtual Point finalPoint() const { return inner.at1(); }
+ virtual bool isDegenerate() const { return inner.isConstant(); }
+ virtual void setInitial(Point const &v) { setPoint(0, v); }
+ virtual void setFinal(Point const &v) { setPoint(order(), v); }
+ virtual Rect boundsFast() const { return *bounds_fast(inner); }
+ virtual Rect boundsExact() const { return *bounds_exact(inner); }
+ virtual OptRect boundsLocal(OptInterval const &i, unsigned deg) const {
+ if (!i) return OptRect();
+ if(i->min() == 0 && i->max() == 1) return boundsFast();
+ if(deg == 0) return bounds_local(inner, i);
+ // TODO: UUUUUUGGGLLY
+ if(deg == 1 && order() > 1) return OptRect(bounds_local(Geom::derivative(inner[X]), i),
+ bounds_local(Geom::derivative(inner[Y]), i));
+ return OptRect();
+ }
+ virtual int degreesOfFreedom() const {
+ return 2 * (order() + 1);
+ }
+ virtual std::vector<Coord> roots(Coord v, Dim2 d) const {
+ return (inner[d] - v).roots();
+ }
+ Curve *portion(Coord f, Coord t) const {
+ return new BezierCurve(Geom::portion(inner, f, t));
}
- inner = Bezier(x, y);
- }
+ Curve *reverse() const {
+ return new BezierCurve(Geom::reverse(inner));
+ }
+ virtual Curve *transformed(Affine const &m) const {
+ BezierCurve *ret = new BezierCurve(order());
+ std::vector<Point> ps = points();
+ for(unsigned i = 0; i <= order(); i++) ps[i] = ps[i] * m;
+ ret->setPoints(ps);
+ return ret;
+ }
+ virtual Curve *derivative() const;
+ virtual Coord length(Coord tolerance) const;
+ virtual Point pointAt(Coord t) const { return inner.valueAt(t); }
+ virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const { return inner.valueAndDerivatives(t, n); }
+ virtual Coord valueAt(Coord t, Dim2 d) const { return inner[d].valueAt(t); }
+ virtual D2<SBasis> toSBasis() const {return inner.toSBasis(); }
+#endif
};
-// BezierCurve<0> is meaningless; specialize it out
-template<> class BezierCurve<0> : public BezierCurve<1> { public: BezierCurve();};
-
-typedef BezierCurve<1> LineSegment;
-typedef BezierCurve<2> QuadraticBezier;
-typedef BezierCurve<3> CubicBezier;
-
-
-template<>
-inline
-double LineSegment::nearestPoint(Point const& p, double from, double to) const
-{
- if ( from > to ) std::swap(from, to);
- Point ip = pointAt(from);
- Point fp = pointAt(to);
- Point v = fp - ip;
- double l2v = L2sq(v);
- if(l2v == 0) return 0;
- double t = dot( p - ip, v ) / l2v;
- if ( t <= 0 ) return from;
- else if ( t >= 1 ) return to;
- else return from + t*(to-from);
-}
+class LineSegment : public BezierCurve {
+public:
+ LineSegment() : BezierCurve(1) {}
+ LineSegment(Point c0, Point c1) : BezierCurve(c0, c1) {}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ virtual Curve *duplicate() const { return new LineSegment(*this); }
+ virtual Rect boundsFast() const { return Rect(initialPoint(), finalPoint()); }
+ virtual Rect boundsExact() const { return boundsFast(); }
+ virtual Coord nearestPoint(Point const& p, Coord from = 0, Coord to = 1) const;
+ virtual Curve *portion(Coord f, Coord t) const {
+ return new LineSegment(pointAt(f), pointAt(t));
+ }
+ virtual Curve *reverse() const { return new LineSegment(finalPoint(), initialPoint()); }
+ virtual Curve *transformed(Affine const &m) const {
+ return new LineSegment(initialPoint() * m, finalPoint() * m);
+ }
+ virtual Curve *derivative() const {
+ Coord dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0];
+ return new LineSegment(Point(dx,dy),Point(dx,dy));
+ }
+ virtual Coord length(Coord) const { return distance(initialPoint(), finalPoint()); }
+#endif
+};
-inline
-Point middle_point(LineSegment const& _segment)
-{
- return ( _segment.initialPoint() + _segment.finalPoint() ) / 2;
-}
+class QuadraticBezier : public BezierCurve {
+public:
+ QuadraticBezier(Point c0, Point c1, Point c2) : BezierCurve(c0, c1, c2) {}
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ virtual Coord length(Coord tolerance) const;
+#endif
+};
-inline
-double length(LineSegment const& _segment)
-{
- return distance(_segment.initialPoint(), _segment.finalPoint());
-}
+/** @brief Cubic Bezier curve.
+ * Note that if you created a BezierCurve, you will not be able to cast it to a CubicBezier
+ * using a dynamic cast regardless of its order - use the optimize() method.
+ * @ingroup Curves */
+class CubicBezier : public BezierCurve {
+public:
+ CubicBezier(Point c0, Point c1, Point c2, Point c3) : BezierCurve(c0, c1, c2, c3) {}
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ virtual Coord length(Coord tolerance) const;
+#endif
+};
-template <unsigned order>
-inline
-Curve *BezierCurve<order>::derivative() const {
- return new BezierCurve<order-1>(Geom::derivative(inner[X]), Geom::derivative(inner[Y]));
+inline Point middle_point(LineSegment const& _segment) {
+ return ( _segment.initialPoint() + _segment.finalPoint() ) / 2;
}
-template <>
-inline
-Curve *BezierCurve<1>::derivative() const {
- double dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0];
- return new BezierCurve<1>(Point(dx,dy),Point(dx,dy));
+inline Coord length(LineSegment const& seg) {
+ return distance(seg.initialPoint(), seg.finalPoint());
}
+Coord bezier_length(std::vector<Point> const &points, Coord tolerance = 0.01);
+Coord bezier_length(Point p0, Point p1, Point p2, Coord tolerance = 0.01);
+Coord bezier_length(Point p0, Point p1, Point p2, Point p3, Coord tolerance = 0.01);
} // end namespace Geom
-
#endif // _2GEOM_BEZIER_CURVE_H_
-
-
-
/*
Local Variables:
mode:c++
diff --git a/src/2geom/bezier-utils.cpp b/src/2geom/bezier-utils.cpp
index dc8025115..eb317940f 100644
--- a/src/2geom/bezier-utils.cpp
+++ b/src/2geom/bezier-utils.cpp
@@ -56,9 +56,7 @@
#include <2geom/isnan.h>
#include <assert.h>
-namespace Geom{
-
-typedef Point BezierCurve[];
+namespace Geom {
/* Forward declarations */
static void generate_bezier(Point b[], Point const d[], double const u[], unsigned len,
@@ -68,16 +66,16 @@ static void estimate_lengths(Point bezier[],
Point const &tHat1, Point const &tHat2);
static void estimate_bi(Point b[4], unsigned ei,
Point const data[], double const u[], unsigned len);
-static void reparameterize(Point const d[], unsigned len, double u[], BezierCurve const bezCurve);
-static double NewtonRaphsonRootFind(BezierCurve const Q, Point const &P, double u);
+static void reparameterize(Point const d[], unsigned len, double u[], Point const bezCurve[]);
+static double NewtonRaphsonRootFind(Point const Q[], Point const &P, double u);
static Point darray_center_tangent(Point const d[], unsigned center, unsigned length);
static Point darray_right_tangent(Point const d[], unsigned const len);
static unsigned copy_without_nans_or_adjacent_duplicates(Point const src[], unsigned src_len, Point dest[]);
static void chord_length_parameterize(Point const d[], double u[], unsigned len);
static double compute_max_error_ratio(Point const d[], double const u[], unsigned len,
- BezierCurve const bezCurve, double tolerance,
+ Point const bezCurve[], double tolerance,
unsigned *splitPoint);
-static double compute_hook(Point const &a, Point const &b, double const u, BezierCurve const bezCurve,
+static double compute_hook(Point const &a, Point const &b, double const u, Point const bezCurve[],
double const tolerance);
@@ -546,7 +544,7 @@ static void
reparameterize(Point const d[],
unsigned const len,
double u[],
- BezierCurve const bezCurve)
+ Point const bezCurve[])
{
assert( 2 <= len );
@@ -572,7 +570,7 @@ reparameterize(Point const d[],
* \return Improved u
*/
static double
-NewtonRaphsonRootFind(BezierCurve const Q, Point const &P, double const u)
+NewtonRaphsonRootFind(Point const Q[], Point const &P, double const u)
{
assert( 0.0 <= u );
assert( u <= 1.0 );
@@ -904,7 +902,7 @@ chord_length_parameterize(Point const d[], double u[], unsigned const len)
*/
static double
compute_max_error_ratio(Point const d[], double const u[], unsigned const len,
- BezierCurve const bezCurve, double const tolerance,
+ Point const bezCurve[], double const tolerance,
unsigned *const splitPoint)
{
assert( 2 <= len );
@@ -974,7 +972,7 @@ compute_max_error_ratio(Point const d[], double const u[], unsigned const len,
* distance.)
*/
static double
-compute_hook(Point const &a, Point const &b, double const u, BezierCurve const bezCurve,
+compute_hook(Point const &a, Point const &b, double const u, Point const bezCurve[],
double const tolerance)
{
Point const P = bezier_pt(3, bezCurve, u);
diff --git a/src/2geom/bezier.h b/src/2geom/bezier.h
index 2a06d44f5..a7d75da45 100644
--- a/src/2geom/bezier.h
+++ b/src/2geom/bezier.h
@@ -46,7 +46,7 @@ namespace Geom {
inline Coord subdivideArr(Coord t, Coord const *v, Coord *left, Coord *right, unsigned order) {
/*
* Bernstein :
- * Evaluate a Bernstein function at a particular parameter value
+ * Evaluate a Bernstein function at a particular parameter value
* Fill in control points for resulting sub-curves.
*
*/
@@ -248,7 +248,7 @@ public:
// initialize temp storage variables
std::valarray<Coord> d_(order()+1);
- for (unsigned i = 0; i < size(); i++) {
+ for(unsigned i = 0; i < size(); i++) {
d_[i] = c_[i];
}
@@ -256,10 +256,10 @@ public:
if(n_derivs > order()) {
nn = order()+1; // only calculate the non zero derivs
}
- for (unsigned di = 0; di < nn; di++) {
+ for(unsigned di = 0; di < nn; di++) {
//val_n_der[di] = (subdivideArr(t, &d_[0], NULL, NULL, order() - di));
val_n_der[di] = bernsteinValueAt(t, &d_[0], order() - di);
- for (unsigned i = 0; i < order() - di; i++) {
+ for(unsigned i = 0; i < order() - di; i++) {
d_[i] = (order()-di)*(d_[i+1] - d_[i]);
}
}
@@ -381,7 +381,8 @@ inline Bezier integral(const Bezier & a) {
}
inline OptInterval bounds_fast(Bezier const & b) {
- return Interval::fromArray(&const_cast<Bezier&>(b).c_[0], b.size());
+ OptInterval ret = Interval::from_array(&const_cast<Bezier&>(b).c_[0], b.size());
+ return ret;
}
//TODO: better bounds exact
diff --git a/src/2geom/chebyshev.cpp b/src/2geom/chebyshev.cpp
index d0d6edab4..c886daf88 100644
--- a/src/2geom/chebyshev.cpp
+++ b/src/2geom/chebyshev.cpp
@@ -93,7 +93,7 @@ SBasis chebyshev_approximant_interpolating (double (*f)(double,void*),
wr.fa = fa;
wr.fb = fb;
wr.in = in;
- //printf("%f %f\n", fa, fb);
+ printf("%f %f\n", fa, fb);
wr.f = f;
wr.pp = p;
return compose(Linear(in[0], in[1]), Linear(fa, fb)) + chebyshev_approximant(f_interp, order, in, &wr) + Linear(fa, fb);
diff --git a/src/2geom/choose.h b/src/2geom/choose.h
index 579c46718..3fecf1ba2 100644
--- a/src/2geom/choose.h
+++ b/src/2geom/choose.h
@@ -33,7 +33,7 @@
#define _CHOOSE_H
#include <vector>
-// XXX: Can we keep only the left terms easily?
+// XXX: Can we keep only the left terms easily?
// this would more than halve the array
// row index becomes n2 = n/2, row2 = n2*(n2+1)/2, row = row2*2+(n&1)?n2:0
// we could also leave off the ones
@@ -54,7 +54,7 @@ T choose(unsigned n, unsigned k) {
unsigned p = pascals_triangle.size() - rows_done;
pascals_triangle.push_back(1);
for(unsigned i = 0; i < rows_done-1; i++) {
- pascals_triangle.push_back(pascals_triangle[p]
+ pascals_triangle.push_back(pascals_triangle[p]
+ pascals_triangle[p+1]);
p++;
}
@@ -75,6 +75,58 @@ T choose(unsigned n, unsigned k) {
return r;
}*/
+
+
+template <typename ValueType>
+class BinomialCoefficient
+{
+ public:
+ typedef ValueType value_type;
+ typedef std::vector<value_type> container_type;
+
+ BinomialCoefficient(unsigned int _n)
+ : n(_n), m(n >> 1)
+ {
+ coefficients.reserve(m+1);
+ coefficients.push_back(1);
+ int h = m + 1;
+ value_type bct = 1;
+ for (int i = 1; i < h; ++i)
+ {
+ bct *= (n-i+1);
+ bct /= i;
+ coefficients.push_back(bct);
+ }
+ }
+
+ unsigned int size() const
+ {
+ return degree() +1;
+ }
+
+ unsigned int degree() const
+ {
+ return n;
+ }
+
+ value_type operator[] (unsigned int k) const
+ {
+ if (k > m) k = n - k;
+ return coefficients[k];
+ }
+
+ private:
+ const int n;
+ const unsigned int m;
+ container_type coefficients;
+};
+
+
+
+
+
+
+
#endif
/*
diff --git a/src/2geom/circle.cpp b/src/2geom/circle.cpp
index 8a0704735..06eb4c2a1 100644
--- a/src/2geom/circle.cpp
+++ b/src/2geom/circle.cpp
@@ -89,10 +89,11 @@ void Circle::set(std::vector<Point> const& points)
}
-SVGEllipticalArc
+EllipticalArc *
Circle::arc(Point const& initial, Point const& inner, Point const& final,
bool _svg_compliant)
{
+ // TODO native implementation!
Ellipse e(center(X), center(Y), ray(), ray(), 0);
return e.arc(initial, inner, final, _svg_compliant);
}
diff --git a/src/2geom/circle.h b/src/2geom/circle.h
index 987570b62..ec58e163a 100644
--- a/src/2geom/circle.h
+++ b/src/2geom/circle.h
@@ -39,11 +39,12 @@
#include <2geom/point.h>
#include <2geom/exception.h>
#include <2geom/path.h>
+#include <vector>
namespace Geom
{
-class SVGEllipticalArc;
+class EllipticalArc;
class Circle
{
@@ -87,12 +88,11 @@ class Circle
// prerequisite: at least 3 points must be passed
void set(std::vector<Point> const& points);
- SVGEllipticalArc
+ EllipticalArc *
arc(Point const& initial, Point const& inner, Point const& final,
bool _svg_compliant = true);
- void
- getPath(std::vector<Path> &path_out);
+ void getPath(std::vector<Path> &path_out);
Point center() const
{
diff --git a/src/2geom/convex-cover.cpp b/src/2geom/convex-cover.cpp
index db8094540..21a5c3107 100644
--- a/src/2geom/convex-cover.cpp
+++ b/src/2geom/convex-cover.cpp
@@ -33,6 +33,7 @@
#include <2geom/exception.h>
#include <algorithm>
#include <map>
+#include <assert.h>
/** Todo:
+ modify graham scan to work top to bottom, rather than around angles
@@ -48,6 +49,7 @@
using std::vector;
using std::map;
using std::pair;
+using std::make_pair;
namespace Geom{
@@ -338,40 +340,74 @@ ConvexHull::is_degenerate() const {
}
-/* Here we really need a rotating calipers implementation. This implementation is slow and incorrect.
- This incorrectness is a problem because it throws off the algorithms. Perhaps I will come up with
- something better tomorrow. The incorrectness is in the order of the bridges - they must be in the
- order of traversal around. Since the a->b and b->a bridges are seperated, they don't need to be merge
- order, just the order of the traversal of the host hull. Currently some situations make a n->0 bridge
- first.*/
-pair< map<int, int>, map<int, int> >
-bridges(ConvexHull a, ConvexHull b) {
- map<int, int> abridges;
- map<int, int> bbridges;
-
- for(unsigned ia = 0; ia < a.boundary.size(); ia++) {
- for(unsigned ib = 0; ib < b.boundary.size(); ib++) {
- Point d = b[ib] - a[ia];
- Geom::Coord e = cross(d, a[ia - 1] - a[ia]), f = cross(d, a[ia + 1] - a[ia]);
- Geom::Coord g = cross(d, b[ib - 1] - a[ia]), h = cross(d, b[ib + 1] - a[ia]);
- if (e > 0 && f > 0 && g > 0 && h > 0) abridges[ia] = ib;
- else if(e < 0 && f < 0 && g < 0 && h < 0) bbridges[ib] = ia;
- }
- }
-
- return make_pair(abridges, bbridges);
+int sgn(double x) {
+ if(x == 0) return 0;
+ return (x<0)?-1:1;
}
-std::vector<Point> bridge_points(ConvexHull a, ConvexHull b) {
- vector<Point> ret;
- pair< map<int, int>, map<int, int> > indices = bridges(a, b);
- for(map<int, int>::iterator it = indices.first.begin(); it != indices.first.end(); it++) {
- ret.push_back(a[it->first]);
- ret.push_back(b[it->second]);
+bool same_side(Point L[2], Point xs[4]) {
+ int side = 0;
+ for(int i = 0; i < 4; i++) {
+ int sn = sgn(SignedTriangleArea(L[0], L[1], xs[i]));
+ if(sn and not side)
+ side = sn;
+ else if(sn != side) return false;
}
- for(map<int, int>::iterator it = indices.second.begin(); it != indices.second.end(); it++) {
- ret.push_back(b[it->first]);
- ret.push_back(a[it->second]);
+ return true;
+}
+
+/** find bridging pairs between two convex hulls.
+ * this code is based on Hormoz Pirzadeh's masters thesis. There is room for optimisation:
+ * 1. reduce recomputation
+ * 2. use more efficient angle code
+ * 3. write as iterator
+ */
+std::vector<pair<int, int> > bridges(ConvexHull a, ConvexHull b) {
+ vector<pair<int, int> > ret;
+
+ // 1. find maximal points on a and b
+ int ai = 0, bi = 0;
+ // 2. find first copodal pair
+ double ap_angle = atan2(a[ai+1] - a[ai]);
+ double bp_angle = atan2(b[bi+1] - b[bi]);
+ Point L[2] = {a[ai], b[bi]};
+ while(ai < int(a.size()) or bi < int(b.size())) {
+ if(ap_angle == bp_angle) {
+ // In the case of parallel support lines, we must consider all four pairs of copodal points
+ {
+ assert(0); // untested
+ Point xs[4] = {a[ai-1], a[ai+1], b[bi-1], b[bi+1]};
+ if(same_side(L, xs)) ret.push_back(make_pair(ai, bi));
+ xs[2] = b[bi];
+ xs[3] = b[bi+2];
+ if(same_side(L, xs)) ret.push_back(make_pair(ai, bi));
+ xs[0] = a[ai];
+ xs[1] = a[ai+2];
+ if(same_side(L, xs)) ret.push_back(make_pair(ai, bi));
+ xs[2] = b[bi-1];
+ xs[3] = b[bi+1];
+ if(same_side(L, xs)) ret.push_back(make_pair(ai, bi));
+ }
+ ai++;
+ ap_angle += angle_between(a[ai] - a[ai-1], a[ai+1] - a[ai]);
+ L[0] = a[ai];
+ bi++;
+ bp_angle += angle_between(b[bi] - b[bi-1], b[bi+1] - b[bi]);
+ L[1] = b[bi];
+ std::cout << "parallel\n";
+ } else if(ap_angle < bp_angle) {
+ ai++;
+ ap_angle += angle_between(a[ai] - a[ai-1], a[ai+1] - a[ai]);
+ L[0] = a[ai];
+ Point xs[4] = {a[ai-1], a[ai+1], b[bi-1], b[bi+1]};
+ if(same_side(L, xs)) ret.push_back(make_pair(ai, bi));
+ } else {
+ bi++;
+ bp_angle += angle_between(b[bi] - b[bi-1], b[bi+1] - b[bi]);
+ L[1] = b[bi];
+ Point xs[4] = {a[ai-1], a[ai+1], b[bi-1], b[bi+1]};
+ if(same_side(L, xs)) ret.push_back(make_pair(ai, bi));
+ }
}
return ret;
}
@@ -428,16 +464,48 @@ ConvexHull intersection(ConvexHull /*a*/, ConvexHull /*b*/) {
return ret;
}
+template <typename T>
+T idx_to_pair(pair<T, T> p, int idx) {
+ return idx?p.second:p.first;
+}
+
/*** ConvexHull merge(ConvexHull a, ConvexHull b);
* find the smallest convex hull that surrounds a and b.
*/
ConvexHull merge(ConvexHull a, ConvexHull b) {
ConvexHull ret;
- pair< map<int, int>, map<int, int> > bpair = bridges(a, b);
- map<int, int> ab = bpair.first;
- map<int, int> bb = bpair.second;
+ std::cout << "---\n";
+ std::vector<pair<int, int> > bpair = bridges(a, b);
+
+ // Given our list of bridges {(pb1, qb1), ..., (pbk, qbk)}
+ // we start with the highest point in p0, q0, say it is p0.
+ // then the merged hull is p0, ..., pb1, qb1, ..., qb2, pb2, ...
+ // In other words, either of the two polygons vertices are added in order until the vertex coincides with a bridge point, at which point we swap.
+
+ unsigned state = (a[0][Y] < b[0][Y])?0:1;
+ ret.boundary.reserve(a.size() + b.size());
+ ConvexHull chs[2] = {a, b};
+ unsigned idx = 0;
+
+ for(unsigned k = 0; k < bpair.size(); k++) {
+ unsigned limit = idx_to_pair(bpair[k], state);
+ std::cout << bpair[k].first << " , " << bpair[k].second << "; "
+ << idx << ", " << limit << ", s: "
+ << state
+ << " \n";
+ while(idx <= limit) {
+ ret.boundary.push_back(chs[state][idx++]);
+ }
+ state = 1-state;
+ idx = idx_to_pair(bpair[k], state);
+ }
+ while(idx < chs[state].size()) {
+ ret.boundary.push_back(chs[state][idx++]);
+ }
+ return ret;
+ /*
ab[-1] = 0;
bb[-1] = 0;
@@ -460,6 +528,7 @@ ConvexHull merge(ConvexHull a, ConvexHull b) {
if(bb[i] == 0 && i != -1) break;
i = bb[i];
}
+ */
return ret;
}
diff --git a/src/2geom/convex-cover.h b/src/2geom/convex-cover.h
index 8a5124019..d5e2dee44 100644
--- a/src/2geom/convex-cover.h
+++ b/src/2geom/convex-cover.h
@@ -67,6 +67,7 @@ public:
bool contains_point(Point p);
bool strict_contains_point(Point p);
+ inline size_t size() const { return boundary.size();}
inline Point operator[](int i) const {
int l = boundary.size();
@@ -133,7 +134,7 @@ public:
// do two convex hulls intersect?
bool intersectp(ConvexHull a, ConvexHull b);
-std::vector<Point> bridge_points(ConvexHull a, ConvexHull b);
+std::vector<std::pair<int, int> > bridges(ConvexHull a, ConvexHull b);
// find the convex hull intersection
ConvexHull intersection(ConvexHull a, ConvexHull b);
diff --git a/src/2geom/coord.h b/src/2geom/coord.h
index 481723413..9c42f6bfc 100644
--- a/src/2geom/coord.h
+++ b/src/2geom/coord.h
@@ -37,8 +37,11 @@
namespace Geom {
+/** @brief Axis enum (X or Y). */
+enum Dim2 { X=0, Y=1 };
+
/**
- * A "real" type with sufficient precision for coordinates.
+ * @brief Floating point type used to store coordinates.
*
* You may safely assume that double (or even float) provides enough precision for storing
* on-canvas points, and hence that double provides enough precision for dot products of
@@ -51,7 +54,11 @@ const Coord EPSILON = 1e-5; //1e-18;
inline Coord infinity() { return std::numeric_limits<Coord>::infinity(); }
//IMPL: NearConcept
-inline bool are_near(Coord a, Coord b, double eps=EPSILON) { return fabs(a-b) <= eps; }
+inline bool are_near(Coord a, Coord b, double eps=EPSILON) { return a-b <= eps && a-b >= -eps; }
+inline bool rel_error_bound(Coord a, Coord b, double eps=EPSILON) { return a <= eps*b && a >= -eps*b; }
+
+
+typedef long IntCoord;
} /* namespace Geom */
diff --git a/src/2geom/curve.h b/src/2geom/curve.h
index 65bf86ef6..77f6808e1 100644
--- a/src/2geom/curve.h
+++ b/src/2geom/curve.h
@@ -1,12 +1,14 @@
/**
* \file
- * \brief Abstract Curve Type
+ * \brief Abstract curve type
*
+ *//*
* Authors:
- * MenTaLguY <mental@rydia.net>
- * Marco Cecchetti <mrcekets at gmail.com>
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
*
- * Copyright 2007-2008 authors
+ * Copyright 2007-2009 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -33,23 +35,16 @@
*/
-
-
#ifndef _2GEOM_CURVE_H_
#define _2GEOM_CURVE_H_
-
+#include <vector>
#include <2geom/coord.h>
#include <2geom/point.h>
#include <2geom/interval.h>
-#include <2geom/nearest-point.h>
#include <2geom/sbasis.h>
#include <2geom/d2.h>
-#include <2geom/matrix.h>
-#include <2geom/exception.h>
-
-#include <vector>
-
+#include <2geom/affine.h>
namespace Geom
{
@@ -61,99 +56,230 @@ protected:
static int root_winding(Curve const &c, Point p);
};
+
+/**
+ * @brief Abstract continuous curve on a plane defined on [0,1].
+ *
+ * Formally, a curve in 2Geom is defined as a function
+ * \f$\mathbf{C}: [0, 1] \to \mathbb{R}^2\f$
+ * (a function that maps the unit interval to points on a 2D plane). Its image (the set of points
+ * the curve passes through) will be denoted \f$\mathcal{C} = \mathbf{C}[ [0, 1] ]\f$.
+ * All curve types available in 2Geom are continuous and differentiable on their
+ * interior, e.g. \f$(0, 1)\f$. Sometimes the curve's image (value set) is referred to as the curve
+ * itself for simplicity, but keep in mind that it's not strictly correct.
+ *
+ * It is common to think of the parameter as time. The curve can then be interpreted as
+ * describing the position of some moving object from time \f$t=0\f$ to \f$t=1\f$.
+ * Because of this, the parameter is frequently called the time value.
+ *
+ * Some methods return pointers to newly allocated curves. They are expected to be freed
+ * by the caller when no longer used. Default implementations are provided for some methods.
+ *
+ * @ingroup Curves
+ */
class Curve : private CurveHelpers {
public:
- virtual ~Curve() {}
-
- virtual Point initialPoint() const = 0;
- virtual Point finalPoint() const = 0;
-
- /* isDegenerate returns true if the curve has "zero length".
- * For a bezier curve this means for example that all handles are at the same point */
- virtual bool isDegenerate() const = 0;
-
- virtual Curve *duplicate() const = 0;
-
- virtual OptRect boundsFast() const = 0;
- virtual OptRect boundsExact() const = 0;
- virtual OptRect boundsLocal(OptInterval i, unsigned deg) const = 0;
- OptRect boundsLocal(OptInterval i) const { return boundsLocal(i, 0); }
-
- virtual std::vector<double> roots(double v, Dim2 d) const = 0;
-
- virtual int winding(Point p) const { return root_winding(*this, p); }
-
- virtual int degreesOfFreedom() const { return 0;}
-
- //mental: review these
- virtual Curve *portion(double f, double t) const = 0;
- virtual Curve *reverse() const { return portion(1, 0); }
- virtual Curve *derivative() const = 0;
-
- virtual void setInitial(Point v) = 0;
- virtual void setFinal(Point v) = 0;
-
- virtual
- double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
- {
- return nearest_point(p, toSBasis(), from, to);
- }
-
- virtual
- std::vector<double>
- allNearestPoints( Point const& p, double from = 0, double to = 1 ) const
- {
- return all_nearest_points(p, toSBasis(), from, to);
- }
-
- /*
- Path operator*=(Matrix)
- This is not possible, because:
- A Curve can be many things, for example a HLineSegment.
- Such a segment cannot be transformed and stay a HLineSegment in general (take for example rotations).
- This means that these curves become a different type of curve, hence one should use "transformed(Matrix).
- */
-
- virtual Curve *transformed(Matrix const &m) const = 0;
-
- virtual Point pointAt(Coord t) const { return pointAndDerivatives(t, 0).front(); }
- virtual Coord valueAt(Coord t, Dim2 d) const { return pointAt(t)[d]; }
- virtual Point operator() (double t) const { return pointAt(t); }
-
- /* pointAndDerivatives returns a vector that looks like the following:
- * [ point at t, 1st derivative at t, 2nd derivative at t, ... , n'th derivative at t] */
- virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const = 0;
-
- /* unitTangentAt returns the unit vector tangent to the curve at position t
- * (in the direction of increasing t). The method uses l'Hopital's rule when the derivative
- * is (0,0), parameter n determines the maximum nr of iterations (for when higher derivatives are also (0,0) ).
- * Point(0,0) is returned if no non-zero derivative could be found.
- * Note that unitTangentAt(1) will probably not give the desired result. Probably one should do:
- * Curve * c_reverse = c.reverse();
- * Point tangent = - c_reverse->unitTangentAt(0);
- * delete c_reverse;
- */
- virtual Point unitTangentAt(Coord t, unsigned n = 3) const
- {
- std::vector<Point> derivs = pointAndDerivatives(t, n);
- for (unsigned deriv_n = 1; deriv_n < derivs.size(); deriv_n++) {
- Coord length = derivs[deriv_n].length();
- if ( ! are_near(length, 0) ) {
- // length of derivative is non-zero, so return unit vector
- return derivs[deriv_n] / length;
- }
+ virtual ~Curve() {}
+
+ /// @name Evaluate the curve
+ /// @{
+ /** @brief Retrieve the start of the curve.
+ * @return The point corresponding to \f$\mathbf{C}(0)\f$. */
+ virtual Point initialPoint() const = 0;
+ /** Retrieve the end of the curve.
+ * @return The point corresponding to \f$\mathbf{C}(1)\f$. */
+ virtual Point finalPoint() const = 0;
+ /** @brief Check whether the curve has exactly zero length.
+ * @return True if the curve's initial point is exactly the same as its final point, and it contains
+ * no other points (its value set contains only one element).
+ */
+ virtual bool isDegenerate() const = 0;
+ /** @brief Evaluate the curve at a specified time value.
+ * @param t Time value
+ * @return \f$\mathbf{C}(t)\f$ */
+ virtual Point pointAt(Coord t) const { return pointAndDerivatives(t, 0).front(); }
+ /** @brief Evaluate one of the coordinates at the specified time value.
+ * @param t Time value
+ * @param d The dimension to evaluate
+ * @return The specified coordinate of \f$\mathbf{C}(t)\f$ */
+ virtual Coord valueAt(Coord t, Dim2 d) const { return pointAt(t)[d]; }
+ /** @brief Evaluate the function at the specified time value. Allows curves to be used
+ * as functors. */
+ virtual Point operator() (Coord t) const { return pointAt(t); }
+ /** @brief Evaluate the curve and its derivatives.
+ * This will return a vector that contains the value of the curve and the specified number
+ * of derivatives. However, the returned vector might contain less elements than specified
+ * if some derivatives do not exist.
+ * @param t Time value
+ * @param n The number of derivatives to compute
+ * @return Vector of at most \f$n+1\f$ elements of the form \f$[\mathbf{C}(t),
+ \mathbf{C}'(t), \mathbf{C}''(t), \ldots]\f$ */
+ virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const = 0;
+ /// @}
+
+ /// @name Change the curve's endpoints
+ /// @{
+ /** @brief Change the starting point of the curve.
+ * After calling this method, it is guaranteed that \f$\mathbf{C}(0) = \mathbf{p}\f$,
+ * and the curve is still continuous. The precise new shape of the curve varies with curve
+ * type.
+ * @param p New starting point of the curve */
+ virtual void setInitial(Point const &v) = 0;
+ /** @brief Change the ending point of the curve.
+ * After calling this method, it is guaranteed that \f$\mathbf{C}(0) = \mathbf{p}\f$,
+ * and the curve is still continuous. The precise new shape of the curve varies
+ * with curve type.
+ * @param p New ending point of the curve */
+ virtual void setFinal(Point const &v) = 0;
+ /// @}
+
+ /// @name Compute the bounding box
+ /// @{
+ /** @brief Quickly compute the curve's approximate bounding box.
+ * The resulting rectangle is guaranteed to contain all points belonging to the curve,
+ * but it might not be the smallest such rectangle. This method is usually fast.
+ * @return A rectangle that contains all points belonging to the curve. */
+ virtual Rect boundsFast() const = 0;
+ /** @brief Compute the curve's exact bounding box.
+ * This method can be dramatically slower than boundsExact() depending on the curve type.
+ * @return The smallest possible rectangle containing all of the curve's points. */
+ virtual Rect boundsExact() const = 0;
+ // I have no idea what the 'deg' parameter is for, so this is undocumented for now.
+ virtual OptRect boundsLocal(OptInterval const &i, unsigned deg) const = 0;
+ /** @brief Compute the bounding box of a part of the curve.
+ * Since this method returns the smallest possible bounding rectangle of the specified portion,
+ * it can also be rather slow.
+ * @param a An interval specifying a part of the curve, or nothing.
+ * If \f$[0, 1] \subseteq a\f$, then the bounding box for the entire curve
+ * is calculated.
+ * @return The smallest possible rectangle containing all points in \f$\mathbf{C}[a]\f$,
+ * or nothing if the supplied interval is empty. */
+ OptRect boundsLocal(OptInterval const &a) const { return boundsLocal(a, 0); }
+ /// @}
+
+ /// @name Create new curves based on this one
+ /// @{
+ /** @brief Create an exact copy of this curve.
+ * @return Pointer to a newly allocated curve, identical to the original */
+ virtual Curve *duplicate() const = 0;
+ /** @brief Create a curve transformed by an affine transformation.
+ * This method returns a new curve instead modifying the existing one, because some curve
+ * types are not closed under affine transformations. The returned curve may be of different
+ * underlying type (as is the case for horizontal and vertical line segments).
+ * @param m Affine describing the affine transformation
+ * @return Pointer to a new, transformed curve */
+ virtual Curve *transformed(Affine const &m) const = 0;
+ /** @brief Create a curve that corresponds to a part of this curve.
+ * For \f$a > b\f$, the returned portion will be reversed with respect to the original.
+ * The returned curve will always be of the same type.
+ * @param a Beginning of the interval specifying the portion of the curve
+ * @param b End of the interval
+ * @return New curve \f$\mathbf{D}\f$ such that:
+ * - \f$\mathbf{D}(0) = \mathbf{C}(a)\f$
+ * - \f$\mathbf{D}(1) = \mathbf{C}(b)\f$
+ * - \f$\mathbf{D}[ [0, 1] ] = \mathbf{C}[ [a?b] ]\f$,
+ * where \f$[a?b] = [\min(a, b), \max(a, b)]\f$ */
+ virtual Curve *portion(Coord a, Coord b) const = 0;
+ /** @brief A version of that accepts an Interval. */
+ Curve *portion(Interval const &i) const { return portion(i.min(), i.max()); }
+ /** @brief Create a reversed version of this curve.
+ * The result corresponds to <code>portion(1, 0)</code>, but this method might be faster.
+ * @return Pointer to a new curve \f$\mathbf{D}\f$ such that
+ * \f$\forall_{x \in [0, 1]} \mathbf{D}(x) = \mathbf{C}(1-x)\f$ */
+ virtual Curve *reverse() const { return portion(1, 0); }
+ /** @brief Create a derivative of this curve.
+ * It's best to think of the derivative in physical terms: if the curve describes
+ * the position of some object on the plane from time \f$t=0\f$ to \f$t=1\f$ as said in the
+ * introduction, then the curve's derivative describes that object's speed at the same times.
+ * The second derivative refers to its acceleration, the third to jerk, etc.
+ * @return New curve \f$\mathbf{D} = \mathbf{C}'\f$. */
+ virtual Curve *derivative() const = 0;
+ /// @}
+
+ /// @name Advanced operations
+ /// @{
+ /** @brief Compute a time value at which the curve comes closest to a specified point.
+ * The first value with the smallest distance is returned if there are multiple such points.
+ * @param p Query point
+ * @param a Minimum time value to consider
+ * @param b Maximum time value to consider; \f$a < b\f$
+ * @return \f$q \in [a, b]: ||\mathbf{C}(q) - \mathbf{p}|| =
+ \inf(\{r \in \mathbb{R} : ||\mathbf{C}(r) - \mathbf{p}||\})\f$ */
+ virtual Coord nearestPoint( Point const& p, Coord a = 0, Coord b = 1 ) const;
+ /** @brief A version that takes an Interval. */
+ Coord nearestPoint(Point const &p, Interval const &i) const {
+ return nearestPoint(p, i.min(), i.max());
}
- return Point (0,0);
- };
-
- virtual D2<SBasis> toSBasis() const = 0;
- virtual bool operator==(Curve const &c) const { return this == &c;}
+ /** @brief Compute time values at which the curve comes closest to a specified point.
+ * @param p Query point
+ * @param a Minimum time value to consider
+ * @param b Maximum time value to consider; \f$a < b\f$
+ * @return Vector of points closest and equally far away from the query point */
+ virtual std::vector<Coord> allNearestPoints( Point const& p, Coord from = 0,
+ Coord to = 1 ) const;
+ /** @brief A version that takes an Interval. */
+ std::vector<Coord> allNearestPoints(Point const &p, Interval const &i) {
+ return allNearestPoints(p, i.min(), i.max());
+ }
+ /** @brief Compute the arc length of this curve.
+ * For a curve \f$\mathbf{C}(t) = (C_x(t), C_y(t))\f$, arc length is defined for 2D curves as
+ * \f[ \ell = \int_{0}^{1} \sqrt { [C_x'(t)]^2 + [C_y'(t)]^2 }\, \text{d}t \f]
+ * In other words, we divide the curve into infinitely small linear segments
+ * and add together their lengths. Of course we can't subdivide the curve into
+ * infinitely many segments on a computer, so this method returns an approximation.
+ * Not that there is usually no closed form solution to such integrals, so this
+ * method might be slow.
+ * @param tolerance Maximum allowed error
+ * @return Total distance the curve's value travels on the plane when going from 0 to 1 */
+ virtual Coord length(Coord tolerance=0.01) const;
+ /** @brief Computes time values at which the curve intersects an axis-aligned line.
+ * @param v The coordinate of the line
+ * @param d Which axis the coordinate is on. X means a vertical line, Y a horizontal line. */
+ virtual std::vector<Coord> roots(Coord v, Dim2 d) const = 0;
+ /** @brief Compute the winding number of the curve at the specified point.
+ * @todo Does this makes sense for curves at all? */
+ virtual int winding(Point const &p) const { return root_winding(*this, p); }
+ /** @brief Compute a vector tangent to the curve.
+ * This will return an unit vector (a Point with length() equal to 1) that denotes a vector
+ * tangent to the curve. This vector is defined as
+ * \f$ \mathbf{v}(t) = \frac{\mathbf{C}'(t)}{||\mathbf{C}'(t)||} \f$. It is pointed
+ * in the direction of increasing \f$t\f$, at the specfied time value. The method uses
+ * l'Hopital's rule when the derivative is zero. A zero vector is returned if no non-zero
+ * derivative could be found.
+ * @param t Time value
+ * @param n The maximum order of derivative to consider
+ * @return Unit tangent vector \f$\mathbf{v}(t)\f$
+ * @bug This method might currently break for the case of t being exactly 1. A workaround
+ * is to reverse the curve and use the negated unit tangent at 0 like this:
+ * @code
+ Curve *c_reverse = c.reverse();
+ Point tangent = - c_reverse->unitTangentAt(0);
+ delete c_reverse; @endcode */
+ virtual Point unitTangentAt(Coord t, unsigned n = 3) const;
+ /** @brief Convert the curve to a symmetric power basis polynomial.
+ * Symmetric power basis polynomials (S-basis for short) are numerical representations
+ * of curves with excellent numerical properties. Most high level operations provided by 2Geom
+ * are implemented in terms of S-basis operations, so every curve has to provide a method
+ * to convert it to an S-basis polynomial on two variables. See SBasis class reference
+ * for more information. */
+ virtual D2<SBasis> toSBasis() const = 0;
+ /// @}
+
+ /// @name Miscellaneous
+ /// @{
+ /** Return the number of independent parameters required to represent all variations
+ * of this curve. For example, for Bezier curves it returns the curve's order
+ * multiplied by 2. */
+ virtual int degreesOfFreedom() const { return 0;}
+ /** @brief Test equality of two curves.
+ * @return True if the curves are identical, false otherwise */
+ virtual bool operator==(Curve const &c) const { return this == &c;}
+ /// @}
};
inline
-Coord nearest_point(Point const& p, Curve const& c)
-{
- return c.nearestPoint(p);
+Coord nearest_point(Point const& p, Curve const& c) {
+ return c.nearestPoint(p);
}
} // end namespace Geom
@@ -161,8 +287,6 @@ Coord nearest_point(Point const& p, Curve const& c)
#endif // _2GEOM_CURVE_H_
-
-
/*
Local Variables:
mode:c++
diff --git a/src/2geom/curves.h b/src/2geom/curves.h
index 6c8435387..64cf3d4fb 100644
--- a/src/2geom/curves.h
+++ b/src/2geom/curves.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief this file is only a helper header to include all curve types at once
- *
+ * \brief Include all curve types
+ *//*
* Authors:
* MenTaLguY <mental@rydia.net>
* Marco Cecchetti <mrcekets at gmail.com>
@@ -32,9 +32,6 @@
* the specific language governing rights and limitations.
*/
-
-
-
#ifndef _2GEOM_CURVES_H_
#define _2GEOM_CURVES_H_
@@ -43,15 +40,11 @@
#include <2geom/sbasis-curve.h>
#include <2geom/bezier-curve.h>
#include <2geom/hvlinesegment.h>
-//#include <2geom/elliptical-arc.h>
+#include <2geom/elliptical-arc.h>
#include <2geom/svg-elliptical-arc.h>
-
#endif // _2GEOM_CURVES_H_
-
-
-
/*
Local Variables:
mode:c++
diff --git a/src/2geom/d2-sbasis.cpp b/src/2geom/d2-sbasis.cpp
index 4f5a53cd2..697a9d84e 100644
--- a/src/2geom/d2-sbasis.cpp
+++ b/src/2geom/d2-sbasis.cpp
@@ -121,7 +121,7 @@ Piecewise<SBasis> cross(Piecewise<D2<SBasis> > const &a,
return result;
}
-Piecewise<D2<SBasis> > operator*(Piecewise<D2<SBasis> > const &a, Matrix const &m) {
+Piecewise<D2<SBasis> > operator*(Piecewise<D2<SBasis> > const &a, Affine const &m) {
Piecewise<D2<SBasis> > result;
if(a.empty()) return result;
result.push_cut(a.cuts[0]);
@@ -259,6 +259,57 @@ std::vector<Piecewise<D2<SBasis> > > fuse_nearby_ends(std::vector<Piecewise<D2<S
return f;
}
+/*
+ * Computes the intersection of two sets given as (ordered) union of intervals.
+ */
+static std::vector<Interval> intersect( std::vector<Interval> const &a, std::vector<Interval> const &b){
+ std::vector<Interval> result;
+ //TODO: use order!
+ for (unsigned i=0; i < a.size(); i++){
+ for (unsigned j=0; j < b.size(); j++){
+ OptInterval c( a[i] );
+ c &= b[j];
+ if ( c ) {
+ result.push_back( *c );
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<Interval> level_set( D2<SBasis> const &f, Rect region){
+ std::vector<Rect> regions( 1, region );
+ return level_sets( f, regions ).front();
+}
+std::vector<Interval> level_set( D2<SBasis> const &f, Point p, double tol){
+ Rect region(p, p);
+ region.expandBy( tol );
+ return level_set( f, region );
+}
+std::vector<std::vector<Interval> > level_sets( D2<SBasis> const &f, std::vector<Rect> regions){
+ std::vector<Interval> regsX (regions.size(), Interval() );
+ std::vector<Interval> regsY (regions.size(), Interval() );
+ for ( unsigned i=0; i < regions.size(); i++ ){
+ regsX[i] = regions[i][X];
+ regsY[i] = regions[i][Y];
+ }
+ std::vector<std::vector<Interval> > x_in_regs = level_sets( f[X], regsX );
+ std::vector<std::vector<Interval> > y_in_regs = level_sets( f[Y], regsY );
+ std::vector<std::vector<Interval> >result(regions.size(), std::vector<Interval>() );
+ for (unsigned i=0; i<regions.size(); i++){
+ result[i] = intersect ( x_in_regs[i], y_in_regs[i] );
+ }
+ return result;
+}
+std::vector<std::vector<Interval> > level_sets( D2<SBasis> const &f, std::vector<Point> pts, double tol){
+ std::vector<Rect> regions( pts.size(), Rect() );
+ for (unsigned i=0; i<pts.size(); i++){
+ regions[i] = Rect( pts[i], pts[i] );
+ regions[i].expandBy( tol );
+ }
+ return level_sets( f, regions );
+}
+
} // namespace Geom
diff --git a/src/2geom/d2-sbasis.h b/src/2geom/d2-sbasis.h
index 2b087bda6..bd6c35805 100644
--- a/src/2geom/d2-sbasis.h
+++ b/src/2geom/d2-sbasis.h
@@ -45,7 +45,7 @@
#include <2geom/sbasis.h>
#include <2geom/sbasis-2d.h>
#include <2geom/piecewise.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
//TODO: implement intersect
@@ -76,7 +76,7 @@ Piecewise<SBasis> dot(Piecewise<D2<SBasis> > const &a, Piecewise<D2<SBasis> > co
Piecewise<SBasis> dot(Piecewise<D2<SBasis> > const &a, Point const &b);
Piecewise<SBasis> cross(Piecewise<D2<SBasis> > const &a, Piecewise<D2<SBasis> > const &b);
-Piecewise<D2<SBasis> > operator*(Piecewise<D2<SBasis> > const &a, Matrix const &m);
+Piecewise<D2<SBasis> > operator*(Piecewise<D2<SBasis> > const &a, Affine const &m);
Piecewise<D2<SBasis> > force_continuity(Piecewise<D2<SBasis> > const &f, double tol=0, bool closed=false);
@@ -138,6 +138,11 @@ inline OptRect bounds_local(D2<SBasis> const & s, OptInterval i, unsigned order=
return retval;
}
+std::vector<Interval> level_set( D2<SBasis> const &f, Rect region);
+std::vector<Interval> level_set( D2<SBasis> const &f, Point p, double tol);
+std::vector<std::vector<Interval> > level_sets( D2<SBasis> const &f, std::vector<Rect> regions);
+std::vector<std::vector<Interval> > level_sets( D2<SBasis> const &f, std::vector<Point> pts, double tol);
+
}
#endif
diff --git a/src/2geom/d2.h b/src/2geom/d2.h
index bdf042806..3e4de430e 100644
--- a/src/2geom/d2.h
+++ b/src/2geom/d2.h
@@ -34,7 +34,7 @@
#include <2geom/point.h>
#include <2geom/interval.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <boost/concept_check.hpp>
#include <2geom/concepts.h>
@@ -251,7 +251,7 @@ template <typename T>
inline D2<T> operator/=(D2<T> & a, double b) { a[0] /= b; a[1] /= b; return a; }
template<typename T>
-D2<T> operator*(D2<T> const &v, Matrix const &m) {
+D2<T> operator*(D2<T> const &v, Affine const &m) {
boost::function_requires<AddableConcept<T> >();
boost::function_requires<ScalableConcept<T> >();
D2<T> ret;
diff --git a/src/2geom/ellipse.cpp b/src/2geom/ellipse.cpp
index 8030ea517..bea99e5dd 100644
--- a/src/2geom/ellipse.cpp
+++ b/src/2geom/ellipse.cpp
@@ -170,7 +170,7 @@ void Ellipse::set(std::vector<Point> const& points)
}
-SVGEllipticalArc
+EllipticalArc *
Ellipse::arc(Point const& initial, Point const& inner, Point const& final,
bool _svg_compliant)
{
@@ -212,21 +212,27 @@ Ellipse::arc(Point const& initial, Point const& inner, Point const& final,
}
}
- SVGEllipticalArc ea( initial, ray(X), ray(Y), rot_angle(),
- large_arc_flag, sweep_flag, final, _svg_compliant);
- return ea;
+ EllipticalArc *ret_arc;
+ if (_svg_compliant) {
+ ret_arc = new SVGEllipticalArc(initial, ray(X), ray(Y), rot_angle(),
+ large_arc_flag, sweep_flag, final);
+ } else {
+ ret_arc = new EllipticalArc(initial, ray(X), ray(Y), rot_angle(),
+ large_arc_flag, sweep_flag, final);
+ }
+ return ret_arc;
}
-Ellipse Ellipse::transformed(Matrix const& m) const
+Ellipse Ellipse::transformed(Affine const& m) const
{
double cosrot = std::cos(rot_angle());
double sinrot = std::sin(rot_angle());
- Matrix A( ray(X) * cosrot, ray(X) * sinrot,
+ Affine A( ray(X) * cosrot, ray(X) * sinrot,
-ray(Y) * sinrot, ray(Y) * cosrot,
0, 0 );
Point new_center = center() * m;
- Matrix M = m.without_translation();
- Matrix AM = A * M;
+ Affine M = m.withoutTranslation();
+ Affine AM = A * M;
if ( are_near(AM.det(), 0) )
{
double angle;
@@ -250,11 +256,11 @@ Ellipse Ellipse::transformed(Matrix const& m) const
}
std::vector<double> coeff = implicit_form_coefficients();
- Matrix Q( coeff[0], coeff[1]/2,
+ Affine Q( coeff[0], coeff[1]/2,
coeff[1]/2, coeff[2],
0, 0 );
- Matrix invm = M.inverse();
+ Affine invm = M.inverse();
Q = invm * Q ;
std::swap( invm[1], invm[2] );
Q *= invm;
diff --git a/src/2geom/ellipse.h b/src/2geom/ellipse.h
index 8e44f3395..297254366 100644
--- a/src/2geom/ellipse.h
+++ b/src/2geom/ellipse.h
@@ -35,15 +35,15 @@
#ifndef _2GEOM_ELLIPSE_H_
#define _2GEOM_ELLIPSE_H_
-
+#include <vector>
#include <2geom/point.h>
#include <2geom/exception.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
namespace Geom
{
-class SVGEllipticalArc;
+class EllipticalArc;
class Circle;
class Ellipse
@@ -88,9 +88,8 @@ class Ellipse
// prerequisite: at least 5 points must be passed
void set(std::vector<Point> const& points);
- SVGEllipticalArc
- arc(Point const& initial, Point const& inner, Point const& final,
- bool _svg_compliant = true);
+ EllipticalArc *
+ arc(Point const& initial, Point const& inner, Point const& final, bool svg_compliant = true);
Point center() const
{
@@ -114,7 +113,7 @@ class Ellipse
std::vector<double> implicit_form_coefficients() const;
- Ellipse transformed(Matrix const& m) const;
+ Ellipse transformed(Affine const& m) const;
private:
Point m_centre, m_ray;
diff --git a/src/2geom/elliptical-arc.cpp b/src/2geom/elliptical-arc.cpp
index fd0e7cf9b..acaad82cf 100644
--- a/src/2geom/elliptical-arc.cpp
+++ b/src/2geom/elliptical-arc.cpp
@@ -1,7 +1,10 @@
/*
* SVG Elliptical Arc Class
*
- * Copyright 2008 Marco Cecchetti <mrcekets at gmail.com>
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Copyright 2008-2009 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -27,896 +30,881 @@
* the specific language governing rights and limitations.
*/
+#include <cfloat>
+#include <limits>
+#include <memory>
#include <2geom/elliptical-arc.h>
+#include <2geom/ellipse.h>
+#include <2geom/sbasis-geometric.h>
#include <2geom/bezier-curve.h>
#include <2geom/poly.h>
-#include <2geom/sbasis-math.h>
-
-#include <cfloat>
-#include <limits>
-
+#include <2geom/transforms.h>
+#include <2geom/utils.h>
+#include <2geom/numeric/vector.h>
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
namespace Geom
{
+/**
+ * @class EllipticalArc
+ * @brief Elliptical arc curve
+ *
+ * Elliptical arc is a curve taking the shape of a section of an ellipse.
+ *
+ * The arc function has two forms: the regular one, mapping the unit interval to points
+ * on 2D plane (the linear domain), and a second form that maps some interval
+ * \f$A \subseteq [0,2\pi)\f$ to the same points (the angular domain). The interval \f$A\f$
+ * determines which part of the ellipse forms the arc. The arc is said to contain an angle
+ * if its angular domain includes that angle (and therefore it is defined for that angle).
+ *
+ * The angular domain considers each ellipse to be
+ * a rotated, scaled and translated unit circle: 0 corresponds to \f$(1,0)\f$ on the unit circle,
+ * \f$\pi/2\f$ corresponds to \f$(0,1)\f$, \f$\pi\f$ to \f$(-1,0)\f$ and \f$3\pi/2\f$
+ * to \f$(0,-1)\f$. After the angle is mapped to a point from a unit circle, the point is
+ * transformed using a matrix of this form
+ * \f[ M = \left[ \begin{array}{ccc}
+ r_X \cos(\theta) & -r_Y \sin(\theta) & 0 \\
+ r_X \sin(\theta) & r_Y \cos(\theta) & 0 \\
+ c_X & c_Y & 1 \end{array} \right] \f]
+ * where \f$r_X, r_Y\f$ are the X and Y rays of the ellipse, \f$\theta\f$ is its angle of rotation,
+ * and \f$c_X, c_Y\f$ the coordinates of the ellipse's center - thus mapping the angle
+ * to some point on the ellipse. Note that for example the point at angluar coordinate 0,
+ * the center and the point at angular coordinate \f$\pi/4\f$ do not necessarily
+ * create an angle of \f$\pi/4\f$ radians; it is only the case if both axes of the ellipse
+ * are of the same length (i.e. it is a circle).
+ *
+ * @image html ellipse-angular-coordinates.png "An illustration of the angular domain"
+ *
+ * Each arc is defined by five variables: The initial and final point, the ellipse's rays,
+ * and the ellipse's rotation. Each set of those parameters corresponds to four different arcs,
+ * with two of them larger than half an ellipse and two of them turning clockwise while traveling
+ * from initial to final point. The two flags disambiguate between them: "large arc flag" selects
+ * the bigger arc, while the "sweep flag" selects the clockwise arc.
+ *
+ * @image html elliptical-arc-flags.png "The four possible arcs and the meaning of flags"
+ *
+ * @ingroup Curves
+ */
-OptRect EllipticalArc::boundsExact() const
+Rect EllipticalArc::boundsExact() const
{
- std::vector<double> extremes(4);
- double cosrot = std::cos(rotation_angle());
- double sinrot = std::sin(rotation_angle());
- extremes[0] = std::atan2( -ray(Y) * sinrot, ray(X) * cosrot );
- extremes[1] = extremes[0] + M_PI;
- if ( extremes[0] < 0 ) extremes[0] += 2*M_PI;
- extremes[2] = std::atan2( ray(Y) * cosrot, ray(X) * sinrot );
- extremes[3] = extremes[2] + M_PI;
- if ( extremes[2] < 0 ) extremes[2] += 2*M_PI;
-
-
- std::vector<double>arc_extremes(4);
- arc_extremes[0] = initialPoint()[X];
- arc_extremes[1] = finalPoint()[X];
- if ( arc_extremes[0] < arc_extremes[1] )
- std::swap(arc_extremes[0], arc_extremes[1]);
- arc_extremes[2] = initialPoint()[Y];
- arc_extremes[3] = finalPoint()[Y];
- if ( arc_extremes[2] < arc_extremes[3] )
- std::swap(arc_extremes[2], arc_extremes[3]);
-
-
- if ( start_angle() < end_angle() )
- {
- if ( sweep_flag() )
- {
- for ( unsigned int i = 0; i < extremes.size(); ++i )
- {
- if ( start_angle() < extremes[i] && extremes[i] < end_angle() )
- {
- arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1];
- }
- }
- }
- else
- {
- for ( unsigned int i = 0; i < extremes.size(); ++i )
- {
- if ( start_angle() > extremes[i] || extremes[i] > end_angle() )
- {
- arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1];
- }
- }
- }
- }
- else
- {
- if ( sweep_flag() )
- {
- for ( unsigned int i = 0; i < extremes.size(); ++i )
- {
- if ( start_angle() < extremes[i] || extremes[i] < end_angle() )
- {
- arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1];
- }
- }
- }
- else
- {
- for ( unsigned int i = 0; i < extremes.size(); ++i )
- {
- if ( start_angle() > extremes[i] && extremes[i] > end_angle() )
- {
- arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1];
- }
- }
- }
- }
-
- return Rect( Point(arc_extremes[1], arc_extremes[3]) ,
- Point(arc_extremes[0], arc_extremes[2]) );
+ double extremes[4];
+ double sinrot, cosrot;
+ sincos(_rot_angle, sinrot, cosrot);
+
+ extremes[0] = std::atan2( -ray(Y) * sinrot, ray(X) * cosrot );
+ extremes[1] = extremes[0] + M_PI;
+ if ( extremes[0] < 0 ) extremes[0] += 2*M_PI;
+ extremes[2] = std::atan2( ray(Y) * cosrot, ray(X) * sinrot );
+ extremes[3] = extremes[2] + M_PI;
+ if ( extremes[2] < 0 ) extremes[2] += 2*M_PI;
+
+
+ double arc_extremes[4];
+ arc_extremes[0] = initialPoint()[X];
+ arc_extremes[1] = finalPoint()[X];
+ if ( arc_extremes[0] < arc_extremes[1] )
+ std::swap(arc_extremes[0], arc_extremes[1]);
+ arc_extremes[2] = initialPoint()[Y];
+ arc_extremes[3] = finalPoint()[Y];
+ if ( arc_extremes[2] < arc_extremes[3] )
+ std::swap(arc_extremes[2], arc_extremes[3]);
+
+ for (unsigned i = 0; i < 4; ++i) {
+ if (containsAngle(extremes[i])) {
+ arc_extremes[i] = valueAtAngle(extremes[i], i >> 1 ? Y : X);
+ }
+ }
+ return Rect( Point(arc_extremes[1], arc_extremes[3]) ,
+ Point(arc_extremes[0], arc_extremes[2]) );
}
-std::vector<double>
-EllipticalArc::roots(double v, Dim2 d) const
+Point EllipticalArc::pointAtAngle(Coord t) const
{
- if ( d > Y )
- {
- THROW_RANGEERROR("dimention out of range");
- }
-
- std::vector<double> sol;
- if ( are_near(ray(X), 0) && are_near(ray(Y), 0) )
- {
- if ( center(d) == v )
- sol.push_back(0);
- return sol;
- }
-
- const char* msg[2][2] =
- {
- { "d == X; ray(X) == 0; "
- "s = (v - center(X)) / ( -ray(Y) * std::sin(rotation_angle()) ); "
- "s should be contained in [-1,1]",
- "d == X; ray(Y) == 0; "
- "s = (v - center(X)) / ( ray(X) * std::cos(rotation_angle()) ); "
- "s should be contained in [-1,1]"
- },
- { "d == Y; ray(X) == 0; "
- "s = (v - center(X)) / ( ray(Y) * std::cos(rotation_angle()) ); "
- "s should be contained in [-1,1]",
- "d == Y; ray(Y) == 0; "
- "s = (v - center(X)) / ( ray(X) * std::sin(rotation_angle()) ); "
- "s should be contained in [-1,1]"
- },
- };
-
- for ( unsigned int dim = 0; dim < 2; ++dim )
- {
- if ( are_near(ray(dim), 0) )
- {
-
- if ( initialPoint()[d] == v && finalPoint()[d] == v )
- {
- THROW_INFINITESOLUTIONS(0);
- }
- if ( (initialPoint()[d] < finalPoint()[d])
- && (initialPoint()[d] > v || finalPoint()[d] < v) )
- {
- return sol;
- }
- if ( (initialPoint()[d] > finalPoint()[d])
- && (finalPoint()[d] > v || initialPoint()[d] < v) )
- {
- return sol;
- }
- double ray_prj;
- switch(d)
- {
- case X:
- switch(dim)
- {
- case X: ray_prj = -ray(Y) * std::sin(rotation_angle());
- break;
- case Y: ray_prj = ray(X) * std::cos(rotation_angle());
- break;
- }
- break;
- case Y:
- switch(dim)
- {
- case X: ray_prj = ray(Y) * std::cos(rotation_angle());
- break;
- case Y: ray_prj = ray(X) * std::sin(rotation_angle());
- break;
- }
- break;
- }
-
- double s = (v - center(d)) / ray_prj;
- if ( s < -1 || s > 1 )
- {
- THROW_LOGICALERROR(msg[d][dim]);
- }
- switch(dim)
- {
- case X:
- s = std::asin(s); // return a value in [-PI/2,PI/2]
- if ( logical_xor( sweep_flag(), are_near(start_angle(), M_PI/2) ) )
- {
- if ( s < 0 ) s += 2*M_PI;
- }
- else
- {
- s = M_PI - s;
- if (!(s < 2*M_PI) ) s -= 2*M_PI;
- }
- break;
- case Y:
- s = std::acos(s); // return a value in [0,PI]
- if ( logical_xor( sweep_flag(), are_near(start_angle(), 0) ) )
- {
- s = 2*M_PI - s;
- if ( !(s < 2*M_PI) ) s -= 2*M_PI;
- }
- break;
- }
-
- //std::cerr << "s = " << rad_to_deg(s);
- s = map_to_01(s);
- //std::cerr << " -> t: " << s << std::endl;
- if ( !(s < 0 || s > 1) )
- sol.push_back(s);
- return sol;
- }
- }
-
- double rotx, roty;
- switch(d)
- {
- case X:
- rotx = std::cos(rotation_angle());
- roty = -std::sin(rotation_angle());
- break;
- case Y:
- rotx = std::sin(rotation_angle());
- roty = std::cos(rotation_angle());
- break;
- }
- double rxrotx = ray(X) * rotx;
- double c_v = center(d) - v;
-
- double a = -rxrotx + c_v;
- double b = ray(Y) * roty;
- double c = rxrotx + c_v;
- //std::cerr << "a = " << a << std::endl;
- //std::cerr << "b = " << b << std::endl;
- //std::cerr << "c = " << c << std::endl;
-
- if ( are_near(a,0) )
- {
- sol.push_back(M_PI);
- if ( !are_near(b,0) )
- {
- double s = 2 * std::atan(-c/(2*b));
- if ( s < 0 ) s += 2*M_PI;
- sol.push_back(s);
- }
- }
- else
- {
- double delta = b * b - a * c;
- //std::cerr << "delta = " << delta << std::endl;
- if ( are_near(delta, 0) )
- {
- double s = 2 * std::atan(-b/a);
- if ( s < 0 ) s += 2*M_PI;
- sol.push_back(s);
- }
- else if ( delta > 0 )
- {
- double sq = std::sqrt(delta);
- double s = 2 * std::atan( (-b - sq) / a );
- if ( s < 0 ) s += 2*M_PI;
- sol.push_back(s);
- s = 2 * std::atan( (-b + sq) / a );
- if ( s < 0 ) s += 2*M_PI;
- sol.push_back(s);
- }
- }
-
- std::vector<double> arc_sol;
- for (unsigned int i = 0; i < sol.size(); ++i )
- {
- //std::cerr << "s = " << rad_to_deg(sol[i]);
- sol[i] = map_to_01(sol[i]);
- //std::cerr << " -> t: " << sol[i] << std::endl;
- if ( !(sol[i] < 0 || sol[i] > 1) )
- arc_sol.push_back(sol[i]);
- }
- return arc_sol;
-
-
-// return SBasisCurve(toSBasis()).roots(v, d);
+ Point ret = Point::polar(t) * unitCircleTransform();
+ return ret;
}
-// D(E(t,C),t) = E(t+PI/2,O)
-Curve* EllipticalArc::derivative() const
+Coord EllipticalArc::valueAtAngle(Coord t, Dim2 d) const
{
- EllipticalArc* result = new EllipticalArc(*this);
- result->m_center[X] = result->m_center[Y] = 0;
- result->m_start_angle += M_PI/2;
- if( !( result->m_start_angle < 2*M_PI ) )
- {
- result->m_start_angle -= 2*M_PI;
- }
- result->m_end_angle += M_PI/2;
- if( !( result->m_end_angle < 2*M_PI ) )
- {
- result->m_end_angle -= 2*M_PI;
- }
- result->m_initial_point = result->pointAtAngle( result->start_angle() );
- result->m_final_point = result->pointAtAngle( result->end_angle() );
- return result;
+ Coord sinrot, cosrot, cost, sint;
+ sincos(_rot_angle, sinrot, cosrot);
+ sincos(t, sint, cost);
+ if ( d == X ) {
+ return ray(X) * cosrot * cost
+ - ray(Y) * sinrot * sint
+ + center(X);
+ } else {
+ return ray(X) * sinrot * cost
+ + ray(Y) * cosrot * sint
+ + center(Y);
+ }
}
-std::vector<Point>
-EllipticalArc::pointAndDerivatives(Coord t, unsigned int n) const
+Affine EllipticalArc::unitCircleTransform() const
{
- unsigned int nn = n+1; // nn represents the size of the result vector.
- std::vector<Point> result;
- result.reserve(nn);
- double angle = map_unit_interval_on_circular_arc(t, start_angle(),
- end_angle(), sweep_flag());
- EllipticalArc ea(*this);
- ea.m_center = Point(0,0);
- unsigned int m = std::min(nn, 4u);
- for ( unsigned int i = 0; i < m; ++i )
- {
- result.push_back( ea.pointAtAngle(angle) );
- angle += M_PI/2;
- if ( !(angle < 2*M_PI) ) angle -= 2*M_PI;
- }
- m = nn / 4;
- for ( unsigned int i = 1; i < m; ++i )
- {
- for ( unsigned int j = 0; j < 4; ++j )
- result.push_back( result[j] );
- }
- m = nn - 4 * m;
- for ( unsigned int i = 0; i < m; ++i )
- {
- result.push_back( result[i] );
- }
- if ( !result.empty() ) // nn != 0
- result[0] = pointAtAngle(angle);
- return result;
+ Affine ret = Scale(ray(X), ray(Y)) * Rotate(_rot_angle);
+ ret.setTranslation(center());
+ return ret;
}
-D2<SBasis> EllipticalArc::toSBasis() const
+std::vector<Coord> EllipticalArc::roots(Coord v, Dim2 d) const
{
- // the interval of parametrization has to be [0,1]
- Coord et = start_angle() + ( sweep_flag() ? sweep_angle() : -sweep_angle() );
- Linear param(start_angle(), et);
- Coord cos_rot_angle = std::cos(rotation_angle());
- Coord sin_rot_angle = std::sin(rotation_angle());
- // order = 4 seems to be enough to get a perfect looking elliptical arc
- // should it be choosen in function of the arc length anyway ?
- // or maybe a user settable parameter: toSBasis(unsigned int order) ?
- SBasis arc_x = ray(X) * cos(param,4);
- SBasis arc_y = ray(Y) * sin(param,4);
- D2<SBasis> arc;
- arc[0] = arc_x * cos_rot_angle - arc_y * sin_rot_angle + Linear(center(X),center(X));
- arc[1] = arc_x * sin_rot_angle + arc_y * cos_rot_angle + Linear(center(Y),center(Y));
- return arc;
+ std::vector<Coord> sol;
+
+ if ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) {
+ if ( center(d) == v )
+ sol.push_back(0);
+ return sol;
+ }
+
+ static const char* msg[2][2] =
+ {
+ { "d == X; ray(X) == 0; "
+ "s = (v - center(X)) / ( -ray(Y) * std::sin(_rot_angle) ); "
+ "s should be contained in [-1,1]",
+ "d == X; ray(Y) == 0; "
+ "s = (v - center(X)) / ( ray(X) * std::cos(_rot_angle) ); "
+ "s should be contained in [-1,1]"
+ },
+ { "d == Y; ray(X) == 0; "
+ "s = (v - center(X)) / ( ray(Y) * std::cos(_rot_angle) ); "
+ "s should be contained in [-1,1]",
+ "d == Y; ray(Y) == 0; "
+ "s = (v - center(X)) / ( ray(X) * std::sin(_rot_angle) ); "
+ "s should be contained in [-1,1]"
+ },
+ };
+
+ for ( unsigned int dim = 0; dim < 2; ++dim )
+ {
+ if ( are_near(ray((Dim2) dim), 0) )
+ {
+ if ( initialPoint()[d] == v && finalPoint()[d] == v )
+ {
+ THROW_INFINITESOLUTIONS(0);
+ }
+ if ( (initialPoint()[d] < finalPoint()[d])
+ && (initialPoint()[d] > v || finalPoint()[d] < v) )
+ {
+ return sol;
+ }
+ if ( (initialPoint()[d] > finalPoint()[d])
+ && (finalPoint()[d] > v || initialPoint()[d] < v) )
+ {
+ return sol;
+ }
+ double ray_prj;
+ switch(d)
+ {
+ case X:
+ switch(dim)
+ {
+ case X: ray_prj = -ray(Y) * std::sin(_rot_angle);
+ break;
+ case Y: ray_prj = ray(X) * std::cos(_rot_angle);
+ break;
+ }
+ break;
+ case Y:
+ switch(dim)
+ {
+ case X: ray_prj = ray(Y) * std::cos(_rot_angle);
+ break;
+ case Y: ray_prj = ray(X) * std::sin(_rot_angle);
+ break;
+ }
+ break;
+ }
+
+ double s = (v - center(d)) / ray_prj;
+ if ( s < -1 || s > 1 )
+ {
+ THROW_LOGICALERROR(msg[d][dim]);
+ }
+ switch(dim)
+ {
+ case X:
+ s = std::asin(s); // return a value in [-PI/2,PI/2]
+ if ( logical_xor( _sweep, are_near(initialAngle(), M_PI/2) ) )
+ {
+ if ( s < 0 ) s += 2*M_PI;
+ }
+ else
+ {
+ s = M_PI - s;
+ if (!(s < 2*M_PI) ) s -= 2*M_PI;
+ }
+ break;
+ case Y:
+ s = std::acos(s); // return a value in [0,PI]
+ if ( logical_xor( _sweep, are_near(initialAngle(), 0) ) )
+ {
+ s = 2*M_PI - s;
+ if ( !(s < 2*M_PI) ) s -= 2*M_PI;
+ }
+ break;
+ }
+
+ //std::cerr << "s = " << rad_to_deg(s);
+ s = map_to_01(s);
+ //std::cerr << " -> t: " << s << std::endl;
+ if ( !(s < 0 || s > 1) )
+ sol.push_back(s);
+ return sol;
+ }
+ }
+
+ double rotx, roty;
+ sincos(_rot_angle, roty, rotx);
+ if (d == X) roty = -roty;
+
+ double rxrotx = ray(X) * rotx;
+ double c_v = center(d) - v;
+
+ double a = -rxrotx + c_v;
+ double b = ray(Y) * roty;
+ double c = rxrotx + c_v;
+ //std::cerr << "a = " << a << std::endl;
+ //std::cerr << "b = " << b << std::endl;
+ //std::cerr << "c = " << c << std::endl;
+
+ if ( are_near(a,0) )
+ {
+ sol.push_back(M_PI);
+ if ( !are_near(b,0) )
+ {
+ double s = 2 * std::atan(-c/(2*b));
+ if ( s < 0 ) s += 2*M_PI;
+ sol.push_back(s);
+ }
+ }
+ else
+ {
+ double delta = b * b - a * c;
+ //std::cerr << "delta = " << delta << std::endl;
+ if ( are_near(delta, 0) )
+ {
+ double s = 2 * std::atan(-b/a);
+ if ( s < 0 ) s += 2*M_PI;
+ sol.push_back(s);
+ }
+ else if ( delta > 0 )
+ {
+ double sq = std::sqrt(delta);
+ double s = 2 * std::atan( (-b - sq) / a );
+ if ( s < 0 ) s += 2*M_PI;
+ sol.push_back(s);
+ s = 2 * std::atan( (-b + sq) / a );
+ if ( s < 0 ) s += 2*M_PI;
+ sol.push_back(s);
+ }
+ }
+
+ std::vector<double> arc_sol;
+ for (unsigned int i = 0; i < sol.size(); ++i )
+ {
+ //std::cerr << "s = " << rad_to_deg(sol[i]);
+ sol[i] = map_to_01(sol[i]);
+ //std::cerr << " -> t: " << sol[i] << std::endl;
+ if ( !(sol[i] < 0 || sol[i] > 1) )
+ arc_sol.push_back(sol[i]);
+ }
+ return arc_sol;
}
-bool EllipticalArc::containsAngle(Coord angle) const
+// D(E(t,C),t) = E(t+PI/2,O), where C is the ellipse center
+// the derivative doesn't rotate the ellipse but there is a translation
+// of the parameter t by an angle of PI/2 so the ellipse points are shifted
+// of such an angle in the cw direction
+Curve *EllipticalArc::derivative() const
{
- if ( sweep_flag() )
- if ( start_angle() < end_angle() )
- return ( !( angle < start_angle() || angle > end_angle() ) );
- else
- return ( !( angle < start_angle() && angle > end_angle() ) );
- else
- if ( start_angle() > end_angle() )
- return ( !( angle > start_angle() || angle < end_angle() ) );
- else
- return ( !( angle > start_angle() && angle < end_angle() ) );
+ EllipticalArc *result = static_cast<EllipticalArc*>(duplicate());
+ result->_center[X] = result->_center[Y] = 0;
+ result->_start_angle += M_PI/2;
+ if( !( result->_start_angle < 2*M_PI ) )
+ {
+ result->_start_angle -= 2*M_PI;
+ }
+ result->_end_angle += M_PI/2;
+ if( !( result->_end_angle < 2*M_PI ) )
+ {
+ result->_end_angle -= 2*M_PI;
+ }
+ result->_initial_point = result->pointAtAngle( result->initialAngle() );
+ result->_final_point = result->pointAtAngle( result->finalAngle() );
+ return result;
}
-double EllipticalArc::valueAtAngle(Coord t, Dim2 d) const
+std::vector<Point>
+EllipticalArc::pointAndDerivatives(Coord t, unsigned int n) const
{
- double sin_rot_angle = std::sin(rotation_angle());
- double cos_rot_angle = std::cos(rotation_angle());
- if ( d == X )
+ unsigned int nn = n+1; // nn represents the size of the result vector.
+ std::vector<Point> result;
+ result.reserve(nn);
+ double angle = map_unit_interval_on_circular_arc(t, initialAngle(),
+ finalAngle(), _sweep);
+ std::auto_ptr<EllipticalArc> ea( static_cast<EllipticalArc*>(duplicate()) );
+ ea->_center = Point(0,0);
+ unsigned int m = std::min(nn, 4u);
+ for ( unsigned int i = 0; i < m; ++i )
{
- return ray(X) * cos_rot_angle * std::cos(t)
- - ray(Y) * sin_rot_angle * std::sin(t)
- + center(X);
+ result.push_back( ea->pointAtAngle(angle) );
+ angle += M_PI/2;
+ if ( !(angle < 2*M_PI) ) angle -= 2*M_PI;
}
- else if ( d == Y )
+ m = nn / 4;
+ for ( unsigned int i = 1; i < m; ++i )
{
- return ray(X) * sin_rot_angle * std::cos(t)
- + ray(Y) * cos_rot_angle * std::sin(t)
- + center(Y);
+ for ( unsigned int j = 0; j < 4; ++j )
+ result.push_back( result[j] );
+ }
+ m = nn - 4 * m;
+ for ( unsigned int i = 0; i < m; ++i )
+ {
+ result.push_back( result[i] );
}
- THROW_RANGEERROR("dimension parameter out of range");
+ if ( !result.empty() ) // nn != 0
+ result[0] = pointAtAngle(angle);
+ return result;
}
+bool EllipticalArc::containsAngle(Coord angle) const
+{
+ return AngleInterval::contains(angle);
+}
Curve* EllipticalArc::portion(double f, double t) const
{
- if (f < 0) f = 0;
- if (f > 1) f = 1;
- if (t < 0) t = 0;
- if (t > 1) t = 1;
- if ( are_near(f, t) )
- {
- EllipticalArc* arc = new EllipticalArc();
- arc->m_center = arc->m_initial_point = arc->m_final_point = pointAt(f);
- arc->m_start_angle = arc->m_end_angle = m_start_angle;
- arc->m_rot_angle = m_rot_angle;
- arc->m_sweep = m_sweep;
- arc->m_large_arc = m_large_arc;
- }
- EllipticalArc* arc = new EllipticalArc( *this );
- arc->m_initial_point = pointAt(f);
- arc->m_final_point = pointAt(t);
- double sa = sweep_flag() ? sweep_angle() : -sweep_angle();
- arc->m_start_angle = m_start_angle + sa * f;
- if ( !(arc->m_start_angle < 2*M_PI) )
- arc->m_start_angle -= 2*M_PI;
- if ( arc->m_start_angle < 0 )
- arc->m_start_angle += 2*M_PI;
- arc->m_end_angle = m_start_angle + sa * t;
- if ( !(arc->m_end_angle < 2*M_PI) )
- arc->m_end_angle -= 2*M_PI;
- if ( arc->m_end_angle < 0 )
- arc->m_end_angle += 2*M_PI;
- if ( f > t ) arc->m_sweep = !sweep_flag();
- if ( large_arc_flag() && (arc->sweep_angle() < M_PI) )
- arc->m_large_arc = false;
+ // fix input arguments
+ if (f < 0) f = 0;
+ if (f > 1) f = 1;
+ if (t < 0) t = 0;
+ if (t > 1) t = 1;
+
+ if ( are_near(f, t) )
+ {
+ EllipticalArc *arc = static_cast<EllipticalArc*>(duplicate());
+ arc->_center = arc->_initial_point = arc->_final_point = pointAt(f);
+ arc->_start_angle = arc->_end_angle = _start_angle;
+ arc->_rot_angle = _rot_angle;
+ arc->_sweep = _sweep;
+ arc->_large_arc = _large_arc;
+ return arc;
+ }
+
+ EllipticalArc *arc = static_cast<EllipticalArc*>(duplicate());
+ arc->_initial_point = pointAt(f);
+ arc->_final_point = pointAt(t);
+ if ( f > t ) arc->_sweep = !_sweep;
+ if ( _large_arc && fabs(sweepAngle() * (t-f)) < M_PI)
+ arc->_large_arc = false;
+ arc->_updateCenterAndAngles(arc->isSVGCompliant()); //TODO: be more clever
return arc;
}
-// NOTE: doesn't work with 360 deg arcs
-void EllipticalArc::calculate_center_and_extreme_angles()
+// the arc is the same but traversed in the opposite direction
+Curve *EllipticalArc::reverse() const {
+ EllipticalArc *rarc = static_cast<EllipticalArc*>(duplicate());
+ rarc->_sweep = !_sweep;
+ rarc->_initial_point = _final_point;
+ rarc->_final_point = _initial_point;
+ rarc->_start_angle = _end_angle;
+ rarc->_end_angle = _start_angle;
+ rarc->_updateCenterAndAngles(rarc->isSVGCompliant());
+ return rarc;
+}
+
+#ifdef HAVE_GSL // GSL is required for function "solve_reals"
+std::vector<double> EllipticalArc::allNearestPoints( Point const& p, double from, double to ) const
{
- // as stated in the svg standard the rotation angle parameter
- // value must be modulo 2*PI
- m_rot_angle = std::fmod(m_rot_angle, 2*M_PI);
- if (m_rot_angle < 0) m_rot_angle += 2*M_PI;
+ std::vector<double> result;
+
+ if ( from > to ) std::swap(from, to);
+ if ( from < 0 || to > 1 )
+ {
+ THROW_RANGEERROR("[from,to] interval out of range");
+ }
- if ( are_near(initialPoint(), finalPoint()) )
+ if ( ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) || are_near(from, to) )
{
- if ( are_near(ray(X), 0) && are_near(ray(Y), 0) )
- {
- m_start_angle = m_end_angle = 0;
- m_center = initialPoint();
- return;
- }
- else
- {
- THROW_RANGEERROR("initial and final point are the same");
- }
- }
- if ( are_near(ray(X), 0) && are_near(ray(Y), 0) )
- { // but initialPoint != finalPoint
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints: "
- "ray(X) == 0 && ray(Y) == 0 but initialPoint != finalPoint"
- );
- }
- if ( are_near(ray(Y), 0) )
- {
- Point v = initialPoint() - finalPoint();
- if ( are_near(L2sq(v), 4*ray(X)*ray(X)) )
- {
- double angle = std::atan2(v[Y], v[X]);
- if (angle < 0) angle += 2*M_PI;
- if ( are_near( angle, rotation_angle() ) )
- {
- m_start_angle = 0;
- m_end_angle = M_PI;
- m_center = v/2 + finalPoint();
- return;
- }
- angle -= M_PI;
- if ( angle < 0 ) angle += 2*M_PI;
- if ( are_near( angle, rotation_angle() ) )
- {
- m_start_angle = M_PI;
- m_end_angle = 0;
- m_center = v/2 + finalPoint();
- return;
- }
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints: "
- "ray(Y) == 0 "
- "and slope(initialPoint - finalPoint) != rotation_angle "
- "and != rotation_angle + PI"
- );
- }
- if ( L2sq(v) > 4*ray(X)*ray(X) )
- {
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints: "
- "ray(Y) == 0 and distance(initialPoint, finalPoint) > 2*ray(X)"
- );
- }
- else
- {
- THROW_RANGEERROR(
- "there is infinite ellipses that satisfy the given constraints: "
- "ray(Y) == 0 and distance(initialPoint, finalPoint) < 2*ray(X)"
- );
- }
-
- }
-
- if ( are_near(ray(X), 0) )
- {
- Point v = initialPoint() - finalPoint();
- if ( are_near(L2sq(v), 4*ray(Y)*ray(Y)) )
- {
- double angle = std::atan2(v[Y], v[X]);
- if (angle < 0) angle += 2*M_PI;
- double rot_angle = rotation_angle() + M_PI/2;
- if ( !(rot_angle < 2*M_PI) ) rot_angle -= 2*M_PI;
- if ( are_near( angle, rot_angle ) )
- {
- m_start_angle = M_PI/2;
- m_end_angle = 3*M_PI/2;
- m_center = v/2 + finalPoint();
- return;
- }
- angle -= M_PI;
- if ( angle < 0 ) angle += 2*M_PI;
- if ( are_near( angle, rot_angle ) )
- {
- m_start_angle = 3*M_PI/2;
- m_end_angle = M_PI/2;
- m_center = v/2 + finalPoint();
- return;
- }
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints: "
- "ray(X) == 0 "
- "and slope(initialPoint - finalPoint) != rotation_angle + PI/2 "
- "and != rotation_angle + (3/2)*PI"
- );
- }
- if ( L2sq(v) > 4*ray(Y)*ray(Y) )
- {
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints: "
- "ray(X) == 0 and distance(initialPoint, finalPoint) > 2*ray(Y)"
- );
- }
- else
- {
- THROW_RANGEERROR(
- "there is infinite ellipses that satisfy the given constraints: "
- "ray(X) == 0 and distance(initialPoint, finalPoint) < 2*ray(Y)"
- );
- }
-
- }
-
- double sin_rot_angle = std::sin(rotation_angle());
- double cos_rot_angle = std::cos(rotation_angle());
-
- Point sp = sweep_flag() ? initialPoint() : finalPoint();
- Point ep = sweep_flag() ? finalPoint() : initialPoint();
-
- Matrix m( ray(X) * cos_rot_angle, ray(X) * sin_rot_angle,
- -ray(Y) * sin_rot_angle, ray(Y) * cos_rot_angle,
- 0, 0 );
- Matrix im = m.inverse();
- Point sol = (ep - sp) * im;
- double half_sum_angle = std::atan2(-sol[X], sol[Y]);
- double half_diff_angle;
- if ( are_near(std::fabs(half_sum_angle), M_PI/2) )
+ result.push_back(from);
+ return result;
+ }
+ else if ( are_near(ray(X), 0) || are_near(ray(Y), 0) )
{
- double anti_sgn_hsa = (half_sum_angle > 0) ? -1 : 1;
- double arg = anti_sgn_hsa * sol[X] / 2;
- // if |arg| is a little bit > 1 acos returns nan
- if ( are_near(arg, 1) )
- half_diff_angle = 0;
- else if ( are_near(arg, -1) )
- half_diff_angle = M_PI;
+ LineSegment seg(pointAt(from), pointAt(to));
+ Point np = seg.pointAt( seg.nearestPoint(p) );
+ if ( are_near(ray(Y), 0) )
+ {
+ if ( are_near(_rot_angle, M_PI/2)
+ || are_near(_rot_angle, 3*M_PI/2) )
+ {
+ result = roots(np[Y], Y);
+ }
+ else
+ {
+ result = roots(np[X], X);
+ }
+ }
else
{
- if ( !(-1 < arg && arg < 1) )
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints"
- );
- // assert( -1 < arg && arg < 1 );
- // if it fails
- // => there is no ellipse that satisfies the given constraints
- half_diff_angle = std::acos( arg );
+ if ( are_near(_rot_angle, M_PI/2)
+ || are_near(_rot_angle, 3*M_PI/2) )
+ {
+ result = roots(np[X], X);
+ }
+ else
+ {
+ result = roots(np[Y], Y);
+ }
}
+ return result;
+ }
+ else if ( are_near(ray(X), ray(Y)) )
+ {
+ Point r = p - center();
+ if ( are_near(r, Point(0,0)) )
+ {
+ THROW_INFINITESOLUTIONS(0);
+ }
+ // TODO: implement case r != 0
+// Point np = ray(X) * unit_vector(r);
+// std::vector<double> solX = roots(np[X],X);
+// std::vector<double> solY = roots(np[Y],Y);
+// double t;
+// if ( are_near(solX[0], solY[0]) || are_near(solX[0], solY[1]))
+// {
+// t = solX[0];
+// }
+// else
+// {
+// t = solX[1];
+// }
+// if ( !(t < from || t > to) )
+// {
+// result.push_back(t);
+// }
+// else
+// {
+//
+// }
+ }
- half_diff_angle = M_PI/2 - half_diff_angle;
+ // solve the equation <D(E(t),t)|E(t)-p> == 0
+ // that provides min and max distance points
+ // on the ellipse E wrt the point p
+ // after the substitutions:
+ // cos(t) = (1 - s^2) / (1 + s^2)
+ // sin(t) = 2t / (1 + s^2)
+ // where s = tan(t/2)
+ // we get a 4th degree equation in s
+ /*
+ * ry s^4 ((-cy + py) Cos[Phi] + (cx - px) Sin[Phi]) +
+ * ry ((cy - py) Cos[Phi] + (-cx + px) Sin[Phi]) +
+ * 2 s^3 (rx^2 - ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) +
+ * 2 s (-rx^2 + ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi])
+ */
+
+ Point p_c = p - center();
+ double rx2_ry2 = (ray(X) - ray(Y)) * (ray(X) + ray(Y));
+ double sinrot, cosrot;
+ sincos(_rot_angle, sinrot, cosrot);
+ double expr1 = ray(X) * (p_c[X] * cosrot + p_c[Y] * sinrot);
+ Poly coeff;
+ coeff.resize(5);
+ coeff[4] = ray(Y) * ( p_c[Y] * cosrot - p_c[X] * sinrot );
+ coeff[3] = 2 * ( rx2_ry2 + expr1 );
+ coeff[2] = 0;
+ coeff[1] = 2 * ( -rx2_ry2 + expr1 );
+ coeff[0] = -coeff[4];
+
+// for ( unsigned int i = 0; i < 5; ++i )
+// std::cerr << "c[" << i << "] = " << coeff[i] << std::endl;
+
+ std::vector<double> real_sol;
+ // gsl_poly_complex_solve raises an error
+ // if the leading coefficient is zero
+ if ( are_near(coeff[4], 0) )
+ {
+ real_sol.push_back(0);
+ if ( !are_near(coeff[3], 0) )
+ {
+ double sq = -coeff[1] / coeff[3];
+ if ( sq > 0 )
+ {
+ double s = std::sqrt(sq);
+ real_sol.push_back(s);
+ real_sol.push_back(-s);
+ }
+ }
}
else
{
- double arg = sol[Y] / ( 2 * std::cos(half_sum_angle) );
- // if |arg| is a little bit > 1 asin returns nan
- if ( are_near(arg, 1) )
- half_diff_angle = M_PI/2;
- else if ( are_near(arg, -1) )
- half_diff_angle = -M_PI/2;
- else
+ real_sol = solve_reals(coeff);
+ }
+
+ for ( unsigned int i = 0; i < real_sol.size(); ++i )
+ {
+ real_sol[i] = 2 * std::atan(real_sol[i]);
+ if ( real_sol[i] < 0 ) real_sol[i] += 2*M_PI;
+ }
+ // when s -> Infinity then <D(E)|E-p> -> 0 iff coeff[4] == 0
+ // so we add M_PI to the solutions being lim arctan(s) = PI when s->Infinity
+ if ( (real_sol.size() % 2) != 0 )
+ {
+ real_sol.push_back(M_PI);
+ }
+
+ double mindistsq1 = std::numeric_limits<double>::max();
+ double mindistsq2 = std::numeric_limits<double>::max();
+ double dsq;
+ unsigned int mi1, mi2;
+ for ( unsigned int i = 0; i < real_sol.size(); ++i )
+ {
+ dsq = distanceSq(p, pointAtAngle(real_sol[i]));
+ if ( mindistsq1 > dsq )
{
- if ( !(-1 < arg && arg < 1) )
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints"
- );
- // assert( -1 < arg && arg < 1 );
- // if it fails
- // => there is no ellipse that satisfies the given constraints
- half_diff_angle = std::asin( arg );
+ mindistsq2 = mindistsq1;
+ mi2 = mi1;
+ mindistsq1 = dsq;
+ mi1 = i;
+ }
+ else if ( mindistsq2 > dsq )
+ {
+ mindistsq2 = dsq;
+ mi2 = i;
}
}
- if ( ( m_large_arc && half_diff_angle > 0 )
- || (!m_large_arc && half_diff_angle < 0 ) )
+ double t = map_to_01( real_sol[mi1] );
+ if ( !(t < from || t > to) )
{
- half_diff_angle = -half_diff_angle;
- }
- if ( half_sum_angle < 0 ) half_sum_angle += 2*M_PI;
- if ( half_diff_angle < 0 ) half_diff_angle += M_PI;
-
- m_start_angle = half_sum_angle - half_diff_angle;
- m_end_angle = half_sum_angle + half_diff_angle;
- // 0 <= m_start_angle, m_end_angle < 2PI
- if ( m_start_angle < 0 ) m_start_angle += 2*M_PI;
- if( !(m_end_angle < 2*M_PI) ) m_end_angle -= 2*M_PI;
- sol[0] = std::cos(m_start_angle);
- sol[1] = std::sin(m_start_angle);
- m_center = sp - sol * m;
- if ( !sweep_flag() )
+ result.push_back(t);
+ }
+
+ bool second_sol = false;
+ t = map_to_01( real_sol[mi2] );
+ if ( real_sol.size() == 4 && !(t < from || t > to) )
{
- double angle = m_start_angle;
- m_start_angle = m_end_angle;
- m_end_angle = angle;
+ if ( result.empty() || are_near(mindistsq1, mindistsq2) )
+ {
+ result.push_back(t);
+ second_sol = true;
+ }
}
+
+ // we need to test extreme points too
+ double dsq1 = distanceSq(p, pointAt(from));
+ double dsq2 = distanceSq(p, pointAt(to));
+ if ( second_sol )
+ {
+ if ( mindistsq2 > dsq1 )
+ {
+ result.clear();
+ result.push_back(from);
+ mindistsq2 = dsq1;
+ }
+ else if ( are_near(mindistsq2, dsq) )
+ {
+ result.push_back(from);
+ }
+ if ( mindistsq2 > dsq2 )
+ {
+ result.clear();
+ result.push_back(to);
+ }
+ else if ( are_near(mindistsq2, dsq2) )
+ {
+ result.push_back(to);
+ }
+
+ }
+ else
+ {
+ if ( result.empty() )
+ {
+ if ( are_near(dsq1, dsq2) )
+ {
+ result.push_back(from);
+ result.push_back(to);
+ }
+ else if ( dsq2 > dsq1 )
+ {
+ result.push_back(from);
+ }
+ else
+ {
+ result.push_back(to);
+ }
+ }
+ }
+
+ return result;
}
+#endif
-Coord EllipticalArc::map_to_02PI(Coord t) const
+/*
+ * NOTE: this implementation follows Standard SVG 1.1 implementation guidelines
+ * for elliptical arc curves. See Appendix F.6.
+ */
+void EllipticalArc::_updateCenterAndAngles(bool svg)
{
- if ( sweep_flag() )
+ Point d = initialPoint() - finalPoint();
+
+ // TODO move this to SVGElipticalArc?
+ if (svg)
{
- Coord angle = start_angle() + sweep_angle() * t;
- if ( !(angle < 2*M_PI) )
- angle -= 2*M_PI;
- return angle;
+ if ( initialPoint() == finalPoint() )
+ {
+ _rot_angle = _start_angle = _end_angle = 0;
+ _center = initialPoint();
+ _rays = Geom::Point(0,0);
+ _large_arc = _sweep = false;
+ return;
+ }
+
+ _rays[X] = std::fabs(_rays[X]);
+ _rays[Y] = std::fabs(_rays[Y]);
+
+ if ( are_near(ray(X), 0) || are_near(ray(Y), 0) )
+ {
+ _rays[X] = L2(d) / 2;
+ _rays[Y] = 0;
+ _rot_angle = std::atan2(d[Y], d[X]);
+ _start_angle = 0;
+ _end_angle = M_PI;
+ _center = middle_point(initialPoint(), finalPoint());
+ _large_arc = false;
+ _sweep = false;
+ return;
+ }
}
else
{
- Coord angle = start_angle() - sweep_angle() * t;
- if ( angle < 0 ) angle += 2*M_PI;
- return angle;
+ if ( are_near(initialPoint(), finalPoint()) )
+ {
+ if ( are_near(ray(X), 0) && are_near(ray(Y), 0) )
+ {
+ _start_angle = _end_angle = 0;
+ _center = initialPoint();
+ return;
+ }
+ else
+ {
+ THROW_RANGEERROR("initial and final point are the same");
+ }
+ }
+ if ( are_near(ray(X), 0) && are_near(ray(Y), 0) )
+ { // but initialPoint != finalPoint
+ THROW_RANGEERROR(
+ "there is no ellipse that satisfies the given constraints: "
+ "ray(X) == 0 && ray(Y) == 0 but initialPoint != finalPoint"
+ );
+ }
+ if ( are_near(ray(Y), 0) )
+ {
+ Point v = initialPoint() - finalPoint();
+ if ( are_near(L2sq(v), 4*ray(X)*ray(X)) )
+ {
+ Angle angle(v);
+ if ( are_near( angle, _rot_angle ) )
+ {
+ _start_angle = 0;
+ _end_angle = M_PI;
+ _center = v/2 + finalPoint();
+ return;
+ }
+ angle -= M_PI;
+ if ( are_near( angle, _rot_angle ) )
+ {
+ _start_angle = M_PI;
+ _end_angle = 0;
+ _center = v/2 + finalPoint();
+ return;
+ }
+ THROW_RANGEERROR(
+ "there is no ellipse that satisfies the given constraints: "
+ "ray(Y) == 0 "
+ "and slope(initialPoint - finalPoint) != rotation_angle "
+ "and != rotation_angle + PI"
+ );
+ }
+ if ( L2sq(v) > 4*ray(X)*ray(X) )
+ {
+ THROW_RANGEERROR(
+ "there is no ellipse that satisfies the given constraints: "
+ "ray(Y) == 0 and distance(initialPoint, finalPoint) > 2*ray(X)"
+ );
+ }
+ else
+ {
+ THROW_RANGEERROR(
+ "there is infinite ellipses that satisfy the given constraints: "
+ "ray(Y) == 0 and distance(initialPoint, finalPoint) < 2*ray(X)"
+ );
+ }
+
+ }
+
+ if ( are_near(ray(X), 0) )
+ {
+ Point v = initialPoint() - finalPoint();
+ if ( are_near(L2sq(v), 4*ray(Y)*ray(Y)) )
+ {
+ double angle = std::atan2(v[Y], v[X]);
+ if (angle < 0) angle += 2*M_PI;
+ double rot_angle = _rot_angle.radians() + M_PI/2;
+ if ( !(rot_angle < 2*M_PI) ) rot_angle -= 2*M_PI;
+ if ( are_near( angle, rot_angle ) )
+ {
+ _start_angle = M_PI/2;
+ _end_angle = 3*M_PI/2;
+ _center = v/2 + finalPoint();
+ return;
+ }
+ angle -= M_PI;
+ if ( angle < 0 ) angle += 2*M_PI;
+ if ( are_near( angle, rot_angle ) )
+ {
+ _start_angle = 3*M_PI/2;
+ _end_angle = M_PI/2;
+ _center = v/2 + finalPoint();
+ return;
+ }
+ THROW_RANGEERROR(
+ "there is no ellipse that satisfies the given constraints: "
+ "ray(X) == 0 "
+ "and slope(initialPoint - finalPoint) != rotation_angle + PI/2 "
+ "and != rotation_angle + (3/2)*PI"
+ );
+ }
+ if ( L2sq(v) > 4*ray(Y)*ray(Y) )
+ {
+ THROW_RANGEERROR(
+ "there is no ellipse that satisfies the given constraints: "
+ "ray(X) == 0 and distance(initialPoint, finalPoint) > 2*ray(Y)"
+ );
+ }
+ else
+ {
+ THROW_RANGEERROR(
+ "there is infinite ellipses that satisfy the given constraints: "
+ "ray(X) == 0 and distance(initialPoint, finalPoint) < 2*ray(Y)"
+ );
+ }
+
+ }
+
}
+
+ Rotate rm(_rot_angle);
+ Affine m(rm);
+ m[1] = -m[1];
+ m[2] = -m[2];
+
+ Point p = (d / 2) * m;
+ double rx2 = _rays[X] * _rays[X];
+ double ry2 = _rays[Y] * _rays[Y];
+ double rxpy = _rays[X] * p[Y];
+ double rypx = _rays[Y] * p[X];
+ double rx2py2 = rxpy * rxpy;
+ double ry2px2 = rypx * rypx;
+ double num = rx2 * ry2;
+ double den = rx2py2 + ry2px2;
+ assert(den != 0);
+ double rad = num / den;
+ Point c(0,0);
+ if (rad > 1)
+ {
+ rad -= 1;
+ rad = std::sqrt(rad);
+
+ if (_large_arc == _sweep) rad = -rad;
+ c = rad * Point(rxpy / ray(Y), -rypx / ray(X));
+
+ _center = c * rm + middle_point(initialPoint(), finalPoint());
+ }
+ else if (rad == 1 || svg)
+ {
+ double lamda = std::sqrt(1 / rad);
+ _rays[X] *= lamda;
+ _rays[Y] *= lamda;
+ _center = middle_point(initialPoint(), finalPoint());
+ }
+ else
+ {
+ THROW_RANGEERROR(
+ "there is no ellipse that satisfies the given constraints"
+ );
+ }
+
+ Point sp((p[X] - c[X]) / ray(X), (p[Y] - c[Y]) / ray(Y));
+ Point ep((-p[X] - c[X]) / ray(X), (-p[Y] - c[Y]) / ray(Y));
+ Point v(1, 0);
+ _start_angle = angle_between(v, sp);
+ double sweep_angle = angle_between(sp, ep);
+ if (!_sweep && sweep_angle > 0) sweep_angle -= 2*M_PI;
+ if (_sweep && sweep_angle < 0) sweep_angle += 2*M_PI;
+
+ _end_angle = _start_angle;
+ _end_angle += sweep_angle;
}
-Coord EllipticalArc::map_to_01(Coord angle) const
+D2<SBasis> EllipticalArc::toSBasis() const
{
- return map_circular_arc_on_unit_interval(angle, start_angle(),
- end_angle(), sweep_flag());
+ D2<SBasis> arc;
+ // the interval of parametrization has to be [0,1]
+ Coord et = initialAngle().radians() + ( _sweep ? sweepAngle() : -sweepAngle() );
+ Linear param(initialAngle(), et);
+ Coord cos_rot_angle, sin_rot_angle;
+ sincos(_rot_angle, sin_rot_angle, cos_rot_angle);
+
+ // order = 4 seems to be enough to get a perfect looking elliptical arc
+ SBasis arc_x = ray(X) * cos(param,4);
+ SBasis arc_y = ray(Y) * sin(param,4);
+ arc[0] = arc_x * cos_rot_angle - arc_y * sin_rot_angle + Linear(center(X),center(X));
+ arc[1] = arc_x * sin_rot_angle + arc_y * cos_rot_angle + Linear(center(Y),center(Y));
+
+ // ensure that endpoints remain exact
+ for ( int d = 0 ; d < 2 ; d++ ) {
+ arc[d][0][0] = initialPoint()[d];
+ arc[d][0][1] = finalPoint()[d];
+ }
+
+ return arc;
}
-std::vector<double> EllipticalArc::
-allNearestPoints( Point const& p, double from, double to ) const
+Curve *EllipticalArc::transformed(Affine const& m) const
{
- if ( from > to ) std::swap(from, to);
- if ( from < 0 || to > 1 )
- {
- THROW_RANGEERROR("[from,to] interval out of range");
- }
- std::vector<double> result;
- if ( ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) || are_near(from, to) )
- {
- result.push_back(from);
- return result;
- }
- else if ( are_near(ray(X), 0) || are_near(ray(Y), 0) )
- {
- LineSegment seg(pointAt(from), pointAt(to));
- Point np = seg.pointAt( seg.nearestPoint(p) );
- if ( are_near(ray(Y), 0) )
- {
- if ( are_near(rotation_angle(), M_PI/2)
- || are_near(rotation_angle(), 3*M_PI/2) )
- {
- result = roots(np[Y], Y);
- }
- else
- {
- result = roots(np[X], X);
- }
- }
- else
- {
- if ( are_near(rotation_angle(), M_PI/2)
- || are_near(rotation_angle(), 3*M_PI/2) )
- {
- result = roots(np[X], X);
- }
- else
- {
- result = roots(np[Y], Y);
- }
- }
- return result;
- }
- else if ( are_near(ray(X), ray(Y)) )
- {
- Point r = p - center();
- if ( are_near(r, Point(0,0)) )
- {
- THROW_INFINITESOLUTIONS(0);
- }
- // TODO: implement case r != 0
-// Point np = ray(X) * unit_vector(r);
-// std::vector<double> solX = roots(np[X],X);
-// std::vector<double> solY = roots(np[Y],Y);
-// double t;
-// if ( are_near(solX[0], solY[0]) || are_near(solX[0], solY[1]))
-// {
-// t = solX[0];
-// }
-// else
-// {
-// t = solX[1];
-// }
-// if ( !(t < from || t > to) )
-// {
-// result.push_back(t);
-// }
-// else
-// {
-//
-// }
- }
-
- // solve the equation <D(E(t),t)|E(t)-p> == 0
- // that provides min and max distance points
- // on the ellipse E wrt the point p
- // after the substitutions:
- // cos(t) = (1 - s^2) / (1 + s^2)
- // sin(t) = 2t / (1 + s^2)
- // where s = tan(t/2)
- // we get a 4th degree equation in s
- /*
- * ry s^4 ((-cy + py) Cos[Phi] + (cx - px) Sin[Phi]) +
- * ry ((cy - py) Cos[Phi] + (-cx + px) Sin[Phi]) +
- * 2 s^3 (rx^2 - ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) +
- * 2 s (-rx^2 + ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi])
- */
-
- Point p_c = p - center();
- double rx2_ry2 = (ray(X) - ray(Y)) * (ray(X) + ray(Y));
- double cosrot = std::cos( rotation_angle() );
- double sinrot = std::sin( rotation_angle() );
- double expr1 = ray(X) * (p_c[X] * cosrot + p_c[Y] * sinrot);
- Poly coeff;
- coeff.resize(5);
- coeff[4] = ray(Y) * ( p_c[Y] * cosrot - p_c[X] * sinrot );
- coeff[3] = 2 * ( rx2_ry2 + expr1 );
- coeff[2] = 0;
- coeff[1] = 2 * ( -rx2_ry2 + expr1 );
- coeff[0] = -coeff[4];
-
-// for ( unsigned int i = 0; i < 5; ++i )
-// std::cerr << "c[" << i << "] = " << coeff[i] << std::endl;
-
- std::vector<double> real_sol;
- // gsl_poly_complex_solve raises an error
- // if the leading coefficient is zero
- if ( are_near(coeff[4], 0) )
- {
- real_sol.push_back(0);
- if ( !are_near(coeff[3], 0) )
- {
- double sq = -coeff[1] / coeff[3];
- if ( sq > 0 )
- {
- double s = std::sqrt(sq);
- real_sol.push_back(s);
- real_sol.push_back(-s);
- }
- }
- }
- else
- {
- real_sol = solve_reals(coeff);
- }
-// else
-// {
-// double sol[8];
-// gsl_poly_complex_workspace * w = gsl_poly_complex_workspace_alloc(5);
-// gsl_poly_complex_solve(coeff, 5, w, sol );
-// gsl_poly_complex_workspace_free(w);
-//
-// for ( unsigned int i = 0; i < 4; ++i )
-// {
-// if ( sol[2*i+1] == 0 ) real_sol.push_back(sol[2*i]);
-// }
-// }
-
- for ( unsigned int i = 0; i < real_sol.size(); ++i )
- {
- real_sol[i] = 2 * std::atan(real_sol[i]);
- if ( real_sol[i] < 0 ) real_sol[i] += 2*M_PI;
- }
- // when s -> Infinity then <D(E)|E-p> -> 0 iff coeff[4] == 0
- // so we add M_PI to the solutions being lim arctan(s) = PI when s->Infinity
- if ( (real_sol.size() % 2) != 0 )
- {
- real_sol.push_back(M_PI);
- }
-
- double mindistsq1 = std::numeric_limits<double>::max();
- double mindistsq2 = std::numeric_limits<double>::max();
- double dsq;
- unsigned int mi1, mi2;
- for ( unsigned int i = 0; i < real_sol.size(); ++i )
- {
- dsq = distanceSq(p, pointAtAngle(real_sol[i]));
- if ( mindistsq1 > dsq )
- {
- mindistsq2 = mindistsq1;
- mi2 = mi1;
- mindistsq1 = dsq;
- mi1 = i;
- }
- else if ( mindistsq2 > dsq )
- {
- mindistsq2 = dsq;
- mi2 = i;
- }
- }
-
- double t = map_to_01( real_sol[mi1] );
- if ( !(t < from || t > to) )
- {
- result.push_back(t);
- }
-
- bool second_sol = false;
- t = map_to_01( real_sol[mi2] );
- if ( real_sol.size() == 4 && !(t < from || t > to) )
- {
- if ( result.empty() || are_near(mindistsq1, mindistsq2) )
- {
- result.push_back(t);
- second_sol = true;
- }
- }
-
- // we need to test extreme points too
- double dsq1 = distanceSq(p, pointAt(from));
- double dsq2 = distanceSq(p, pointAt(to));
- if ( second_sol )
- {
- if ( mindistsq2 > dsq1 )
- {
- result.clear();
- result.push_back(from);
- mindistsq2 = dsq1;
- }
- else if ( are_near(mindistsq2, dsq) )
- {
- result.push_back(from);
- }
- if ( mindistsq2 > dsq2 )
- {
- result.clear();
- result.push_back(to);
- }
- else if ( are_near(mindistsq2, dsq2) )
- {
- result.push_back(to);
- }
-
- }
- else
- {
- if ( result.empty() )
- {
- if ( are_near(dsq1, dsq2) )
- {
- result.push_back(from);
- result.push_back(to);
- }
- else if ( dsq2 > dsq1 )
- {
- result.push_back(from);
- }
- else
- {
- result.push_back(to);
- }
- }
- }
-
- return result;
+ Ellipse e(center(X), center(Y), ray(X), ray(Y), _rot_angle);
+ Ellipse et = e.transformed(m);
+ Point inner_point = pointAt(0.5);
+ return et.arc( initialPoint() * m,
+ inner_point * m,
+ finalPoint() * m,
+ isSVGCompliant() );
}
+Coord EllipticalArc::map_to_01(Coord angle) const
+{
+ return map_circular_arc_on_unit_interval(angle, initialAngle(),
+ finalAngle(), _sweep);
+}
} // end namespace Geom
-
/*
Local Variables:
mode:c++
@@ -928,4 +916,3 @@ allNearestPoints( Point const& p, double from, double to ) const
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
-
diff --git a/src/2geom/elliptical-arc.h b/src/2geom/elliptical-arc.h
index 002735944..e1e757207 100644
--- a/src/2geom/elliptical-arc.h
+++ b/src/2geom/elliptical-arc.h
@@ -1,12 +1,14 @@
/**
* \file
- * \brief Elliptical Arc - implementation of the svg elliptical arc path element
+ * \brief Elliptical arc curve
*
+ *//*
* Authors:
- * MenTaLguY <mental@rydia.net>
- * Marco Cecchetti <mrcekets at gmail.com>
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
*
- * Copyright 2007-2008 authors
+ * Copyright 2007-2009 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -32,272 +34,234 @@
* the specific language governing rights and limitations.
*/
-
-
-
#ifndef _2GEOM_ELLIPTICAL_ARC_H_
#define _2GEOM_ELLIPTICAL_ARC_H_
-
-#include <2geom/curve.h>
+#include <algorithm>
#include <2geom/angle.h>
-#include <2geom/utils.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/curve.h>
+#include <2geom/affine.h>
#include <2geom/sbasis-curve.h> // for non-native methods
-
-#include <algorithm>
-
+#include <2geom/utils.h>
namespace Geom
{
-class EllipticalArc : public Curve
+class EllipticalArc : public Curve, public AngleInterval
{
- public:
- EllipticalArc()
- : m_initial_point(Point(0,0)), m_final_point(Point(0,0)),
- m_rx(0), m_ry(0), m_rot_angle(0),
- m_large_arc(true), m_sweep(true)
- {
- m_start_angle = m_end_angle = 0;
- m_center = Point(0,0);
- }
-
- EllipticalArc( Point _initial_point, double _rx, double _ry,
- double _rot_angle, bool _large_arc, bool _sweep,
- Point _final_point
- )
- : m_initial_point(_initial_point), m_final_point(_final_point),
- m_rx(_rx), m_ry(_ry), m_rot_angle(_rot_angle),
- m_large_arc(_large_arc), m_sweep(_sweep)
- {
- calculate_center_and_extreme_angles();
- }
-
- void set( Point _initial_point, double _rx, double _ry,
- double _rot_angle, bool _large_arc, bool _sweep,
- Point _final_point
- )
+public:
+ /** @brief Creates an arc with all variables set to zero, and both flags to true. */
+ EllipticalArc()
+ : AngleInterval(0, 0, true)
+ , _initial_point(0,0)
+ , _final_point(0,0)
+ , _rays(0,0)
+ , _center(0,0)
+ , _rot_angle(0)
+ , _large_arc(true)
+ {}
+ /** @brief Create a new elliptical arc.
+ * @param ip Initial point of the arc
+ * @param rx First ray of the ellipse
+ * @param ry Second ray of the ellipse
+ * @param rot Angle of rotation of the X axis of the ellipse in radians
+ * @param large If true, the large arc is chosen (always >= 180 degrees), otherwise
+ * the smaller arc is chosen
+ * @param sweep If true, the clockwise arc is chosen, otherwise the counter-clockwise
+ * arc is chosen
+ * @param fp Final point of the arc */
+ EllipticalArc( Point ip, Coord rx, Coord ry,
+ Coord rot_angle, bool large_arc, bool sweep,
+ Point fp
+ )
+ : AngleInterval(0,0,sweep)
+ , _initial_point(ip)
+ , _final_point(fp)
+ , _rays(rx, ry)
+ , _rot_angle(rot_angle)
+ , _large_arc(large_arc)
{
- m_initial_point = _initial_point;
- m_final_point = _final_point;
- m_rx = _rx;
- m_ry = _ry;
- m_rot_angle = _rot_angle;
- m_large_arc = _large_arc;
- m_sweep = _sweep;
- calculate_center_and_extreme_angles();
+ _updateCenterAndAngles(false);
}
- Curve* duplicate() const
- {
- return new EllipticalArc(*this);
- }
-
- double center(unsigned int i) const
- {
- return m_center[i];
+ // methods new to EllipticalArc go here
+
+ /// @name Retrieve and modify parameters
+ /// @{
+ /** @brief Get the interval of angles the arc contains
+ * @return The interval between the final and initial angles of the arc */
+ Interval angleInterval() const { return Interval(initialAngle(), finalAngle()); }
+ /** @brief Get a coordinate of the elliptical arc's center.
+ * @param d The dimension to retrieve
+ * @return The selected coordinate of the center */
+ /** @brief Get the defining ellipse's rotation
+ * @return Angle between the +X ray of the ellipse and the +X axis */
+ Angle rotationAngle() const {
+ return _rot_angle;
}
-
- Point center() const
+ /** @brief Get one of the ellipse's rays
+ * @param d Dimension to retrieve
+ * @return The selected ray of the ellipse */
+ Coord ray(Dim2 d) const { return _rays[d]; }
+ /** @brief Get both rays as a point
+ * @return Point with X equal to the X ray and Y to Y ray */
+ Point rays() const { return _rays; }
+ /** @brief Whether the arc is larger than half an ellipse.
+ * @return True if the arc is larger than \f$\pi\f$, false otherwise */
+ bool largeArc() const { return _large_arc; }
+ /** @brief Whether the arc turns clockwise
+ * @return True if the arc makes a clockwise turn when going from initial to final
+ * point, false otherwise */
+ bool sweep() const { return _sweep; }
+ /** @brief Get the line segment connecting the arc's endpoints.
+ * @return A linear segment with initial and final point correspoding to those of the arc. */
+ LineSegment chord() const { return LineSegment(_initial_point, _final_point); }
+ /** @brief Change the arc's parameters. */
+ void set( Point const &ip, double rx, double ry,
+ double rot_angle, bool large_arc, bool sweep,
+ Point const &fp
+ )
{
- return m_center;
+ _initial_point = ip;
+ _final_point = fp;
+ _rays[X] = rx;
+ _rays[Y] = ry;
+ _rot_angle = Angle(rot_angle);
+ _large_arc = large_arc;
+ _sweep = sweep;
+ _updateCenterAndAngles(isSVGCompliant());
}
-
- Point initialPoint() const
- {
- return m_initial_point;
+ /** @brief Change the initial and final point in one operation.
+ * This method exists because modifying any of the endpoints causes rather costly
+ * recalculations of the center and extreme angles.
+ * @param ip New initial point
+ * @param fp New final point */
+ void setExtremes(Point const &ip, Point const &fp) {
+ _initial_point = ip;
+ _final_point = fp;
+ _updateCenterAndAngles(isSVGCompliant());
}
-
- Point finalPoint() const
- {
- return m_final_point;
+ /// @}
+
+ /// @name Access computed parameters of the arc
+ /// @{
+ Coord center(Dim2 d) const { return _center[d]; }
+ /** @brief Get the arc's center
+ * @return The arc's center, situated on the intersection of the ellipse's rays */
+ Point center() const { return _center; }
+ /** @brief Get the extent of the arc
+ * @return The angle between the initial and final point, in arc's angular coordinates */
+ Coord sweepAngle() const {
+ return extent();
}
-
- double start_angle() const
- {
- return m_start_angle;
- }
-
- double end_angle() const
- {
- return m_end_angle;
- }
-
- double ray(unsigned int i) const
- {
- return (i == 0) ? m_rx : m_ry;
- }
-
- bool large_arc_flag() const
- {
- return m_large_arc;
- }
-
- bool sweep_flag() const
- {
- return m_sweep;
- }
-
- double rotation_angle() const
- {
- return m_rot_angle;
- }
-
- void setInitial( const Point _point)
- {
- m_initial_point = _point;
- calculate_center_and_extreme_angles();
+ /// @}
+
+ /// @name Angular evaluation
+ /// @{
+ /** Check whether the arc contains the given angle
+ * @param t The angle to check
+ * @return True if the arc contains the angle, false otherwise */
+ bool containsAngle(Coord angle) const;
+ /** @brief Evaluate the arc at the specified angular coordinate
+ * @param t Angle
+ * @return Point corresponding to the given angle */
+ Point pointAtAngle(Coord t) const;
+ /** @brief Evaluate one of the arc's coordinates at the specified angle
+ * @param t Angle
+ * @param d The dimension to retrieve
+ * @return Selected coordinate of the arc at the specified angle */
+ Coord valueAtAngle(Coord t, Dim2 d) const;
+ /** @brief Retrieve the unit circle transform.
+ * Each ellipse can be interpreted as a translated, scaled and rotate unit circle.
+ * This function returns the transform that maps the unit circle to the arc's ellipse.
+ * @return Transform from unit circle to the arc's ellipse */
+ Affine unitCircleTransform() const;
+ /// @}
+
+ /** @brief Check whether the arc adheres to SVG 1.1 implementation guidelines */
+ virtual bool isSVGCompliant() const { return false; }
+
+ std::pair<EllipticalArc, EllipticalArc> subdivide(Coord t) const {
+ EllipticalArc* arc1 = static_cast<EllipticalArc*>(portion(0, t));
+ EllipticalArc* arc2 = static_cast<EllipticalArc*>(portion(t, 1));
+ assert( arc1 != NULL && arc2 != NULL);
+ std::pair<EllipticalArc, EllipticalArc> arc_pair(*arc1, *arc2);
+ delete arc1;
+ delete arc2;
+ return arc_pair;
}
- void setFinal( const Point _point)
- {
- m_final_point = _point;
- calculate_center_and_extreme_angles();
+ // implementation of overloads goes here
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ virtual Point initialPoint() const { return _initial_point; }
+ virtual Point finalPoint() const { return _final_point; }
+ virtual Curve* duplicate() const { return new EllipticalArc(*this); }
+ virtual void setInitial(Point const &p) {
+ _initial_point = p;
+ _updateCenterAndAngles(isSVGCompliant());
}
-
- void setExtremes( const Point& _initial_point, const Point& _final_point )
- {
- m_initial_point = _initial_point;
- m_final_point = _final_point;
- calculate_center_and_extreme_angles();
+ virtual void setFinal(Point const &p) {
+ _final_point = p;
+ _updateCenterAndAngles(isSVGCompliant());
}
-
- bool isDegenerate() const
- {
+ virtual bool isDegenerate() const {
return ( are_near(ray(X), 0) || are_near(ray(Y), 0) );
}
-
-
- virtual OptRect boundsFast() const
- {
+ virtual Rect boundsFast() const {
return boundsExact();
}
-
- virtual OptRect boundsExact() const;
-
+ virtual Rect boundsExact() const;
// TODO: native implementation of the following methods
- virtual OptRect boundsLocal(OptInterval i, unsigned int deg) const
- {
+ virtual OptRect boundsLocal(OptInterval const &i, unsigned int deg) const {
return SBasisCurve(toSBasis()).boundsLocal(i, deg);
}
-
- std::vector<double> roots(double v, Dim2 d) const;
-
- std::vector<double>
- allNearestPoints( Point const& p, double from = 0, double to = 1 ) const;
-
- double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
- {
- if ( are_near(ray(X), ray(Y)) && are_near(center(), p) )
- {
- return from;
- }
- return allNearestPoints(p, from, to).front();
- }
-
- // TODO: native implementation of the following methods
- int winding(Point p) const
- {
- return SBasisCurve(toSBasis()).winding(p);
- }
-
- int degreesOfFreedom() const { return 7;}
-
- Curve *derivative() const;
-
- // TODO: native implementation of the following methods
- Curve *transformed(Matrix const &m) const
- {
- return SBasisCurve(toSBasis()).transformed(m);
- }
-
- std::vector<Point> pointAndDerivatives(Coord t, unsigned int n) const;
-
- D2<SBasis> toSBasis() const;
-
- bool containsAngle(Coord angle) const;
-
- double valueAtAngle(Coord t, Dim2 d) const;
-
- Point pointAtAngle(Coord t) const
- {
- double sin_rot_angle = std::sin(rotation_angle());
- double cos_rot_angle = std::cos(rotation_angle());
- Matrix m( ray(X) * cos_rot_angle, ray(X) * sin_rot_angle,
- -ray(Y) * sin_rot_angle, ray(Y) * cos_rot_angle,
- center(X), center(Y) );
- Point p( std::cos(t), std::sin(t) );
- return p * m;
+ virtual std::vector<double> roots(double v, Dim2 d) const;
+#ifdef HAVE_GSL
+ virtual std::vector<double> allNearestPoints( Point const& p, double from = 0, double to = 1 ) const;
+#endif
+ virtual double nearestPoint( Point const& p, double from = 0, double to = 1 ) const {
+ if ( are_near(ray(X), ray(Y)) && are_near(center(), p) ) {
+ return from;
+ }
+ return allNearestPoints(p, from, to).front();
}
-
- double valueAt(Coord t, Dim2 d) const
- {
- Coord tt = map_to_02PI(t);
- return valueAtAngle(tt, d);
+ virtual int degreesOfFreedom() const { return 7; }
+ virtual Curve *derivative() const;
+ virtual Curve *transformed(Affine const &m) const;
+
+ /**
+ * The size of the returned vector equals n+1.
+ */
+ virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned int n) const;
+
+ virtual D2<SBasis> toSBasis() const;
+ virtual double valueAt(Coord t, Dim2 d) const {
+ return valueAtAngle(angleAt(t), d);
}
-
- Point pointAt(Coord t) const
- {
- Coord tt = map_to_02PI(t);
- return pointAtAngle(tt);
+ virtual Point pointAt(Coord t) const {
+ return pointAtAngle(angleAt(t));
}
+ virtual Curve* portion(double f, double t) const;
+ virtual Curve* reverse() const;
+#endif
- std::pair<EllipticalArc, EllipticalArc>
- subdivide(Coord t) const
- {
- EllipticalArc* arc1 = static_cast<EllipticalArc*>(portion(0, t));
- EllipticalArc* arc2 = static_cast<EllipticalArc*>(portion(t, 1));
- assert( arc1 != NULL && arc2 != NULL);
- std::pair<EllipticalArc, EllipticalArc> arc_pair(*arc1, *arc2);
- delete arc1;
- delete arc2;
- return arc_pair;
- }
+protected:
+ void _updateCenterAndAngles(bool svg);
- Curve* portion(double f, double t) const;
-
- // the arc is the same but traversed in the opposite direction
- Curve* reverse() const
- {
- EllipticalArc* rarc = new EllipticalArc( *this );
- rarc->m_sweep = !m_sweep;
- rarc->m_initial_point = m_final_point;
- rarc->m_final_point = m_initial_point;
- rarc->m_start_angle = m_end_angle;
- rarc->m_end_angle = m_start_angle;
- return rarc;
- }
+ Point _initial_point, _final_point;
+ Point _rays, _center;
+ Angle _rot_angle;
+ bool _large_arc;
- double sweep_angle() const
- {
- Coord d = end_angle() - start_angle();
- if ( !sweep_flag() ) d = -d;
- if ( d < 0 )
- d += 2*M_PI;
- return d;
- }
-
- private:
- Coord map_to_02PI(Coord t) const;
+private:
Coord map_to_01(Coord angle) const;
- void calculate_center_and_extreme_angles();
- private:
- Point m_initial_point, m_final_point;
- double m_rx, m_ry, m_rot_angle;
- bool m_large_arc, m_sweep;
- double m_start_angle, m_end_angle;
- Point m_center;
-
}; // end class EllipticalArc
-
} // end namespace Geom
#endif // _2GEOM_ELLIPTICAL_ARC_H_
-
-
-
/*
Local Variables:
mode:c++
diff --git a/src/2geom/exception.h b/src/2geom/exception.h
index fd92ca5e1..12736d639 100644
--- a/src/2geom/exception.h
+++ b/src/2geom/exception.h
@@ -1,11 +1,17 @@
-#ifndef LIB2GEOM_EXCEPTION_HEADER
-#define LIB2GEOM_EXCEPTION_HEADER
-
/**
* \file
* \brief Defines the different types of exceptions that 2geom can throw.
*
- * Copyright 2007 Johan Engelen <goejendaagh@zonnet.nl>
+ * There are two main exception classes: LogicalError and RangeError.
+ * Logical errors are 2geom faults/bugs; RangeErrors are 'user' faults,
+ * e.g. invalid arguments to lib2geom methods.
+ * This way, the 'user' can distinguish between groups of exceptions
+ * ('user' is the coder that uses lib2geom)
+ *
+ * Several macro's are defined for easily throwing exceptions
+ * (e.g. THROW_CONTINUITYERROR).
+ */
+/* Copyright 2007 Johan Engelen <goejendaagh@zonnet.nl>
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -32,13 +38,18 @@
*
*/
+#ifndef LIB2GEOM_EXCEPTION_HEADER
+#define LIB2GEOM_EXCEPTION_HEADER
+
#include <exception>
#include <sstream>
#include <string>
namespace Geom {
-// Base exception class, all 2geom exceptions should be derived from this one.
+/**
+ * Base exception class, all 2geom exceptions should be derived from this one.
+ */
class Exception : public std::exception {
public:
Exception(const char * message, const char *file, const int line) {
@@ -58,10 +69,7 @@ protected:
#define THROW_EXCEPTION(message) throw(Geom::Exception(message, __FILE__, __LINE__))
//-----------------------------------------------------------------------
-// Two main exception classes: LogicalError and RangeError.
-// Logical errors are 2geom faults/bugs, RangeErrors are 'user' faults.
-// This way, the 'user' can distinguish between groups of exceptions
-// ('user' is the coder that uses lib2geom)
+
class LogicalError : public Exception {
public:
LogicalError(const char * message, const char *file, const int line)
diff --git a/src/2geom/forward.h b/src/2geom/forward.h
index adc099379..93a762022 100644
--- a/src/2geom/forward.h
+++ b/src/2geom/forward.h
@@ -1,11 +1,12 @@
/**
* \file
* \brief Contains forward declarations of 2geom types
- *
+ *//*
* Authors:
* Johan Engelen <goejendaagh@zonnet.nl>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
*
- * Copyright 2008 authors
+ * Copyright (C) 2008-2010 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -38,21 +39,34 @@
namespace Geom {
+// basic types
+typedef double Coord;
+class Point;
+class Interval;
+class OptInterval;
+class Line;
+class Ray;
+
+// fragments
+class Linear;
class Bezier;
-template <unsigned> class BezierCurve;
-template<> class BezierCurve<0>;
-typedef BezierCurve<2> QuadraticBezier;
-typedef BezierCurve<1> LineSegment;
-typedef BezierCurve<3> CubicBezier;
-class EllipticalArc;
-class SVGEllipticalArc;
+class SBasis;
+// curves
+class Curve;
+class SBasisCurve;
+class BezierCurve;
class HLineSegment;
class VLineSegment;
+class LineSegment;
+class EllipticalArc;
+class SVGEllipticalArc;
-typedef double Coord;
-class Point;
+// paths and path sequences
+class Path;
+typedef std::vector<Path> PathVector;
+// errors
class Exception;
class LogicalError;
class RangeError;
@@ -61,32 +75,27 @@ class InvariantsViolation;
class NotInvertible;
class ContinuityError;
-class Interval;
-class OptInterval;
-class Linear;
-class Hat;
-class Tri;
-
-class Matrix;
+// transforms
+class Affine;
class Translate;
class Rotate;
class Scale;
+class HShear;
+class VShear;
-class Curve;
-class Path;
-typedef std::vector<Path> PathVector;
-
-template <class> class D2;
+// templates
+template <typename> class D2;
template <typename> class Piecewise;
-class SBasis;
-class SBasisCurve;
typedef D2<Interval> Rect;
class OptRect;
class Shape;
class Region;
+class Hat;
+class Tri;
+// misc
class SVGPathSink;
template <typename> class SVGPathGenerator;
diff --git a/src/2geom/hvlinesegment.h b/src/2geom/hvlinesegment.h
index 6a9edbcea..9419be8f6 100644
--- a/src/2geom/hvlinesegment.h
+++ b/src/2geom/hvlinesegment.h
@@ -39,127 +39,37 @@
namespace Geom
{
-class HLineSegment : public Curve
+template <Dim2 axis>
+class AxisLineSegment : public LineSegment
{
- public:
- HLineSegment()
- {}
-
- HLineSegment(Coord _x0, Coord _x1, Coord _y)
- : m_line_seg(Point(_x0, _y), Point(_x1, _y))
- {
- }
-
- HLineSegment(Point const& _p, double _length)
- : m_line_seg(_p, Point(_p[X] + _length, _p[Y]))
- {
- }
-
- HLineSegment(Point const& _p0, Point const& _p1)
- : m_line_seg(_p0, _p1)
- {
- if ( _p0[Y] != _p1[Y] )
- {
- THROW_RANGEERROR("HLineSegment::HLineSegment passed points should "
- "have the same Y value");
- }
- }
-
- Curve* duplicate() const
- {
- return new HLineSegment(*this);
- }
-
- bool isDegenerate() const
- {
- return m_line_seg.isDegenerate();
- }
-
- Point initialPoint() const
- {
- return m_line_seg.initialPoint();
- }
-
- Point finalPoint() const
- {
- return m_line_seg.finalPoint();
- }
-
- Coord getY()
- {
- return initialPoint()[Y];
- }
-
- void setInitial(Point _p)
- {
- m_line_seg.setInitial( Point(_p[X], initialPoint()[Y]) );
- }
-
- void setFinal(Point _p)
- {
- m_line_seg.setFinal( Point(_p[X], finalPoint()[Y]) );
- }
-
- void setX0(Coord _x)
- {
- m_line_seg.setInitial( Point(_x, initialPoint()[Y]) );
- }
-
- void setX1(Coord _x)
- {
- m_line_seg.setFinal( Point(_x, finalPoint()[Y]) );
- }
-
- void setY(Coord _y)
- {
- m_line_seg.setInitial( Point(initialPoint()[X], _y) );
- m_line_seg.setFinal( Point(finalPoint()[X], _y) );
- }
-
- virtual OptRect boundsFast() const
- {
- return boundsExact();
- }
-
- virtual OptRect boundsExact() const
- {
- return Rect( initialPoint(), finalPoint() );
- }
-
- virtual OptRect boundsLocal(OptInterval i, unsigned deg) const
- {
- return m_line_seg.boundsLocal(i, deg);
- }
-
- int winding(Point p) const
- {
- return m_line_seg.winding(p);
- }
-
- int degreesOfFreedom() const { return 3;}
-
- std::vector<double>
- roots(double v, Dim2 d) const
- {
- if (d < 0 || d > 1)
- {
- THROW_RANGEERROR("dimension argument out of range");
- }
- std::vector<double> result;
- if (d == X)
- {
- if ( v >= initialPoint()[X] && v <= finalPoint()[X] )
- {
- double t = 0;
+public:
+ static const Dim2 other_axis = static_cast<Dim2>((axis + 1) % 2);
+ virtual void setInitial(Point const &p) {
+ Point f = finalPoint();
+ f[axis] = p[axis];
+ LineSegment::setInitial(p);
+ LineSegment::setFinal(f);
+ }
+ virtual void setFinal(Point const &p) {
+ Point i = initialPoint();
+ i[axis] = p[axis];
+ LineSegment::setFinal(p);
+ LineSegment::setInitial(i);
+ }
+ virtual Rect boundsFast() const { return boundsExact(); }
+ virtual Rect boundsExact() const { Rect r(initialPoint(), finalPoint()); return r; }
+ virtual int degreesOfFreedom() const { return 3; }
+ virtual std::vector<Coord> roots(Coord v, Dim2 d) const {
+ std::vector<Coord> result;
+ if (d == axis) {
+ if ( v >= initialPoint()[axis] && v <= finalPoint()[axis] ) {
+ Coord t = 0;
if (!isDegenerate())
- t = (v - initialPoint()[X]) / (finalPoint()[X] - initialPoint()[X]);
+ t = (v - initialPoint()[axis]) / (finalPoint()[axis] - initialPoint()[axis]);
result.push_back(t);
}
- }
- else
- {
- if (v == initialPoint()[Y])
- {
+ } else {
+ if (v == initialPoint()[other_axis]) {
if (!isDegenerate())
THROW_INFINITESOLUTIONS(0);
result.push_back(0);
@@ -167,270 +77,161 @@ class HLineSegment : public Curve
}
return result;
}
-
- double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
- {
+ virtual Coord nearestPoint( Point const &p, Coord from = 0, Coord to = 1 ) const {
if ( from > to ) std::swap(from, to);
- double xfrom = pointAt(from)[X];
- double xto = pointAt(to)[X];
- if ( xfrom > xto )
- {
+ Coord xfrom = valueAt(from, axis);
+ Coord xto = valueAt(to, axis);
+ if ( xfrom > xto ) {
std::swap(xfrom, xto);
std::swap(from, to);
}
- if ( p[X] > xfrom && p[X] < xto )
- {
- return (p[X] - initialPoint()[X]) / (finalPoint()[X] - initialPoint()[X]);
+ if ( p[axis] > xfrom && p[axis] < xto ) {
+ return (p[axis] - initialPoint()[axis]) / (finalPoint()[axis] - initialPoint()[axis]);
}
else if ( p[X] <= xfrom )
return from;
else
return to;
}
-
- std::pair<HLineSegment, HLineSegment> subdivide(Coord t) const
- {
- std::pair<HLineSegment, HLineSegment> result;
- Point p = pointAt(t);
- result.first.setInitial(initialPoint());
- result.first.setFinal(p);
- result.second.setInitial(p);
- result.second.setFinal(finalPoint());
- return result;
- }
-
- Curve* portion(double f, double t) const
- {
- Point ip = pointAt(f);
- Point ep = pointAt(t);
- return new HLineSegment(ip[X], ep[X], ip[Y]);
- }
-
- Curve* reverse() const
- {
- return
- new HLineSegment(finalPoint()[X], initialPoint()[X], initialPoint()[Y]);
- }
-
- Curve* transformed(Matrix const & m) const
- {
- Point ip = initialPoint() * m;
- Point ep = finalPoint() * m;
- if (ip[Y] == ep[Y]) {
- return new HLineSegment(ip[X], ep[X], ip[Y]);
- } else {
- return new LineSegment(ip, ep);
- }
- }
-
- Curve* derivative() const
- {
- double x = finalPoint()[X] - initialPoint()[X];
- return new HLineSegment(x, x, 0);
- }
-
- Point pointAt(double t) const
- {
+ virtual Point pointAt(Coord t) const {
if ( t < 0 || t > 1 )
- THROW_RANGEERROR("domain parameter out of range");
- double x = initialPoint()[X] + t * (finalPoint()[X] - initialPoint()[X]);
- return Point(x, initialPoint()[Y]);
+ THROW_RANGEERROR("HLineSegment: Time value out of range");
+ Coord x = initialPoint()[axis] + t * (finalPoint()[axis] - initialPoint()[axis]);
+ Point ret(x, initialPoint()[other_axis]);
+ return ret;
}
-
- double valueAt(double t, Dim2 d) const
- {
- if (d < 0 || d > 1)
- {
- THROW_RANGEERROR("dimension argument out of range");
- }
+ virtual Coord valueAt(Coord t, Dim2 d) const {
if ( t < 0 || t > 1 )
- THROW_RANGEERROR("domain parameter out of range");
-
- if (d == Y) return initialPoint()[Y];
-
- return initialPoint()[X] + t * (finalPoint()[X] - initialPoint()[X]);
+ THROW_RANGEERROR("HLineSegment: Time value out of range");
+ if (d != axis) return initialPoint()[other_axis];
+ return initialPoint()[axis] + t * (finalPoint()[axis] - initialPoint()[axis]);
}
- std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const
- {
+ /**
+ * The size of the returned vector equals n+1.
+ */
+ virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const {
std::vector<Point> result;
result.push_back(pointAt(t));
- if (n > 0)
- {
- double x = finalPoint()[X] - initialPoint()[X];
+ if (n > 0) {
+ Coord x = finalPoint()[axis] - initialPoint()[axis];
result.push_back( Point(x, 0) );
}
- if (n > 1)
- {
+ if (n > 1) {
/* higher order derivatives are zero,
* so the other n-1 vector elements are (0,0) */
result.insert( result.end(), n-1, Point(0, 0) );
}
return result;
}
+protected:
+ AxisLineSegment(Point const &p0, Point const &p1) : LineSegment(p0, p1) {}
+ AxisLineSegment() {}
+};
- D2<SBasis> toSBasis() const
- {
- return m_line_seg.toSBasis();
- }
-
- private:
- LineSegment m_line_seg;
-
-}; // end class HLineSegment
-
-
-class VLineSegment : public Curve
+class HLineSegment : public AxisLineSegment<X>
{
- public:
- VLineSegment()
+public:
+ HLineSegment() {}
+ HLineSegment(Coord x0, Coord x1, Coord y)
+ : AxisLineSegment<X>(Point(x0, y), Point(x1, y))
{}
- VLineSegment(Coord _x, Coord _y0, Coord _y1)
- : m_line_seg(Point(_x, _y0), Point(_x, _y1))
- {
- }
-
- VLineSegment(Point const& _p, double _length)
- : m_line_seg(_p, Point(_p[X], _p[Y] + _length))
- {
- }
+ HLineSegment(Point const& p, Coord len)
+ : AxisLineSegment<X>(p, Point(p[X] + len, p[Y]))
+ {}
- VLineSegment(Point const& _p0, Point const& _p1)
- : m_line_seg(_p0, _p1)
+ HLineSegment(Point const& p0, Point const& p1)
+ : AxisLineSegment<X>(p0, p1)
{
- if ( _p0[X] != _p1[X] )
- {
- THROW_RANGEERROR("VLineSegment::VLineSegment passed points should "
- "have the same X value");
+ if ( p0[Y] != p1[Y] ) {
+ THROW_RANGEERROR("HLineSegment::HLineSegment passed points should "
+ "have the same Y value");
}
}
- Curve* duplicate() const
- {
- return new VLineSegment(*this);
+ Coord getY() { return initialPoint()[Y]; }
+ void setInitialX(Coord x) {
+ LineSegment::setInitial(Point(x, initialPoint()[Y]));
}
-
- bool isDegenerate() const
- {
- return m_line_seg.isDegenerate();
+ void setFinalX(Coord x) {
+ LineSegment::setFinal(Point(x, initialPoint()[Y]));
}
-
- Point initialPoint() const
- {
- return m_line_seg.initialPoint();
- }
-
- Point finalPoint() const
- {
- return m_line_seg.finalPoint();
+ void setY(Coord y) {
+ LineSegment::setInitial( Point(initialPoint()[X], y) );
+ LineSegment::setFinal( Point(finalPoint()[X], y) );
}
-
- Coord getX()
- {
- return initialPoint()[X];
+ std::pair<HLineSegment, HLineSegment> subdivide(Coord t) const {
+ std::pair<HLineSegment, HLineSegment> result;
+ Point p = pointAt(t);
+ result.first.setInitial(initialPoint());
+ result.first.setFinal(p);
+ result.second.setInitial(p);
+ result.second.setFinal(finalPoint());
+ return result;
}
- void setInitial(Point _p)
- {
- m_line_seg.setInitial( Point(initialPoint()[X], _p[Y]) );
+ virtual Curve* duplicate() const { return new HLineSegment(*this); }
+ virtual Curve *portion(Coord f, Coord t) const {
+ Point ip = pointAt(f);
+ Point ep = pointAt(t);
+ return new HLineSegment(ip[X], ep[X], ip[Y]);
}
-
- void setFinal(Point _p)
- {
- m_line_seg.setFinal( Point(finalPoint()[X], _p[Y]) );
+ virtual Curve *reverse() const {
+ Point ip = initialPoint();
+ return new HLineSegment(finalPoint()[X], ip[X], ip[Y]);
}
-
- void setY0(Coord _y)
- {
- m_line_seg.setInitial( Point(initialPoint()[X], _y) );
+ virtual Curve *transformed(Affine const & m) const {
+ Point ip = initialPoint() * m;
+ Point ep = finalPoint() * m;
+ // cannot afford to lose precision here since it can lead to discontinuous paths
+ if (m.isZoom(0)) {
+ return new HLineSegment(ip[X], ep[X], ip[Y]);
+ } else {
+ return new LineSegment(ip, ep);
+ }
}
-
- void setY1(Coord _y)
- {
- m_line_seg.setFinal( Point(finalPoint()[Y], _y) );
+ virtual Curve *derivative() const {
+ Coord x = finalPoint()[X] - initialPoint()[X];
+ return new HLineSegment(x, x, 0);
}
+}; // end class HLineSegment
- void setX(Coord _x)
- {
- m_line_seg.setInitial( Point(_x, initialPoint()[Y]) );
- m_line_seg.setFinal( Point(_x, finalPoint()[Y]) );
- }
- virtual OptRect boundsFast() const
- {
- return boundsExact();
- }
+class VLineSegment : public AxisLineSegment<Y>
+{
+public:
+ VLineSegment() {}
- virtual OptRect boundsExact() const
- {
- return Rect( initialPoint(), finalPoint() );
- }
+ VLineSegment(Coord x, Coord y0, Coord y1)
+ : AxisLineSegment<Y>(Point(x, y0), Point(x, y1))
+ {}
- virtual OptRect boundsLocal(OptInterval i, unsigned deg) const
- {
- return m_line_seg.boundsLocal(i, deg);
- }
+ VLineSegment(Point const& _p, Coord _length)
+ : AxisLineSegment<Y>(_p, Point(_p[X], _p[Y] + _length))
+ {}
- int winding(Point p) const
+ VLineSegment(Point const& _p0, Point const& _p1)
+ : AxisLineSegment<Y>(_p0, _p1)
{
- return m_line_seg.winding(p);
+ if ( _p0[X] != _p1[X] ) {
+ THROW_RANGEERROR("VLineSegment::VLineSegment passed points should "
+ "have the same X value");
+ }
}
-
- int degreesOfFreedom() const { return 3;}
- std::vector<double>
- roots(double v, Dim2 d) const
- {
- if (d < 0 || d > 1)
- {
- THROW_RANGEERROR("dimension argument out of range");
- }
- std::vector<double> result;
- if (d == Y)
- {
- if ( v >= initialPoint()[Y] && v <= finalPoint()[Y] )
- {
- double t = 0;
- if (!isDegenerate())
- t = (v - initialPoint()[Y]) / (finalPoint()[Y] - initialPoint()[Y]);
- result.push_back(t);
- }
- }
- else
- {
- if (v == initialPoint()[X])
- {
- if (!isDegenerate())
- THROW_INFINITESOLUTIONS(0);
- result.push_back(0);
- }
- }
- return result;
+ Coord getX() { return initialPoint()[X]; }
+ void setInitialY(Coord _y) {
+ LineSegment::setInitial( Point(initialPoint()[X], _y) );
}
-
- double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
- {
- if ( from > to ) std::swap(from, to);
- double yfrom = pointAt(from)[Y];
- double yto = pointAt(to)[Y];
- if (yfrom > yto)
- {
- std::swap(yfrom, yto);
- std::swap(from, to);
- }
- if ( p[Y] > yfrom && p[Y] < yto )
- {
- return (p[Y] - initialPoint()[Y]) / (finalPoint()[Y] - initialPoint()[Y]);
- }
- else if ( p[Y] <= yfrom )
- return from;
- else
- return to;
+ void setFinalY(Coord _y) {
+ LineSegment::setFinal( Point(finalPoint()[Y], _y) );
}
-
- std::pair<VLineSegment, VLineSegment> subdivide(Coord t) const
- {
+ void setX(Coord _x) {
+ LineSegment::setInitial( Point(_x, initialPoint()[Y]) );
+ LineSegment::setFinal( Point(_x, finalPoint()[Y]) );
+ }
+ std::pair<VLineSegment, VLineSegment> subdivide(Coord t) const {
std::pair<VLineSegment, VLineSegment> result;
Point p = pointAt(t);
result.first.setInitial(initialPoint());
@@ -440,88 +241,31 @@ class VLineSegment : public Curve
return result;
}
- Curve* portion(double f, double t) const
- {
+ virtual Curve *duplicate() const { return new VLineSegment(*this); }
+ virtual Curve *portion(Coord f, Coord t) const {
Point ip = pointAt(f);
- Point ep = pointAt(t);
- return new VLineSegment(ip[X], ip[Y], ep[Y]);
+ Coord epy = valueAt(t, Y);
+ return new VLineSegment(ip[X], ip[Y], epy);
}
-
- Curve* reverse() const
- {
- return
- new VLineSegment(initialPoint()[X], finalPoint()[Y], initialPoint()[Y]);
+ virtual Curve *reverse() const {
+ Point ip = initialPoint();
+ return new VLineSegment(ip[X], finalPoint()[Y], ip[Y]);
}
-
- Curve* transformed(Matrix const & m) const
- {
+ virtual Curve *transformed(Affine const & m) const {
Point ip = initialPoint() * m;
Point ep = finalPoint() * m;
- if (ip[X] == ep[X]) {
+ if (m.isZoom()) {
return new VLineSegment(ip[X], ip[Y], ep[Y]);
} else {
return new LineSegment(ip, ep);
}
}
-
- Curve* derivative() const
- {
- double y = finalPoint()[Y] - initialPoint()[Y];
+ virtual Curve* derivative() const {
+ Coord y = finalPoint()[Y] - initialPoint()[Y];
return new VLineSegment(0, y, y);
}
-
- Point pointAt(double t) const
- {
- if ( t < 0 || t > 1 )
- THROW_RANGEERROR("domain parameter out of range");
- double y = initialPoint()[Y] + t * (finalPoint()[Y] - initialPoint()[Y]);
- return Point(initialPoint()[X], y);
- }
-
- double valueAt(double t, Dim2 d) const
- {
- if (d < 0 || d > 1)
- {
- THROW_RANGEERROR("dimension argument out of range");
- }
- if ( t < 0 || t > 1 )
- THROW_RANGEERROR("domain parameter out of range");
-
- if (d == X) return initialPoint()[X];
-
- return initialPoint()[Y] + t * (finalPoint()[Y] - initialPoint()[Y]);
- }
-
- std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const
- {
- std::vector<Point> result;
- result.push_back(pointAt(t));
- if (n > 0)
- {
- double y = finalPoint()[Y] - initialPoint()[Y];
- result.push_back( Point(0, y) );
- }
- if (n > 1)
- {
- /* higher order derivatives are zero,
- * so the other n-1 vector elements are (0,0) */
- result.insert( result.end(), n-1, Point(0, 0) );
- }
- return result;
- }
-
- D2<SBasis> toSBasis() const
- {
- return m_line_seg.toSBasis();
- }
-
- private:
- LineSegment m_line_seg;
-
}; // end class VLineSegment
-
-
} // end namespace Geom
diff --git a/src/2geom/interval.h b/src/2geom/interval.h
index 68a406318..a790a6c3b 100644
--- a/src/2geom/interval.h
+++ b/src/2geom/interval.h
@@ -1,7 +1,7 @@
/**
* \file
* \brief Simple closed interval class
- *
+ *//*
* Copyright 2007 Michael Sloan <mgsloan@gmail.com>
*
* Original Rect/Range code by:
@@ -34,216 +34,295 @@
* the specific language governing rights and limitations.
*
*/
-#ifndef SEEN_INTERVAL_H
-#define SEEN_INTERVAL_H
+#ifndef LIB2GEOM_SEEN_INTERVAL_H
+#define LIB2GEOM_SEEN_INTERVAL_H
#include <assert.h>
+#include <boost/none.hpp>
+#include <boost/optional.hpp>
+#include <boost/operators.hpp>
#include <2geom/coord.h>
-
-#include <boost/optional/optional.hpp>
+#include <2geom/isnan.h>
namespace Geom {
-class Interval;
+class OptInterval;
/**
- * \brief This class represents a range of numbers that is never empty.
+ * @brief Range of numbers that is never empty.
+ *
+ * Intervals are closed ranges \f$[a, b]\f$, which means they include their endpoints.
+ * To use them as open ranges, you can use the interiorContains() methods.
*
- * The endpoints are included in the range.
+ * @ingroup Primitives
*/
-class Interval {
+class Interval
+ : boost::equality_comparable< Interval
+ , boost::additive< Interval
+ , boost::multipliable< Interval
+ , boost::arithmetic< Interval, Coord
+ , boost::orable< Interval
+ > > > > >
+{
private:
+ /// @invariant _b[0] <= _b[1]
Coord _b[2];
public:
- /// The default constructor creates an interval [0,0] DO NOT RELY ON THIS, BEST NOT TO USE THIS CONSTRUCTOR
+ /// @name Create intervals.
+ /// @{
+ /** @brief Create an interval that contains only zero. */
explicit Interval() { _b[0] = 0; _b[1] = 0; }
+ /** @brief Create an interval that contains a single point. */
explicit Interval(Coord u) { _b[0] = _b[1] = u; }
- /* When creating an Interval using the constructor specifying the exact range, the created interval
- * will be [u,v] when u<=v ; and will be [v,u] when v < u !!!
- */
+ /** @brief Create an interval that contains all points between @c u and @c v. */
Interval(Coord u, Coord v) {
- if(u < v) {
+ if (u <= v) {
_b[0] = u; _b[1] = v;
} else {
_b[0] = v; _b[1] = u;
}
}
-
- double operator[](unsigned i) const {
- assert(i < 2);
- return _b[i];
- }
- inline double& operator[](unsigned i) { return _b[i]; } //Trust the user...
-
- inline Coord min() const { return _b[0]; }
- inline Coord max() const { return _b[1]; }
- inline Coord extent() const { return _b[1] - _b[0]; }
- inline Coord middle() const { return (_b[1] + _b[0]) * 0.5; }
-
-// inline bool isEmpty() const { return _b[0] > _b[1]; }
- inline bool isSingular() const { return _b[0] == _b[1]; }
- inline bool contains(Coord val) const { return _b[0] <= val && val <= _b[1]; }
- bool contains(const Interval & val) const { return _b[0] <= val._b[0] && val._b[1] <= _b[1]; }
- bool intersects(const Interval & val) const {
- return contains(val._b[0]) || contains(val._b[1]) || val.contains(*this);
- }
-
- inline bool operator==(Interval other) const { return _b[0] == other._b[0] && _b[1] == other._b[1]; }
- inline bool operator!=(Interval other) const { return _b[0] != other._b[0] || _b[1] != other._b[1]; }
-
- //IMPL: OffsetableConcept
- //TODO: rename output_type to something else in the concept
- typedef Coord output_type;
- inline Interval operator+(Coord amnt) {
- return Interval(_b[0] + amnt, _b[1] + amnt);
- }
- inline Interval operator-(Coord amnt) {
- return Interval(_b[0] - amnt, _b[1] - amnt);
+
+ /** @brief Create an interval containing a range of values.
+ * The resulting interval will contain all values from the given range.
+ * The return type of iterators must be convertible to Coord. The given range
+ * must not be empty. For potentially empty ranges, see OptInterval.
+ * @param start Beginning of the range
+ * @param end End of the range
+ * @return Interval that contains all values from [start, end). */
+ template <typename InputIterator>
+ static Interval from_range(InputIterator start, InputIterator end) {
+ assert(start != end);
+ Interval result(*start++);
+ for (; start != end; ++start) result.expandTo(*start);
+ return result;
}
- inline Interval operator+=(Coord amnt) {
- _b[0] += amnt; _b[1] += amnt;
- return *this;
+ /** @brief Create an interval from a C-style array of values it should contain. */
+ static Interval from_array(Coord const *c, unsigned n) {
+ Interval result = from_range(c, c+n);
+ return result;
}
- inline Interval operator-=(Coord amnt) {
- _b[0] -= amnt; _b[1] -= amnt;
- return *this;
+ /// @}
+
+ /// @name Inspect endpoints.
+ /// @{
+ Coord operator[](unsigned i) const { return _b[i]; }
+ Coord& operator[](unsigned i) { return _b[i]; }
+
+ Coord min() const { return _b[0]; }
+ Coord max() const { return _b[1]; }
+ Coord extent() const { return _b[1] - _b[0]; }
+ Coord middle() const { return (_b[1] + _b[0]) * 0.5; }
+ bool isSingular() const { return _b[0] == _b[1]; }
+ bool isFinite() const {
+ return IS_FINITE(_b[0]) && IS_FINITE(_b[1]);
}
-
- //IMPL: ScalableConcept
- inline Interval operator-() const { return Interval(*this); }
- inline Interval operator*(Coord s) const { return Interval(_b[0]*s, _b[1]*s); }
- inline Interval operator/(Coord s) const { return Interval(_b[0]/s, _b[1]/s); }
- Interval operator*=(Coord s) {
- if(s < 0) {
- Coord temp = _b[0];
- _b[0] = _b[1]*s;
- _b[1] = temp*s;
- } else {
- _b[0] *= s;
- _b[1] *= s;
- }
- return *this;
+ /// @}
+
+ /// @name Test coordinates and other intervals for inclusion.
+ /// @{
+ /** @brief Check whether the interval includes this number. */
+ bool contains(Coord val) const { return _b[0] <= val && val <= _b[1]; }
+ /** @brief Check whether the interior of the interval includes this number.
+ * Interior means all numbers in the interval except its ends. */
+ bool interiorContains(Coord val) const { return _b[0] < val && val < _b[1]; }
+ /** @brief Check whether the interval includes the given interval. */
+ bool contains(Interval const &val) const { return _b[0] <= val._b[0] && val._b[1] <= _b[1]; }
+ /** @brief Check whether the interior of the interval includes the given interval.
+ * Interior means all numbers in the interval except its ends. */
+ bool interiorContains(Interval const &val) const { return _b[0] < val._b[0] && val._b[1] < _b[1]; }
+ /** @brief Check whether the intervals have any common elements. */
+ bool intersects(Interval const &val) const {
+ return contains(val._b[0]) || contains(val._b[1]) || val.contains(*this);
}
- Interval operator/=(Coord s) {
- //TODO: what about s=0?
- if(s < 0) {
- Coord temp = _b[0];
- _b[0] = _b[1]/s;
- _b[1] = temp/s;
- } else {
- _b[0] /= s;
- _b[1] /= s;
- }
- return *this;
+ /** @brief Check whether the interiors of the intervals have any common elements. */
+ bool interiorIntersects(Interval const &val) const {
+ return interiorContains(val._b[0]) || interiorContains(val._b[1]) || val.interiorContains(*this);
}
-
+ /// @}
+
+ /// @name Modify the interval.
+ /// @{
//TODO: NaN handleage for the next two?
- //TODO: Evaluate if wrap behaviour is proper.
- //If val > max, then rather than becoming a min==max range, it 'wraps' over
+ /** @brief Set the lower boundary of the interval.
+ * When the given number is larger than the interval's largest element,
+ * it will be reduced to the single number @c val. */
void setMin(Coord val) {
if(val > _b[1]) {
- _b[0] = _b[1];
- _b[1] = val;
+ _b[0] = _b[1] = val;
} else {
_b[0] = val;
}
}
- //If val < min, then rather than becoming a min==max range, it 'wraps' over
+ /** @brief Set the upper boundary of the interval.
+ * When the given number is smaller than the interval's smallest element,
+ * it will be reduced to the single number @c val. */
void setMax(Coord val) {
if(val < _b[0]) {
- _b[1] = _b[0];
- _b[0] = val;
+ _b[1] = _b[0] = val;
} else {
_b[1] = val;
}
}
-
- inline void extendTo(Coord val) {
+ /** @brief Extend the interval to include the given number. */
+ void expandTo(Coord val) {
if(val < _b[0]) _b[0] = val;
if(val > _b[1]) _b[1] = val; //no else, as we want to handle NaN
}
-
- static Interval fromArray(const Coord* c, int n) {
- assert(n > 0);
- Interval result(c[0]);
- for(int i = 1; i < n; i++) result.extendTo(c[i]);
- return result;
- }
-
- /** When this would create an empty interval, the interval will be the centerpoint of the old range only.
- */
- inline void expandBy(double amnt) {
- _b[0] -= amnt;
- _b[1] += amnt;
+ /** @brief Expand or shrink the interval in both directions by the given amount.
+ * After this method, the interval's length (extent) will be increased by
+ * <code>amount * 2</code>. Negative values can be given; they will shrink the interval.
+ * Shrinking by a value larger than half the interval's length will create a degenerate
+ * interval containing only the midpoint of the original. */
+ void expandBy(double amount) {
+ _b[0] -= amount;
+ _b[1] += amount;
if (_b[0] > _b[1]) {
Coord halfway = (_b[0]+_b[1])/2;
_b[0] = _b[1] = halfway;
}
}
-
- inline void unionWith(const Interval & a) {
+ /** @brief Union the interval with another one.
+ * The resulting interval will contain all points of both intervals.
+ * It might also contain some points which didn't belong to either - this happens
+ * when the intervals did not have any common elements. */
+ void unionWith(const Interval & a) {
if(a._b[0] < _b[0]) _b[0] = a._b[0];
if(a._b[1] > _b[1]) _b[1] = a._b[1];
}
-};
-
-//IMPL: AddableConcept
-inline Interval operator+(const Interval & a, const Interval & b) {
- return Interval(a.min() + b.min(), a.max() + b.max());
-}
-inline Interval operator-(const Interval & a, const Interval & b) {
- return Interval(a.min() - b.max(), a.max() - b.min());
-}
-inline Interval operator+=(Interval & a, const Interval & b) { a = a + b; return a; }
-inline Interval operator-=(Interval & a, const Interval & b) { a = a - b; return a; }
-
-//There might be impls of this based off sign checks
-inline Interval operator*(const Interval & a, const Interval & b) {
- Interval res(a.min() * b.min());
- res.extendTo(a.min() * b.max());
- res.extendTo(a.max() * b.min());
- res.extendTo(a.max() * b.max());
- return res;
-}
-inline Interval operator*=(Interval & a, const Interval & b) { a = a * b; return a; }
+ /// @}
-/* reinstate if useful (doesn't do the proper thing for 0 inclusion)
-inline Interval operator/(const Interval & a, const Interval & b) {
- Interval res(a.min() / b.min());
- res.extendTo(a.min() / b.max());
- res.extendTo(a.max() / b.min());
- res.extendTo(a.max() / b.max());
- return res;
-}
-inline Interval operator/=(Interval & a, const Interval & b) { a = a / b; return a; }
-*/
+ /// @name Operators
+ /// @{
+ inline operator OptInterval();
+ bool operator==(Interval const &other) const { return _b[0] == other._b[0] && _b[1] == other._b[1]; }
+
+ //IMPL: OffsetableConcept
+ //TODO: rename output_type to something else in the concept
+ typedef Coord output_type;
+ /** @brief Offset the interval by a specified amount */
+ Interval &operator+=(Coord amnt) {
+ _b[0] += amnt; _b[1] += amnt;
+ return *this;
+ }
+ /** @brief Offset the interval by the negation of the specified amount */
+ Interval &operator-=(Coord amnt) {
+ _b[0] -= amnt; _b[1] -= amnt;
+ return *this;
+ }
+
+ // IMPL: ScalableConcept
+ /** @brief Return an interval mirrored about 0 */
+ Interval operator-() const { return Interval(-_b[1], -_b[0]); }
+ /** @brief Scale an interval */
+ Interval &operator*=(Coord s) {
+ _b[0] *= s;
+ _b[1] *= s;
+ if(s < 0) std::swap(_b[0], _b[1]);
+ return *this;
+ }
+ /** @brief Scale an interval by the inverse of the specified value */
+ Interval &operator/=(Coord s) {
+ _b[0] /= s;
+ _b[1] /= s;
+ if(s < 0) std::swap(_b[0], _b[1]);
+ return *this;
+ }
+ // IMPL: AddableConcept
+ /** @brief Add two intervals.
+ * Sum is defined as the set of points that can be obtained by adding any two values
+ * from both operands: \f$S = \{x \in A, y \in B: x + y\}\f$ */
+ Interval &operator+=(Interval const &o) {
+ _b[0] += o._b[0];
+ _b[1] += o._b[1];
+ return *this;
+ }
+ /** @brief Subtract two intervals.
+ * Difference is defined as the set of points that can be obtained by subtracting
+ * any value from the second operand from any value from the first operand:
+ * \f$S = \{x \in A, y \in B: x - y\}\f$ */
+ Interval &operator-=(Interval const &o) {
+ // equal to *this += -o
+ _b[0] -= o._b[1];
+ _b[1] -= o._b[0];
+ return *this;
+ }
+ /** @brief Multiply two intervals.
+ * Product is defined as the set of points that can be obtained by multiplying
+ * any value from the second operand by any value from the first operand:
+ * \f$S = \{x \in A, y \in B: x * y\}\f$ */
+ Interval &operator*=(Interval const &o) {
+ // TODO implement properly
+ Coord mn = min(), mx = max();
+ expandTo(mn * o.min());
+ expandTo(mn * o.max());
+ expandTo(mx * o.min());
+ expandTo(mx * o.max());
+ return *this;
+ }
+ /** @brief Union two intervals.
+ * Note that intersection is only defined for OptIntervals, because the result
+ * of an intersection can be empty, while an Interval cannot. */
+ Interval &operator|=(Interval const &o) {
+ unionWith(o);
+ return *this;
+ }
+ /// @}
+};
-// 'union' conflicts with C keyword
-inline Interval unify(const Interval & a, const Interval & b) {
- return Interval(std::min(a.min(), b.min()),
- std::max(a.max(), b.max()));
+/** @brief Union two intervals
+ * @relates Interval */
+inline Interval unify(Interval const &a, Interval const &b) {
+ return a | b;
}
/**
- * \brief OptInterval is an Interval that can be empty.
+ * @brief A range of numbers that can be empty.
+ * @ingroup Primitives
*/
-class OptInterval : public boost::optional<Interval> {
+class OptInterval
+ : public boost::optional<Interval>
+ , boost::orable< OptInterval
+ , boost::andable< OptInterval
+ > >
+{
public:
+ /// @name Create optionally empty intervals.
+ /// @{
+ /** @brief Create an empty interval. */
OptInterval() : boost::optional<Interval>() {};
+ /** @brief Wrap an existing interval. */
OptInterval(Interval const &a) : boost::optional<Interval>(a) {};
+ /** @brief Create an interval containing a single point. */
OptInterval(Coord u) : boost::optional<Interval>(Interval(u)) {};
+ /** @brief Create an interval containing a range of numbers. */
OptInterval(Coord u, Coord v) : boost::optional<Interval>(Interval(u,v)) {};
- /**
- * Check whether this OptInterval is empty or not.
- */
- inline bool isEmpty() { return (*this == false); };
-
- /**
- * If \c this is empty, copy argument \c a. Otherwise, union with it (and do nothing when \c a is empty)
- */
- inline void unionWith(const OptInterval & a) {
+ /** @brief Create a possibly empty interval containing a range of values.
+ * The resulting interval will contain all values from the given range.
+ * The return type of iterators must be convertible to double. The given range
+ * may be empty.
+ * @param start Beginning of the range
+ * @param end End of the range
+ * @return Interval that contains all values from [start, end), or nothing if the range
+ * is empty. */
+ template <typename InputIterator>
+ static OptInterval from_range(InputIterator start, InputIterator end) {
+ if (start == end) {
+ OptInterval ret;
+ return ret;
+ }
+ OptInterval ret(Interval::from_range(start, end));
+ return ret;
+ }
+ /// @}
+
+ /** @brief Check whether this OptInterval is empty. */
+ bool isEmpty() { return !*this; };
+
+ /** @brief Union with another interval, gracefully handling empty ones. */
+ inline void unionWith(OptInterval const &a) {
if (a) {
if (*this) { // check that we are not empty
(*this)->unionWith(*a);
@@ -252,14 +331,41 @@ public:
}
}
}
+ inline void intersectWith(OptInterval const &o) {
+ if (o && *this) {
+ Coord u, v;
+ u = std::max((*this)->min(), o->min());
+ v = std::min((*this)->max(), o->max());
+ if (u <= v) {
+ *this = Interval(u, v);
+ return;
+ }
+ }
+ (*static_cast<boost::optional<Interval>*>(this)) = boost::none;
+ }
+ OptInterval &operator|=(OptInterval const &o) {
+ unionWith(o);
+ return *this;
+ }
+ OptInterval &operator&=(OptInterval const &o) {
+ intersectWith(o);
+ return *this;
+ }
};
-inline OptInterval intersect(const Interval & a, const Interval & b) {
- Coord u = std::max(a.min(), b.min()),
- v = std::min(a.max(), b.max());
- //technically >= might be incorrect, but singulars suck
- return u > v ? OptInterval()
- : OptInterval(Interval(u, v));
+/** @brief Intersect two intervals and return a possibly empty range of numbers
+ * @relates OptInterval */
+inline OptInterval intersect(Interval const &a, Interval const &b) {
+ return OptInterval(a) & OptInterval(b);
+}
+/** @brief Intersect two intervals and return a possibly empty range of numbers
+ * @relates OptInterval */
+inline OptInterval operator&(Interval const &a, Interval const &b) {
+ return OptInterval(a) & OptInterval(b);
+}
+
+inline Interval::operator OptInterval() {
+ return OptInterval(*this);
}
#ifdef _GLIBCXX_IOSTREAM
diff --git a/src/2geom/line.cpp b/src/2geom/line.cpp
index a91ff03a3..5ef8dfddc 100644
--- a/src/2geom/line.cpp
+++ b/src/2geom/line.cpp
@@ -37,6 +37,90 @@
namespace Geom
{
+/**
+ * @class Line
+ * @brief Infinite line on a plane.
+ *
+ * Every line in 2Geom has a special point on it, called the origin. The direction of the line
+ * is stored as a unit vector (versor). This way a line can be interpreted as a function
+ * \f$ f: (-\infty, \infty) \to \mathbb{R}^2\f$. Zero corresponds to the origin point,
+ * positive values to the points in the direction of the unit vector, and negative values
+ * to points in the opposite direction.
+ *
+ * @ingroup Primitives
+ */
+
+/** @brief Set the line by solving the line equation.
+ * A line is a set of points that satisfies the line equation
+ * \f$Ax + By + C = 0\f$. This function changes the line so that its points
+ * satisfy the line equation with the given coefficients. */
+void Line::setCoefficients (double a, double b, double c) {
+ if (a == 0 && b == 0) {
+ if (c != 0) {
+ THROW_LOGICALERROR("the passed coefficients gives the empty set");
+ }
+ m_versor = Point(0,0);
+ m_origin = Point(0,0);
+ } else {
+ double l = hypot(a,b);
+ a /= l;
+ b /= l;
+ c /= l;
+ Point N(a, b);
+ m_versor = N.ccw();
+ m_origin = -c * N;
+ }
+}
+
+/** @brief Get the line equation coefficients of this line.
+ * @return Vector with three values corresponding to the A, B and C
+ * coefficients of the line equation for this line. */
+std::vector<double> Line::coefficients() const {
+ std::vector<double> coeff;
+ coeff.reserve(3);
+ Point N = versor().cw();
+ coeff.push_back (N[X]);
+ coeff.push_back (N[Y]);
+ double d = - dot (N, origin());
+ coeff.push_back (d);
+ return coeff;
+}
+
+/** @brief Find intersection with an axis-aligned line.
+ * @param v Coordinate of the axis-aligned line
+ * @param d Which axis the coordinate is on. X means a vertical line, Y means a horizontal line.
+ * @return Time values at which this line intersects the query line. */
+std::vector<Coord> Line::roots(Coord v, Dim2 d) const {
+ if (d < 0 || d > 1)
+ THROW_RANGEERROR("Line::roots, dimension argument out of range");
+ std::vector<Coord> result;
+ if ( m_versor[d] != 0 )
+ {
+ result.push_back( (v - m_origin[d]) / m_versor[d] );
+ }
+ // TODO: else ?
+ return result;
+}
+
+/** @brief Get a time value corresponding to a point.
+ * @param p Point on the line. If the point is not on the line,
+ * the returned value will be meaningless.
+ * @return Time value t such that \f$f(t) = p\f$.
+ * @see timeAtProjection */
+Coord Line::timeAt(Point const& _point) const {
+ Coord t;
+ if ( m_versor[X] != 0 ) {
+ t = (_point[X] - m_origin[X]) / m_versor[X];
+ }
+ else if ( m_versor[Y] != 0 ) {
+ t = (_point[Y] - m_origin[Y]) / m_versor[Y];
+ }
+ else { // degenerate case
+ t = 0;
+ }
+ return t;
+}
+
namespace detail
{
@@ -55,18 +139,18 @@ OptCrossing intersection_impl(Point const& V1, Point const O1,
Crossing c;
c.ta = detBV2 * inv_detV1V2;
c.tb = detV1B * inv_detV1V2;
-// std::cerr << "ta = " << solution.ta << std::endl;
-// std::cerr << "tb = " << solution.tb << std::endl;
+// std::cerr << "ta = " << c.ta << std::endl;
+// std::cerr << "tb = " << c.tb << std::endl;
return OptCrossing(c);
}
OptCrossing intersection_impl(Ray const& r1, Line const& l2, unsigned int i)
{
- OptCrossing crossing =
+ OptCrossing crossing =
intersection_impl(r1.versor(), r1.origin(),
l2.versor(), l2.origin() );
-
+
if (crossing)
{
if (crossing->ta < 0)
@@ -97,7 +181,7 @@ OptCrossing intersection_impl( LineSegment const& ls1,
Line const& l2,
unsigned int i )
{
- OptCrossing crossing =
+ OptCrossing crossing =
intersection_impl(ls1.finalPoint() - ls1.initialPoint(),
ls1.initialPoint(),
l2.versor(),
@@ -135,7 +219,7 @@ OptCrossing intersection_impl( LineSegment const& ls1,
unsigned int i )
{
Point direction = ls1.finalPoint() - ls1.initialPoint();
- OptCrossing crossing =
+ OptCrossing crossing =
intersection_impl( direction,
ls1.initialPoint(),
r2.versor(),
@@ -143,9 +227,9 @@ OptCrossing intersection_impl( LineSegment const& ls1,
if (crossing)
{
- if ( crossing->getTime(0) < 0
- || crossing->getTime(0) > 1
- || crossing->getTime(1) < 0 )
+ if ( (crossing->getTime(0) < 0)
+ || (crossing->getTime(0) > 1)
+ || (crossing->getTime(1) < 0) )
{
return OptCrossing();
}
@@ -203,7 +287,7 @@ OptCrossing intersection_impl( LineSegment const& ls1,
OptCrossing intersection(Line const& l1, Line const& l2)
{
- OptCrossing crossing =
+ OptCrossing crossing =
detail::intersection_impl( l1.versor(), l1.origin(),
l2.versor(), l2.origin() );
if (crossing)
@@ -223,7 +307,7 @@ OptCrossing intersection(Line const& l1, Line const& l2)
OptCrossing intersection(Ray const& r1, Ray const& r2)
{
- OptCrossing crossing =
+ OptCrossing crossing =
detail::intersection_impl( r1.versor(), r1.origin(),
r2.versor(), r2.origin() );
@@ -333,6 +417,62 @@ OptCrossing intersection( LineSegment const& ls1, LineSegment const& ls2 )
}
+boost::optional<LineSegment> clip (Line const& l, Rect const& r)
+{
+ typedef boost::optional<LineSegment> opt_linesegment;
+ LineSegment result;
+ //size_t index = 0;
+ std::vector<Point> points;
+ LineSegment ls (r.corner(0), r.corner(1));
+ try
+ {
+ OptCrossing oc = intersection (ls, l);
+ if (oc)
+ {
+ points.push_back (l.pointAt (oc->tb));
+ }
+ }
+ catch (InfiniteSolutions e)
+ {
+ return opt_linesegment(ls);
+ }
+
+ for (size_t i = 2; i < 5; ++i)
+ {
+ ls.setInitial (ls[1]);
+ ls.setFinal (r.corner(i));
+ try
+ {
+ OptCrossing oc = intersection (ls, l);
+ if (oc)
+ {
+ points.push_back (l.pointAt (oc->tb));
+ if (points.size() > 1)
+ {
+ size_t sz = points.size();
+ if (!are_near (points[sz - 2], points[sz - 1], 1e-10))
+ {
+ result.setInitial (points[sz - 2]);
+ result.setFinal (points[sz - 1]);
+ return opt_linesegment(result);
+ }
+ }
+ }
+ }
+ catch (InfiniteSolutions e)
+ {
+ return opt_linesegment(ls);
+ }
+ }
+ if (points.size() != 0)
+ {
+ result.setInitial (points[0]);
+ result.setFinal (points[0]);
+ return opt_linesegment(result);
+ }
+ return opt_linesegment();
+}
+
Line make_angle_bisector_line(Line const& l1, Line const& l2)
{
@@ -359,6 +499,8 @@ Line make_angle_bisector_line(Line const& l1, Line const& l2)
}
+
+
} // end namespace Geom
diff --git a/src/2geom/line.h b/src/2geom/line.h
index a7e6a54bb..ccb0ae6c5 100644
--- a/src/2geom/line.h
+++ b/src/2geom/line.h
@@ -35,265 +35,278 @@
#include <cmath>
#include <2geom/bezier-curve.h> // for LineSegment
+#include <2geom/rect.h>
#include <2geom/crossing.h>
#include <2geom/exception.h>
#include <2geom/ray.h>
+#include <boost/optional.hpp>
+
namespace Geom
{
-class Line
-{
- public:
- Line()
- : m_origin(0,0), m_versor(1,0)
- {
- }
-
- Line(Point const& _origin, Coord angle )
- : m_origin(_origin), m_versor(std::cos(angle), std::sin(angle))
- {
- }
-
- Line(Point const& A, Point const& B)
- {
- setBy2Points(A, B);
- }
-
- explicit
- Line(LineSegment const& _segment)
- {
- setBy2Points(_segment.initialPoint(), _segment.finalPoint());
- }
-
- explicit
- Line(Ray const& _ray)
- : m_origin(_ray.origin()), m_versor(_ray.versor())
- {
- }
-
- static Line fromNormalDistance(Point n, double c) {
- Point P = n*c/(dot(n,n));
-
- return Line(P, P+rot90(n));
+class Line {
+private:
+ Point m_origin;
+ Point m_versor;
+public:
+ /// @name Creating lines.
+ /// @{
+ /** @brief Create a default horizontal line. */
+ Line()
+ : m_origin(0,0), m_versor(1,0)
+ {}
+ /** @brief Create a line with the specified inclination.
+ * @param _origin One of the points on the line
+ * @param angle Angle of the line in mathematical convention */
+ Line(Point const& _origin, Coord angle )
+ : m_origin(_origin)
+ {
+ sincos(angle, m_versor[Y], m_versor[X]);
+ }
+
+ /** @brief Create a line going through two points.
+ * @param A First point
+ * @param B Second point */
+ Line(Point const& A, Point const& B) {
+ setPoints(A, B);
}
- static Line fromPointDirection(Point o, Point v) {
+
+ /** @brief Create a line based on the coefficients of its equation.
+ @see Line::setCoefficients() */
+ Line(double a, double b, double c) {
+ setCoefficients(a, b, c);
+ }
+
+ /** @brief Create a line by extending a line segment. */
+ explicit Line(LineSegment const& _segment) {
+ setPoints(_segment.initialPoint(), _segment.finalPoint());
+ }
+
+ /** @brief Create a line by extending a ray. */
+ explicit Line(Ray const& _ray)
+ : m_origin(_ray.origin()), m_versor(_ray.versor())
+ {}
+
+ // huh?
+ static Line from_normal_distance(Point n, double c) {
+ Point P = n * c / dot(n,n);
+ Line l(P, P+rot90(n));
+ return l;
+ }
+ /** @brief Create a line from origin and unit vector.
+ * Note that each line direction has two possible unit vectors.
+ * @param o Point through which the line will pass
+ * @param v Unit vector of the line's direction */
+ static Line from_origin_and_versor(Point o, Point v) {
Line l;
l.m_origin = o;
l.m_versor = v;
return l;
}
- Line* duplicate() const
- {
- return new Line(*this);
- }
-
- Point origin() const
- {
- return m_origin;
- }
-
- Point versor() const
- {
- return m_versor;
- }
-
- void origin(Point const& _point)
- {
- m_origin = _point;
- }
-
- void versor(Point const& _versor)
- {
- m_versor = _versor;
- }
-
- // return the angle described by rotating the X-axis in cw direction
- // until it overlaps the line
- // the returned value is in the interval [0, PI[
- Coord angle() const
- {
- double a = std::atan2(m_versor[Y], m_versor[X]);
- if (a < 0) a += M_PI;
- if (a == M_PI) a = 0;
- return a;
- }
-
- void angle(Coord _angle)
- {
- m_versor[X] = std::cos(_angle);
- m_versor[Y] = std::sin(_angle);
- }
-
- void setBy2Points(Point const& A, Point const& B)
- {
- m_origin = A;
- m_versor = B - A;
- if ( are_near(m_versor, Point(0,0)) )
- m_versor = Point(0,0);
- else
- m_versor.normalize();
- }
-
- bool isDegenerate() const
- {
- return ( m_versor[X] == 0 && m_versor[Y] == 0 );
- }
-
- Point pointAt(Coord t) const
- {
- return m_origin + m_versor * t;
- }
-
- Coord valueAt(Coord t, Dim2 d) const
- {
- if (d < 0 || d > 1)
- THROW_RANGEERROR("Ray::valueAt, dimension argument out of range");
- return m_origin[d] + m_versor[d] * t;
- }
-
- std::vector<Coord> roots(Coord v, Dim2 d) const
- {
- if (d < 0 || d > 1)
- THROW_RANGEERROR("Ray::roots, dimension argument out of range");
- std::vector<Coord> result;
- if ( m_versor[d] != 0 )
- {
- result.push_back( (v - m_origin[d]) / m_versor[d] );
- }
- // TODO: else ?
- return result;
- }
-
- // require are_near(_point, *this)
- // on the contrary the result value is meaningless
- Coord timeAt(Point const& _point) const
- {
- Coord t;
- if ( m_versor[X] != 0 )
- {
- t = (_point[X] - m_origin[X]) / m_versor[X];
- }
- else if ( m_versor[Y] != 0 )
- {
- t = (_point[Y] - m_origin[Y]) / m_versor[Y];
- }
- else // degenerate case
- {
- t = 0;
- }
- return t;
- }
-
- Coord timeAtProjection(Point const& _point) const
- {
- if ( isDegenerate() ) return 0;
- return dot( _point - m_origin, m_versor );
- }
-
- Coord nearestPoint(Point const& _point) const
- {
- return timeAtProjection(_point);
- }
-
- Line reverse() const
- {
- Line result;
- result.origin(m_origin);
- result.versor(-m_versor);
- return result;
- }
-
- Curve* portion(Coord f, Coord t) const
- {
- LineSegment* seg = new LineSegment(pointAt(f), pointAt(t));
- return seg;
- }
-
- LineSegment segment(Coord f, Coord t) const
- {
- return LineSegment(pointAt(f), pointAt(t));
- }
-
- Ray ray(Coord t)
- {
- Ray result;
- result.origin(pointAt(t));
- result.versor(m_versor);
- return result;
- }
-
- Line derivative() const
- {
- Line result;
- result.origin(m_versor);
- result.versor(Point(0,0));
- return result;
- }
-
- Line transformed(Matrix const& m) const
- {
- return Line(m_origin * m, (m_origin + m_versor) * m);
- }
-
- static Line from_normal_and_dist(Point const &n, double d) {
- return Line(n*d, n*d + rot90(n));
+ Line* duplicate() const {
+ return new Line(*this);
+ }
+ /// @}
+
+ /// @name Retrieve and set the line's parameters.
+ /// @{
+ /** @brief Get the line's origin point. */
+ Point origin() const { return m_origin; }
+ /** @brief Get the line's direction unit vector. */
+ Point versor() const { return m_versor; }
+ // return the angle described by rotating the X-axis in cw direction
+ // until it overlaps the line
+ // the returned value is in the interval [0, PI[
+ Coord angle() const {
+ double a = std::atan2(m_versor[Y], m_versor[X]);
+ if (a < 0) a += M_PI;
+ if (a == M_PI) a = 0;
+ return a;
}
- private:
- Point m_origin;
- Point m_versor;
+ void setOrigin(Point const& _point) {
+ m_origin = _point;
+ }
+ void setVersor(Point const& _versor) {
+ m_versor = _versor;
+ }
+
+ void setAngle(Coord _angle) {
+ sincos(_angle, m_versor[Y], m_versor[X]);
+ }
+
+ /** @brief Set a line based on two points it should pass through. */
+ void setPoints(Point const& A, Point const& B) {
+ m_origin = A;
+ if ( are_near(A, B) )
+ m_versor = Point(0,0);
+ else
+ m_versor = B - A;
+ m_versor.normalize();
+ }
+ void setCoefficients (double a, double b, double c);
+ std::vector<double> coefficients() const;
+
+ /** @brief Check if the line has any points.
+ * A degenerate line can be created if the line is created from a line equation
+ * that has no solutions.
+ * @return True if the line has no points */
+ bool isDegenerate() const {
+ return ( m_versor[X] == 0 && m_versor[Y] == 0 );
+ }
+ /// @}
+
+ /// @name Evaluate the line as a function.
+ ///@{
+ Point pointAt(Coord t) const {
+ return m_origin + m_versor * t;
+ }
+
+ Coord valueAt(Coord t, Dim2 d) const {
+ if (d < 0 || d > 1)
+ THROW_RANGEERROR("Line::valueAt, dimension argument out of range");
+ return m_origin[d] + m_versor[d] * t;
+ }
+
+ Coord timeAt(Point const &p) const;
+
+ /** @brief Get a time value corresponding to a projection of a point on the line.
+ * @param p Arbitrary point.
+ * @return Time value corresponding to a point closest to @c p. */
+ Coord timeAtProjection(Point const& p) const {
+ if ( isDegenerate() ) return 0;
+ return dot( p - m_origin, m_versor );
+ }
+
+ /** @brief Find a point on the line closest to the query point.
+ * This is an alias for timeAtProjection(). */
+ Coord nearestPoint(Point const& _point) const {
+ return timeAtProjection(_point);
+ }
+
+ std::vector<Coord> roots(Coord v, Dim2 d) const;
+ /// @}
+
+ /// @name Create other objects based on this line.
+ /// @{
+ /** @brief Create a line containing the same points, but with negated time values.
+ * @return Line \f$g\f$ such that \f$g(t) = f(-t)\f$ */
+ Line reverse() const
+ {
+ Line result;
+ result.setOrigin(m_origin);
+ result.setVersor(-m_versor);
+ return result;
+ }
+
+ /** @brief Same as segment(), but allocate the line segment dynamically. */
+ // TODO remove this?
+ Curve* portion(Coord f, Coord t) const {
+ LineSegment* seg = new LineSegment(pointAt(f), pointAt(t));
+ return seg;
+ }
+
+ /** @brief Create a segment of this line.
+ * @param f Time value for the initial point of the segment
+ * @param t Time value for the final point of the segment
+ * @return Created line segment */
+ LineSegment segment(Coord f, Coord t) const {
+ return LineSegment(pointAt(f), pointAt(t));
+ }
+
+ /** @brief Create a ray starting at the specified time value.
+ * The created ray will go in the direction of the line's versor (in the direction
+ * of increasing time values).
+ * @param t Time value where the ray should start
+ * @return Ray starting at t and going in the direction of the versor */
+ Ray ray(Coord t) {
+ Ray result;
+ result.origin(pointAt(t));
+ result.versor(m_versor);
+ return result;
+ }
+
+ /** @brief Create a derivative of the line.
+ * The new line will always be degenerate. Its origin will be equal to this
+ * line's versor. */
+ Line derivative() const {
+ Line result;
+ result.setOrigin(m_versor);
+ result.setVersor(Point(0,0));
+ return result;
+ }
+
+ /** @brief Create a line transformed by an affine transformation. */
+ Line transformed(Affine const& m) const {
+ return Line(m_origin * m, (m_origin + m_versor) * m);
+ }
+
+ /** @brief Get a vector normal to the line.
+ * If Y grows upwards, then this is the left normal. If Y grows downwards,
+ * then this is the right normal. */
+ Point normal() const {
+ return rot90(m_versor);
+ }
+
+ // what does this do?
+ Point normalAndDist(double & dist) const {
+ Point n = normal();
+ dist = -dot(n, m_origin);
+ return n;
+ }
+ /// @}
}; // end class Line
inline
double distance(Point const& _point, Line const& _line)
{
- if ( _line.isDegenerate() )
- {
- return distance( _point, _line.origin() );
- }
- else
- {
- return fabs( dot(_point - _line.origin(), _line.versor().ccw()) );
- }
+ if ( _line.isDegenerate() )
+ {
+ return ::Geom::distance( _point, _line.origin() );
+ }
+ else
+ {
+ return fabs( dot(_point - _line.origin(), _line.versor().ccw()) );
+ }
}
inline
bool are_near(Point const& _point, Line const& _line, double eps = EPSILON)
{
- return are_near(distance(_point, _line), 0, eps);
+ return are_near(distance(_point, _line), 0, eps);
}
inline
bool are_parallel(Line const& l1, Line const& l2, double eps = EPSILON)
{
- return ( are_near(l1.versor(), l2.versor(), eps)
- || are_near(l1.versor(), -l2.versor(), eps) );
+ return ( are_near(l1.versor(), l2.versor(), eps)
+ || are_near(l1.versor(), -l2.versor(), eps) );
}
inline
bool are_same(Line const& l1, Line const& l2, double eps = EPSILON)
{
- return are_parallel(l1, l2, eps) && are_near(l1.origin(), l2, eps);
+ return are_parallel(l1, l2, eps) && are_near(l1.origin(), l2, eps);
}
inline
bool are_orthogonal(Line const& l1, Line const& l2, double eps = EPSILON)
{
- return ( are_near(l1.versor(), l2.versor().cw(), eps)
- || are_near(l1.versor(), l2.versor().ccw(), eps) );
+ return ( are_near(l1.versor(), l2.versor().cw(), eps)
+ || are_near(l1.versor(), l2.versor().ccw(), eps) );
}
inline
bool are_collinear(Point const& p1, Point const& p2, Point const& p3,
- double eps = EPSILON)
+ double eps = EPSILON)
{
- return are_near( cross(p3, p2) - cross(p3, p1) + cross(p2, p1), 0, eps);
+ return are_near( cross(p3, p2) - cross(p3, p1) + cross(p2, p1), 0, eps);
}
// evaluate the angle between l1 and l2 rotating l1 in cw direction
@@ -302,10 +315,10 @@ bool are_collinear(Point const& p1, Point const& p2, Point const& p3,
inline
double angle_between(Line const& l1, Line const& l2)
{
- double angle = angle_between(l1.versor(), l2.versor());
- if (angle < 0) angle += M_PI;
- if (angle == M_PI) angle = 0;
- return angle;
+ double angle = angle_between(l1.versor(), l2.versor());
+ if (angle < 0) angle += M_PI;
+ if (angle == M_PI) angle = 0;
+ return angle;
}
inline
@@ -317,60 +330,60 @@ double distance(Point const& _point, LineSegment const& _segment)
inline
bool are_near(Point const& _point, LineSegment const& _segment,
- double eps = EPSILON)
+ double eps = EPSILON)
{
- return are_near(distance(_point, _segment), 0, eps);
+ return are_near(distance(_point, _segment), 0, eps);
}
// build a line passing by _point and orthogonal to _line
inline
Line make_orthogonal_line(Point const& _point, Line const& _line)
{
- Line l;
- l.origin(_point);
- l.versor(_line.versor().cw());
- return l;
+ Line l;
+ l.setOrigin(_point);
+ l.setVersor(_line.versor().cw());
+ return l;
}
// build a line passing by _point and parallel to _line
inline
Line make_parallel_line(Point const& _point, Line const& _line)
{
- Line l(_line);
- l.origin(_point);
- return l;
+ Line l(_line);
+ l.setOrigin(_point);
+ return l;
}
// build a line passing by the middle point of _segment and orthogonal to it.
inline
Line make_bisector_line(LineSegment const& _segment)
{
- return make_orthogonal_line( middle_point(_segment), Line(_segment) );
+ return make_orthogonal_line( middle_point(_segment), Line(_segment) );
}
// build the bisector line of the angle between ray(O,A) and ray(O,B)
inline
Line make_angle_bisector_line(Point const& A, Point const& O, Point const& B)
{
- Point M = middle_point(A,B);
- return Line(O,M);
+ Point M = middle_point(A,B);
+ return Line(O,M);
}
// prj(P) = rot(v, Point( rot(-v, P-O)[X], 0 )) + O
inline
Point projection(Point const& _point, Line const& _line)
{
- return _line.pointAt( _line.nearestPoint(_point) );
+ return _line.pointAt( _line.nearestPoint(_point) );
}
inline
LineSegment projection(LineSegment const& _segment, Line const& _line)
{
- return _line.segment( _line.nearestPoint(_segment.initialPoint()),
- _line.nearestPoint(_segment.finalPoint()) );
+ return _line.segment( _line.nearestPoint(_segment.initialPoint()),
+ _line.nearestPoint(_segment.finalPoint()) );
}
-
+boost::optional<LineSegment> clip (Line const& l, Rect const& r);
namespace detail
diff --git a/src/2geom/matrix.cpp b/src/2geom/matrix.cpp
deleted file mode 100644
index e130d2027..000000000
--- a/src/2geom/matrix.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-#define __Geom_MATRIX_C__
-
-/** \file
- * Various matrix routines. Currently includes some Geom::Rotate etc. routines too.
- */
-
-/*
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- * Michael G. Sloan <mgsloan@gmail.com>
- *
- * This code is in public domain
- */
-
-#include <2geom/utils.h>
-#include <2geom/matrix.h>
-#include <2geom/point.h>
-
-namespace Geom {
-
-/** Creates a Matrix given an axis and origin point.
- * The axis is represented as two vectors, which represent skew, rotation, and scaling in two dimensions.
- * from_basis(Point(1, 0), Point(0, 1), Point(0, 0)) would return the identity matrix.
-
- \param x_basis the vector for the x-axis.
- \param y_basis the vector for the y-axis.
- \param offset the translation applied by the matrix.
- \return The new Matrix.
- */
-//NOTE: Inkscape's version is broken, so when including this version, you'll have to search for code with this func
-//TODO: move to Matrix::from_basis
-Matrix from_basis(Point const x_basis, Point const y_basis, Point const offset) {
- return Matrix(x_basis[X], x_basis[Y],
- y_basis[X], y_basis[Y],
- offset [X], offset [Y]);
-}
-
-Point Matrix::xAxis() const {
- return Point(_c[0], _c[1]);
-}
-
-Point Matrix::yAxis() const {
- return Point(_c[2], _c[3]);
-}
-
-/** Gets the translation imparted by the Matrix.
- */
-Point Matrix::translation() const {
- return Point(_c[4], _c[5]);
-}
-
-void Matrix::setXAxis(Point const &vec) {
- for(int i = 0; i < 2; i++)
- _c[i] = vec[i];
-}
-
-void Matrix::setYAxis(Point const &vec) {
- for(int i = 0; i < 2; i++)
- _c[i + 2] = vec[i];
-}
-
-/** Sets the translation imparted by the Matrix.
- */
-void Matrix::setTranslation(Point const &loc) {
- for(int i = 0; i < 2; i++)
- _c[i + 4] = loc[i];
-}
-
-/** Calculates the amount of x-scaling imparted by the Matrix. This is the scaling applied to
- * the original x-axis region. It is \emph{not} the overall x-scaling of the transformation.
- * Equivalent to L2(m.xAxis())
- */
-double Matrix::expansionX() const {
- return sqrt(_c[0] * _c[0] + _c[1] * _c[1]);
-}
-
-/** Calculates the amount of y-scaling imparted by the Matrix. This is the scaling applied before
- * the other transformations. It is \emph{not} the overall y-scaling of the transformation.
- * Equivalent to L2(m.yAxis())
- */
-double Matrix::expansionY() const {
- return sqrt(_c[2] * _c[2] + _c[3] * _c[3]);
-}
-
-void Matrix::setExpansionX(double val) {
- double exp_x = expansionX();
- if(!are_near(exp_x, 0.0)) { //TODO: best way to deal with it is to skip op?
- double coef = val / expansionX();
- for(unsigned i=0;i<2;i++) _c[i] *= coef;
- }
-}
-
-void Matrix::setExpansionY(double val) {
- double exp_y = expansionY();
- if(!are_near(exp_y, 0.0)) { //TODO: best way to deal with it is to skip op?
- double coef = val / expansionY();
- for(unsigned i=2; i<4; i++) _c[i] *= coef;
- }
-}
-
-/** Sets this matrix to be the Identity Matrix. */
-void Matrix::setIdentity() {
- _c[0] = 1.0; _c[1] = 0.0;
- _c[2] = 0.0; _c[3] = 1.0;
- _c[4] = 0.0; _c[5] = 0.0;
-}
-
-//TODO: use eps
-
-bool Matrix::isIdentity(Coord const eps) const {
- return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) &&
- are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps) &&
- are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps);
-}
-
-/** Answers the question "Does this matrix perform a translation, and \em{only} a translation?"
- \param eps an epsilon value defaulting to EPSILON
- \return A bool representing yes/no.
- */
-bool Matrix::isTranslation(Coord const eps) const {
- return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) &&
- are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps) &&
- (!are_near(_c[4], 0.0, eps) || !are_near(_c[5], 0.0, eps));
-}
-
-/** Answers the question "Does this matrix perform a scale, and \em{only} a Scale?"
- \param eps an epsilon value defaulting to EPSILON
- \return A bool representing yes/no.
- */
-bool Matrix::isScale(Coord const eps) const {
- return (!are_near(_c[0], 1.0, eps) || !are_near(_c[3], 1.0, eps)) && //NOTE: these are the diags, and the next line opposite diags
- are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) &&
- are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps);
-}
-
-/** Answers the question "Does this matrix perform a uniform scale, and \em{only} a uniform scale?"
- \param eps an epsilon value defaulting to EPSILON
- \return A bool representing yes/no.
- */
-bool Matrix::isUniformScale(Coord const eps) const {
- return !are_near(_c[0], 1.0, eps) && are_near(_c[0], _c[3], eps) &&
- are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) &&
- are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps);
-}
-
-/** Answers the question "Does this matrix perform a rotation, and \em{only} a rotation?"
- \param eps an epsilon value defaulting to EPSILON
- \return A bool representing yes/no.
- */
-bool Matrix::isRotation(Coord const eps) const {
- return are_near(_c[0], _c[3], eps) && are_near(_c[1], -_c[2], eps) &&
- are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps) &&
- are_near(_c[0]*_c[0] + _c[1]*_c[1], 1.0, eps);
-}
-
-bool Matrix::onlyScaleAndTranslation(Coord const eps) const {
- return are_near(_c[0], _c[3], eps) && are_near(_c[1], 0, eps) && are_near(_c[2], 0, eps);
-}
-
-bool Matrix::isSingular(Coord const eps) const {
- return are_near(det(), 0.0, eps);
-}
-
-bool Matrix::flips() const {
- return cross(xAxis(), yAxis()) > 0;
-}
-
-/** Returns the Scale/Rotate/skew part of the matrix without the translation part. */
-Matrix Matrix::without_translation() const {
- return Matrix(_c[0], _c[1], _c[2], _c[3], 0, 0);
-}
-
-/** Attempts to calculate the inverse of a matrix.
- * This is a Matrix such that m * m.inverse() is very near (hopefully < epsilon difference) the identity Matrix.
- * \textbf{The Identity Matrix is returned if the matrix has no inverse.}
- \return The inverse of the Matrix if defined, otherwise the Identity Matrix.
- */
-Matrix Matrix::inverse() const {
- Matrix d;
-
- Geom::Coord const determ = det();
- // the numerical precision of the determinant must be significant
- if (fabs(determ) > 1e-18) {
- Geom::Coord const ideterm = 1.0 / determ;
-
- d._c[0] = _c[3] * ideterm;
- d._c[1] = -_c[1] * ideterm;
- d._c[2] = -_c[2] * ideterm;
- d._c[3] = _c[0] * ideterm;
- d._c[4] = -_c[4] * d._c[0] - _c[5] * d._c[2];
- d._c[5] = -_c[4] * d._c[1] - _c[5] * d._c[3];
- } else {
- d.setIdentity();
- }
-
- return d;
-}
-
-/** Calculates the determinant of a Matrix. */
-Geom::Coord Matrix::det() const {
- return _c[0] * _c[3] - _c[1] * _c[2];
-}
-
-/** Calculates the scalar of the descriminant of the Matrix.
- * This is simply the absolute value of the determinant.
- */
-Geom::Coord Matrix::descrim2() const {
- return fabs(det());
-}
-
-/** Calculates the descriminant of the Matrix. */
-Geom::Coord Matrix::descrim() const {
- return sqrt(descrim2());
-}
-
-Matrix operator*(Matrix const &m0, Matrix const &m1) {
- Matrix ret;
- for(int a = 0; a < 5; a += 2) {
- for(int b = 0; b < 2; b++) {
- ret[a + b] = m0[a] * m1[b] + m0[a + 1] * m1[b + 2];
- }
- }
- ret[4] += m1[4];
- ret[5] += m1[5];
- return ret;
-}
-
-//TODO: What's this!?!
-Matrix elliptic_quadratic_form(Matrix const &m) {
- double const od = m[0] * m[1] + m[2] * m[3];
- return Matrix(m[0]*m[0] + m[1]*m[1], od,
- od, m[2]*m[2] + m[3]*m[3],
- 0, 0);
-}
-
-Eigen::Eigen(Matrix const &m) {
- double const B = -m[0] - m[3];
- double const C = m[0]*m[3] - m[1]*m[2];
- double const center = -B/2.0;
- double const delta = sqrt(B*B-4*C)/2.0;
- values[0] = center + delta; values[1] = center - delta;
- for (int i = 0; i < 2; i++) {
- vectors[i] = unit_vector(rot90(Point(m[0]-values[i], m[1])));
- }
-}
-
-} //namespace Geom
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/matrix.h b/src/2geom/matrix.h
deleted file mode 100644
index 6a378dbf1..000000000
--- a/src/2geom/matrix.h
+++ /dev/null
@@ -1,165 +0,0 @@
-#ifndef __Geom_MATRIX_H__
-#define __Geom_MATRIX_H__
-
-/** \file
- * \brief Definition of Geom::Matrix types.
- *
- * Main authors:
- * Lauris Kaplinski <lauris@kaplinski.com>:
- * Original NRMatrix definition and related macros.
- *
- * Nathan Hurst <njh@mail.csse.monash.edu.au>:
- * Geom::Matrix class version of the above.
- *
- * Michael G. Sloan <mgsloan@gmail.com>:
- * Reorganization and additions.
- *
- * This code is in public domain.
- */
-
-//#include <glib/gmessages.h>
-
-#include <2geom/point.h>
-
-namespace Geom {
-
-/**
- * The Matrix class.
- *
- * For purposes of multiplication, points should be thought of as row vectors
- *
- * \f$(p_X p_Y 1)\f$
- *
- * to be right-multiplied by transformation matrices of the form
- * \f[
- \left[
- \begin{array}{ccc}
- c_0&c_1&0 \\
- c_2&c_3&0 \\
- c_4&c_5&1
- \end{array}
- \right]
- \f]
- * (so the columns of the matrix correspond to the columns (elements) of the result,
- * and the rows of the matrix correspond to columns (elements) of the "input").
- */
-class Matrix {
- private:
- Coord _c[6];
- public:
- Matrix() {}
-
- Matrix(Matrix const &m) {
- for(int i = 0; i < 6; i++) {
- _c[i] = m[i];
- }
- }
-
- Matrix(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5) {
- _c[0] = c0; _c[1] = c1;
- _c[2] = c2; _c[3] = c3;
- _c[4] = c4; _c[5] = c5;
- }
-
- Matrix &operator=(Matrix const &m) {
- for(int i = 0; i < 6; i++)
- _c[i] = m._c[i];
- return *this;
- }
-
- inline Coord operator[](unsigned const i) const { return _c[i]; }
- inline Coord &operator[](unsigned const i) { return _c[i]; }
-
-
- Point xAxis() const;
- Point yAxis() const;
- void setXAxis(Point const &vec);
- void setYAxis(Point const &vec);
-
- Point translation() const;
- void setTranslation(Point const &loc);
-
- double expansionX() const;
- double expansionY() const;
- inline Point expansion() const { return Point(expansionX(), expansionY()); }
- void setExpansionX(double val);
- void setExpansionY(double val);
-
- void setIdentity();
-
- bool isIdentity(Coord eps = EPSILON) const;
- bool isTranslation(Coord eps = EPSILON) const;
- bool isRotation(double eps = EPSILON) const;
- bool isScale(double eps = EPSILON) const;
- bool isUniformScale(double eps = EPSILON) const;
- bool onlyScaleAndTranslation(double eps = EPSILON) const;
- bool isSingular(double eps = EPSILON) const;
-
- bool flips() const;
-
- Matrix without_translation() const;
-
- Matrix inverse() const;
-
- Coord det() const;
- Coord descrim2() const;
- Coord descrim() const;
-};
-
-Matrix operator*(Matrix const &a, Matrix const &b);
-inline Matrix &operator*=(Matrix &a, Matrix const &b) { a = a * b; return a; }
-
-/** A function to print out the Matrix (for debugging) */
-inline std::ostream &operator<< (std::ostream &out_file, const Geom::Matrix &m) {
- out_file << "A: " << m[0] << " C: " << m[2] << " E: " << m[4] << "\n";
- out_file << "B: " << m[1] << " D: " << m[3] << " F: " << m[5] << "\n";
- return out_file;
-}
-
-/** Given a matrix m such that unit_circle = m*x, this returns the
- * quadratic form x*A*x = 1. */
-Matrix elliptic_quadratic_form(Matrix const &m);
-
-/** Given a matrix (ignoring the translation) this returns the eigen
- * values and vectors. */
-class Eigen{
-public:
- Point vectors[2];
- double values[2];
- Eigen(Matrix const &m);
-};
-
-// Matrix factories
-Matrix from_basis(const Point x_basis, const Point y_basis, const Point offset=Point(0,0));
-
-/** Returns the Identity Matrix. */
-inline Matrix identity() {
- return Matrix(1.0, 0.0,
- 0.0, 1.0,
- 0.0, 0.0);
-}
-
-inline bool operator==(Matrix const &a, Matrix const &b) {
- for(unsigned i = 0; i < 6; ++i) {
- if ( a[i] != b[i] ) return false;
- }
- return true;
-}
-inline bool operator!=(Matrix const &a, Matrix const &b) { return !( a == b ); }
-
-
-
-} /* namespace Geom */
-
-#endif /* !__Geom_MATRIX_H__ */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/numeric/fitting-model.h b/src/2geom/numeric/fitting-model.h
index dcf0e8e1d..b1ecbe92c 100644
--- a/src/2geom/numeric/fitting-model.h
+++ b/src/2geom/numeric/fitting-model.h
@@ -43,6 +43,7 @@
#include <2geom/ellipse.h>
#include <2geom/circle.h>
#include <2geom/utils.h>
+#include <2geom/conicsec.h>
namespace Geom { namespace NL {
@@ -83,6 +84,10 @@ namespace Geom { namespace NL {
* instance type: the type of the objects produced by using
* the fitting raw data solution
*/
+
+
+
+
template< typename ParameterType, typename ValueType, typename InstanceType >
class LinearFittingModel
{
@@ -230,8 +235,32 @@ class LFMNormalizedPowerBasis
// incomplete model, it can be inherited to make up different kinds of
// instance type; the raw data is a vector of coefficients of the equation
// of an ellipse curve
+//template< typename InstanceType >
+//class LFMEllipseEquation
+// : public LinearFittingModelWithFixedTerms<Point, double, InstanceType>
+//{
+// public:
+// void feed( VectorView & coeff, double & fixed_term, Point const& p ) const
+// {
+// coeff[0] = p[X] * p[Y];
+// coeff[1] = p[Y] * p[Y];
+// coeff[2] = p[X];
+// coeff[3] = p[Y];
+// coeff[4] = 1;
+// fixed_term = p[X] * p[X];
+// }
+//
+// size_t size() const
+// {
+// return 5;
+// }
+//};
+
+// incomplete model, it can be inherited to make up different kinds of
+// instance type; the raw data is a vector of coefficients of the equation
+// of a conic section
template< typename InstanceType >
-class LFMEllipseEquation
+class LFMConicEquation
: public LinearFittingModelWithFixedTerms<Point, double, InstanceType>
{
public:
@@ -251,10 +280,20 @@ class LFMEllipseEquation
}
};
+// this model generates Ellipse curves
+class LFMConicSection
+ : public LFMConicEquation<xAx>
+{
+ public:
+ void instance(xAx & c, ConstVectorView const& coeff) const
+ {
+ c.set(1, coeff[0], coeff[1], coeff[2], coeff[3], coeff[4]);
+ }
+};
// this model generates Ellipse curves
class LFMEllipse
- : public LFMEllipseEquation<Ellipse>
+ : public LFMConicEquation<Ellipse>
{
public:
void instance(Ellipse & e, ConstVectorView const& coeff) const
@@ -431,9 +470,8 @@ class LFMBezier
// this model generates Bezier curves
-template< unsigned int N >
class LFMBezierCurve
- : public LinearFittingModel< double, Point, BezierCurve<N> >
+ : public LinearFittingModel< double, Point, BezierCurve >
{
public:
LFMBezierCurve( size_t _order )
@@ -451,13 +489,13 @@ class LFMBezierCurve
return mob.size();
}
- void instance(BezierCurve<N> & bc, ConstMatrixView const& raw_data) const
+ void instance(BezierCurve & bc, ConstMatrixView const& raw_data) const
{
Bezier bx(size()-1);
Bezier by(size()-1);
mob.instance(bx, raw_data.column_const_view(X));
mob.instance(by, raw_data.column_const_view(Y));
- bc = BezierCurve<N>(bx, by);
+ bc = BezierCurve(bx, by);
}
private:
diff --git a/src/2geom/numeric/matrix.cpp b/src/2geom/numeric/matrix.cpp
index 94a345fd5..98ff3b6ca 100644
--- a/src/2geom/numeric/matrix.cpp
+++ b/src/2geom/numeric/matrix.cpp
@@ -37,10 +37,8 @@
#include <2geom/numeric/vector.h>
-
namespace Geom { namespace NL {
-
Vector operator*( detail::BaseMatrixImpl const& A,
detail::BaseVectorImpl const& v )
{
@@ -101,6 +99,47 @@ Matrix pseudo_inverse(detail::BaseMatrixImpl const& A)
return P;
}
+
+double trace (detail::BaseMatrixImpl const& A)
+{
+ if (A.rows() != A.columns())
+ {
+ THROW_RANGEERROR ("NL::Matrix: computing trace: "
+ "rows() != columns()");
+ }
+ double t = 0;
+ for (size_t i = 0; i < A.rows(); ++i)
+ {
+ t += A(i,i);
+ }
+ return t;
+}
+
+
+double det (detail::BaseMatrixImpl const& A)
+{
+ if (A.rows() != A.columns())
+ {
+ THROW_RANGEERROR ("NL::Matrix: computing determinant: "
+ "rows() != columns()");
+ }
+
+ Matrix LU(A);
+ int s;
+ gsl_permutation * p = gsl_permutation_alloc(LU.rows());
+ gsl_linalg_LU_decomp (LU.get_gsl_matrix(), p, &s);
+
+ double t = 1;
+ for (size_t i = 0; i < LU.rows(); ++i)
+ {
+ t *= LU(i,i);
+ }
+
+ gsl_permutation_free(p);
+ return t;
+}
+
+
} } // end namespaces
/*
diff --git a/src/2geom/numeric/matrix.h b/src/2geom/numeric/matrix.h
index f2a934235..a130bd748 100644
--- a/src/2geom/numeric/matrix.h
+++ b/src/2geom/numeric/matrix.h
@@ -38,6 +38,7 @@
#ifndef _NL_MATRIX_H_
#define _NL_MATRIX_H_
+#include <2geom/exception.h>
#include <2geom/numeric/vector.h>
#include <cassert>
@@ -45,7 +46,6 @@
#include <algorithm> // for std::swap
#include <sstream>
#include <string>
-
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_linalg.h>
@@ -232,13 +232,13 @@ class MatrixImpl : public BaseMatrixImpl
gsl_matrix_set_identity(m_matrix);
}
- using base_type::operator(); // VSC legacy support
- const double & operator() (size_t i, size_t j) const
- {
- return base_type::operator ()(i, j);
- }
+ using base_type::operator(); // VSC legacy support
+ const double & operator() (size_t i, size_t j) const
+ {
+ return base_type::operator ()(i, j);
+ }
- double & operator() (size_t i, size_t j)
+ double & operator() (size_t i, size_t j)
{
return *gsl_matrix_ptr(m_matrix, i, j);
}
@@ -310,6 +310,8 @@ using detail::operator==;
using detail::operator<<;
+template <size_t N>
+class ConstBaseSymmetricMatrix;
class Matrix: public detail::MatrixImpl
@@ -352,6 +354,18 @@ class Matrix: public detail::MatrixImpl
gsl_matrix_memcpy(m_matrix, _matrix.get_gsl_matrix());
}
+ template <size_t N>
+ explicit
+ Matrix(ConstBaseSymmetricMatrix<N> const& _smatrix)
+ {
+ m_rows = N;
+ m_columns = N;
+ m_matrix = gsl_matrix_alloc(N, N);
+ for (size_t i = 0; i < N; ++i)
+ for (size_t j = 0; j < N ; ++j)
+ (*gsl_matrix_ptr(m_matrix, i, j)) = _smatrix(i,j);
+ }
+
Matrix & operator=(Matrix const& _matrix)
{
assert( rows() == _matrix.rows() && columns() == _matrix.columns() );
@@ -366,6 +380,16 @@ class Matrix: public detail::MatrixImpl
return *this;
}
+ template <size_t N>
+ Matrix & operator=(ConstBaseSymmetricMatrix<N> const& _smatrix)
+ {
+ assert (rows() == N && columns() == N);
+ for (size_t i = 0; i < N; ++i)
+ for (size_t j = 0; j < N ; ++j)
+ (*this)(i,j) = _smatrix(i,j);
+ return *this;
+ }
+
virtual ~Matrix()
{
gsl_matrix_free(m_matrix);
@@ -557,6 +581,10 @@ Matrix operator*( detail::BaseMatrixImpl const& A,
Matrix pseudo_inverse(detail::BaseMatrixImpl const& A);
+double trace (detail::BaseMatrixImpl const& A);
+
+double det (detail::BaseMatrixImpl const& A);
+
} } // end namespaces
#endif /*_NL_MATRIX_H_*/
diff --git a/src/2geom/numeric/vector.h b/src/2geom/numeric/vector.h
index 46701645a..6ab898f29 100644
--- a/src/2geom/numeric/vector.h
+++ b/src/2geom/numeric/vector.h
@@ -555,6 +555,24 @@ void swap_view(VectorView & v1, VectorView & v2)
std::swap(v1.m_vector_view, v2.m_vector_view); // not swap m_vector too
}
+inline
+const VectorView & const_vector_view_cast (const ConstVectorView & view)
+{
+ const detail::BaseVectorImpl & bvi
+ = static_cast<const detail::BaseVectorImpl &>(view);
+ const VectorView & vv = reinterpret_cast<const VectorView &>(bvi);
+ return vv;
+}
+
+inline
+VectorView & const_vector_view_cast (ConstVectorView & view)
+{
+ detail::BaseVectorImpl & bvi
+ = static_cast<detail::BaseVectorImpl &>(view);
+ VectorView & vv = reinterpret_cast<VectorView &>(bvi);
+ return vv;
+}
+
} } // end namespaces
diff --git a/src/2geom/path-intersection.cpp b/src/2geom/path-intersection.cpp
index 5e58525c7..58ee6232b 100644
--- a/src/2geom/path-intersection.cpp
+++ b/src/2geom/path-intersection.cpp
@@ -28,7 +28,7 @@ int winding(Path const &path, Point p) {
if(iter == path.end_closed()) { return 0; }
if(iter->initialPoint()[Y]!=p[Y]) { start = iter; break; }
if(iter->finalPoint()[Y]!=p[Y]) { start = iter; break; }
- if(iter->boundsFast()->height()!=0.){ start = iter; break; }
+ if(iter->boundsFast().height()!=0.){ start = iter; break; }
}
int wind = 0;
unsigned cnt = 0;
@@ -39,18 +39,18 @@ int winding(Path const &path, Point p) {
cnt++;
if(cnt > path.size()) return wind; //some bug makes this required
starting = false;
- Rect bounds = *(iter->boundsFast());
+ Rect bounds = (iter->boundsFast());
Coord x = p[X], y = p[Y];
-
+
if(x > bounds.right() || !bounds[Y].contains(y)) continue; //ray doesn't intersect box
-
+
Point final = iter->finalPoint();
Point initial = iter->initialPoint();
Cmp final_to_ray = cmp(final[Y], y);
Cmp initial_to_ray = cmp(initial[Y], y);
-
+
// if y is included, these will have opposite values, giving order.
- Cmp c = cmp(final_to_ray, initial_to_ray);
+ Cmp c = cmp(final_to_ray, initial_to_ray);
if(x < bounds.left()) {
// ray goes through bbox
// winding delta determined by position of endpoints
@@ -73,7 +73,7 @@ int winding(Path const &path, Point p) {
next++;
for(; ; next++) {
if(next == path.end_closed()) next = path.begin();
- Rect bnds = *(next->boundsFast());
+ Rect bnds = (next->boundsFast());
//TODO: X considerations
if(bnds.height() > 0) {
//It has diverged
@@ -100,7 +100,7 @@ int winding(Path const &path, Point p) {
//Looks like it looped, which means everything's flat
return 0;
}
-
+
cont:(void)0;
}
return wind;
@@ -135,10 +135,10 @@ bool path_direction(Path const &p) {
} else if(final_to_ray == EQUAL_TO) goto doh;
}
return res < 0;
-
+
doh:
//Otherwise fallback on area
-
+
Piecewise<D2<SBasis> > pw = p.toPwSb();
double area;
Point centre;
@@ -214,39 +214,41 @@ intersect_polish_f (const gsl_vector * x, void *params,
{
const double x0 = gsl_vector_get (x, 0);
const double x1 = gsl_vector_get (x, 1);
-
- Geom::Point dx = ((struct rparams *) params)->A(x0) -
+
+ Geom::Point dx = ((struct rparams *) params)->A(x0) -
((struct rparams *) params)->B(x1);
-
+
gsl_vector_set (f, 0, dx[0]);
gsl_vector_set (f, 1, dx[1]);
-
+
return GSL_SUCCESS;
}
#endif
-static void
+static void
intersect_polish_root (Curve const &A, double &s,
Curve const &B, double &t) {
+ int status;
+ size_t iter = 0;
std::vector<Point> as, bs;
as = A.pointAndDerivatives(s, 2);
bs = B.pointAndDerivatives(t, 2);
Point F = as[0] - bs[0];
double best = dot(F, F);
-
+
for(int i = 0; i < 4; i++) {
-
+
/**
we want to solve
J*(x1 - x0) = f(x0)
-
+
|dA(s)[0] -dB(t)[0]| (X1 - X0) = A(s) - B(t)
- |dA(s)[1] -dB(t)[1]|
+ |dA(s)[1] -dB(t)[1]|
**/
// We're using the standard transformation matricies, which is numerically rather poor. Much better to solve the equation using elimination.
- Matrix jack(as[1][0], as[1][1],
+ Affine jack(as[1][0], as[1][1],
-bs[1][0], -bs[1][1],
0, 0);
Point soln = (F)*jack.inverse();
@@ -257,7 +259,7 @@ intersect_polish_root (Curve const &A, double &s,
else if (ns>1) ns=1;
if (nt<0) nt=0;
else if (nt>1) nt=1;
-
+
as = A.pointAndDerivatives(ns, 2);
bs = B.pointAndDerivatives(nt, 2);
F = as[0] - bs[0];
@@ -275,35 +277,33 @@ intersect_polish_root (Curve const &A, double &s,
const size_t n = 2;
struct rparams p = {A, B};
gsl_multiroot_function f = {&intersect_polish_f, n, &p};
-
+
double x_init[2] = {s, t};
gsl_vector *x = gsl_vector_alloc (n);
-
+
gsl_vector_set (x, 0, x_init[0]);
gsl_vector_set (x, 1, x_init[1]);
-
+
const gsl_multiroot_fsolver_type *T = gsl_multiroot_fsolver_hybrids;
gsl_multiroot_fsolver *sol = gsl_multiroot_fsolver_alloc (T, 2);
gsl_multiroot_fsolver_set (sol, &f, x);
-
- int status = 0;
- size_t iter = 0;
+
do
{
iter++;
status = gsl_multiroot_fsolver_iterate (sol);
-
+
if (status) /* check if solver is stuck */
break;
-
+
status =
gsl_multiroot_test_residual (sol->f, 1e-12);
}
while (status == GSL_CONTINUE && iter < 1000);
-
+
s = gsl_vector_get (sol->x, 0);
t = gsl_vector_get (sol->x, 1);
-
+
gsl_multiroot_fsolver_free (sol);
gsl_vector_free (x);
}
@@ -315,7 +315,7 @@ intersect_polish_root (Curve const &A, double &s,
* 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,
+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";
@@ -324,15 +324,15 @@ void pair_intersect(Curve const & A, double Al, double Ah,
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
+ 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),
+ 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;
@@ -385,8 +385,8 @@ void mono_intersect(Curve const &A, double Al, double Ah,
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),
+ 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;
@@ -483,7 +483,7 @@ std::vector<double> offset_doubles(std::vector<double> const &x, double offs) {
std::vector<double> path_mono_splits(Path const &p) {
std::vector<double> ret;
if(p.empty()) return ret;
-
+
bool pdx=2, pdy=2; //Previous derivative direction
for(unsigned i = 0; i < p.size(); i++) {
std::vector<double> spl = offset_doubles(curve_mono_splits(p[i]), i);
@@ -502,7 +502,7 @@ std::vector<double> path_mono_splits(Path const &p) {
}
/**
- * Applies path_mono_splits to multiple paths, and returns the results such that
+ * Applies path_mono_splits to multiple paths, and returns the results such that
* time-set i corresponds to Path i.
*/
std::vector<std::vector<double> > paths_mono_splits(std::vector<Path> const &ps) {
@@ -541,14 +541,14 @@ CrossingSet MonoCrosser::crossings(std::vector<Path> const &a, std::vector<Path>
if(b.empty()) return CrossingSet(a.size(), Crossings());
CrossingSet results(a.size() + b.size(), Crossings());
if(a.empty()) return results;
-
+
std::vector<std::vector<double> > splits_a = paths_mono_splits(a), splits_b = paths_mono_splits(b);
std::vector<std::vector<Rect> > bounds_a = split_bounds(a, splits_a), bounds_b = split_bounds(b, splits_b);
-
- std::vector<Rect> bounds_a_union, bounds_b_union;
+
+ std::vector<Rect> bounds_a_union, bounds_b_union;
for(unsigned i = 0; i < bounds_a.size(); i++) bounds_a_union.push_back(union_list(bounds_a[i]));
for(unsigned i = 0; i < bounds_b.size(); i++) bounds_b_union.push_back(union_list(bounds_b[i]));
-
+
std::vector<std::vector<unsigned> > cull = sweep_bounds(bounds_a_union, bounds_b_union);
Crossings n;
for(unsigned i = 0; i < cull.size(); i++) {
@@ -556,7 +556,7 @@ CrossingSet MonoCrosser::crossings(std::vector<Path> const &a, std::vector<Path>
unsigned j = cull[i][jx];
unsigned jc = j + a.size();
Crossings res;
-
+
//Sweep of the monotonic portions
std::vector<std::vector<unsigned> > cull2 = sweep_bounds(bounds_a[i], bounds_b[j]);
for(unsigned k = 0; k < cull2.size(); k++) {
@@ -567,9 +567,9 @@ CrossingSet MonoCrosser::crossings(std::vector<Path> const &a, std::vector<Path>
res, .1);
}
}
-
+
for(unsigned k = 0; k < res.size(); k++) { res[k].a = i; res[k].b = jc; }
-
+
merge_crossings(results[i], res, i);
merge_crossings(results[i], res, jc);
}
@@ -583,22 +583,22 @@ CrossingSet MonoCrosser::crossings(std::vector<Path> const &a, std::vector<Path>
CrossingSet crossings_among(std::vector<Path> const &p) {
CrossingSet results(p.size(), Crossings());
if(p.empty()) return results;
-
+
std::vector<std::vector<double> > splits = paths_mono_splits(p);
std::vector<std::vector<Rect> > prs = split_bounds(p, splits);
std::vector<Rect> rs;
for(unsigned i = 0; i < prs.size(); i++) rs.push_back(union_list(prs[i]));
-
+
std::vector<std::vector<unsigned> > cull = sweep_bounds(rs);
-
+
//we actually want to do the self-intersections, so add em in:
for(unsigned i = 0; i < cull.size(); i++) cull[i].push_back(i);
-
+
for(unsigned i = 0; i < cull.size(); i++) {
for(unsigned jx = 0; jx < cull[i].size(); jx++) {
unsigned j = cull[i][jx];
Crossings res;
-
+
//Sweep of the monotonic portions
std::vector<std::vector<unsigned> > cull2 = sweep_bounds(prs[i], prs[j]);
for(unsigned k = 0; k < cull2.size(); k++) {
@@ -609,14 +609,14 @@ CrossingSet crossings_among(std::vector<Path> const &p) {
res, .1);
}
}
-
+
for(unsigned k = 0; k < res.size(); k++) { res[k].a = i; res[k].b = j; }
-
+
merge_crossings(results[i], res, i);
merge_crossings(results[j], res, j);
}
}
-
+
return results;
}
*/
@@ -635,7 +635,7 @@ Crossings curve_self_crossings(Curve const &a) {
}
/*
-void mono_curve_intersect(Curve const & A, double Al, double Ah,
+void mono_curve_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";
@@ -643,9 +643,9 @@ void mono_curve_intersect(Curve const & A, double Al, double 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
+ 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)) {
@@ -705,7 +705,7 @@ Crossings path_self_crossings(Path const &p) {
for(unsigned jx = 0; jx < cull[i].size(); jx++) {
unsigned j = cull[i][jx];
res.clear();
-
+
std::vector<std::vector<unsigned> > cull2 = sweep_bounds(bnds[i], bnds[j]);
for(unsigned k = 0; k < cull2.size(); k++) {
for(unsigned lx = 0; lx < cull2[k].size(); lx++) {
@@ -713,7 +713,7 @@ Crossings path_self_crossings(Path const &p) {
mono_curve_intersect(p[i], spl[i][k-1], spl[i][k], p[j], spl[j][l-1], spl[j][l], res);
}
}
-
+
//if(fabs(int(i)-j) == 1 || fabs(int(i)-j) == p.size()-1) {
Crossings res2;
for(unsigned k = 0; k < res.size(); k++) {
@@ -742,7 +742,7 @@ Crossings self_crossings(Path const &p) {
unsigned j = cull[i][jx];
res.clear();
pair_intersect(p[i], 0, 1, p[j], 0, 1, res);
-
+
//if(fabs(int(i)-j) == 1 || fabs(int(i)-j) == p.size()-1) {
Crossings res2;
for(unsigned k = 0; k < res.size(); k++) {
@@ -767,9 +767,9 @@ void flip_crossings(Crossings &crs) {
CrossingSet crossings_among(std::vector<Path> const &p) {
CrossingSet results(p.size(), Crossings());
if(p.empty()) return results;
-
+
SimpleCrosser cc;
-
+
std::vector<std::vector<unsigned> > cull = sweep_bounds(bounds(p));
for(unsigned i = 0; i < cull.size(); i++) {
Crossings res = self_crossings(p[i]);
@@ -779,7 +779,7 @@ CrossingSet crossings_among(std::vector<Path> const &p) {
merge_crossings(results[i], res, i);
for(unsigned jx = 0; jx < cull[i].size(); jx++) {
unsigned j = cull[i][jx];
-
+
Crossings res = cc.crossings(p[i], p[j]);
for(unsigned k = 0; k < res.size(); k++) { res[k].a = i; res[k].b = j; }
merge_crossings(results[i], res, i);
diff --git a/src/2geom/path.cpp b/src/2geom/path.cpp
index c47902649..58d6b9b5e 100644
--- a/src/2geom/path.cpp
+++ b/src/2geom/path.cpp
@@ -46,8 +46,9 @@ namespace Geom
OptRect Path::boundsFast() const {
OptRect bounds;
if (empty()) return bounds;
- bounds=front().boundsFast();
+ bounds = front().boundsFast();
const_iterator iter = begin();
+ // the closing path segment can be ignored, because it will always lie within the bbox of the rest of the path
if ( iter != end() ) {
for ( ++iter; iter != end() ; ++iter ) {
bounds.unionWith(iter->boundsFast());
@@ -59,8 +60,9 @@ OptRect Path::boundsFast() const {
OptRect Path::boundsExact() const {
OptRect bounds;
if (empty()) return bounds;
- bounds=front().boundsExact();
+ bounds = front().boundsExact();
const_iterator iter = begin();
+ // the closing path segment can be ignored, because it will always lie within the bbox of the rest of the path
if ( iter != end() ) {
for ( ++iter; iter != end() ; ++iter ) {
bounds.unionWith(iter->boundsExact());
@@ -77,7 +79,7 @@ iter inc(iter const &x, unsigned n) {
return ret;
}
-Path &Path::operator*=(Matrix const &m) {
+Path &Path::operator*=(Affine const &m) {
unshare();
Sequence::iterator last = get_curves().end() - 1;
Sequence::iterator it;
@@ -146,7 +148,7 @@ Path::allNearestPoints(Point const& _point, double from, double to) const
Rect bb(Geom::Point(0,0),Geom::Point(0,0));
for ( unsigned int i = si + 1; i < ei; ++i )
{
- bb = *(_path[i].boundsFast());
+ bb = (_path[i].boundsFast());
dsq = distanceSq(_point, bb);
if ( mindistsq < dsq ) continue;
all_t = _path[i].allNearestPoints(_point);
@@ -165,7 +167,7 @@ Path::allNearestPoints(Point const& _point, double from, double to) const
ni.push_back(i);
}
}
- bb = *(_path[ei].boundsFast());
+ bb = (_path[ei].boundsFast());
dsq = distanceSq(_point, bb);
if ( mindistsq >= dsq )
{
@@ -203,7 +205,7 @@ Path::nearestPointPerCurve(Point const& _point) const
{
//return a single nearest point for each curve in this path
std::vector<double> np;
- for (const_iterator it = begin() ; it != end_default(); ++it)
+ for (const_iterator it = begin() ; it != end_default() ; ++it)
//for (std::vector<Path>::const_iterator it = _path.begin(); it != _path.end(), ++it){
{
np.push_back(it->nearestPoint(_point));
@@ -256,7 +258,7 @@ double Path::nearestPoint(Point const &_point, double from, double to, double *d
Rect bb(Geom::Point(0,0),Geom::Point(0,0));
for ( unsigned int i = si + 1; i < ei; ++i )
{
- bb = *(_path[i].boundsFast());
+ bb = (_path[i].boundsFast());
dsq = distanceSq(_point, bb);
if ( mindistsq <= dsq ) continue;
t = _path[i].nearestPoint(_point);
@@ -268,7 +270,7 @@ double Path::nearestPoint(Point const &_point, double from, double to, double *d
mindistsq = dsq;
}
}
- bb = *(_path[ei].boundsFast());
+ bb = (_path[ei].boundsFast());
dsq = distanceSq(_point, bb);
if ( mindistsq > dsq )
{
diff --git a/src/2geom/path.h b/src/2geom/path.h
index 3167bb09e..cbd449248 100644
--- a/src/2geom/path.h
+++ b/src/2geom/path.h
@@ -291,13 +291,13 @@ public:
return !( *this == other );
}
- Path operator*(Matrix const &m) const {
+ Path operator*(Affine const &m) const {
Path ret(*this);
ret *= m;
return ret;
}
- Path &operator*=(Matrix const &m);
+ Path &operator*=(Affine const &m);
Point pointAt(double t) const
{
diff --git a/src/2geom/pathvector.cpp b/src/2geom/pathvector.cpp
index 3d11dd48b..fc0ad75c4 100644
--- a/src/2geom/pathvector.cpp
+++ b/src/2geom/pathvector.cpp
@@ -38,7 +38,7 @@
#include <2geom/pathvector.h>
#include <2geom/path.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
namespace Geom {
diff --git a/src/2geom/pathvector.h b/src/2geom/pathvector.h
index a531cc955..2f45b9d86 100644
--- a/src/2geom/pathvector.h
+++ b/src/2geom/pathvector.h
@@ -3,7 +3,8 @@
* \brief PathVector - std::vector containing Geom::Path
* This file provides a set of operations that can be performed on PathVector,
* e.g. an affine transform.
- *
+ */
+/*
* Authors:
* Johan Engelen <goejendaagh@zonnet.nl>
*
@@ -46,13 +47,13 @@ typedef std::vector<Geom::Path> PathVector;
/* general path transformation: */
inline
-void operator*= (PathVector & path_in, Matrix const &m) {
+void operator*= (PathVector & path_in, Affine const &m) {
for(PathVector::iterator it = path_in.begin(); it != path_in.end(); ++it) {
(*it) *= m;
}
}
inline
-PathVector operator*(PathVector const & path_in, Matrix const &m) {
+PathVector operator*(PathVector const & path_in, Affine const &m) {
PathVector ret(path_in);
ret *= m;
return ret;
diff --git a/src/2geom/piecewise.cpp b/src/2geom/piecewise.cpp
index fcecc13c1..ba1e60ea3 100644
--- a/src/2geom/piecewise.cpp
+++ b/src/2geom/piecewise.cpp
@@ -154,6 +154,54 @@ int compose_findSegIdx(std::map<double,unsigned>::iterator const &cut,
return idx;
}
+
+Piecewise<SBasis> pw_compose_inverse(SBasis const &f, SBasis const &g, unsigned order, double zero){
+ Piecewise<SBasis> result;
+
+ assert( f.size()>0 && g.size()>0);
+ SBasis g01 = g;
+ bool flip = ( g01.at0() > g01.at1() );
+
+ //OptInterval g_range = bounds_exact(g);
+ OptInterval g_range( Interval( g.at0(), g.at1() ));
+
+ g01 -= g_range->min();
+ g01 /= g_range->extent();
+ if ( flip ){
+ g01 *= -1.;
+ g01 += 1.;
+ }
+#if 1
+ assert( std::abs( g01.at0() - 0. ) < zero );
+ assert( std::abs( g01.at1() - 1. ) < zero );
+ //g[0][0] = 0.;
+ //g[0][1] = 1.;
+#endif
+
+ SBasis foginv = compose_inverse( f, g01, order, zero );
+ SBasis err = compose( foginv, g01) - f;
+
+ if ( err.tailError(0) < zero ){
+ result = Piecewise<SBasis> (foginv);
+ }else{
+ SBasis g_portion = portion( g01, Interval(0.,.5) );
+ SBasis f_portion = portion( f, Interval(0.,.5) );
+ result = pw_compose_inverse(f_portion, g_portion, order, zero);
+
+ g_portion = portion( g01, Interval(.5, 1.) );
+ f_portion = portion( f, Interval(.5, 1.) );
+ Piecewise<SBasis> result_next;
+ result_next = pw_compose_inverse(f_portion, g_portion, order, zero);
+ result.concat( result_next );
+ }
+ if (flip) {
+ result = reverse(result);
+ }
+ result.setDomain(*g_range);
+ return result;
+}
+
+
std::vector<double> roots(Piecewise<SBasis> const &f){
std::vector<double> result;
for (unsigned i=0; i<f.size(); i++){
@@ -179,6 +227,32 @@ std::vector<std::vector<double> > multi_roots(Piecewise<SBasis> const &f, std::v
return result;
}
+
+std::vector<Interval> level_set(Piecewise<SBasis> const &f, Interval const &level, double tol){
+ std::vector<Interval> result;
+ for (unsigned i=0; i<f.size(); i++){
+ std::vector<Interval> resulti = level_set( f[i], level, 0., 1., tol);
+ for (unsigned j=0; j<resulti.size(); j++){
+ double a = f.cuts[i] + resulti[j].min() * ( f.cuts[i+1] - f.cuts[i] );
+ double b = f.cuts[i] + resulti[j].max() * ( f.cuts[i+1] - f.cuts[i] );
+ Interval domj( a, b );
+ //Interval domj( f.mapToDomain(resulti[j].min(), i ), f.mapToDomain(resulti[j].max(), i ) );
+
+ if ( j==0 && result.size() > 0 && result.back().intersects(domj) ){
+ result.back().unionWith(domj);
+ }else{
+ result.push_back(domj);
+ }
+ }
+ }
+ return result;
+}
+std::vector<Interval> level_set(Piecewise<SBasis> const &f, double v, double vtol, double tol){
+ Interval level ( v-vtol, v+vtol );
+ return level_set( f, level, tol);
+}
+
+
}
/*
Local Variables:
diff --git a/src/2geom/piecewise.h b/src/2geom/piecewise.h
index 62185b472..19c66d8f0 100644
--- a/src/2geom/piecewise.h
+++ b/src/2geom/piecewise.h
@@ -265,6 +265,11 @@ class Piecewise {
};
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
template<typename T>
inline typename FragmentConcept<T>::BoundsType bounds_fast(const Piecewise<T> &f) {
boost::function_requires<FragmentConcept<T> >();
@@ -276,6 +281,11 @@ inline typename FragmentConcept<T>::BoundsType bounds_fast(const Piecewise<T> &f
return ret;
}
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
template<typename T>
inline typename FragmentConcept<T>::BoundsType bounds_exact(const Piecewise<T> &f) {
boost::function_requires<FragmentConcept<T> >();
@@ -287,6 +297,11 @@ inline typename FragmentConcept<T>::BoundsType bounds_exact(const Piecewise<T> &
return ret;
}
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
template<typename T>
inline typename FragmentConcept<T>::BoundsType bounds_local(const Piecewise<T> &f, const OptInterval &_m) {
boost::function_requires<FragmentConcept<T> >();
@@ -308,7 +323,10 @@ inline typename FragmentConcept<T>::BoundsType bounds_local(const Piecewise<T> &
return ret;
}
-//returns a portion of a piece of a Piecewise<T>, given the piece's index and a to/from time.
+/**
+ * Returns a portion of a piece of a Piecewise<T>, given the piece's index and a to/from time.
+ * \relates Piecewise
+ */
template<typename T>
T elem_portion(const Piecewise<T> &a, unsigned i, double from, double to) {
assert(i < a.size());
@@ -324,6 +342,8 @@ T elem_portion(const Piecewise<T> &a, unsigned i, double from, double to) {
* Piecewise<T> ac = a.partition(b.cuts);
* Piecewise<T> bc = b.partition(a.cuts);
* //ac.cuts should be equivalent to bc.cuts
+ *
+ * \relates Piecewise
*/
template<typename T>
Piecewise<T> partition(const Piecewise<T> &pw, std::vector<double> const &c) {
@@ -389,8 +409,9 @@ Piecewise<T> partition(const Piecewise<T> &pw, std::vector<double> const &c) {
return ret;
}
-/**Piecewise<T> portion(const Piecewise<T> &pw, double from, double to);
- * Returns a Piecewise<T> with a defined domain of [min(from, to), max(from, to)].
+/**
+ * Returns a Piecewise<T> with a defined domain of [min(from, to), max(from, to)].
+ * \relates Piecewise
*/
template<typename T>
Piecewise<T> portion(const Piecewise<T> &pw, double from, double to) {
@@ -424,6 +445,11 @@ Piecewise<T> portion(const Piecewise<T> &pw, double from, double to) {
}
//TODO: seems like these should be mutating
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> remove_short_cuts(Piecewise<T> const &f, double tol) {
if(f.empty()) return f;
@@ -439,6 +465,11 @@ Piecewise<T> remove_short_cuts(Piecewise<T> const &f, double tol) {
}
//TODO: seems like these should be mutating
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> remove_short_cuts_extending(Piecewise<T> const &f, double tol) {
if(f.empty()) return f;
@@ -455,6 +486,11 @@ Piecewise<T> remove_short_cuts_extending(Piecewise<T> const &f, double tol) {
return ret;
}
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
template<typename T>
std::vector<double> roots(const Piecewise<T> &pw) {
std::vector<double> ret;
@@ -467,6 +503,11 @@ std::vector<double> roots(const Piecewise<T> &pw) {
}
//IMPL: OffsetableConcept
+/**
+ * ...
+ * \return \f$ a + b = \f$
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> operator+(Piecewise<T> const &a, typename T::output_type b) {
boost::function_requires<OffsetableConcept<T> >();
@@ -511,6 +552,11 @@ Piecewise<T>& operator-=(Piecewise<T>& a, typename T::output_type b) {
}
//IMPL: ScalableConcept
+/**
+ * ...
+ * \return \f$ -a = \f$
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> operator-(Piecewise<T> const &a) {
boost::function_requires<ScalableConcept<T> >();
@@ -522,6 +568,11 @@ Piecewise<T> operator-(Piecewise<T> const &a) {
ret.push_seg(- a[i]);
return ret;
}
+/**
+ * ...
+ * \return \f$ a * b = \f$
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> operator*(Piecewise<T> const &a, double b) {
boost::function_requires<ScalableConcept<T> >();
@@ -535,6 +586,11 @@ Piecewise<T> operator*(Piecewise<T> const &a, double b) {
ret.push_seg(a[i] * b);
return ret;
}
+/**
+ * ...
+ * \return \f$ a * b = \f$
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> operator*(Piecewise<T> const &a, T b) {
boost::function_requires<ScalableConcept<T> >();
@@ -548,6 +604,11 @@ Piecewise<T> operator*(Piecewise<T> const &a, T b) {
ret.push_seg(a[i] * b);
return ret;
}
+/**
+ * ...
+ * \return \f$ a / b = \f$
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> operator/(Piecewise<T> const &a, double b) {
boost::function_requires<ScalableConcept<T> >();
@@ -582,6 +643,11 @@ Piecewise<T>& operator/=(Piecewise<T>& a, double b) {
}
//IMPL: AddableConcept
+/**
+ * ...
+ * \return \f$ a + b = \f$
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> operator+(Piecewise<T> const &a, Piecewise<T> const &b) {
boost::function_requires<AddableConcept<T> >();
@@ -595,6 +661,11 @@ Piecewise<T> operator+(Piecewise<T> const &a, Piecewise<T> const &b) {
ret.push_seg(pa[i] + pb[i]);
return ret;
}
+/**
+ * ...
+ * \return \f$ a - b = \f$
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> operator-(Piecewise<T> const &a, Piecewise<T> const &b) {
boost::function_requires<AddableConcept<T> >();
@@ -619,6 +690,11 @@ inline Piecewise<T>& operator-=(Piecewise<T> &a, Piecewise<T> const &b) {
return a;
}
+/**
+ * ...
+ * \return \f$ a \cdot b = \f$
+ * \relates Piecewise
+ */
template<typename T1,typename T2>
Piecewise<T2> operator*(Piecewise<T1> const &a, Piecewise<T2> const &b) {
//function_requires<MultiplicableConcept<T1> >();
@@ -635,6 +711,11 @@ Piecewise<T2> operator*(Piecewise<T1> const &a, Piecewise<T2> const &b) {
return ret;
}
+/**
+ * ...
+ * \return \f$ a \cdot b \f$
+ * \relates Piecewise
+ */
template<typename T>
inline Piecewise<T>& operator*=(Piecewise<T> &a, Piecewise<T> const &b) {
a = a * b;
@@ -661,9 +742,14 @@ int compose_findSegIdx(std::map<double,unsigned>::iterator const &cut,
std::vector<double> const &levels,
SBasis const &g);
-//TODO: add concept check
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> compose(Piecewise<T> const &f, SBasis const &g){
+ /// \todo add concept check
Piecewise<T> result;
if (f.empty()) return result;
if (g.isZero()) return Piecewise<T>(f(0));
@@ -707,9 +793,14 @@ Piecewise<T> compose(Piecewise<T> const &f, SBasis const &g){
return(result);
}
-//TODO: add concept check for following composition functions
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> compose(Piecewise<T> const &f, Piecewise<SBasis> const &g){
+/// \todo add concept check
Piecewise<T> result;
for(unsigned i = 0; i < g.segs.size(); i++){
Piecewise<T> fgi=compose(f, g.segs[i]);
@@ -721,6 +812,7 @@ Piecewise<T> compose(Piecewise<T> const &f, Piecewise<SBasis> const &g){
/*
Piecewise<D2<SBasis> > compose(D2<SBasis2d> const &sb2d, Piecewise<D2<SBasis> > const &pwd2sb){
+/// \todo add concept check
Piecewise<D2<SBasis> > result;
result.push_cut(0.);
for(unsigned i = 0; i < pwd2sb.size(); i++){
@@ -729,11 +821,26 @@ Piecewise<D2<SBasis> > compose(D2<SBasis2d> const &sb2d, Piecewise<D2<SBasis> >
return result;
}*/
+/** Compose an SBasis with the inverse of another.
+ * WARNING: It's up to the user to check that the second SBasis is indeed
+ * invertible (i.e. strictly increasing or decreasing).
+ * \return \f$ f \cdot g^{-1} \f$
+ * \relates Piecewise
+ */
+Piecewise<SBasis> pw_compose_inverse(SBasis const &f, SBasis const &g, unsigned order, double zero);
+
+
+
template <typename T>
Piecewise<T> Piecewise<T>::operator()(SBasis f){return compose((*this),f);}
template <typename T>
Piecewise<T> Piecewise<T>::operator()(Piecewise<SBasis>f){return compose((*this),f);}
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> integral(Piecewise<T> const &a) {
Piecewise<T> result;
@@ -748,6 +855,11 @@ Piecewise<T> integral(Piecewise<T> const &a) {
return result;
}
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> derivative(Piecewise<T> const &a) {
Piecewise<T> result;
@@ -763,6 +875,19 @@ std::vector<double> roots(Piecewise<SBasis> const &f);
std::vector<std::vector<double> >multi_roots(Piecewise<SBasis> const &f, std::vector<double> const &values);
+//TODO: implement level_sets directly for pwsb instead of sb (and derive it fo sb).
+//It should be faster than the reverse as the algorithm may jump over full cut intervals.
+std::vector<Interval> level_set(Piecewise<SBasis> const &f, Interval const &level, double tol=1e-5);
+std::vector<Interval> level_set(Piecewise<SBasis> const &f, double v, double vtol, double tol=1e-5);
+//std::vector<Interval> level_sets(Piecewise<SBasis> const &f, std::vector<Interval> const &levels, double tol=1e-5);
+//std::vector<Interval> level_sets(Piecewise<SBasis> const &f, std::vector<double> &v, double vtol, double tol=1e-5);
+
+
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
template<typename T>
Piecewise<T> reverse(Piecewise<T> const &f) {
Piecewise<T> ret = Piecewise<T>();
diff --git a/src/2geom/point.cpp b/src/2geom/point.cpp
index 45e035d4a..9df88df92 100644
--- a/src/2geom/point.cpp
+++ b/src/2geom/point.cpp
@@ -1,25 +1,46 @@
-#include <2geom/point.h>
#include <assert.h>
-#include <2geom/coord.h>
-#include <2geom/isnan.h> //temporary fix for isnan()
+#include <math.h>
+#include <2geom/point.h>
#include <2geom/transforms.h>
namespace Geom {
-/** \brief Scales this vector to make it a unit vector (within rounding error).
+/**
+ * @class Point
+ * @brief Two-dimensional point that doubles as a vector.
+ *
+ * Points in 2Geom are represented in Cartesian coordinates, e.g. as a pair of numbers
+ * that store the X and Y coordinates. Each point is also a vector in \f$\mathbb{R}^2\f$
+ * from the origin (point at 0,0) to the stored coordinates,
+ * and has methods implementing several vector operations (like length()).
*
- * The current version tries to handle infinite coordinates gracefully,
- * but it's not clear that any callers need that.
+ * \par Operator note
+ * \par
+ * Most operators are provided by Boost operator helpers, so they are not visible in this class.
+ * If @a p, @a q, @a r denote points, @a s a floating-point scalar, and @a m a transformation matrix,
+ * then the following operations are available:
+ * @code
+ p += q; p -= q; r = p + q; r = p - q;
+ p *= s; p /= s; q = p * s; q = s * p; q = p / s;
+ p *= m; p /= m; q = p * m; q = m * p; q = p / m;
+ @endcode
+ * It is possible to left-multiply a point by a matrix, even though mathematically speaking
+ * this is undefined. The result is a point identical to that obtained by right-multiplying.
+ * Division of points by matrices is defined as multiplication by their inverses.
*
- * \pre \f$this \neq (0, 0)\f$
- * \pre Neither component is NaN.
- * \post \f$-\epsilon<\left|this\right|-1<\epsilon\f$
- */
+ * @ingroup Primitives */
+
+/** @brief Normalize the vector representing the point.
+ * After this method returns, the length of the vector will be 1 (unless both coordinates are
+ * zero - the zero point will be returned then). The function tries to handle infinite
+ * coordinates gracefully. If any of the coordinates are NaN, the function will do nothing.
+ * @post \f$-\epsilon < \left|this\right| - 1 < \epsilon\f$
+ * @see unit_vector(Geom::Point const &) */
void Point::normalize() {
double len = hypot(_pt[0], _pt[1]);
if(len == 0) return;
if(IS_NAN(len)) return;
- static double const inf = 1e400;
+ static double const inf = HUGE_VAL;
if(len != inf) {
*this /= len;
} else {
@@ -58,7 +79,10 @@ void Point::normalize() {
}
}
-/** Compute the L1 norm, or manhattan distance, of \a p. */
+/** @brief Compute the first norm (Manhattan distance) of @a p.
+ * This is equal to the sum of absolutes values of the coordinates.
+ * @return \f$|p_X| + |p_Y|\f$
+ * @relates Point */
Coord L1(Point const &p) {
Coord d = 0;
for ( int i = 0 ; i < 2 ; i++ ) {
@@ -67,7 +91,9 @@ Coord L1(Point const &p) {
return d;
}
-/** Compute the L infinity, or maximum, norm of \a p. */
+/** @brief Compute the infinity norm (maximum norm) of @a p.
+ * @return \f$\max(p_X, p_Y)\f$
+ * @relates Point */
Coord LInfty(Point const &p) {
Coord const a(fabs(p[0]));
Coord const b(fabs(p[1]));
@@ -76,80 +102,83 @@ Coord LInfty(Point const &p) {
: a );
}
-/** Returns true iff p is a zero vector, i.e.\ Point(0, 0).
- *
- * (NaN is considered non-zero.)
- */
-bool
-is_zero(Point const &p)
-{
+/** @brief True if the point has both coordinates zero.
+ * NaNs are treated as not equal to zero.
+ * @relates Point */
+bool is_zero(Point const &p) {
return ( p[0] == 0 &&
p[1] == 0 );
}
-bool
-is_unit_vector(Point const &p)
-{
- return fabs(1.0 - L2(p)) <= 1e-4;
- /* The tolerance of 1e-4 is somewhat arbitrary. Point::normalize is believed to return
- points well within this tolerance. I'm not aware of any callers that want a small
- tolerance; most callers would be ok with a tolerance of 0.25. */
+/** @brief True if the point has a length near 1. The are_near() function is used.
+ * @relates Point */
+bool is_unit_vector(Point const &p) {
+ return are_near(L2(p), 1.0);
}
-
-Coord atan2(Point const p) {
+/** @brief Return the angle between the point and the +X axis.
+ * @return Angle in \f$(-\pi, \pi]\f$.
+ * @relates Point */
+Coord atan2(Point const &p) {
return std::atan2(p[Y], p[X]);
}
-/** compute the angle turning from a to b. This should give \f$\pi/2\f$ for angle_between(a, rot90(a));
- * This works by projecting b onto the basis defined by a, rot90(a)
- */
-Coord angle_between(Point const a, Point const b) {
+/** @brief Compute the angle between a and b relative to the origin.
+ * The computation is done by projecting b onto the basis defined by a, rot90(a).
+ * @return Angle in \f$(-\pi, \pi]\f$.
+ * @relates Point */
+Coord angle_between(Point const &a, Point const &b) {
return std::atan2(cross(b,a), dot(b,a));
}
-
-
-/** Returns a version of \a a scaled to be a unit vector (within rounding error).
- *
- * The current version tries to handle infinite coordinates gracefully,
- * but it's not clear that any callers need that.
- *
- * \pre a != Point(0, 0).
- * \pre Neither coordinate is NaN.
- * \post L2(ret) very near 1.0.
- */
+/** @brief Create a normalized version of a point.
+ * This is equivalent to copying the point and calling its normalize() method.
+ * The returned point will be (0,0) if the argument has both coordinates equal to zero.
+ * If any coordinate is NaN, this function will do nothing.
+ * @param a Input point
+ * @return Point on the unit circle in the same direction from origin as a, or the origin
+ * if a has both coordinates equal to zero
+ * @relates Point */
Point unit_vector(Point const &a)
{
Point ret(a);
ret.normalize();
return ret;
}
-
+/** @brief Return the "absolute value" of the point's vector.
+ * This is defined in terms of the default lexicographical ordering. If the point is "larger"
+ * that the origin (0, 0), its negation is returned. This corresponds to making the Y coordinate
+ * positive. You can check whether the points' vectors have the same direction (e.g. lie
+ * on the same line passing through the origin) using
+ * @code abs(a).normalize() == abs(b).normalize() @endcode.
+ * To check with some margin of error, use
+ * @code are_near(abs(a).normalize(), abs(b).normalize()) @endcode.
+ * Although naively this should take the absolute value of each coordinate, such an operation
+ * is not very useful.
+ * @return \f$p' = (p_X, -p_Y)\f$
+ * @relates Point */
Point abs(Point const &b)
{
- Point ret;
- for ( int i = 0 ; i < 2 ; i++ ) {
- ret[i] = fabs(b[i]);
- }
+ Point ret = b;
+ ret[Y] = fabs(ret[Y]);
return ret;
}
-Point operator*(Point const &v, Matrix const &m) {
- Point ret;
+/** @brief Transform the point by the specified matrix. */
+Point &Point::operator*=(Affine const &m) {
+ double x = _pt[X], y = _pt[Y];
for(int i = 0; i < 2; i++) {
- ret[i] = v[X] * m[i] + v[Y] * m[i + 2] + m[i + 4];
+ _pt[i] = x * m[i] + y * m[i + 2] + m[i + 4];
}
- return ret;
-}
-
-Point operator/(Point const &p, Matrix const &m) { return p * m.inverse(); }
-
-Point &Point::operator*=(Matrix const &m)
-{
- *this = *this * m;
return *this;
}
+/** @brief Snap the angle B - A - dir to miltiples of \f$2\pi/n\f$.
+ * The 'dir' argument must be normalized (have an unit length), otherwise the result
+ * is undefined.
+ * @return Point with the same distance from A as B, with a snapped angle.
+ * @post distance(A, B) == distance(A, result)
+ * @post angle_between(result - A, dir) == \f$2k\pi/n, k \in \mathbb{N}\f$
+ * @relates Point */
Point constrain_angle(Point const &A, Point const &B, unsigned int n, Point const &dir)
{
// for special cases we could perhaps use explicit testing (which might be faster)
diff --git a/src/2geom/point.h b/src/2geom/point.h
index 562950525..97f5142e3 100644
--- a/src/2geom/point.h
+++ b/src/2geom/point.h
@@ -1,241 +1,367 @@
-#ifndef SEEN_Geom_POINT_H
-#define SEEN_Geom_POINT_H
-
/**
* \file
- * \brief Defines a Cartesian 2D Point class.
+ * \brief Cartesian point / 2D vector and related operations
+ *//*
+ * Authors:
+ * Michael G. Sloan <mgsloan@gmail.com>
+ * Nathan Hurst <njh@njhurst.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2006-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
*/
-#include <iostream>
+#ifndef SEEN_Geom_POINT_H
+#define SEEN_Geom_POINT_H
+#include "config.h"
+#include <iostream>
+#include <iterator>
+#include <boost/operators.hpp>
+#include <2geom/forward.h>
#include <2geom/coord.h>
-#include <2geom/isnan.h>
-#include <2geom/utils.h>
+#include <2geom/isnan.h> //temporary fix for isnan()
+#include <2geom/math-utils.h>
namespace Geom {
-enum Dim2 { X=0, Y=1 };
-
-class Matrix;
-
-/// Cartesian 2D point.
-class Point {
+class Point
+ : boost::additive< Point
+ , boost::totally_ordered< Point
+ , boost::multiplicative< Point, Coord
+ , boost::multiplicative< Point, Affine
+ , boost::multiplicative< Point, Translate
+ , boost::multiplicative< Point, Rotate
+ , boost::multiplicative< Point, Scale
+ , boost::multiplicative< Point, HShear
+ , boost::multiplicative< Point, VShear
+ > > > > > > > > > // this uses chaining so it looks weird, but works
+{
Coord _pt[2];
- public:
- /// The default constructor creates an Point(0,0) DO NOT RELY ON THIS, BEST NOT TO USE THIS CONSTRUCTOR
- inline Point()
+public:
+ /** Construct a point on the origin. */
+ Point()
{ _pt[X] = _pt[Y] = 0; }
- inline Point(Coord x, Coord y) {
+ /** Construct a point from its coordinates. */
+ Point(Coord x, Coord y) {
_pt[X] = x; _pt[Y] = y;
}
-
- inline Point(Point const &p) {
+ Point(Point const &p) {
for (unsigned i = 0; i < 2; ++i)
_pt[i] = p._pt[i];
}
-
- inline Point &operator=(Point const &p) {
+ Point &operator=(Point const &p) {
for (unsigned i = 0; i < 2; ++i)
_pt[i] = p._pt[i];
return *this;
}
- inline Coord operator[](unsigned i) const { return _pt[i]; }
- inline Coord &operator[](unsigned i) { return _pt[i]; }
+ /// @name Access the coordinates of a point
+ /// @{
+ Coord operator[](unsigned i) const { return _pt[i]; }
+ Coord &operator[](unsigned i) { return _pt[i]; }
Coord operator[](Dim2 d) const throw() { return _pt[d]; }
Coord &operator[](Dim2 d) throw() { return _pt[d]; }
+ /// @}
- static inline Point polar(Coord angle, Coord radius) {
- return Point(radius * std::cos(angle), radius * std::sin(angle));
- }
-
- inline Coord length() const { return hypot(_pt[0], _pt[1]); }
+ /// @name Vector operations
+ /// @{
+ /** @brief Compute the distance from origin.
+ * @return Length of the vector from origin to this point */
+ Coord length() const { return hypot(_pt[0], _pt[1]); }
+ void normalize();
- /** Return a point like this point but rotated -90 degrees.
- (If the y axis grows downwards and the x axis grows to the
- right, then this is 90 degrees counter-clockwise.)
- **/
+ /** @brief Return a point like this point but rotated -90 degrees.
+ * If the y axis grows downwards and the x axis grows to the
+ * right, then this is 90 degrees counter-clockwise. */
Point ccw() const {
return Point(_pt[Y], -_pt[X]);
}
- /** Return a point like this point but rotated +90 degrees.
- (If the y axis grows downwards and the x axis grows to the
- right, then this is 90 degrees clockwise.)
- **/
+ /** @brief Return a point like this point but rotated +90 degrees.
+ * If the y axis grows downwards and the x axis grows to the
+ * right, then this is 90 degrees clockwise. */
Point cw() const {
return Point(-_pt[Y], _pt[X]);
}
+ /// @}
- /**
- \brief A function to lower the precision of the point
- \param places The number of decimal places that should be in
- the final number.
- */
- inline void round (int places = 0) {
- _pt[X] = (Coord)(decimal_round((double)_pt[X], places));
- _pt[Y] = (Coord)(decimal_round((double)_pt[Y], places));
- return;
- }
-
- void normalize();
-
- inline bool isFinite() const {
- for ( unsigned i = 0 ; i < 2 ; ++i ) {
- if(!IS_FINITE(_pt[i])) return false;
- }
- return true;
- }
-
- inline Point operator+(Point const &o) const {
- return Point(_pt[X] + o._pt[X], _pt[Y] + o._pt[Y]);
- }
- inline Point operator-(Point const &o) const {
- return Point(_pt[X] - o._pt[X], _pt[Y] - o._pt[Y]);
+ /// @name Vector-like arithmetic operations
+ /// @{
+ Point operator-() const {
+ return Point(-_pt[X], -_pt[Y]);
}
- inline Point &operator+=(Point const &o) {
+ Point &operator+=(Point const &o) {
for ( unsigned i = 0 ; i < 2 ; ++i ) {
_pt[i] += o._pt[i];
}
return *this;
}
- inline Point &operator-=(Point const &o) {
+ Point &operator-=(Point const &o) {
for ( unsigned i = 0 ; i < 2 ; ++i ) {
_pt[i] -= o._pt[i];
}
return *this;
}
-
- inline Point operator-() const {
- return Point(-_pt[X], -_pt[Y]);
- }
- inline Point operator*(double const s) const {
- return Point(_pt[X] * s, _pt[Y] * s);
- }
- inline Point operator/(double const s) const {
- //TODO: s == 0?
- return Point(_pt[X] / s, _pt[Y] / s);
- }
- inline Point &operator*=(double const s) {
+ Point &operator*=(Coord s) {
for ( unsigned i = 0 ; i < 2 ; ++i ) _pt[i] *= s;
return *this;
}
- inline Point &operator/=(double const s) {
+ Point &operator/=(Coord s) {
//TODO: s == 0?
for ( unsigned i = 0 ; i < 2 ; ++i ) _pt[i] /= s;
return *this;
}
+ /// @}
+
+ /// @name Affine transformations
+ /// @{
+ Point &operator*=(Affine const &m);
+ // implemented in transforms.cpp
+ Point &operator*=(Translate const &t);
+ Point &operator*=(Scale const &s);
+ Point &operator*=(Rotate const &r);
+ Point &operator*=(HShear const &s);
+ Point &operator*=(VShear const &s);
+ /** @brief Transform the point by the inverse of the specified matrix. */
+ template <typename T>
+ Point &operator/=(T const &m) {
+ *this *= m.inverse();
+ return *this;
+ }
+ /// @}
+
+ /// @name Various utilities
+ /// @{
+ /** @brief Lower the precision of the point.
+ * This will round both coordinates to multiples of \f$10^p\f$. */
+ void round (int p = 0) {
+ _pt[X] = (Coord)(decimal_round((double)_pt[X], p));
+ _pt[Y] = (Coord)(decimal_round((double)_pt[Y], p));
+ return;
+ }
- Point &operator*=(Matrix const &m);
-
- inline int operator == (const Point &in_pnt) {
+ /** @brief Check whether both coordinates are finite.
+ * @return True if neither coordinate is infinite. */
+ bool isFinite() const {
+ for ( unsigned i = 0 ; i < 2 ; ++i ) {
+ if(!IS_FINITE(_pt[i])) return false;
+ }
+ return true;
+ }
+ /** @brief Equality operator.
+ * This tests for exact identity (as opposed to are_near()). Note that due to numerical
+ * errors, this test might return false even if the points should be identical. */
+ bool operator==(const Point &in_pnt) const {
return ((_pt[X] == in_pnt[X]) && (_pt[Y] == in_pnt[Y]));
}
+ /** @brief Lexicographical ordering for points.
+ * Y coordinate is regarded as more significant. When sorting according to this
+ * ordering, the points will be sorted according to the Y coordinate, and within
+ * points with the same Y coordinate according to the X coordinate. */
+ bool operator<(const Point &p) const {
+ return ( ( _pt[Y] < p[Y] ) ||
+ (( _pt[Y] == p[Y] ) && ( _pt[X] < p[X] )));
+ }
+ /// @}
+
+ /// @name Point factories
+ /// @{
+ /** @brief Construct a point from its polar coordinates.
+ * The angle is specified in radians, in the mathematical convention (increasing
+ * counter-clockwise from +X). */
+ static Point polar(Coord angle, Coord radius) {
+ Point ret(polar(angle));
+ ret *= radius;
+ return ret;
+ }
+ /** @brief Construct an unit vector from its angle.
+ * The angle is specified in radians, in the mathematical convention (increasing
+ * counter-clockwise from +X). */
+ static Point polar(Coord angle) {
+ Point ret;
+ sincos(angle, ret[Y], ret[X]);
+ return ret;
+ }
+ /// @}
+
+ /** @brief Lexicographical ordering functor. */
+ template <Dim2 d> struct LexOrder;
+ /** @brief Lexicographical ordering functor with runtime dimension. */
+ class LexOrderRt {
+ public:
+ LexOrderRt(Dim2 d) : dim(d) {}
+ inline bool operator()(Point const &a, Point const &b);
+ private:
+ Dim2 dim;
+ };
friend inline std::ostream &operator<< (std::ostream &out_file, const Geom::Point &in_pnt);
};
-inline Point operator*(double const s, Point const &p) { return p * s; }
-
-/** A function to print out the Point. It just prints out the coords
- on the given output stream */
+/** @brief Output operator for points.
+ * Prints out the coordinates.
+ * @relates Point */
inline std::ostream &operator<< (std::ostream &out_file, const Geom::Point &in_pnt) {
out_file << "X: " << in_pnt[X] << " Y: " << in_pnt[Y];
return out_file;
}
-/** This is a rotation (sort of). */
-inline Point operator^(Point const &a, Point const &b) {
- Point const ret(a[0] * b[0] - a[1] * b[1],
- a[1] * b[0] + a[0] * b[1]);
- return ret;
+template<> struct Point::LexOrder<X> {
+ bool operator()(Point const &a, Point const &b) {
+ return a[X] < b[X] || (a[X] == b[X] && a[Y] < b[Y]);
+ }
+};
+template<> struct Point::LexOrder<Y> {
+ bool operator()(Point const &a, Point const &b) {
+ return a[Y] < b[Y] || (a[Y] == b[Y] && a[X] < b[X]);
+ }
+};
+inline bool Point::LexOrderRt::operator()(Point const &a, Point const &b) {
+ return dim ? Point::LexOrder<Y>()(a, b) : Point::LexOrder<X>()(a, b);
}
-//IMPL: boost::EqualityComparableConcept
-inline bool operator==(Point const &a, Point const &b) {
- return (a[X] == b[X]) && (a[Y] == b[Y]);
-}
-inline bool operator!=(Point const &a, Point const &b) {
- return (a[X] != b[X]) || (a[Y] != b[Y]);
+/** @brief Compute the second (Euclidean) norm of @a p.
+ * This corresponds to the length of @a p. The result will not overflow even if
+ * \f$p_X^2 + p_Y^2\f$ is larger that the maximum value that can be stored
+ * in a <code>double</code>.
+ * @return \f$\sqrt{p_X^2 + p_Y^2}\f$
+ * @relates Point */
+inline Coord L2(Point const &p)
+{
+ return p.length();
}
-/** This is a lexicographical ordering for points. It is remarkably useful for sweepline algorithms*/
-inline bool operator<=(Point const &a, Point const &b) {
- return ( ( a[Y] < b[Y] ) ||
- (( a[Y] == b[Y] ) && ( a[X] < b[X] )));
+/** @brief Compute the square of the Euclidean norm of @a p.
+ * Warning: this can overflow where L2 won't.
+ * @return \f$p_X^2 + p_Y^2\f$
+ * @relates Point */
+inline Coord L2sq(Point const &p)
+{
+ return p[0]*p[0] + p[1]*p[1];
}
-Coord L1(Point const &p);
-
-/** Compute the L2, or euclidean, norm of \a p. */
-inline Coord L2(Point const &p) { return p.length(); }
-
-/** Compute the square of L2 norm of \a p. Warning: this can overflow where L2 won't.*/
-inline Coord L2sq(Point const &p) { return p[0]*p[0] + p[1]*p[1]; }
-
-double LInfty(Point const &p);
-bool is_zero(Point const &p);
-bool is_unit_vector(Point const &p);
-
-extern double atan2(Point const p);
-/** compute the angle turning from a to b (signed). */
-extern double angle_between(Point const a, Point const b);
-
//IMPL: NearConcept
-inline bool are_near(Point const &a, Point const &b, double const eps=EPSILON) {
+/** @brief Nearness predicate for points.
+ * True if neither coordinate of @a a is further than @a eps from the corresponding
+ * coordinate of @a b.
+ * @relates Point */
+inline bool are_near(Point const &a, Point const &b, double const eps=EPSILON)
+{
return ( are_near(a[X],b[X],eps) && are_near(a[Y],b[Y],eps) );
}
-inline
-Point middle_point(Point const& P1, Point const& P2)
+/** @brief Return a point halfway between the specified ones.
+ * @relates Point */
+inline Point middle_point(Point const& P1, Point const& P2)
{
return (P1 + P2) / 2;
}
-/** Returns p * Geom::rotate_degrees(90), but more efficient.
+/** @brief Returns p * Geom::rotate_degrees(90), but more efficient.
*
- * Angle direction in Inkscape code: If you use the traditional mathematics convention that y
+ * Angle direction in 2Geom: If you use the traditional mathematics convention that y
* increases upwards, then positive angles are anticlockwise as per the mathematics convention. If
* you take the common non-mathematical convention that y increases downwards, then positive angles
* are clockwise, as is common outside of mathematics.
*
- * There is no rot_neg90 function: use -rot90(p) instead.
- */
-inline Point rot90(Point const &p) { return Point(-p[Y], p[X]); }
+ * There is no function to rotate by -90 degrees: use -rot90(p) instead.
+ * @relates Point */
+inline Point rot90(Point const &p)
+{
+ return Point(-p[Y], p[X]);
+}
-/** Given two points and a parameter t \in [0, 1], return a point
- * proportionally from a to b by t. Akin to 1 degree bezier.*/
-inline Point lerp(double const t, Point const a, Point const b) { return (a * (1 - t) + b * t); }
+/** @brief Linear interpolation between two points.
+ * @param t Time value
+ * @param a First point
+ * @param b Second point
+ * @return Point on a line between a and b. The ratio of its distance from a
+ * and the distance between a and b will be equal to t.
+ * @relates Point */
+inline Point lerp(double const t, Point const &a, Point const &b)
+{
+ return (a * (1 - t) + b * t);
+}
-Point unit_vector(Point const &a);
+/** @brief Compute the dot product of a and b.
+ * Dot product can be interpreted as a measure of how parallel the vectors are.
+ * For perpendicular vectors, it is zero. For parallel ones, its absolute value is highest,
+ * and the sign depends on whether they point in the same direction (+) or opposite ones (-).
+ * @return \f$a \cdot b = a_X b_X + a_Y b_Y\f$.
+ * @relates Point*/
+inline Coord dot(Point const &a, Point const &b)
+{
+ return a[0] * b[0] + a[1] * b[1];
+}
-/** compute the dot product (inner product) between the vectors a and b. */
-inline Coord dot(Point const &a, Point const &b) { return a[0] * b[0] + a[1] * b[1]; }
-/** Defined as dot(a, b.cw()). */
-inline Coord cross(Point const &a, Point const &b) { return dot(a, b.cw()); }
+/** @brief Compute the 2D cross product.
+ * Defined as dot(a, b.cw()). This means it will be zero for parallel vectors,
+ * and its absolute value highest for perpendicular vectors.
+ * @relates Point*/
+inline Coord cross(Point const &a, Point const &b)
+{
+ return dot(a, b.cw());
+}
-/** compute the euclidean distance between points a and b. TODO: hypot safer/faster? */
-inline Coord distance (Point const &a, Point const &b) { return L2(a - b); }
+/** @brief Compute the (Euclidean) distance between points.
+ * @relates Point */
+inline Coord distance (Point const &a, Point const &b)
+{
+ return L2(a - b);
+}
-/** compute the square of the distance between points a and b. */
-inline Coord distanceSq (Point const &a, Point const &b) { return L2sq(a - b); }
+/** @brief Compute the square of the distance between points.
+ * @relates Point */
+inline Coord distanceSq (Point const &a, Point const &b)
+{
+ return L2sq(a - b);
+}
+Point unit_vector(Point const &a);
+Coord L1(Point const &p);
+Coord LInfty(Point const &p);
+bool is_zero(Point const &p);
+bool is_unit_vector(Point const &p);
+extern double atan2(Point const &p);
+extern double angle_between(Point const &a, Point const &b);
Point abs(Point const &b);
-
-Point operator*(Point const &v, Matrix const &m);
-
-Point operator/(Point const &p, Matrix const &m);
-
-/** Constrains the angle (with respect to dir) of the line
- * joining A and B to a multiple of pi/n.
- */
Point constrain_angle(Point const &A, Point const &B, unsigned int n = 4, Geom::Point const &dir = Geom::Point(1,0));
} /* namespace Geom */
+// This is required to fix a bug in GCC 4.3.3 (and probably others) that causes the compiler
+// to try to instantiate the iterator_traits template and fail. Probably it thinks that Point
+// is an iterator and tries to use std::distance instead of Geom::distance.
+namespace std {
+template <> class iterator_traits<Geom::Point> {};
+}
+
#endif /* !SEEN_Geom_POINT_H */
/*
diff --git a/src/2geom/poly.cpp b/src/2geom/poly.cpp
index 9fa8e47db..de0229172 100644
--- a/src/2geom/poly.cpp
+++ b/src/2geom/poly.cpp
@@ -1,6 +1,5 @@
#include <2geom/poly.h>
-#define HAVE_GSL
#ifdef HAVE_GSL
#include <gsl/gsl_poly.h>
#endif
diff --git a/src/2geom/poly.h b/src/2geom/poly.h
index e0ba0580f..3567bda6d 100644
--- a/src/2geom/poly.h
+++ b/src/2geom/poly.h
@@ -34,6 +34,7 @@
#ifndef LIB2GEOM_SEEN_POLY_H
#define LIB2GEOM_SEEN_POLY_H
+
#include <assert.h>
#include <vector>
#include <iostream>
@@ -205,11 +206,13 @@ Poly gcd(Poly const &a, Poly const &b, const double tol=1e-10);
*/
std::vector<std::complex<double> > solve(const Poly & p);
+#ifdef HAVE_GSL
/*** solve_reals(Poly p)
* find all real solutions to Poly p.
* currently we just use solve and pick out the suitably real looking values, there may be a better algorithm.
*/
std::vector<double> solve_reals(const Poly & p);
+#endif
double polish_root(Poly const & p, double guess, double tol);
inline std::ostream &operator<< (std::ostream &out_file, const Poly &in_poly) {
diff --git a/src/2geom/ray.h b/src/2geom/ray.h
index 3156a944d..638b86195 100644
--- a/src/2geom/ray.h
+++ b/src/2geom/ray.h
@@ -28,21 +28,30 @@
* the specific language governing rights and limitations.
*/
-#ifndef _2GEOM_RAY_H_
-#define _2GEOM_RAY_H_
+#ifndef LIB2GEOM_SEEN_RAY_H
+#define LIB2GEOM_SEEN_RAY_H
+#include <vector>
#include <2geom/point.h>
#include <2geom/bezier-curve.h> // for LineSegment
#include <2geom/exception.h>
-#include <vector>
-
-
namespace Geom
{
-class Ray
-{
+/**
+ * @brief Straight ray from a specific point to infinity.
+ *
+ * Rays are "half-lines" - they begin at some specific point and extend in a straight line
+ * to infinity.
+ *
+ * @ingroup Primitives
+ */
+class Ray {
+private:
+ Point m_origin;
+ Point m_versor;
+
public:
Ray()
: m_origin(0,0), m_versor(1,0)
@@ -183,22 +192,17 @@ public:
return LineSegment(pointAt(f), pointAt(t));
}
- Ray transformed(Matrix const& m) const
+ Ray transformed(Affine const& m) const
{
return Ray(m_origin * m, (m_origin + m_versor) * m);
}
-
-private:
- Point m_origin;
- Point m_versor;
-
}; // end class ray
inline
double distance(Point const& _point, Ray const& _ray)
{
double t = _ray.nearestPoint(_point);
- return distance(_point, _ray.pointAt(t));
+ return ::Geom::distance(_point, _ray.pointAt(t));
}
inline
diff --git a/src/2geom/rect.h b/src/2geom/rect.h
index cce1d64f0..65bb1bb76 100644
--- a/src/2geom/rect.h
+++ b/src/2geom/rect.h
@@ -1,8 +1,7 @@
/**
* \file
- * \brief D2<Interval> specialization to Rect
- */
-/*
+ * \brief Axis-aligned rectangle
+ *//*
* Copyright 2007 Michael Sloan <mgsloan@gmail.com>
*
* This library is free software; you can redistribute it and/or
@@ -28,9 +27,7 @@
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
- */
-
-/* Authors of original rect class:
+ * Authors of original rect class:
* Lauris Kaplinski <lauris@kaplinski.com>
* Nathan Hurst <njh@mail.csse.monash.edu.au>
* bulia byak <buliabyak@users.sf.net>
@@ -39,52 +36,81 @@
#include <2geom/d2.h>
-#ifndef _2GEOM_RECT
-#define _2GEOM_RECT
+#ifndef LIB2GEOM_RECT_H
+#define LIB2GEOM_RECT_H
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <boost/optional/optional.hpp>
namespace Geom {
-/** D2<Interval> specialization to Rect */
+
+/**
+ * @brief Axis-aligned, non-empty rectangle - convenience typedef
+ * @ingroup Primitives
+ */
typedef D2<Interval> Rect;
class OptRect;
-Rect unify(const Rect &, const Rect &);
+inline Rect unify(Rect const &, Rect const &);
+
/**
- * %Rect class.
- * The Rect class is actually a specialisation of D2<Interval>.
- *
+ * @brief Axis aligned, non-empty rectangle.
+ * @ingroup Primitives
*/
template<>
class D2<Interval> {
- private:
+private:
Interval f[2];
- public:
- /** Best not to use this constructor, do not rely on what it initializes the object to.
- *The default constructor creates a rect of default intervals.
- */
+public:
+ /// @name Create rectangles.
+ /// @{
+ /** @brief Create a rectangle that contains only the point at (0,0). */
D2<Interval>() { f[X] = f[Y] = Interval(); }
-
- public:
+ /** @brief Create a rectangle from X and Y intervals. */
D2<Interval>(Interval const &a, Interval const &b) {
f[X] = a;
f[Y] = b;
}
-
+ /** @brief Create a rectangle from two points. */
D2<Interval>(Point const & a, Point const & b) {
f[X] = Interval(a[X], b[X]);
f[Y] = Interval(a[Y], b[Y]);
}
+ /** @brief Create a rectangle from a range of points.
+ * The resulting rectangle will contain all ponts from the range.
+ * The return type of iterators must be convertible to Point.
+ * The range must not be empty. For possibly empty ranges, see OptRect.
+ * @param start Beginning of the range
+ * @param end End of the range
+ * @return Rectangle that contains all points from [start, end). */
+ template <typename InputIterator>
+ static Rect from_range(InputIterator start, InputIterator end) {
+ assert(start != end);
+ Point p1 = *start++;
+ Rect result(p1, p1);
+ for (; start != end; ++start) {
+ result.expandTo(*start);
+ }
+ return result;
+ }
+ /** @brief Create a rectangle from a C-style array of points it should contain. */
+ static Rect from_array(Point const *c, unsigned n) {
+ Rect result = Rect::from_range(c, c+n);
+ return result;
+ }
+ /// @}
- inline Interval& operator[](unsigned i) { return f[i]; }
- inline Interval const & operator[](unsigned i) const { return f[i]; }
-
- inline Point min() const { return Point(f[X].min(), f[Y].min()); }
- inline Point max() const { return Point(f[X].max(), f[Y].max()); }
+ /// @name Inspect dimensions.
+ /// @{
+ Interval& operator[](unsigned i) { return f[i]; }
+ Interval const & operator[](unsigned i) const { return f[i]; }
- /** Returns the four corners of the rectangle in positive order
- * (clockwise if +Y is up, anticlockwise if +Y is down) */
+ Point min() const { return Point(f[X].min(), f[Y].min()); }
+ Point max() const { return Point(f[X].max(), f[Y].max()); }
+ /** @brief Return the n-th corner of the rectangle.
+ * If the Y axis grows upwards, this returns corners in clockwise order
+ * starting from the lower left. If Y grows downwards, it returns the corners
+ * in counter-clockwise order starting from the upper left. */
Point corner(unsigned i) const {
switch(i % 4) {
case 0: return Point(f[X].min(), f[Y].min());
@@ -95,17 +121,23 @@ class D2<Interval> {
}
//We should probably remove these - they're coord sys gnostic
- inline double top() const { return f[Y].min(); }
- inline double bottom() const { return f[Y].max(); }
- inline double left() const { return f[X].min(); }
- inline double right() const { return f[X].max(); }
-
- inline double width() const { return f[X].extent(); }
- inline double height() const { return f[Y].extent(); }
+ /** @brief Return top coordinate of the rectangle (+Y is downwards). */
+ Coord top() const { return f[Y].min(); }
+ /** @brief Return bottom coordinate of the rectangle (+Y is downwards). */
+ Coord bottom() const { return f[Y].max(); }
+ /** @brief Return leftmost coordinate of the rectangle (+X is to the right). */
+ Coord left() const { return f[X].min(); }
+ /** @brief Return rightmost coordinate of the rectangle (+X is to the right). */
+ Coord right() const { return f[X].max(); }
+
+ Coord width() const { return f[X].extent(); }
+ Coord height() const { return f[Y].extent(); }
- /** Returns a vector from min to max. */
- inline Point dimensions() const { return Point(f[X].extent(), f[Y].extent()); }
- inline Point midpoint() const { return Point(f[X].middle(), f[Y].middle()); }
+ /** @brief Get rectangle's width and height as a point.
+ * @return Point with X coordinate corresponding to the width and the Y coordinate
+ * corresponding to the height of the rectangle. */
+ Point dimensions() const { return Point(f[X].extent(), f[Y].extent()); }
+ Point midpoint() const { return Point(f[X].middle(), f[Y].middle()); }
/**
* \brief Compute the area of this rectangle.
@@ -113,39 +145,92 @@ class D2<Interval> {
* Note that a zero area rectangle is not empty - just as the interval [0,0] contains one point, the rectangle [0,0] x [0,0] contains 1 point and no area.
* \retval For a valid return value, the rect must be tested for emptyness first.
*/
- inline double area() const { return f[X].extent() * f[Y].extent(); }
- inline bool hasZeroArea(double eps = EPSILON) const { return (area() <= eps); }
+ /** @brief Compute rectangle's area. */
+ Coord area() const { return f[X].extent() * f[Y].extent(); }
+ /** @brief Check whether the rectangle has zero area up to specified tolerance.
+ * @param eps Maximum value of the area to consider empty
+ * @return True if rectangle has an area smaller than tolerance, false otherwise */
+ bool hasZeroArea(double eps = EPSILON) const { return (area() <= eps); }
- inline double maxExtent() const { return std::max(f[X].extent(), f[Y].extent()); }
- inline double minExtent() const { return std::min(f[X].extent(), f[Y].extent()); }
+ /** @brief Get the larger extent (width or height) of the rectangle. */
+ Coord maxExtent() const { return std::max(f[X].extent(), f[Y].extent()); }
+ /** @brief Get the smaller extent (width or height) of the rectangle. */
+ Coord minExtent() const { return std::min(f[X].extent(), f[Y].extent()); }
+ /// @}
-// inline bool isEmpty() const {
-// return f[X].isEmpty() || f[Y].isEmpty();
-// }
- inline bool intersects(Rect const &r) const {
- return f[X].intersects(r[X]) && f[Y].intersects(r[Y]);
+ /// @name Test other rectangles and points for inclusion.
+ /// @{
+ /** @brief Check whether the rectangles have any common points. */
+ bool intersects(Rect const &r) const {
+ return f[X].intersects(r[X]) && f[Y].intersects(r[Y]);
}
- inline bool contains(Rect const &r) const {
- return f[X].contains(r[X]) && f[Y].contains(r[Y]);
+ /** @brief Check whether the interiors of the rectangles have any common points. */
+ bool interiorIntersects(Rect const &r) const {
+ return f[X].interiorIntersects(r[X]) && f[Y].interiorIntersects(r[Y]);
}
- inline bool contains(Point const &p) const {
+ /** @brief Check whether the rectangle includes all points in the given rectangle. */
+ bool contains(Rect const &r) const {
+ return f[X].contains(r[X]) && f[Y].contains(r[Y]);
+ }
+ /** @brief Check whether the interior includes all points in the given rectangle.
+ * Interior of the rectangle is the entire rectangle without its borders. */
+ bool interiorContains(Rect const &r) const {
+ return f[X].interiorContains(r[X]) && f[Y].interiorContains(r[Y]);
+ }
+
+ /** @brief Check whether the rectangles have any common points.
+ * A non-empty rectangle will not intersect empty rectangles. */
+ inline bool intersects(OptRect const &r) const;
+ /** @brief Check whether the rectangle includes all points in the given rectangle.
+ * A non-empty rectangle will contain any empty rectangle. */
+ inline bool contains(OptRect const &r) const;
+ /** @brief Check whether the interior includes all points in the given rectangle.
+ * The interior of a non-empty rectangle will contain any empty rectangle. */
+ inline bool interiorContains(OptRect const &r) const;
+
+ /** @brief Check whether the given point is within the rectangle. */
+ bool contains(Point const &p) const {
return f[X].contains(p[X]) && f[Y].contains(p[Y]);
}
+ /** @brief Check whether the given point is in the rectangle's interior.
+ * This means the point must lie within the rectangle but not on its border. */
+ bool interiorContains(Point const &p) const {
+ return f[X].interiorContains(p[X]) && f[Y].interiorContains(p[Y]);
+ }
+ /// @}
- inline void expandTo(Point p) {
- f[X].extendTo(p[X]); f[Y].extendTo(p[Y]);
+ /// @name Modify the rectangle.
+ /// @{
+ /** @brief Enlarge the rectangle to contain the given point. */
+ void expandTo(Point p) {
+ f[X].expandTo(p[X]); f[Y].expandTo(p[Y]);
}
- inline void unionWith(Rect const &b) {
- f[X].unionWith(b[X]); f[Y].unionWith(b[Y]);
+ /** @brief Enlarge the rectangle to contain the given rectangle. */
+ void unionWith(Rect const &b) {
+ f[X].unionWith(b[X]); f[Y].unionWith(b[Y]);
}
+ /** @brief Enlarge the rectangle to contain the given rectangle.
+ * Unioning with an empty rectangle results in no changes. */
void unionWith(OptRect const &b);
-
- inline void expandBy(double amnt) {
- f[X].expandBy(amnt); f[Y].expandBy(amnt);
+
+ //TODO: figure out how these work with negative values and OptRect
+ /** @brief Expand the rectangle in both directions by the specified amount.
+ * Note that this is different from scaling. Negative values wil shrink the
+ * rectangle. If <code>-amount</code> is larger than
+ * half of the width, the X interval will contain only the X coordinate
+ * of the midpoint; same for height. */
+ void expandBy(Coord amount) {
+ f[X].expandBy(amount); f[Y].expandBy(amount);
}
- inline void expandBy(Point const p) {
- f[X].expandBy(p[X]); f[Y].expandBy(p[Y]);
+ /** @brief Expand the rectangle by the coordinates of the given point.
+ * This will expand the width by the X coordinate of the point in both directions
+ * and the height by Y coordinate of the point. Negative coordinate values will
+ * shrink the rectangle. If <code>-p[X]</code> is larger than half of the width,
+ * the X interval will contain only the X coordinate of the midpoint; same for height. */
+ void expandBy(Point const p) {
+ f[X].expandBy(p[X]); f[Y].expandBy(p[Y]);
}
+ /// @}
};
inline Rect unify(Rect const & a, Rect const & b) {
@@ -161,7 +246,7 @@ inline Rect union_list(std::vector<Rect> const &r) {
}
inline
-double distanceSq( Point const& p, Rect const& rect )
+Coord distanceSq( Point const& p, Rect const& rect )
{
double dx = 0, dy = 0;
if ( p[X] < rect.left() )
@@ -187,15 +272,14 @@ double distanceSq( Point const& p, Rect const& rect )
* Returns the smallest distance between p and rect.
*/
inline
-double distance( Point const& p, Rect const& rect )
+Coord distance( Point const& p, Rect const& rect )
{
return std::sqrt(distanceSq(p, rect));
}
/**
- * The OptRect class can represent and empty Rect and non-empty Rects.
- * If OptRect is not empty, it means that both X and Y intervals are not empty.
- *
+ * @brief Axis-aligned rectangle that can be empty.
+ * @ingroup Primitives
*/
class OptRect : public boost::optional<Rect> {
public:
@@ -212,22 +296,25 @@ public:
// else, stay empty.
}
- /**
- * Check whether this OptRect is empty or not.
- */
+ /** @brief Check for emptiness. */
inline bool isEmpty() const { return (*this == false); };
- /**
- * If \c this is empty, copy argument \c b. Otherwise, union with it (and do nothing when \c b is empty)
- */
+ bool intersects(Rect const &r) const { return r.intersects(*this); }
+ bool contains(Rect const &r) const { return *this && (*this)->contains(r); }
+ bool interiorContains(Rect const &r) const { return *this && (*this)->interiorContains(r); }
+
+ bool intersects(OptRect const &r) const { return *this && (*this)->intersects(r); }
+ bool contains(OptRect const &r) const { return *this && (*this)->contains(r); }
+ bool interiorContains(OptRect const &r) const { return *this && (*this)->interiorContains(r); }
+
+ bool contains(Point const &p) const { return *this && (*this)->contains(p); }
+ bool interiorContains(Point const &p) const { return *this && (*this)->contains(p); }
+
inline void unionWith(OptRect const &b) {
- if (b) {
- if (*this) { // check that we are not empty
- (**this)[X].unionWith((*b)[X]);
- (**this)[Y].unionWith((*b)[Y]);
- } else {
- *this = b;
- }
+ if (*this) { // check that we are not empty
+ (*this)->unionWith(b);
+ } else {
+ *this = b;
}
}
};
@@ -256,6 +343,15 @@ inline void Rect::unionWith(OptRect const &b) {
unionWith(*b);
}
}
+inline bool Rect::intersects(OptRect const &r) const {
+ return r && intersects(*r);
+}
+inline bool Rect::contains(OptRect const &r) const {
+ return !r || contains(*r);
+}
+inline bool Rect::interiorContains(OptRect const &r) const {
+ return !r || interiorContains(*r);
+}
} // end namespace Geom
diff --git a/src/2geom/recursive-bezier-intersection.cpp b/src/2geom/recursive-bezier-intersection.cpp
index 421f61308..b4c81e08e 100644
--- a/src/2geom/recursive-bezier-intersection.cpp
+++ b/src/2geom/recursive-bezier-intersection.cpp
@@ -63,7 +63,7 @@ void
find_intersections_bezier_recursive( std::vector<std::pair<double, double> > &xs,
vector<Geom::Point> const & A,
vector<Geom::Point> const & B,
- double precision) {
+ double /*precision*/) {
OldBezier a, b;
a.p = A;
b.p = B;
@@ -317,9 +317,9 @@ double Lmax(Point p) {
return std::max(fabs(p[X]), fabs(p[Y]));
}
-unsigned wangs_theorem(OldBezier a) {
+unsigned wangs_theorem(OldBezier /*a*/) {
return 6; // seems a good approximation!
- double la1 = Lmax( ( a.p[2] - a.p[1] ) - (a.p[1] - a.p[0]) );
+ /*double la1 = Lmax( ( a.p[2] - a.p[1] ) - (a.p[1] - a.p[0]) );
double la2 = Lmax( ( a.p[3] - a.p[2] ) - (a.p[2] - a.p[1]) );
double l0 = std::max(la1, la2);
unsigned ra;
@@ -328,7 +328,7 @@ unsigned wangs_theorem(OldBezier a) {
else
ra = (unsigned)ceil( log4( M_SQRT2 * 6.0 / 8.0 * INV_EPS * l0 ) );
//std::cout << ra << std::endl;
- return ra;
+ return ra;*/
}
struct rparams
@@ -337,7 +337,7 @@ struct rparams
OldBezier &B;
};
-static int
+/*static int
intersect_polish_f (const gsl_vector * x, void *params,
gsl_vector * f)
{
@@ -351,22 +351,22 @@ intersect_polish_f (const gsl_vector * x, void *params,
gsl_vector_set (f, 1, dx[1]);
return GSL_SUCCESS;
-}
+}*/
-union dbl_64{
+/*union dbl_64{
long long i64;
double d64;
-};
+};*/
-static double EpsilonBy(double value, int eps)
+/*static double EpsilonBy(double value, int eps)
{
dbl_64 s;
s.d64 = value;
s.i64 += eps;
return s.d64;
-}
-
+}*/
+/*
static void intersect_polish_root (OldBezier &A, double &s,
OldBezier &B, double &t) {
const gsl_multiroot_fsolver_type *T;
@@ -394,7 +394,7 @@ static void intersect_polish_root (OldBezier &A, double &s,
iter++;
status = gsl_multiroot_fsolver_iterate (sol);
- if (status) /* check if solver is stuck */
+ if (status) // check if solver is stuck
break;
status =
@@ -439,7 +439,7 @@ static void intersect_polish_root (OldBezier &A, double &s,
best_v = trial_v;
}
}
-}
+}*/
void find_intersections_bezier_recursive( std::vector<std::pair<double, double> > &xs,
diff --git a/src/2geom/region.cpp b/src/2geom/region.cpp
index 3c8c7fd1c..8cfb1c68c 100644
--- a/src/2geom/region.cpp
+++ b/src/2geom/region.cpp
@@ -5,9 +5,9 @@
namespace Geom {
-Region Region::operator*(Matrix const &m) const {
+Region Region::operator*(Affine const &m) const {
Region r((m.flips() ? boundary.reverse() : boundary) * m, fill);
- if(box && m.onlyScaleAndTranslation()) r.box = (*box) * m;
+ if(box && m.isZoom()) r.box = (*box) * m;
return r;
}
diff --git a/src/2geom/region.h b/src/2geom/region.h
index 937817595..e23d6a158 100644
--- a/src/2geom/region.h
+++ b/src/2geom/region.h
@@ -81,7 +81,7 @@ class Region {
Region inverse() const { return Region(boundary.reverse(), box, !fill); }
- Region operator*(Matrix const &m) const;
+ Region operator*(Affine const &m) const;
bool invariants() const;
};
diff --git a/src/2geom/sbasis-curve.h b/src/2geom/sbasis-curve.h
index 6641c0fe1..22fe4fc1f 100644
--- a/src/2geom/sbasis-curve.h
+++ b/src/2geom/sbasis-curve.h
@@ -1,12 +1,13 @@
/**
* \file
- * \brief Symmetric Power Basis Curve
- *
+ * \brief Symmetric power basis curve
+ *//*
* Authors:
- * MenTaLguY <mental@rydia.net>
- * Marco Cecchetti <mrcekets at gmail.com>
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
*
- * Copyright 2007-2008 authors
+ * Copyright 2007-2009 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -32,75 +33,77 @@
* the specific language governing rights and limitations.
*/
-
-
-
#ifndef _2GEOM_SBASIS_CURVE_H_
#define _2GEOM_SBASIS_CURVE_H_
-
#include <2geom/curve.h>
-
+#include <2geom/nearest-point.h>
+#include <2geom/sbasis-geometric.h>
namespace Geom
{
+/** @brief Symmetric power basis curve.
+ *
+ * Symmetric power basis (S-basis for short) polynomials are a versatile numeric representation
+ * of arbitrary continuous curves. They combine the properties of Bezier curves
+ * (geometric interpretation of parameters, numerical stability near ends of the curve)
+ * and the monomial basis (fast evaluation). They are the main representation of curves
+ * in 2Geom.
+ *
+ * @ingroup Curves
+ */
class SBasisCurve : public Curve {
-
+
private:
- SBasisCurve();
- D2<SBasis> inner;
+ SBasisCurve();
+ D2<SBasis> inner;
public:
- explicit SBasisCurve(D2<SBasis> const &sb) : inner(sb) {}
- explicit SBasisCurve(Curve const &other) : inner(other.toSBasis()) {}
- Curve *duplicate() const { return new SBasisCurve(*this); }
-
- Point initialPoint() const { return inner.at0(); }
- Point finalPoint() const { return inner.at1(); }
- bool isDegenerate() const { return inner.isConstant(); }
- Point pointAt(Coord t) const { return inner.valueAt(t); }
- std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const {
- return inner.valueAndDerivatives(t, n);
- }
- double valueAt(Coord t, Dim2 d) const { return inner[d].valueAt(t); }
-
- void setInitial(Point v) { for(unsigned d = 0; d < 2; d++) { inner[d][0][0] = v[d]; } }
- void setFinal(Point v) { for(unsigned d = 0; d < 2; d++) { inner[d][0][1] = v[d]; } }
-
- virtual OptRect boundsFast() const { return bounds_fast(inner); }
- virtual OptRect boundsExact() const { return bounds_exact(inner); }
- virtual OptRect boundsLocal(OptInterval i, unsigned deg) const { return bounds_local(inner, i, deg); }
-
- std::vector<double> roots(double v, Dim2 d) const { return Geom::roots(inner[d] - v); }
-
- double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
- {
- return nearest_point(p, inner, from, to);
- }
-
- std::vector<double>
- allNearestPoints( Point const& p, double from = 0, double to = 1 ) const
- {
- return all_nearest_points(p, inner, from, to);
- }
-
- Curve *portion(double f, double t) const {
- return new SBasisCurve(Geom::portion(inner, f, t));
- }
-
- Curve *transformed(Matrix const &m) const {
- return new SBasisCurve(inner * m);
- }
-
- Curve *derivative() const {
- return new SBasisCurve(Geom::derivative(inner));
- }
-
- D2<SBasis> toSBasis() const { return inner; }
-
- virtual int degreesOfFreedom() const { return inner[0].degreesOfFreedom() + inner[1].degreesOfFreedom();
- }
+ explicit SBasisCurve(D2<SBasis> const &sb) : inner(sb) {}
+ explicit SBasisCurve(Curve const &other) : inner(other.toSBasis()) {}
+
+ virtual Curve *duplicate() const { return new SBasisCurve(*this); }
+ virtual Point initialPoint() const { return inner.at0(); }
+ virtual Point finalPoint() const { return inner.at1(); }
+ virtual bool isDegenerate() const { return inner.isConstant(); }
+ virtual Point pointAt(Coord t) const { return inner.valueAt(t); }
+ virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const {
+ return inner.valueAndDerivatives(t, n);
+ }
+ virtual Coord valueAt(Coord t, Dim2 d) const { return inner[d].valueAt(t); }
+ virtual void setInitial(Point const &v) {
+ for (unsigned d = 0; d < 2; d++) { inner[d][0][0] = v[d]; }
+ }
+ virtual void setFinal(Point const &v) {
+ for (unsigned d = 0; d < 2; d++) { inner[d][0][1] = v[d]; }
+ }
+ virtual Rect boundsFast() const { return *bounds_fast(inner); }
+ virtual Rect boundsExact() const { return *bounds_exact(inner); }
+ virtual OptRect boundsLocal(OptInterval const &i, unsigned deg) const {
+ return bounds_local(inner, i, deg);
+ }
+ virtual std::vector<Coord> roots(Coord v, Dim2 d) const { return Geom::roots(inner[d] - v); }
+ virtual Coord nearestPoint( Point const& p, Coord from = 0, Coord to = 1 ) const {
+ return nearest_point(p, inner, from, to);
+ }
+ virtual std::vector<Coord> allNearestPoints( Point const& p, Coord from = 0,
+ Coord to = 1 ) const
+ {
+ return all_nearest_points(p, inner, from, to);
+ }
+ virtual Coord length(Coord tolerance) const { return ::Geom::length(inner, tolerance); }
+ virtual Curve *portion(Coord f, Coord t) const {
+ return new SBasisCurve(Geom::portion(inner, f, t));
+ }
+ virtual Curve *transformed(Affine const &m) const { return new SBasisCurve(inner * m); }
+ virtual Curve *derivative() const {
+ return new SBasisCurve(Geom::derivative(inner));
+ }
+ virtual D2<SBasis> toSBasis() const { return inner; }
+ virtual int degreesOfFreedom() const {
+ return inner[0].degreesOfFreedom() + inner[1].degreesOfFreedom();
+ }
};
diff --git a/src/2geom/sbasis-geometric.cpp b/src/2geom/sbasis-geometric.cpp
index 3fd667224..f4b445faa 100644
--- a/src/2geom/sbasis-geometric.cpp
+++ b/src/2geom/sbasis-geometric.cpp
@@ -151,7 +151,7 @@ Geom::cutAtRoots(Piecewise<D2<SBasis> > const &M, double ZERO){
\param vect a piecewise parameteric curve.
\param tol the maximum error allowed.
\param order the maximum degree to use for approximation
-
+ \relates Piecewise
*/
Piecewise<SBasis>
Geom::atan2(Piecewise<D2<SBasis> > const &vect, double tol, unsigned order){
@@ -182,7 +182,7 @@ Geom::atan2(Piecewise<D2<SBasis> > const &vect, double tol, unsigned order){
\param vect a piecewise parameteric curve.
\param tol the maximum error allowed.
\param order the maximum degree to use for approximation
-
+ \relates Piecewise, D2
*/
Piecewise<SBasis>
Geom::atan2(D2<SBasis> const &vect, double tol, unsigned order){
@@ -193,7 +193,7 @@ Geom::atan2(D2<SBasis> const &vect, double tol, unsigned order){
\param angle a piecewise function of angle wrt t.
\param tol the maximum error allowed.
\param order the maximum degree to use for approximation
-
+ \relates D2, SBasis
*/
D2<Piecewise<SBasis> >
Geom::tan2(SBasis const &angle, double tol, unsigned order){
@@ -204,7 +204,7 @@ Geom::tan2(SBasis const &angle, double tol, unsigned order){
\param angle a piecewise function of angle wrt t.
\param tol the maximum error allowed.
\param order the maximum degree to use for approximation
-
+ \relates Piecewise, D2
*/
D2<Piecewise<SBasis> >
Geom::tan2(Piecewise<SBasis> const &angle, double tol, unsigned order){
@@ -218,6 +218,8 @@ Geom::tan2(Piecewise<SBasis> const &angle, double tol, unsigned order){
unitVector(x,y) is computed as (b,-a) where a and b are solutions of:
ax+by=0 (eqn1) and a^2+b^2=1 (eqn2)
+
+ \relates Piecewise, D2
*/
Piecewise<D2<SBasis> >
Geom::unitVector(D2<SBasis> const &V_in, double tol, unsigned order){
@@ -296,6 +298,8 @@ Geom::unitVector(D2<SBasis> const &V_in, double tol, unsigned order){
unitVector(x,y) is computed as (b,-a) where a and b are solutions of:
ax+by=0 (eqn1) and a^2+b^2=1 (eqn2)
+
+ \relates Piecewise
*/
Piecewise<D2<SBasis> >
Geom::unitVector(Piecewise<D2<SBasis> > const &V, double tol, unsigned order){
@@ -314,7 +318,7 @@ Geom::unitVector(Piecewise<D2<SBasis> > const &V, double tol, unsigned order){
/** returns a function giving the arclength at each point in M.
\param M the Element.
\param tol the maximum error allowed.
-
+ \relates Piecewise
*/
Piecewise<SBasis>
Geom::arcLengthSb(Piecewise<D2<SBasis> > const &M, double tol){
@@ -328,7 +332,7 @@ Geom::arcLengthSb(Piecewise<D2<SBasis> > const &M, double tol){
/** returns a function giving the arclength at each point in M.
\param M the Element.
\param tol the maximum error allowed.
-
+ \relates Piecewise, D2
*/
Piecewise<SBasis>
Geom::arcLengthSb(D2<SBasis> const &M, double tol){
@@ -353,9 +357,8 @@ Geom::length(Piecewise<D2<SBasis> > const &M,
/** returns a function giving the curvature at each point in M.
\param M the Element.
\param tol the maximum error allowed.
-
- Todo:
- * claimed incomplete. Check.
+ \relates Piecewise, D2
+ \todo claimed incomplete. Check.
*/
Piecewise<SBasis>
Geom::curvature(D2<SBasis> const &M, double tol) {
@@ -371,9 +374,8 @@ Geom::curvature(D2<SBasis> const &M, double tol) {
/** returns a function giving the curvature at each point in M.
\param M the Element.
\param tol the maximum error allowed.
-
- Todo:
- * claimed incomplete. Check.
+ \relates Piecewise
+ \todo claimed incomplete. Check.
*/
Piecewise<SBasis>
Geom::curvature(Piecewise<D2<SBasis> > const &V, double tol){
@@ -395,7 +397,7 @@ Geom::curvature(Piecewise<D2<SBasis> > const &V, double tol){
\param M the Element.
\param tol the maximum error allowed.
\param order the maximum degree to use for approximation
-
+ \relates Piecewise, D2
*/
Piecewise<D2<SBasis> >
Geom::arc_length_parametrization(D2<SBasis> const &M,
@@ -424,7 +426,7 @@ Geom::arc_length_parametrization(D2<SBasis> const &M,
\param M the Element.
\param tol the maximum error allowed.
\param order the maximum degree to use for approximation
-
+ \relates Piecewise
*/
Piecewise<D2<SBasis> >
Geom::arc_length_parametrization(Piecewise<D2<SBasis> > const &M,
@@ -449,7 +451,7 @@ static double sb_length_integrating(double t, void* param) {
\param tol the maximum error allowed.
\param result variable to be incremented with the length of the path
\param abs_error variable to be incremented with the estimated error
-
+ \relates D2
If you only want the length, this routine may be faster/more accurate.
*/
void Geom::length_integrating(D2<SBasis> const &B, double &result, double &abs_error, double tol) {
@@ -474,7 +476,7 @@ void Geom::length_integrating(D2<SBasis> const &B, double &result, double &abs_e
/** Calculates the length of a D2<SBasis> through gsl integration.
\param s the Element.
\param tol the maximum error allowed.
-
+ \relates D2
If you only want the total length, this routine faster and more accurate than constructing an arcLengthSb.
*/
double
@@ -488,7 +490,7 @@ Geom::length(D2<SBasis> const &s,
/** Calculates the length of a Piecewise<D2<SBasis> > through gsl integration.
\param s the Element.
\param tol the maximum error allowed.
-
+ \relates Piecewise
If you only want the total length, this routine faster and more accurate than constructing an arcLengthSb.
*/
double
@@ -507,7 +509,7 @@ Geom::length(Piecewise<D2<SBasis> > const &s,
\param p the Element.
\param centroid on return contains the centroid of the shape
\param area on return contains the signed area of the shape.
-
+ \relates Piecewise
This approach uses green's theorem to compute the area and centroid using integrals. For curved shapes this is much faster than converting to polyline. Note that without an uncross operation the output is not the absolute area.
* Returned values:
@@ -620,6 +622,8 @@ solve_lambda0(double a0,double a1,double c0,double c1,
* proportional to the given ones.
* If insist_on_speed_signs == 0, allow speeds to point in the opposite direction (both at the same time)
* If insist_on_speed_signs == -1, allow speeds to point in both direction independantly.
+*
+* \relates D2
*/
std::vector<D2<SBasis> >
Geom::cubics_fitting_curvature(Point const &M0, Point const &M1,
@@ -743,6 +747,7 @@ Geom::cubics_with_prescribed_curvature(Point const &M0, Point const &M1,
/**
* \brief returns all the parameter values of A whose tangent passes through P.
+* \relates D2
*/
std::vector<double> find_tangents(Point P, D2<SBasis> const &A) {
SBasis crs (cross(A - P, derivative(A)));
diff --git a/src/2geom/sbasis-roots.cpp b/src/2geom/sbasis-roots.cpp
index 95fd0cf3b..1b870d88f 100644
--- a/src/2geom/sbasis-roots.cpp
+++ b/src/2geom/sbasis-roots.cpp
@@ -74,7 +74,7 @@ OptInterval bounds_exact(SBasis const &a) {
SBasis df = derivative(a);
vector<double>extrema = roots(df);
for (unsigned i=0; i<extrema.size(); i++){
- result.extendTo(a(extrema[i]));
+ result.expandTo(a(extrema[i]));
}
return result;
}
@@ -326,6 +326,211 @@ std::vector<std::vector<double> > multi_roots(SBasis const &f,
return(roots);
}
+
+
+static bool compareIntervalMin( Interval I, Interval J ){
+ return I.min()<J.min();
+}
+static bool compareIntervalMax( Interval I, Interval J ){
+ return I.max()<J.max();
+}
+
+//find the first interval whose max is >= x
+static unsigned upper_level(vector<Interval> const &levels, double x ){
+ return( lower_bound( levels.begin(), levels.end(), Interval(x,x), compareIntervalMax) - levels.begin() );
+}
+
+static std::vector<Interval> fuseContiguous(std::vector<Interval> const &sets, double tol=0.){
+ std::vector<Interval> result;
+ if (sets.size() == 0 ) return result;
+ result.push_back( sets.front() );
+ for (unsigned i=1; i < sets.size(); i++ ){
+ if ( result.back().max() + tol >= sets[i].min() ){
+ result.back().unionWith( sets[i] );
+ }else{
+ result.push_back( sets[i] );
+ }
+ }
+ return result;
+}
+
+/** level_sets internal method.
+* algorithm: (~adaptation of Newton method versus 'accroissements finis')
+ -compute f at both ends of the given segment [a,b].
+ -compute bounds m<df(t)<M for df on the segment.
+ Suppose f(a) is between two 'levels' c and C. Then
+ f wont enter c before a + (f(a)-c.max())/m
+ f wont enter C before a + (C.min()-f(a))/M
+ From this we conclude nothing happens before a'=a+min((f(a)-c.max())/m,(C.min()-f(a))/M).
+ We do the same for b: compute some b' such that nothing happens in (b',b].
+ -if [a',b'] is not empty, repeat the process with [a',(a'+b')/2] and [(a'+b')/2,b'].
+
+ If f(a) or f(b) belongs to some 'level' C, then use the same argument to find a' or b' such
+ that f remains in C on [a,a'] or [b',b]. In case f is monotonic, we also know f won't enter another
+ level before or after some time, allowing us to restrict the search a little more.
+
+ unfortunately, extra care is needed about rounding errors, and also to avoid the repetition of roots,
+ making things tricky and unpleasant...
+*/
+
+static void level_sets_internal(SBasis const &f,
+ SBasis const &df,
+ std::vector<Interval> const &levels,
+ std::vector<std::vector<Interval> > &solsets,
+ double a,
+ double fa,
+ double b,
+ double fb,
+ double tol=1e-5){
+
+ if (f.size()==0){
+ unsigned idx;
+ idx=upper_level( levels, 0. );
+ if (idx<levels.size() && levels[idx].contains(0.)){
+ solsets[idx].push_back( Interval(a,b) ) ;
+ }
+ return;
+ }
+
+ unsigned idxa=upper_level(levels,fa);
+ unsigned idxb=upper_level(levels,fb);
+
+ Interval bs = *bounds_local(df,Interval(a,b));
+
+ //first times when a level (higher or lower) can be reached from a or b.
+ double ta_hi; // f remains below next level for t<ta_hi
+ double ta_lo; // f remains above prev level for t<ta_lo
+ double tb_hi; // f remains below next level for t>tb_hi
+ double tb_lo; // f remains above next level for t>tb_lo
+
+ ta_hi=ta_lo=b+1;//default values => no root there.
+ tb_hi=tb_lo=a-1;//default values => no root there.
+
+ //--- if f(a) belongs to a level.-------
+ if ( idxa < levels.size() && levels[idxa].contains( fa ) ){
+ //find the first time when we may exit this level.
+ ta_lo = a + ( levels[idxa].min() - fa)/bs.min();
+ ta_hi = a + ( levels[idxa].max() - fa)/bs.max();
+ if ( ta_lo < a || ta_lo > b ) ta_lo = b;
+ if ( ta_hi < a || ta_hi > b ) ta_hi = b;
+ //move to that time for the next iteration.
+ solsets[idxa].push_back( Interval( a, std::min( ta_lo, ta_hi ) ) );
+ }else{
+ //--- if f(b) does not belong to a level.-------
+ if ( idxa == 0 ){
+ ta_lo = b;
+ }else{
+ ta_lo = a + ( levels[idxa-1].max() - fa)/bs.min();
+ if ( ta_lo < a ) ta_lo = b;
+ }
+ if ( idxa == levels.size() ){
+ ta_hi = b;
+ }else{
+ ta_hi = a + ( levels[idxa].min() - fa)/bs.max();
+ if ( ta_hi < a ) ta_hi = b;
+ }
+ }
+
+ //--- if f(b) belongs to a level.-------
+ if (idxb<levels.size() && levels.at(idxb).contains(fb)){
+ //find the first time from b when we may exit this level.
+ tb_lo = b + ( levels[idxb].min() - fb ) / bs.max();
+ tb_hi = b + ( levels[idxb].max() - fb ) / bs.min();
+ if ( tb_lo > b || tb_lo < a ) tb_lo = a;
+ if ( tb_hi > b || tb_hi < a ) tb_hi = a;
+ //move to that time for the next iteration.
+ solsets[idxb].push_back( Interval( std::max( tb_lo, tb_hi ), b) );
+ }else{
+ //--- if f(b) does not belong to a level.-------
+ if ( idxb == 0 ){
+ tb_lo = a;
+ }else{
+ tb_lo = b + ( levels[idxb-1].max() - fb)/bs.max();
+ if ( tb_lo > b ) tb_lo = a;
+ }
+ if ( idxb == levels.size() ){
+ tb_hi = a;
+ }else{
+ tb_hi = b + ( levels[idxb].min() - fb)/bs.min();
+ if ( tb_hi > b ) tb_hi = a;
+ }
+
+
+ if ( bs.min() < 0 && idxb < levels.size() )
+ tb_hi = b + ( levels[idxb ].min() - fb ) / bs.min();
+ if ( bs.max() > 0 && idxb > 0 )
+ tb_lo = b + ( levels[idxb-1].max() - fb ) / bs.max();
+ }
+
+ //let [t0,t1] be the next interval where to search.
+ double t0=std::min(ta_hi,ta_lo);
+ double t1=std::max(tb_hi,tb_lo);
+
+ if (t0>=t1) return;//no root here.
+
+ //if the interval is smaller than our resolution:
+ //pretend f simultaneously meets all the levels between f(t0) and f(t1)...
+ if ( t1 - t0 <= tol ){
+ Interval f_t0t1 ( f(t0), f(t1) );
+ unsigned idxmin = std::min(idxa, idxb);
+ unsigned idxmax = std::max(idxa, idxb);
+ //push [t0,t1] into all crossed level. Cheat to avoid overlapping intervals on different levels?
+ if ( idxmax > idxmin ){
+ for (unsigned idx = idxmin; idx < idxmax; idx++){
+ solsets[idx].push_back( Interval( t0, t1 ) );
+ }
+ }
+ if ( idxmax < levels.size() && f_t0t1.intersects( levels[idxmax] ) ){
+ solsets[idxmax].push_back( Interval( t0, t1 ) );
+ }
+ return;
+ }
+
+ //To make sure we finally exit the level jump at least by tol:
+ t0 = std::min( std::max( t0, a + tol ), b );
+ t1 = std::max( std::min( t1, b - tol ), a );
+
+ double t =(t0+t1)/2;
+ double ft=f(t);
+ level_sets_internal( f, df, levels, solsets, t0, f(t0), t, ft );
+ level_sets_internal( f, df, levels, solsets, t, ft, t1, f(t1) );
+}
+
+std::vector<std::vector<Interval> > level_sets(SBasis const &f,
+ std::vector<Interval> const &levels,
+ double a, double b, double tol){
+
+ std::vector<std::vector<Interval> > solsets(levels.size(), std::vector<Interval>());
+
+ SBasis df=derivative(f);
+ level_sets_internal(f,df,levels,solsets,a,f(a),b,f(b),tol);
+ // Fuse overlapping intervals...
+ for (unsigned i=0; i<solsets.size(); i++){
+ if ( solsets[i].size() == 0 ) continue;
+ std::sort( solsets[i].begin(), solsets[i].end(), compareIntervalMin );
+ solsets[i] = fuseContiguous( solsets[i], tol );
+ }
+ return solsets;
+}
+
+std::vector<Interval> level_set (SBasis const &f, double level, double vtol, double a, double b, double tol){
+ Interval fat_level( level - vtol, level + vtol );
+ return level_set(f, fat_level, a, b, tol);
+}
+std::vector<Interval> level_set (SBasis const &f, Interval const &level, double a, double b, double tol){
+ std::vector<Interval> levels(1,level);
+ return level_sets(f,levels, a, b, tol).front() ;
+}
+std::vector<std::vector<Interval> > level_sets (SBasis const &f, std::vector<double> const &levels, double vtol, double a, double b, double tol){
+ std::vector<Interval> fat_levels( levels.size(), Interval());
+ for (unsigned i = 0; i < levels.size(); i++){
+ fat_levels[i] = Interval( levels[i]-vtol, levels[i]+vtol);
+ }
+ return level_sets(f, fat_levels, a, b, tol);
+}
+
+
+//-------------------------------------
//-------------------------------------
@@ -358,6 +563,17 @@ std::vector<double> roots1(SBasis const & s) {
return res;
}
+std::vector<double> roots1(SBasis const & s, Interval const ivl) {
+ std::vector<double> res;
+ double d = s[0][0] - s[0][1];
+ if(d != 0) {
+ double r = s[0][0] / d;
+ if(ivl.contains(r))
+ res.push_back(r);
+ }
+ return res;
+}
+
/** Find all t s.t s(t) = 0
\param a sbasis function
\returns vector of zeros (roots)
@@ -377,6 +593,20 @@ std::vector<double> roots(SBasis const & s) {
}
}
}
+std::vector<double> roots(SBasis const & s, Interval const ivl) {
+ switch(s.size()) {
+ case 0:
+ return std::vector<double>();
+ case 1:
+ return roots1(s, ivl);
+ default:
+ {
+ Bezier bz;
+ sbasis_to_bezier(bz, s);
+ return bz.roots(ivl);
+ }
+ }
+}
};
diff --git a/src/2geom/sbasis.h b/src/2geom/sbasis.h
index d7390c64d..b1b0b6c2a 100644
--- a/src/2geom/sbasis.h
+++ b/src/2geom/sbasis.h
@@ -63,7 +63,10 @@ class SBasis : public SBasisN<1>;
namespace Geom{
-/*** An empty SBasis is identically 0. */
+/**
+* \brief S-power basis function class
+*
+* An empty SBasis is identically 0. */
class SBasis{
std::vector<Linear> d;
void push_back(Linear const&l) { d.push_back(l); }
@@ -125,8 +128,9 @@ public:
}
inline bool isConstant() const {
if (empty()) return true;
- for (unsigned i = 0; i < size(); i++) {
- if(!(*this)[i].isConstant()) return false;
+ if(!(*this)[0].isConstant()) return false;
+ for (unsigned i = 1; i < size(); i++) {
+ if(!(*this)[i].isZero()) return false;
}
return true;
}
@@ -188,6 +192,7 @@ OptInterval bounds_local(SBasis const &a, const OptInterval &t, int order = 0);
/** Returns a function which reverses the domain of a.
\param a sbasis function
+ \relates SBasis
useful for reversing a parameteric curve.
*/
@@ -312,7 +317,8 @@ inline SBasis& operator*=(SBasis& a, SBasis const & b) {
/** Returns the degree of the first non zero coefficient.
\param a sbasis function
\param tol largest abs val considered 0
- \returns first non zero coefficient
+ \return first non zero coefficient
+ \relates SBasis
*/
inline unsigned
valuation(SBasis const &a, double tol=0){
@@ -333,10 +339,10 @@ SBasis inverse(SBasis a, int k);
SBasis compose_inverse(SBasis const &f, SBasis const &g, unsigned order=2, double tol=1e-3);
/** Returns the sbasis on domain [0,1] that was t on [from, to]
- \param a sbasis function
+ \param t sbasis function
\param from,to interval
- \returns sbasis
-
+ \return sbasis
+ \relates SBasis
*/
inline SBasis portion(const SBasis &t, double from, double to) { return compose(t, Linear(from, to)); }
inline SBasis portion(const SBasis &t, Interval ivl) { return compose(t, Linear(ivl[0], ivl[1])); }
@@ -364,13 +370,75 @@ SBasis sin(Linear bo, int k);
SBasis cos(Linear bo, int k);
std::vector<double> roots(SBasis const & s);
+std::vector<double> roots(SBasis const & s, Interval const inside);
std::vector<std::vector<double> > multi_roots(SBasis const &f,
std::vector<double> const &levels,
double htol=1e-7,
double vtol=1e-7,
double a=0,
double b=1);
-
+
+//--------- Levelset like functions -----------------------------------------------------
+
+/** Solve f(t) = v +/- tolerance. The collection of intervals where
+ * v - vtol <= f(t) <= v+vtol
+ * is returned (with a precision tol on the boundaries).
+ \param f sbasis function
+ \param level the value of v.
+ \param vtol: error tolerance on v.
+ \param a, b limit search on domain [a,b]
+ \param tol: tolerance on the result bounds.
+ \returns a vector of intervals.
+*/
+std::vector<Interval> level_set (SBasis const &f,
+ double level,
+ double vtol = 1e-5,
+ double a=0.,
+ double b=1.,
+ double tol = 1e-5);
+
+/** Solve f(t)\in I=[u,v], which defines a collection of intervals (J_k). More precisely,
+ * a collection (J'_k) is returned with J'_k = J_k up to a given tolerance.
+ \param f sbasis function
+ \param level: the given interval of deisred values for f.
+ \param a, b limit search on domain [a,b]
+ \param tol: tolerance on the bounds of the result.
+ \returns a vector of intervals.
+*/
+std::vector<Interval> level_set (SBasis const &f,
+ Interval const &level,
+ double a=0.,
+ double b=1.,
+ double tol = 1e-5);
+
+/** 'Solve' f(t) = v +/- tolerance for several values of v at once.
+ \param f sbasis function
+ \param levels vector of values, that should be sorted.
+ \param vtol: error tolerance on v.
+ \param a, b limit search on domain [a,b]
+ \param tol: the bounds of the returned intervals are exact up to that tolerance.
+ \returns a vector of vectors of intervals.
+*/
+std::vector<std::vector<Interval> > level_sets (SBasis const &f,
+ std::vector<double> const &levels,
+ double a=0.,
+ double b=1.,
+ double vtol = 1e-5,
+ double tol = 1e-5);
+
+/** 'Solve' f(t)\in I=[u,v] for several intervals I at once.
+ \param f sbasis function
+ \param levels vector of 'y' intervals, that should be disjoints and sorted.
+ \param a, b limit search on domain [a,b]
+ \param tol: the bounds of the returned intervals are exact up to that tolerance.
+ \returns a vector of vectors of intervals.
+*/
+std::vector<std::vector<Interval> > level_sets (SBasis const &f,
+ std::vector<Interval> const &levels,
+ double a=0.,
+ double b=1.,
+ double tol = 1e-5);
+
}
#endif
diff --git a/src/2geom/shape.cpp b/src/2geom/shape.cpp
index 92af814cb..e9f5e55dc 100644
--- a/src/2geom/shape.cpp
+++ b/src/2geom/shape.cpp
@@ -622,7 +622,7 @@ Shape sanitize(std::vector<Path> const & ps) {
/* This transforms a shape by a matrix. In the case that the matrix flips
* the shape, it reverses the paths in order to preserve the fill.
*/
-Shape Shape::operator*(Matrix const &m) const {
+Shape Shape::operator*(Affine const &m) const {
Shape ret;
for(unsigned i = 0; i < size(); i++)
ret.content.push_back(content[i] * m);
diff --git a/src/2geom/shape.h b/src/2geom/shape.h
index 960f9668b..0a7ee9709 100644
--- a/src/2geom/shape.h
+++ b/src/2geom/shape.h
@@ -89,7 +89,7 @@ class Shape {
const Region &operator[](unsigned ix) const { return content[ix]; }
Shape inverse() const;
- Shape operator*(Matrix const &m) const;
+ Shape operator*(Affine const &m) const;
bool contains(Point const &p) const;
diff --git a/src/2geom/solve-bezier-one-d.cpp b/src/2geom/solve-bezier-one-d.cpp
index 876c483fe..c74e3243c 100644
--- a/src/2geom/solve-bezier-one-d.cpp
+++ b/src/2geom/solve-bezier-one-d.cpp
@@ -1,7 +1,12 @@
+
#include <2geom/solver.h>
+#include <2geom/choose.h>
+#include <2geom/bezier.h>
#include <2geom/point.h>
+
+#include <cmath>
#include <algorithm>
-#include <valarray>
+//#include <valarray>
/*** Find the zeros of the bernstein function. The code subdivides until it is happy with the
* linearity of the function. This requires an O(degree^2) subdivision for each step, even when
@@ -11,176 +16,208 @@
namespace Geom{
template<class t>
-static int SGN(t x) { return (x > 0 ? 1 : (x < 0 ? -1 : 0)); }
+static int SGN(t x) { return (x > 0 ? 1 : (x < 0 ? -1 : 0)); }
-const unsigned MAXDEPTH = 23; // Maximum depth for recursion. Using floats means 23 bits precision max
+//const unsigned MAXDEPTH = 23; // Maximum depth for recursion. Using floats means 23 bits precision max
-const double BEPSILON = ldexp(1.0,(-MAXDEPTH-1)); /*Flatness control value */
-const double SECANT_EPSILON = 1e-13; // secant method converges much faster, get a bit more precision
+//const double BEPSILON = ldexp(1.0,(-MAXDEPTH-1)); /*Flatness control value */
+//const double SECANT_EPSILON = 1e-13; // secant method converges much faster, get a bit more precision
/**
* This function is called _a lot_. We have included various manual memory management stuff to reduce the amount of mallocing that goes on. In the future it is possible that this will hurt performance.
**/
class Bernsteins{
public:
- double *Vtemp;
- unsigned N,degree;
+ static const size_t MAX_DEPTH = 22;
+ size_t degree, N;
std::vector<double> &solutions;
- bool use_secant;
- Bernsteins(int degr, std::vector<double> &so) : N(degr+1), degree(degr),solutions(so), use_secant(false) {
- Vtemp = new double[N*2];
- }
- ~Bernsteins() {
- delete[] Vtemp;
+ //std::vector<double> bc;
+ BinomialCoefficient<double> bc;
+
+ Bernsteins(size_t _degree, std::vector<double> & sol)
+ : degree(_degree), N(degree+1), solutions(sol), bc(degree)
+ {
}
+
void subdivide(double const *V,
double t,
double *Left,
double *Right);
- double horner(const double *b, double t);
-
- unsigned
+ unsigned
control_poly_flat_enough(double const *V);
+ double horner(const double *b, double t);
+
+
void
find_bernstein_roots(double const *w, /* The control points */
unsigned depth, /* The depth of the recursion */
double left_t, double right_t);
};
/*
- * find_bernstein_roots : Given an equation in Bernstein-Bernstein form, find all
+ * find_bernstein_roots : Given an equation in Bernstein-Bernstein form, find all
* of the roots in the open interval (0, 1). Return the number of roots found.
*/
void
find_bernstein_roots(double const *w, /* The control points */
- unsigned degree, /* The degree of the polynomial */
+ unsigned degree, /* The degree of the polynomial */
std::vector<double> &solutions, /* RETURN candidate t-values */
- unsigned depth, /* The depth of the recursion */
- double left_t, double right_t, bool use_secant)
-{
+ unsigned depth, /* The depth of the recursion */
+ double left_t, double right_t, bool /*use_secant*/)
+{
Bernsteins B(degree, solutions);
- B.use_secant = use_secant;
B.find_bernstein_roots(w, depth, left_t, right_t);
}
void
-Bernsteins::find_bernstein_roots(double const *w, /* The control points */
- unsigned depth, /* The depth of the recursion */
- double left_t, double right_t)
+find_bernstein_roots(std::vector<double> &solutions, /* RETURN candidate t-values */
+ Geom::Bezier const& bz, /* The control points */
+ double left_t, double right_t)
+{
+ Bernsteins B(bz.degree(), solutions);
+ Geom::Bezier& bzl = const_cast<Geom::Bezier&>(bz);
+ double* w = &(bzl[0]);
+ B.find_bernstein_roots(w, 0, left_t, right_t);
+}
+
+
+
+void Bernsteins::find_bernstein_roots(double const *w, /* The control points */
+ unsigned depth, /* The depth of the recursion */
+ double left_t,
+ double right_t)
{
- unsigned n_crossings = 0; /* Number of zero-crossings */
-
+ size_t n_crossings = 0;
+
int old_sign = SGN(w[0]);
- for (unsigned i = 1; i < N; i++) {
- int sign = SGN(w[i]);
- if (sign) {
- if (sign != old_sign && old_sign) {
- n_crossings++;
+ //std::cout << "w[0] = " << w[0] << std::endl;
+ int sign;
+ for (size_t i = 1; i < N; i++)
+ {
+ //std::cout << "w[" << i << "] = " << w[i] << std::endl;
+ sign = SGN(w[i]);
+ if (sign != 0)
+ {
+ if (sign != old_sign && old_sign != 0)
+ {
+ ++n_crossings;
}
old_sign = sign;
}
}
-
- if (n_crossings == 0) // no solutions here
- return;
-
- if (n_crossings == 1) {
- /* Unique solution */
- /* Stop recursion when the tree is deep enough */
+ //std::cout << "n_crossings = " << n_crossings << std::endl;
+ if (n_crossings == 0) return; // no solutions here
+
+ if (n_crossings == 1) /* Unique solution */
+ {
+ //std::cout << "depth = " << depth << std::endl;
+ /* Stop recursion when the tree is deep enough */
/* if deep enough, return 1 solution at midpoint */
- if (depth >= MAXDEPTH) {
+ if (depth > MAX_DEPTH)
+ {
//printf("bottom out %d\n", depth);
const double Ax = right_t - left_t;
const double Ay = w[degree] - w[0];
-
+
solutions.push_back(left_t - Ax*w[0] / Ay);
return;
- solutions.push_back((left_t + right_t) / 2.0);
- return;
}
-
- // I thought secant method would be faster here, but it'aint. -- njh
- // Actually, it was, I just was using the wrong method for bezier evaluation. Horner's rule results in a very efficient algorithm - 10* faster (20080816)
- // Future work: try using brent's method
- if(use_secant) { // false position
- double s = 0;double t = 1;
- double e = 1e-10;
- int n,side=0;
- double r,fr,fs = w[0],ft = w[degree];
-
- for (n = 1; n <= 100; n++)
+
+
+ double s = 0, t = 1;
+ double e = 1e-10;
+ int side = 0;
+ double r, fr, fs = w[0], ft = w[degree];
+
+ for (size_t n = 0; n < 100; ++n)
+ {
+ r = (fs*t - ft*s) / (fs - ft);
+ if (fabs(t-s) < e * fabs(t+s)) break;
+
+ fr = horner(w, r);
+
+ if (fr * ft > 0)
{
- r = (fs*t - ft*s) / (fs - ft);
- if (fabs(t-s) < e*fabs(t+s)) break;
- fr = horner(w, r);
-
- if (fr * ft > 0)
- {
- t = r; ft = fr;
- if (side==-1) fs /= 2;
- side = -1;
- }
- else if (fs * fr > 0)
- {
- s = r; fs = fr;
- if (side==+1) ft /= 2;
- side = +1;
- }
- else break;
+ t = r; ft = fr;
+ if (side == -1) fs /= 2;
+ side = -1;
}
- solutions.push_back(r*right_t + (1-r)*left_t);
- return;
+ else if (fs * fr > 0)
+ {
+ s = r; fs = fr;
+ if (side == +1) ft /= 2;
+ side = +1;
+ }
+ else break;
}
+ solutions.push_back(r*right_t + (1-r)*left_t);
+ return;
+
}
/* Otherwise, solve recursively after subdividing control polygon */
- std::valarray<double> new_controls(2*N); // New left and right control polygons
- const double t = 0.5;
+// double Left[N], /* New left and right */
+// Right[N]; /* control polygons */
+ //const double t = 0.5;
+ double* LR = new double[2*N];
+ double* Left = LR;
+ double* Right = LR + N;
+ std::copy(w, w + N, Right);
-/*
- * Bernstein :
- * Evaluate a Bernstein function at a particular parameter value
- * Fill in control points for resulting sub-curves.
- *
- */
- for (unsigned i = 0; i < N; i++)
- Vtemp[i] = w[i];
-
- /* Triangle computation */
- const double omt = (1-t);
- new_controls[0] = Vtemp[0];
- new_controls[N+degree] = Vtemp[degree];
- double *prev_row = Vtemp;
- double *row = Vtemp + N;
- for (unsigned i = 1; i < N; i++) {
- for (unsigned j = 0; j < N - i; j++) {
- row[j] = omt*prev_row[j] + t*prev_row[j+1];
+ Left[0] = Right[0];
+ for (size_t i = 1; i < N; ++i)
+ {
+ for (size_t j = 0; j < N-i; ++j)
+ {
+ Right[j] = (Right[j] + Right[j+1]) * 0.5;
}
- new_controls[i] = row[0];
- new_controls[N+degree-i] = row[degree-i];
- std::swap(prev_row, row);
+ Left[i] = Right[0];
}
-
- double mid_t = left_t*(1-t) + right_t*t;
-
- find_bernstein_roots(&new_controls[0], depth+1, left_t, mid_t);
-
+
+ double mid_t = (left_t + right_t) * 0.5;
+
+
+ find_bernstein_roots(Left, depth+1, left_t, mid_t);
+
+
/* Solution is exactly on the subdivision point. */
- if (new_controls[N] == 0)
+ if (Right[0] == 0)
+ {
solutions.push_back(mid_t);
-
- find_bernstein_roots(&new_controls[N], depth+1, mid_t, right_t);
+ }
+
+ find_bernstein_roots(Right, depth+1, mid_t, right_t);
+ delete[] LR;
}
+
+// suggested by Sederberg.
+double Bernsteins::horner(const double *b, double t)
+{
+ double u, tn, tmp;
+ u = 1.0 - t;
+ tn = 1.0;
+ tmp = b[0] * u;
+ for(size_t i = 1; i < degree; ++i)
+ {
+ tn *= t;
+ tmp = (tmp + tn*bc[i]*b[i]) * u;
+ }
+ return (tmp + tn*t*b[degree]);
+}
+
+
+
+#if 0
/*
* control_poly_flat_enough :
* Check if the control polygon of a Bernstein curve is flat enough
* for recursive subdivision to bottom out.
*
*/
-unsigned
+unsigned
Bernsteins::control_poly_flat_enough(double const *V)
{
/* Find the perpendicular distance from each interior control point to line connecting V[0] and
@@ -204,7 +241,7 @@ Bernsteins::control_poly_flat_enough(double const *V)
else
max_distance_above = std::max(max_distance_above, dist);
}
-
+
const double abSquared = 1./((a * a) + 1);
const double intercept_1 = (a - max_distance_above * abSquared);
@@ -218,23 +255,7 @@ Bernsteins::control_poly_flat_enough(double const *V)
//printf("error %g %g %g\n", error, a, BEPSILON * a);
return error < BEPSILON * a;
}
-
-// suggested by Sederberg.
-double Bernsteins::horner(const double *b, double t) {
- int n = degree;
- double u, bc, tn, tmp;
- int i;
- u = 1.0 - t;
- bc = 1;
- tn = 1;
- tmp = b[0]*u;
- for(i=1; i<n; i++){
- tn = tn*t;
- bc = bc*(n-i+1)/i;
- tmp = (tmp + tn*bc*b[i])*u;
- }
- return (tmp + tn*t*b[n]);
-}
+#endif
};
diff --git a/src/2geom/solver.h b/src/2geom/solver.h
index 2aadaa476..5e77f13dc 100644
--- a/src/2geom/solver.h
+++ b/src/2geom/solver.h
@@ -4,7 +4,7 @@
*
* Authors:
* ? <?@?.?>
- *
+ *
* Copyright ?-? authors
*
* This library is free software; you can redistribute it and/or
@@ -37,9 +37,14 @@
#include <2geom/point.h>
#include <2geom/sbasis.h>
+
+#include <vector>
+
+
namespace Geom{
class Point;
+ class Bezier;
unsigned
crossing_count(Geom::Point const *V, /* Control pts of Bezier curve */
@@ -55,6 +60,8 @@ unsigned
crossing_count(double const *V, /* Control pts of Bezier curve */
unsigned degree, /* Degree of Bezier curve */
double left_t, double right_t);
+
+
void
find_bernstein_roots(
double const *w, /* The control points */
@@ -64,6 +71,12 @@ find_bernstein_roots(
double left_t=0, double right_t=1, bool use_secant=true);
};
+
+void
+find_bernstein_roots(std::vector<double> &solutions, /* RETURN candidate t-values */
+ Geom::Bezier const& bz,
+ double left_t, double right_t);
+
#endif
/*
diff --git a/src/2geom/svg-elliptical-arc.cpp b/src/2geom/svg-elliptical-arc.cpp
index 877667b43..ae8a3192c 100644
--- a/src/2geom/svg-elliptical-arc.cpp
+++ b/src/2geom/svg-elliptical-arc.cpp
@@ -36,6 +36,7 @@
#include <cfloat>
#include <limits>
+#include <memory>
#include <2geom/numeric/vector.h>
#include <2geom/numeric/fitting-tool.h>
@@ -46,929 +47,15 @@
namespace Geom
{
-
-OptRect SVGEllipticalArc::boundsExact() const
-{
- if (isDegenerate() && is_svg_compliant())
- return chord().boundsExact();
-
- std::vector<double> extremes(4);
- double cosrot = std::cos(rotation_angle());
- double sinrot = std::sin(rotation_angle());
- extremes[0] = std::atan2( -ray(Y) * sinrot, ray(X) * cosrot );
- extremes[1] = extremes[0] + M_PI;
- if ( extremes[0] < 0 ) extremes[0] += 2*M_PI;
- extremes[2] = std::atan2( ray(Y) * cosrot, ray(X) * sinrot );
- extremes[3] = extremes[2] + M_PI;
- if ( extremes[2] < 0 ) extremes[2] += 2*M_PI;
-
-
- std::vector<double>arc_extremes(4);
- arc_extremes[0] = initialPoint()[X];
- arc_extremes[1] = finalPoint()[X];
- if ( arc_extremes[0] < arc_extremes[1] )
- std::swap(arc_extremes[0], arc_extremes[1]);
- arc_extremes[2] = initialPoint()[Y];
- arc_extremes[3] = finalPoint()[Y];
- if ( arc_extremes[2] < arc_extremes[3] )
- std::swap(arc_extremes[2], arc_extremes[3]);
-
-
- if ( start_angle() < end_angle() )
- {
- if ( sweep_flag() )
- {
- for ( unsigned int i = 0; i < extremes.size(); ++i )
- {
- if ( start_angle() < extremes[i] && extremes[i] < end_angle() )
- {
- arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1];
- }
- }
- }
- else
- {
- for ( unsigned int i = 0; i < extremes.size(); ++i )
- {
- if ( start_angle() > extremes[i] || extremes[i] > end_angle() )
- {
- arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1];
- }
- }
- }
- }
- else
- {
- if ( sweep_flag() )
- {
- for ( unsigned int i = 0; i < extremes.size(); ++i )
- {
- if ( start_angle() < extremes[i] || extremes[i] < end_angle() )
- {
- arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1];
- }
- }
- }
- else
- {
- for ( unsigned int i = 0; i < extremes.size(); ++i )
- {
- if ( start_angle() > extremes[i] && extremes[i] > end_angle() )
- {
- arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1];
- }
- }
- }
- }
-
- return Rect( Point(arc_extremes[1], arc_extremes[3]) ,
- Point(arc_extremes[0], arc_extremes[2]) );
-}
-
-
-double SVGEllipticalArc::valueAtAngle(Coord t, Dim2 d) const
-{
- double sin_rot_angle = std::sin(rotation_angle());
- double cos_rot_angle = std::cos(rotation_angle());
- if ( d == X )
- {
- return ray(X) * cos_rot_angle * std::cos(t)
- - ray(Y) * sin_rot_angle * std::sin(t)
- + center(X);
- }
- else if ( d == Y )
- {
- return ray(X) * sin_rot_angle * std::cos(t)
- + ray(Y) * cos_rot_angle * std::sin(t)
- + center(Y);
- }
- THROW_RANGEERROR("dimension parameter out of range");
-}
-
-
-std::vector<double>
-SVGEllipticalArc::roots(double v, Dim2 d) const
-{
- if ( d > Y )
- {
- THROW_RANGEERROR("dimention out of range");
- }
-
- std::vector<double> sol;
-
- if (isDegenerate() && is_svg_compliant())
- {
- return chord().roots(v, d);
- }
- else
- {
- if ( are_near(ray(X), 0) && are_near(ray(Y), 0) )
- {
- if ( center(d) == v )
- sol.push_back(0);
- return sol;
- }
-
- const char* msg[2][2] =
- {
- { "d == X; ray(X) == 0; "
- "s = (v - center(X)) / ( -ray(Y) * std::sin(rotation_angle()) ); "
- "s should be contained in [-1,1]",
- "d == X; ray(Y) == 0; "
- "s = (v - center(X)) / ( ray(X) * std::cos(rotation_angle()) ); "
- "s should be contained in [-1,1]"
- },
- { "d == Y; ray(X) == 0; "
- "s = (v - center(X)) / ( ray(Y) * std::cos(rotation_angle()) ); "
- "s should be contained in [-1,1]",
- "d == Y; ray(Y) == 0; "
- "s = (v - center(X)) / ( ray(X) * std::sin(rotation_angle()) ); "
- "s should be contained in [-1,1]"
- },
- };
-
- for ( unsigned int dim = 0; dim < 2; ++dim )
- {
- if ( are_near(ray(dim), 0) )
- {
- if ( initialPoint()[d] == v && finalPoint()[d] == v )
- {
- THROW_INFINITESOLUTIONS(0);
- }
- if ( (initialPoint()[d] < finalPoint()[d])
- && (initialPoint()[d] > v || finalPoint()[d] < v) )
- {
- return sol;
- }
- if ( (initialPoint()[d] > finalPoint()[d])
- && (finalPoint()[d] > v || initialPoint()[d] < v) )
- {
- return sol;
- }
- double ray_prj;
- switch(d)
- {
- case X:
- switch(dim)
- {
- case X: ray_prj = -ray(Y) * std::sin(rotation_angle());
- break;
- case Y: ray_prj = ray(X) * std::cos(rotation_angle());
- break;
- }
- break;
- case Y:
- switch(dim)
- {
- case X: ray_prj = ray(Y) * std::cos(rotation_angle());
- break;
- case Y: ray_prj = ray(X) * std::sin(rotation_angle());
- break;
- }
- break;
- }
-
- double s = (v - center(d)) / ray_prj;
- if ( s < -1 || s > 1 )
- {
- THROW_LOGICALERROR(msg[d][dim]);
- }
- switch(dim)
- {
- case X:
- s = std::asin(s); // return a value in [-PI/2,PI/2]
- if ( logical_xor( sweep_flag(), are_near(start_angle(), M_PI/2) ) )
- {
- if ( s < 0 ) s += 2*M_PI;
- }
- else
- {
- s = M_PI - s;
- if (!(s < 2*M_PI) ) s -= 2*M_PI;
- }
- break;
- case Y:
- s = std::acos(s); // return a value in [0,PI]
- if ( logical_xor( sweep_flag(), are_near(start_angle(), 0) ) )
- {
- s = 2*M_PI - s;
- if ( !(s < 2*M_PI) ) s -= 2*M_PI;
- }
- break;
- }
-
- //std::cerr << "s = " << rad_to_deg(s);
- s = map_to_01(s);
- //std::cerr << " -> t: " << s << std::endl;
- if ( !(s < 0 || s > 1) )
- sol.push_back(s);
- return sol;
- }
- }
-
- }
-
- double rotx, roty;
- switch(d)
- {
- case X:
- rotx = std::cos(rotation_angle());
- roty = -std::sin(rotation_angle());
- break;
- case Y:
- rotx = std::sin(rotation_angle());
- roty = std::cos(rotation_angle());
- break;
- }
- double rxrotx = ray(X) * rotx;
- double c_v = center(d) - v;
-
- double a = -rxrotx + c_v;
- double b = ray(Y) * roty;
- double c = rxrotx + c_v;
- //std::cerr << "a = " << a << std::endl;
- //std::cerr << "b = " << b << std::endl;
- //std::cerr << "c = " << c << std::endl;
-
- if ( are_near(a,0) )
- {
- sol.push_back(M_PI);
- if ( !are_near(b,0) )
- {
- double s = 2 * std::atan(-c/(2*b));
- if ( s < 0 ) s += 2*M_PI;
- sol.push_back(s);
- }
- }
- else
- {
- double delta = b * b - a * c;
- //std::cerr << "delta = " << delta << std::endl;
- if ( are_near(delta, 0) )
- {
- double s = 2 * std::atan(-b/a);
- if ( s < 0 ) s += 2*M_PI;
- sol.push_back(s);
- }
- else if ( delta > 0 )
- {
- double sq = std::sqrt(delta);
- double s = 2 * std::atan( (-b - sq) / a );
- if ( s < 0 ) s += 2*M_PI;
- sol.push_back(s);
- s = 2 * std::atan( (-b + sq) / a );
- if ( s < 0 ) s += 2*M_PI;
- sol.push_back(s);
- }
- }
-
- std::vector<double> arc_sol;
- for (unsigned int i = 0; i < sol.size(); ++i )
- {
- //std::cerr << "s = " << rad_to_deg(sol[i]);
- sol[i] = map_to_01(sol[i]);
- //std::cerr << " -> t: " << sol[i] << std::endl;
- if ( !(sol[i] < 0 || sol[i] > 1) )
- arc_sol.push_back(sol[i]);
- }
- return arc_sol;
-}
-
-
-// D(E(t,C),t) = E(t+PI/2,O), where C is the ellipse center
-// the derivative doesn't rotate the ellipse but there is a translation
-// of the parameter t by an angle of PI/2 so the ellipse points are shifted
-// of such an angle in the cw direction
-Curve* SVGEllipticalArc::derivative() const
-{
- if (isDegenerate() && is_svg_compliant())
- return chord().derivative();
-
- SVGEllipticalArc* result = new SVGEllipticalArc(*this);
- result->m_center[X] = result->m_center[Y] = 0;
- result->m_start_angle += M_PI/2;
- if( !( result->m_start_angle < 2*M_PI ) )
- {
- result->m_start_angle -= 2*M_PI;
- }
- result->m_end_angle += M_PI/2;
- if( !( result->m_end_angle < 2*M_PI ) )
- {
- result->m_end_angle -= 2*M_PI;
- }
- result->m_initial_point = result->pointAtAngle( result->start_angle() );
- result->m_final_point = result->pointAtAngle( result->end_angle() );
- return result;
-}
-
-
-std::vector<Point>
-SVGEllipticalArc::pointAndDerivatives(Coord t, unsigned int n) const
-{
- if (isDegenerate() && is_svg_compliant())
- return chord().pointAndDerivatives(t, n);
-
- unsigned int nn = n+1; // nn represents the size of the result vector.
- std::vector<Point> result;
- result.reserve(nn);
- double angle = map_unit_interval_on_circular_arc(t, start_angle(),
- end_angle(), sweep_flag());
- SVGEllipticalArc ea(*this);
- ea.m_center = Point(0,0);
- unsigned int m = std::min(nn, 4u);
- for ( unsigned int i = 0; i < m; ++i )
- {
- result.push_back( ea.pointAtAngle(angle) );
- angle += M_PI/2;
- if ( !(angle < 2*M_PI) ) angle -= 2*M_PI;
- }
- m = nn / 4;
- for ( unsigned int i = 1; i < m; ++i )
- {
- for ( unsigned int j = 0; j < 4; ++j )
- result.push_back( result[j] );
- }
- m = nn - 4 * m;
- for ( unsigned int i = 0; i < m; ++i )
- {
- result.push_back( result[i] );
- }
- if ( !result.empty() ) // nn != 0
- result[0] = pointAtAngle(angle);
- return result;
-}
-
-bool SVGEllipticalArc::containsAngle(Coord angle) const
-{
- if ( sweep_flag() )
- if ( start_angle() < end_angle() )
- return ( !( angle < start_angle() || angle > end_angle() ) );
- else
- return ( !( angle < start_angle() && angle > end_angle() ) );
- else
- if ( start_angle() > end_angle() )
- return ( !( angle > start_angle() || angle < end_angle() ) );
- else
- return ( !( angle > start_angle() && angle < end_angle() ) );
-}
-
-Curve* SVGEllipticalArc::portion(double f, double t) const
-{
- // fix input arguments
- if (f < 0) f = 0;
- if (f > 1) f = 1;
- if (t < 0) t = 0;
- if (t > 1) t = 1;
-
- if ( are_near(f, t) )
- {
- SVGEllipticalArc* arc = new SVGEllipticalArc();
- arc->m_center = arc->m_initial_point = arc->m_final_point = pointAt(f);
- arc->m_start_angle = arc->m_end_angle = m_start_angle;
- arc->m_rot_angle = m_rot_angle;
- arc->m_sweep = m_sweep;
- arc->m_large_arc = m_large_arc;
- }
-
- SVGEllipticalArc* arc = new SVGEllipticalArc( *this );
- arc->m_initial_point = pointAt(f);
- arc->m_final_point = pointAt(t);
- double sa = sweep_flag() ? sweep_angle() : -sweep_angle();
- arc->m_start_angle = m_start_angle + sa * f;
- if ( !(arc->m_start_angle < 2*M_PI) )
- arc->m_start_angle -= 2*M_PI;
- if ( arc->m_start_angle < 0 )
- arc->m_start_angle += 2*M_PI;
- arc->m_end_angle = m_start_angle + sa * t;
- if ( !(arc->m_end_angle < 2*M_PI) )
- arc->m_end_angle -= 2*M_PI;
- if ( arc->m_end_angle < 0 )
- arc->m_end_angle += 2*M_PI;
- if ( f > t ) arc->m_sweep = !sweep_flag();
- if ( large_arc_flag() && (arc->sweep_angle() < M_PI) )
- arc->m_large_arc = false;
- return arc;
-}
-
-
-std::vector<double> SVGEllipticalArc::
-allNearestPoints( Point const& p, double from, double to ) const
-{
- std::vector<double> result;
- if (isDegenerate() && is_svg_compliant())
- {
- result.push_back( chord().nearestPoint(p, from, to) );
- return result;
- }
-
- if ( from > to ) std::swap(from, to);
- if ( from < 0 || to > 1 )
- {
- THROW_RANGEERROR("[from,to] interval out of range");
- }
-
- if ( ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) || are_near(from, to) )
- {
- result.push_back(from);
- return result;
- }
- else if ( are_near(ray(X), 0) || are_near(ray(Y), 0) )
- {
- LineSegment seg(pointAt(from), pointAt(to));
- Point np = seg.pointAt( seg.nearestPoint(p) );
- if ( are_near(ray(Y), 0) )
- {
- if ( are_near(rotation_angle(), M_PI/2)
- || are_near(rotation_angle(), 3*M_PI/2) )
- {
- result = roots(np[Y], Y);
- }
- else
- {
- result = roots(np[X], X);
- }
- }
- else
- {
- if ( are_near(rotation_angle(), M_PI/2)
- || are_near(rotation_angle(), 3*M_PI/2) )
- {
- result = roots(np[X], X);
- }
- else
- {
- result = roots(np[Y], Y);
- }
- }
- return result;
- }
- else if ( are_near(ray(X), ray(Y)) )
- {
- Point r = p - center();
- if ( are_near(r, Point(0,0)) )
- {
- THROW_INFINITESOLUTIONS(0);
- }
- // TODO: implement case r != 0
-// Point np = ray(X) * unit_vector(r);
-// std::vector<double> solX = roots(np[X],X);
-// std::vector<double> solY = roots(np[Y],Y);
-// double t;
-// if ( are_near(solX[0], solY[0]) || are_near(solX[0], solY[1]))
-// {
-// t = solX[0];
-// }
-// else
-// {
-// t = solX[1];
-// }
-// if ( !(t < from || t > to) )
-// {
-// result.push_back(t);
-// }
-// else
-// {
-//
-// }
- }
-
- // solve the equation <D(E(t),t)|E(t)-p> == 0
- // that provides min and max distance points
- // on the ellipse E wrt the point p
- // after the substitutions:
- // cos(t) = (1 - s^2) / (1 + s^2)
- // sin(t) = 2t / (1 + s^2)
- // where s = tan(t/2)
- // we get a 4th degree equation in s
- /*
- * ry s^4 ((-cy + py) Cos[Phi] + (cx - px) Sin[Phi]) +
- * ry ((cy - py) Cos[Phi] + (-cx + px) Sin[Phi]) +
- * 2 s^3 (rx^2 - ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) +
- * 2 s (-rx^2 + ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi])
- */
-
- Point p_c = p - center();
- double rx2_ry2 = (ray(X) - ray(Y)) * (ray(X) + ray(Y));
- double cosrot = std::cos( rotation_angle() );
- double sinrot = std::sin( rotation_angle() );
- double expr1 = ray(X) * (p_c[X] * cosrot + p_c[Y] * sinrot);
- Poly coeff;
- coeff.resize(5);
- coeff[4] = ray(Y) * ( p_c[Y] * cosrot - p_c[X] * sinrot );
- coeff[3] = 2 * ( rx2_ry2 + expr1 );
- coeff[2] = 0;
- coeff[1] = 2 * ( -rx2_ry2 + expr1 );
- coeff[0] = -coeff[4];
-
-// for ( unsigned int i = 0; i < 5; ++i )
-// std::cerr << "c[" << i << "] = " << coeff[i] << std::endl;
-
- std::vector<double> real_sol;
- // gsl_poly_complex_solve raises an error
- // if the leading coefficient is zero
- if ( are_near(coeff[4], 0) )
- {
- real_sol.push_back(0);
- if ( !are_near(coeff[3], 0) )
- {
- double sq = -coeff[1] / coeff[3];
- if ( sq > 0 )
- {
- double s = std::sqrt(sq);
- real_sol.push_back(s);
- real_sol.push_back(-s);
- }
- }
- }
- else
- {
- real_sol = solve_reals(coeff);
- }
-
- for ( unsigned int i = 0; i < real_sol.size(); ++i )
- {
- real_sol[i] = 2 * std::atan(real_sol[i]);
- if ( real_sol[i] < 0 ) real_sol[i] += 2*M_PI;
- }
- // when s -> Infinity then <D(E)|E-p> -> 0 iff coeff[4] == 0
- // so we add M_PI to the solutions being lim arctan(s) = PI when s->Infinity
- if ( (real_sol.size() % 2) != 0 )
- {
- real_sol.push_back(M_PI);
- }
-
- double mindistsq1 = std::numeric_limits<double>::max();
- double mindistsq2 = std::numeric_limits<double>::max();
- double dsq;
- unsigned int mi1, mi2;
- for ( unsigned int i = 0; i < real_sol.size(); ++i )
- {
- dsq = distanceSq(p, pointAtAngle(real_sol[i]));
- if ( mindistsq1 > dsq )
- {
- mindistsq2 = mindistsq1;
- mi2 = mi1;
- mindistsq1 = dsq;
- mi1 = i;
- }
- else if ( mindistsq2 > dsq )
- {
- mindistsq2 = dsq;
- mi2 = i;
- }
- }
-
- double t = map_to_01( real_sol[mi1] );
- if ( !(t < from || t > to) )
- {
- result.push_back(t);
- }
-
- bool second_sol = false;
- t = map_to_01( real_sol[mi2] );
- if ( real_sol.size() == 4 && !(t < from || t > to) )
- {
- if ( result.empty() || are_near(mindistsq1, mindistsq2) )
- {
- result.push_back(t);
- second_sol = true;
- }
- }
-
- // we need to test extreme points too
- double dsq1 = distanceSq(p, pointAt(from));
- double dsq2 = distanceSq(p, pointAt(to));
- if ( second_sol )
- {
- if ( mindistsq2 > dsq1 )
- {
- result.clear();
- result.push_back(from);
- mindistsq2 = dsq1;
- }
- else if ( are_near(mindistsq2, dsq) )
- {
- result.push_back(from);
- }
- if ( mindistsq2 > dsq2 )
- {
- result.clear();
- result.push_back(to);
- }
- else if ( are_near(mindistsq2, dsq2) )
- {
- result.push_back(to);
- }
-
- }
- else
- {
- if ( result.empty() )
- {
- if ( are_near(dsq1, dsq2) )
- {
- result.push_back(from);
- result.push_back(to);
- }
- else if ( dsq2 > dsq1 )
- {
- result.push_back(from);
- }
- else
- {
- result.push_back(to);
- }
- }
- }
-
- return result;
-}
-
-
-/*
- * NOTE: this implementation follows Standard SVG 1.1 implementation guidelines
- * for elliptical arc curves. See Appendix F.6.
- */
-void SVGEllipticalArc::calculate_center_and_extreme_angles()
-{
- Point d = initialPoint() - finalPoint();
-
- if (is_svg_compliant())
- {
- if ( initialPoint() == finalPoint() )
- {
- m_rx = m_ry = m_rot_angle = m_start_angle = m_end_angle = 0;
- m_center = initialPoint();
- m_large_arc = m_sweep = false;
- return;
- }
-
- m_rx = std::fabs(m_rx);
- m_ry = std::fabs(m_ry);
-
- if ( are_near(ray(X), 0) || are_near(ray(Y), 0) )
- {
- m_rx = L2(d) / 2;
- m_ry = 0;
- m_rot_angle = std::atan2(d[Y], d[X]);
- if (m_rot_angle < 0) m_rot_angle += 2*M_PI;
- m_start_angle = 0;
- m_end_angle = M_PI;
- m_center = middle_point(initialPoint(), finalPoint());
- m_large_arc = false;
- m_sweep = false;
- return;
- }
- }
- else
- {
- if ( are_near(initialPoint(), finalPoint()) )
- {
- if ( are_near(ray(X), 0) && are_near(ray(Y), 0) )
- {
- m_start_angle = m_end_angle = 0;
- m_center = initialPoint();
- return;
- }
- else
- {
- THROW_RANGEERROR("initial and final point are the same");
- }
- }
- if ( are_near(ray(X), 0) && are_near(ray(Y), 0) )
- { // but initialPoint != finalPoint
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints: "
- "ray(X) == 0 && ray(Y) == 0 but initialPoint != finalPoint"
- );
- }
- if ( are_near(ray(Y), 0) )
- {
- Point v = initialPoint() - finalPoint();
- if ( are_near(L2sq(v), 4*ray(X)*ray(X)) )
- {
- double angle = std::atan2(v[Y], v[X]);
- if (angle < 0) angle += 2*M_PI;
- if ( are_near( angle, rotation_angle() ) )
- {
- m_start_angle = 0;
- m_end_angle = M_PI;
- m_center = v/2 + finalPoint();
- return;
- }
- angle -= M_PI;
- if ( angle < 0 ) angle += 2*M_PI;
- if ( are_near( angle, rotation_angle() ) )
- {
- m_start_angle = M_PI;
- m_end_angle = 0;
- m_center = v/2 + finalPoint();
- return;
- }
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints: "
- "ray(Y) == 0 "
- "and slope(initialPoint - finalPoint) != rotation_angle "
- "and != rotation_angle + PI"
- );
- }
- if ( L2sq(v) > 4*ray(X)*ray(X) )
- {
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints: "
- "ray(Y) == 0 and distance(initialPoint, finalPoint) > 2*ray(X)"
- );
- }
- else
- {
- THROW_RANGEERROR(
- "there is infinite ellipses that satisfy the given constraints: "
- "ray(Y) == 0 and distance(initialPoint, finalPoint) < 2*ray(X)"
- );
- }
-
- }
-
- if ( are_near(ray(X), 0) )
- {
- Point v = initialPoint() - finalPoint();
- if ( are_near(L2sq(v), 4*ray(Y)*ray(Y)) )
- {
- double angle = std::atan2(v[Y], v[X]);
- if (angle < 0) angle += 2*M_PI;
- double rot_angle = rotation_angle() + M_PI/2;
- if ( !(rot_angle < 2*M_PI) ) rot_angle -= 2*M_PI;
- if ( are_near( angle, rot_angle ) )
- {
- m_start_angle = M_PI/2;
- m_end_angle = 3*M_PI/2;
- m_center = v/2 + finalPoint();
- return;
- }
- angle -= M_PI;
- if ( angle < 0 ) angle += 2*M_PI;
- if ( are_near( angle, rot_angle ) )
- {
- m_start_angle = 3*M_PI/2;
- m_end_angle = M_PI/2;
- m_center = v/2 + finalPoint();
- return;
- }
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints: "
- "ray(X) == 0 "
- "and slope(initialPoint - finalPoint) != rotation_angle + PI/2 "
- "and != rotation_angle + (3/2)*PI"
- );
- }
- if ( L2sq(v) > 4*ray(Y)*ray(Y) )
- {
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints: "
- "ray(X) == 0 and distance(initialPoint, finalPoint) > 2*ray(Y)"
- );
- }
- else
- {
- THROW_RANGEERROR(
- "there is infinite ellipses that satisfy the given constraints: "
- "ray(X) == 0 and distance(initialPoint, finalPoint) < 2*ray(Y)"
- );
- }
-
- }
-
- }
-
- double sin_rot_angle = std::sin(rotation_angle());
- double cos_rot_angle = std::cos(rotation_angle());
-
-
- Matrix m( cos_rot_angle, -sin_rot_angle,
- sin_rot_angle, cos_rot_angle,
- 0, 0 );
-
- Point p = (d / 2) * m;
- double rx2 = m_rx * m_rx;
- double ry2 = m_ry * m_ry;
- double rxpy = m_rx * p[Y];
- double rypx = m_ry * p[X];
- double rx2py2 = rxpy * rxpy;
- double ry2px2 = rypx * rypx;
- double num = rx2 * ry2;
- double den = rx2py2 + ry2px2;
- assert(den != 0);
- double rad = num / den;
- Point c(0,0);
- if (rad > 1)
- {
- rad -= 1;
- rad = std::sqrt(rad);
-
- if (m_large_arc == m_sweep) rad = -rad;
- c = rad * Point(rxpy / m_ry, -rypx / m_rx);
-
- m[1] = -m[1];
- m[2] = -m[2];
-
- m_center = c * m + middle_point(initialPoint(), finalPoint());
- }
- else if (rad == 1 || is_svg_compliant())
- {
- double lamda = std::sqrt(1 / rad);
- m_rx *= lamda;
- m_ry *= lamda;
- m_center = middle_point(initialPoint(), finalPoint());
- }
- else
- {
- THROW_RANGEERROR(
- "there is no ellipse that satisfies the given constraints"
- );
- }
-
- Point sp((p[X] - c[X]) / m_rx, (p[Y] - c[Y]) / m_ry);
- Point ep((-p[X] - c[X]) / m_rx, (-p[Y] - c[Y]) / m_ry);
- Point v(1, 0);
- m_start_angle = angle_between(v, sp);
- double sweep_angle = angle_between(sp, ep);
- if (!m_sweep && sweep_angle > 0) sweep_angle -= 2*M_PI;
- if (m_sweep && sweep_angle < 0) sweep_angle += 2*M_PI;
-
- if (m_start_angle < 0) m_start_angle += 2*M_PI;
- m_end_angle = m_start_angle + sweep_angle;
- if (m_end_angle < 0) m_end_angle += 2*M_PI;
- if (m_end_angle >= 2*M_PI) m_end_angle -= 2*M_PI;
-}
-
-
-D2<SBasis> SVGEllipticalArc::toSBasis() const
-{
-
- if (isDegenerate() && is_svg_compliant())
- return chord().toSBasis();
-
- D2<SBasis> arc;
- // the interval of parametrization has to be [0,1]
- Coord et = start_angle() + ( sweep_flag() ? sweep_angle() : -sweep_angle() );
- Linear param(start_angle(), et);
- Coord cos_rot_angle = std::cos(rotation_angle());
- Coord sin_rot_angle = std::sin(rotation_angle());
- // order = 4 seems to be enough to get a perfect looking elliptical arc
- SBasis arc_x = ray(X) * cos(param,4);
- SBasis arc_y = ray(Y) * sin(param,4);
- arc[0] = arc_x * cos_rot_angle - arc_y * sin_rot_angle + Linear(center(X),center(X));
- arc[1] = arc_x * sin_rot_angle + arc_y * cos_rot_angle + Linear(center(Y),center(Y));
-
- // ensure that endpoints remain exact
- for ( int d = 0 ; d < 2 ; d++ ) {
- arc[d][0][0] = initialPoint()[d];
- arc[d][0][1] = finalPoint()[d];
- }
-
- return arc;
-}
-
-
-Curve* SVGEllipticalArc::transformed(Matrix const& m) const
-{
- Ellipse e(center(X), center(Y), ray(X), ray(Y), rotation_angle());
- Ellipse et = e.transformed(m);
- Point inner_point = pointAt(0.5);
- SVGEllipticalArc ea = et.arc( initialPoint() * m,
- inner_point * m,
- finalPoint() * m,
- is_svg_compliant() );
- return ea.duplicate();
-}
-
-/*
- * helper routine to convert the parameter t value
- * btw [0,1] and [0,2PI] domain and back
+/**
+ * @class SVGEllipticalArc
+ * @brief SVG 1.1-compliant elliptical arc.
+ *
+ * This class is almost identical to the normal elliptical arc, but it differs slightly
+ * in the handling of degenerate arcs to be compliant with SVG 1.1 implementation guidelines.
*
+ * @ingroup Curves
*/
-Coord SVGEllipticalArc::map_to_02PI(Coord t) const
-{
- Coord angle = start_angle();
- if ( sweep_flag() )
- {
- angle += sweep_angle() * t;
- }
- else
- {
- angle -= sweep_angle() * t;
- }
- angle = std::fmod(angle, 2*M_PI);
- if ( angle < 0 ) angle += 2*M_PI;
- return angle;
-}
-
-Coord SVGEllipticalArc::map_to_01(Coord angle) const
-{
- return map_circular_arc_on_unit_interval(angle, start_angle(),
- end_angle(), sweep_flag());
-}
-
namespace detail
{
@@ -1015,7 +102,7 @@ struct ellipse_equation
}
make_elliptical_arc::
-make_elliptical_arc( SVGEllipticalArc& _ea,
+make_elliptical_arc( EllipticalArc& _ea,
curve_type const& _curve,
unsigned int _total_samples,
double _tolerance )
@@ -1133,13 +220,16 @@ bool make_elliptical_arc::make_elliptiarc()
if (svg_compliant_flag())
{
- ea = e.arc(initial_point, inner_point, final_point);
+ std::auto_ptr<EllipticalArc> arc( e.arc(initial_point, inner_point, final_point, true) );
+ ea = *arc;
}
else
{
try
{
- ea = e.arc(initial_point, inner_point, final_point, false);
+ std::auto_ptr<EllipticalArc> eap(
+ e.arc(initial_point, inner_point, final_point, false) );
+ ea = *eap;
}
catch(RangeError exc)
{
diff --git a/src/2geom/svg-elliptical-arc.h b/src/2geom/svg-elliptical-arc.h
index 34c51508b..79497cdb3 100644
--- a/src/2geom/svg-elliptical-arc.h
+++ b/src/2geom/svg-elliptical-arc.h
@@ -1,12 +1,14 @@
/**
* \file
- * \brief Elliptical Arc - implementation of the SVGEllipticalArc path element
+ * \brief SVG 1.1-compliant elliptical arc curve
*
+ *//*
* Authors:
- * MenTaLguY <mental@rydia.net>
- * Marco Cecchetti <mrcekets at gmail.com>
- *
- * Copyright 2007-2008 authors
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2009 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -36,339 +38,95 @@
#ifndef _2GEOM_SVG_ELLIPTICAL_ARC_H_
#define _2GEOM_SVG_ELLIPTICAL_ARC_H_
-
#include <2geom/curve.h>
#include <2geom/angle.h>
#include <2geom/utils.h>
#include <2geom/bezier-curve.h>
+#include <2geom/elliptical-arc.h>
#include <2geom/sbasis-curve.h> // for non-native methods
#include <2geom/numeric/vector.h>
#include <2geom/numeric/fitting-tool.h>
#include <2geom/numeric/fitting-model.h>
-
-
#include <algorithm>
-
-
namespace Geom
{
-class SVGEllipticalArc : public Curve
-{
- public:
- SVGEllipticalArc(bool _svg_compliant = true)
- : m_initial_point(Point(0,0)), m_final_point(Point(0,0)),
- m_rx(0), m_ry(0), m_rot_angle(0),
- m_large_arc(true), m_sweep(true),
- m_svg_compliant(_svg_compliant),
- m_start_angle(0), m_end_angle(0),
- m_center(Point(0,0))
- {
- }
-
- /**
- * \brief constructor
- *
- * \param _initial_point: initial arc end point;
- * \param _rx: ellipse x-axis ray length
- * \param _ry: ellipse y-axis ray length
- * \param _rot_angle: ellipse x-axis rotation angle in radians;
- * \param _large_arc: if true the largest arc is chosen,
- * if false the smallest arc is chosen;
- * \param _sweep : if true the clockwise arc is chosen,
- * if false the counter-clockwise arc is chosen;
- * \param _final_point: final arc end point;
- * \param _svg_compliant: if true the class behaviour follows the Standard
- * SVG 1.1 implementation guidelines (see Appendix F.6)
- * if false the class behavoiur is more strict
- * on input parameter
- *
- * in case the initial and the final arc end-points overlaps
- * a degenerate arc of zero length is generated
- *
- */
- SVGEllipticalArc( Point _initial_point, double _rx, double _ry,
- double _rot_angle, bool _large_arc, bool _sweep,
- Point _final_point,
- bool _svg_compliant = true
+class SVGEllipticalArc : public EllipticalArc {
+public:
+ SVGEllipticalArc()
+ : EllipticalArc()
+ {}
+ SVGEllipticalArc( Point ip, double rx, double ry,
+ double rot_angle, bool large_arc, bool sweep,
+ Point fp
)
- : m_initial_point(_initial_point), m_final_point(_final_point),
- m_rx(_rx), m_ry(_ry), m_rot_angle(_rot_angle),
- m_large_arc(_large_arc), m_sweep(_sweep),
- m_svg_compliant(_svg_compliant)
+ : EllipticalArc()
{
- calculate_center_and_extreme_angles();
+ _initial_point = ip;
+ _final_point = fp;
+ _rays[X] = rx; _rays[Y] = ry;
+ _rot_angle = rot_angle;
+ _large_arc = large_arc;
+ _sweep = sweep;
+ _updateCenterAndAngles(true);
}
- void set( Point _initial_point, double _rx, double _ry,
- double _rot_angle, bool _large_arc, bool _sweep,
- Point _final_point
- )
- {
- m_initial_point = _initial_point;
- m_final_point = _final_point;
- m_rx = _rx;
- m_ry = _ry;
- m_rot_angle = _rot_angle;
- m_large_arc = _large_arc;
- m_sweep = _sweep;
- calculate_center_and_extreme_angles();
- }
-
- Curve* duplicate() const
- {
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ virtual Curve *duplicate() const {
return new SVGEllipticalArc(*this);
}
-
- double center(unsigned int i) const
- {
- return m_center[i];
+ virtual Coord valueAt(Coord t, Dim2 d) const {
+ if (isDegenerate()) return chord().valueAt(t, d);
+ return EllipticalArc::valueAt(t, d);
}
-
- Point center() const
- {
- return m_center;
+ virtual Point pointAt(Coord t) const {
+ if (isDegenerate()) return chord().pointAt(t);
+ return EllipticalArc::pointAt(t);
}
-
- Point initialPoint() const
- {
- return m_initial_point;
+ virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned int n) const {
+ if (isDegenerate()) return chord().pointAndDerivatives(t, n);
+ return EllipticalArc::pointAndDerivatives(t, n);
}
-
- Point finalPoint() const
- {
- return m_final_point;
+ virtual Rect boundsExact() const {
+ if (isDegenerate()) return chord().boundsExact();
+ return EllipticalArc::boundsExact();
}
-
- double start_angle() const
- {
- return m_start_angle;
+ virtual OptRect boundsLocal(OptInterval const &i, unsigned int deg) const {
+ if (isDegenerate()) return chord().boundsLocal(i, deg);
+ return EllipticalArc::boundsLocal(i, deg);
}
- double end_angle() const
- {
- return m_end_angle;
+ virtual Curve *derivative() const {
+ if (isDegenerate()) return chord().derivative();
+ return EllipticalArc::derivative();
}
- double ray(unsigned int i) const
- {
- return (i == 0) ? m_rx : m_ry;
+ virtual std::vector<Coord> roots(Coord v, Dim2 d) const {
+ if (isDegenerate()) return chord().roots(v, d);
+ return EllipticalArc::roots(v, d);
}
-
- bool large_arc_flag() const
- {
- return m_large_arc;
- }
-
- bool sweep_flag() const
- {
- return m_sweep;
- }
-
- double rotation_angle() const
- {
- return m_rot_angle;
- }
-
- void setInitial( const Point _point)
- {
- m_initial_point = _point;
- calculate_center_and_extreme_angles();
- }
-
- void setFinal( const Point _point)
- {
- m_final_point = _point;
- calculate_center_and_extreme_angles();
- }
-
- void setExtremes( const Point& _initial_point, const Point& _final_point )
- {
- m_initial_point = _initial_point;
- m_final_point = _final_point;
- calculate_center_and_extreme_angles();
- }
-
- bool isDegenerate() const
- {
- return ( are_near(ray(X), 0) || are_near(ray(Y), 0) );
- }
-
- bool is_svg_compliant() const
- {
- return m_svg_compliant;
- }
-
- virtual OptRect boundsFast() const
- {
- return boundsExact();
- }
-
- virtual OptRect boundsExact() const;
-
- // TODO: native implementation of the following methods
- virtual OptRect boundsLocal(OptInterval i, unsigned int deg) const
- {
- if (isDegenerate() && is_svg_compliant())
- return chord().boundsLocal(i, deg);
- else
- return SBasisCurve(toSBasis()).boundsLocal(i, deg);
- }
-
- std::vector<double> roots(double v, Dim2 d) const;
-
- /*
- * find all the points on the curve portion between "from" and "to"
- * at the same smallest distance from the point "p" the points are returned
- * as their parameter t value;
- */
- std::vector<double>
- allNearestPoints( Point const& p, double from = 0, double to = 1 ) const;
-
- /*
- * find a point on the curve portion between "from" and "to"
- * at the same smallest distance from the point "p";
- * the point is returned as its parameter t value;
- */
- double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
- {
- if ( are_near(ray(X), ray(Y)) && are_near(center(), p) )
- {
- return from;
+#ifdef HAVE_GSL
+ virtual std::vector<Coord> allNearestPoints( Point const& p, double from = 0, double to = 1 ) const {
+ if (isDegenerate()) {
+ std::vector<Coord> result;
+ result.push_back(chord().nearestPoint(p, from, to));
+ return result;
}
- return allNearestPoints(p, from, to).front();
- }
-
- // TODO: native implementation of the following methods
- int winding(Point p) const
- {
- if (isDegenerate() && is_svg_compliant())
- return chord().winding(p);
- else
- return SBasisCurve(toSBasis()).winding(p);
- }
-
- int degreesOfFreedom() const { return 5;}
-
- Curve *derivative() const;
-
- Curve *transformed(Matrix const &m) const;
-
- std::vector<Point> pointAndDerivatives(Coord t, unsigned int n) const;
-
- D2<SBasis> toSBasis() const;
-
- /*
- * return true if the angle argument (in radiants) is contained
- * in the range [start_angle(), end_angle() ]
- */
- bool containsAngle(Coord angle) const;
-
- /*
- * return the value of the d-dimensional coordinate related to "t"
- * here t belongs to the [0,2PI] domain
- */
- double valueAtAngle(Coord t, Dim2 d) const;
-
- /*
- * return the point related to the parameter value "t"
- * here t belongs to the [0,2PI] domain
- */
- Point pointAtAngle(Coord t) const
- {
- double sin_rot_angle = std::sin(rotation_angle());
- double cos_rot_angle = std::cos(rotation_angle());
- Matrix m( ray(X) * cos_rot_angle, ray(X) * sin_rot_angle,
- -ray(Y) * sin_rot_angle, ray(Y) * cos_rot_angle,
- center(X), center(Y) );
- Point p( std::cos(t), std::sin(t) );
- return p * m;
- }
-
- /*
- * return the value of the d-dimensional coordinate related to "t"
- * here t belongs to the [0,1] domain
- */
- double valueAt(Coord t, Dim2 d) const
- {
- if (isDegenerate() && is_svg_compliant())
- return chord().valueAt(t, d);
-
- Coord tt = map_to_02PI(t);
- return valueAtAngle(tt, d);
- }
-
- /*
- * return the point related to the parameter value "t"
- * here t belongs to the [0,1] domain
- */
- Point pointAt(Coord t) const
- {
- if (isDegenerate() && is_svg_compliant())
- return chord().pointAt(t);
-
- Coord tt = map_to_02PI(t);
- return pointAtAngle(tt);
- }
-
- std::pair<SVGEllipticalArc, SVGEllipticalArc>
- subdivide(Coord t) const
- {
- SVGEllipticalArc* arc1 = static_cast<SVGEllipticalArc*>(portion(0, t));
- SVGEllipticalArc* arc2 = static_cast<SVGEllipticalArc*>(portion(t, 1));
- assert( arc1 != NULL && arc2 != NULL);
- std::pair<SVGEllipticalArc, SVGEllipticalArc> arc_pair(*arc1, *arc2);
- delete arc1;
- delete arc2;
- return arc_pair;
- }
-
- Curve* portion(double f, double t) const;
-
- // the arc is the same but traversed in the opposite direction
- Curve* reverse() const
- {
- SVGEllipticalArc* rarc = new SVGEllipticalArc( *this );
- rarc->m_sweep = !m_sweep;
- rarc->m_initial_point = m_final_point;
- rarc->m_final_point = m_initial_point;
- rarc->m_start_angle = m_end_angle;
- rarc->m_end_angle = m_start_angle;
- return rarc;
- }
-
-
- double sweep_angle() const
- {
- Coord d = end_angle() - start_angle();
- if ( !sweep_flag() ) d = -d;
- if ( d < 0 )
- d += 2*M_PI;
- return d;
- }
-
- LineSegment chord() const
- {
- return LineSegment(initialPoint(), finalPoint());
- }
-
- private:
- Coord map_to_02PI(Coord t) const;
- Coord map_to_01(Coord angle) const;
- void calculate_center_and_extreme_angles();
-
- private:
- Point m_initial_point, m_final_point;
- double m_rx, m_ry, m_rot_angle;
- bool m_large_arc, m_sweep;
- bool m_svg_compliant;
- double m_start_angle, m_end_angle;
- Point m_center;
-
+ return EllipticalArc::allNearestPoints(p, from, to);
+ }
+#endif
+ virtual D2<SBasis> toSBasis() const {
+ if (isDegenerate()) return chord().toSBasis();
+ return EllipticalArc::toSBasis();
+ }
+ virtual bool isSVGCompliant() const { return true; }
+ // TODO move SVG-specific behavior here.
+//protected:
+ //virtual void _updateCenterAndAngles();
+#endif
}; // end class SVGEllipticalArc
-
/*
* useful for testing and debugging
*/
@@ -379,9 +137,9 @@ operator<< (std::basic_ostream<charT> & os, const SVGEllipticalArc & ea)
{
os << "{ cx: " << ea.center(X) << ", cy: " << ea.center(Y)
<< ", rx: " << ea.ray(X) << ", ry: " << ea.ray(Y)
- << ", rot angle: " << decimal_round(rad_to_deg(ea.rotation_angle()),2)
- << ", start angle: " << decimal_round(rad_to_deg(ea.start_angle()),2)
- << ", end angle: " << decimal_round(rad_to_deg(ea.end_angle()),2)
+ << ", rot angle: " << decimal_round(rad_to_deg(ea.rotationAngle()),2)
+ << ", start angle: " << decimal_round(rad_to_deg(ea.initialAngle()),2)
+ << ", end angle: " << decimal_round(rad_to_deg(ea.finalAngle()),2)
<< " }";
return os;
@@ -396,6 +154,7 @@ namespace detail
struct ellipse_equation;
}
+// TODO this needs to be rewritten and moved to EllipticalArc header
/*
* make_elliptical_arc
*
@@ -428,7 +187,7 @@ class make_elliptical_arc
* and the generated elliptical arc; the smaller it is the
* the tolerance the higher it is the likelihood.
*/
- make_elliptical_arc( SVGEllipticalArc& _ea,
+ make_elliptical_arc( EllipticalArc& _ea,
curve_type const& _curve,
unsigned int _total_samples,
double _tolerance );
@@ -486,7 +245,7 @@ class make_elliptical_arc
}
private:
- SVGEllipticalArc& ea; // output elliptical arc
+ EllipticalArc& ea; // output elliptical arc
const curve_type & curve; // input curve
Piecewise<D2<SBasis> > dcurve; // derivative of the input curve
NL::LFMEllipse model; // model used for fitting
diff --git a/src/2geom/svg-path-parser.cpp b/src/2geom/svg-path-parser.cpp
index 804284077..4d35ccb35 100644
--- a/src/2geom/svg-path-parser.cpp
+++ b/src/2geom/svg-path-parser.cpp
@@ -1,3 +1,4 @@
+#line 1 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
/**
* \file
* \brief parse SVG path specifications
@@ -139,7 +140,7 @@ private:
};
-#line 144 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.cpp"
+#line 144 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.cpp"
static const char _svg_path_actions[] = {
0, 1, 0, 1, 1, 1, 2, 1,
3, 1, 4, 1, 5, 1, 15, 1,
@@ -1144,7 +1145,7 @@ static const int svg_path_first_final = 270;
static const int svg_path_en_main = 1;
-#line 144 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 144 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
void Parser::parse(char const *str)
@@ -1157,12 +1158,12 @@ throw(SVGPathParseError)
_reset();
-#line 1162 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.cpp"
+#line 1162 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.cpp"
{
cs = svg_path_start;
}
-#line 1167 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.cpp"
+#line 1167 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.cpp"
{
int _klen;
unsigned int _trans;
@@ -1235,13 +1236,13 @@ _match:
switch ( *_acts++ )
{
case 0:
-#line 156 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 156 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
start = p;
}
break;
case 1:
-#line 160 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 160 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
char const *end=p;
std::string buf(start, end);
@@ -1250,55 +1251,55 @@ _match:
}
break;
case 2:
-#line 167 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 167 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
_push(1.0);
}
break;
case 3:
-#line 171 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 171 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
_push(0.0);
}
break;
case 4:
-#line 175 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 175 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
_absolute = true;
}
break;
case 5:
-#line 179 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 179 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
_absolute = false;
}
break;
case 6:
-#line 183 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 183 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
_moveTo(_pop_point());
}
break;
case 7:
-#line 187 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 187 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
_lineTo(_pop_point());
}
break;
case 8:
-#line 191 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 191 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
_hlineTo(Point(_pop_coord(X), _current[Y]));
}
break;
case 9:
-#line 195 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 195 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
_vlineTo(Point(_current[X], _pop_coord(Y)));
}
break;
case 10:
-#line 199 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 199 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
Point p = _pop_point();
Point c1 = _pop_point();
@@ -1307,7 +1308,7 @@ _match:
}
break;
case 11:
-#line 206 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 206 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
Point p = _pop_point();
Point c1 = _pop_point();
@@ -1315,7 +1316,7 @@ _match:
}
break;
case 12:
-#line 212 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 212 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
Point p = _pop_point();
Point c = _pop_point();
@@ -1323,14 +1324,14 @@ _match:
}
break;
case 13:
-#line 218 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 218 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
Point p = _pop_point();
_quadTo(_quad_tangent, p);
}
break;
case 14:
-#line 223 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 223 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
Point point = _pop_point();
bool sweep = _pop_flag();
@@ -1343,16 +1344,16 @@ _match:
}
break;
case 15:
-#line 234 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 234 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{
_closePath();
}
break;
case 16:
-#line 370 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 370 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
{goto _out;}
break;
-#line 1357 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.cpp"
+#line 1357 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.cpp"
}
}
@@ -1363,7 +1364,7 @@ _again:
goto _resume;
_out: {}
}
-#line 380 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl"
+#line 380 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl"
if ( cs < svg_path_first_final ) {
diff --git a/src/2geom/svg-path.cpp b/src/2geom/svg-path.cpp
index 3e4bf7bec..d459b3e1b 100644
--- a/src/2geom/svg-path.cpp
+++ b/src/2geom/svg-path.cpp
@@ -61,8 +61,8 @@ void output(QuadraticBezier const &curve, SVGPathSink &sink) {
}
void output(SVGEllipticalArc const &curve, SVGPathSink &sink) {
- sink.arcTo( curve.ray(X), curve.ray(Y), curve.rotation_angle(),
- curve.large_arc_flag(), curve.sweep_flag(),
+ sink.arcTo( curve.ray(X), curve.ray(Y), curve.rotationAngle(),
+ curve.largeArc(), curve.sweep(),
curve.finalPoint() );
}
diff --git a/src/2geom/sweep.h b/src/2geom/sweep.h
index 299813244..1c73efee0 100644
--- a/src/2geom/sweep.h
+++ b/src/2geom/sweep.h
@@ -51,6 +51,9 @@ struct Event {
if(x > other.x) return false;
return closing < other.closing;
}
+ bool operator==(Event const &other) const {
+ return other.x == x && other.ix == ix && other.closing == closing;
+ }
};
std::vector<std::vector<unsigned> >
sweep_bounds(std::vector<Rect>, Dim2 dim = X);
diff --git a/src/2geom/transforms.cpp b/src/2geom/transforms.cpp
index 8182ce16d..2658719c4 100644
--- a/src/2geom/transforms.cpp
+++ b/src/2geom/transforms.cpp
@@ -1,106 +1,143 @@
+/**
+ * @file
+ * @brief Affine transformation classes
+ *//*
+ * Authors:
+ * ? <?@?.?>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright ?-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <boost/concept_check.hpp>
+#include <2geom/point.h>
#include <2geom/transforms.h>
namespace Geom {
-Matrix operator*(Translate const &t, Scale const &s) {
- Matrix ret(s);
- ret[4] = t[X] * s[X];
- ret[5] = t[Y] * s[Y];
- return ret;
+// Point transformation methods.
+Point &Point::operator*=(Translate const &t)
+{
+ _pt[X] += t.vec[X];
+ _pt[Y] += t.vec[Y];
+ return *this;
}
-
-Matrix operator*(Translate const &t, Rotate const &r) {
- Matrix ret(r);
- ret.setTranslation(t.vec * ret);
- return ret;
+Point &Point::operator*=(Scale const &s)
+{
+ _pt[X] *= s.vec[X];
+ _pt[Y] *= s.vec[Y];
+ return *this;
}
-
-Matrix operator*(Scale const &s, Translate const &t) {
- return Matrix(s[0], 0,
- 0 , s[1],
- t[0], t[1]);
+Point &Point::operator*=(Rotate const &r)
+{
+ double x = _pt[X], y = _pt[Y];
+ _pt[X] = x * r.vec[X] - y * r.vec[Y];
+ _pt[Y] = y * r.vec[X] + x * r.vec[Y];
+ return *this;
}
-
-Matrix operator*(Scale const &s, Matrix const &m) {
- Matrix ret(m);
- ret[0] *= s[X];
- ret[1] *= s[X];
- ret[2] *= s[Y];
- ret[3] *= s[Y];
- return ret;
+Point &Point::operator*=(HShear const &h)
+{
+ _pt[X] += h.f * _pt[X];
+ return *this;
}
-
-Matrix operator*(Matrix const &m, Translate const &t) {
- Matrix ret(m);
- ret[4] += t[X];
- ret[5] += t[Y];
- return ret;
+Point &Point::operator*=(VShear const &v)
+{
+ _pt[Y] += v.f * _pt[Y];
+ return *this;
}
-Matrix operator*(Matrix const &m, Scale const &s) {
- Matrix ret(m);
- ret[0] *= s[X]; ret[1] *= s[Y];
- ret[2] *= s[X]; ret[3] *= s[Y];
- ret[4] *= s[X]; ret[5] *= s[Y];
- return ret;
-}
+// Affine multiplication methods.
-Matrix operator*(Matrix const &m, Rotate const &r) {
- // TODO: we just convert the Rotate to a matrix and use the existing operator*(); is there a better way?
- Matrix ret(m);
- ret *= (Matrix) r;
- return ret;
+/** @brief Combine this transformation with a translation. */
+Affine &Affine::operator*=(Translate const &t) {
+ _c[4] += t[X];
+ _c[5] += t[Y];
+ return *this;
}
-Translate pow(Translate const &t, int n) {
- return Translate(t[0]*n, t[1]*n);
+/** @brief Combine this transformation with scaling. */
+Affine &Affine::operator*=(Scale const &s) {
+ _c[0] *= s[X]; _c[1] *= s[Y];
+ _c[2] *= s[X]; _c[3] *= s[Y];
+ _c[4] *= s[X]; _c[5] *= s[Y];
+ return *this;
}
-Coord pow(Coord x, long n) // shamelessly lifted from WP
-{
- Coord result = 1;
- while ( n ) {
- if ( n & 1 ) {
- result = result * x;
- n = n-1;
- }
- x = x*x;
- n = n/2;
- }
- return result;
+/** @brief Combine this transformation a rotation. */
+Affine &Affine::operator*=(Rotate const &r) {
+ // TODO: we just convert the Rotate to an Affine and use the existing operator*=()
+ // is there a better way?
+ *this *= (Affine) r;
+ return *this;
}
-Scale pow(Scale const &s, int n) {
- return Scale(pow(s[0],n), pow(s[1],n));
+/** @brief Combine this transformation with horizontal shearing (skew). */
+Affine &Affine::operator*=(HShear const &h) {
+ _c[0] += h.f * _c[1];
+ _c[2] += h.f * _c[3];
+ _c[4] += h.f * _c[5];
+ return *this;
}
-Rotate pow(Rotate x, long n)
-{
- Rotate result(0,1); // identity
- while ( n ) {
- if ( n & 1 ) {
- result = result * x;
- n = n-1;
- }
- x = x*x;
- n = n/2;
- }
- return result;
+/** @brief Combine this transformation with vertical shearing (skew). */
+Affine &Affine::operator*=(VShear const &v) {
+ _c[1] += v.f * _c[0];
+ _c[3] += v.f * _c[2];
+ _c[5] += v.f * _c[4];
+ return *this;
}
-Matrix pow(Matrix x, long n)
+// this checks whether the requirements of TransformConcept are satisfied for all transforms.
+// if you add a new transform type, include it here!
+void check_transforms()
{
- Matrix result;
- result.setIdentity();
- while ( n ) {
- if ( n & 1 ) {
- result = result * x;
- n = n-1;
- }
- x = x*x;
- n = n/2;
- }
- return result;
+#ifdef BOOST_CONCEPT_ASSERT
+ BOOST_CONCEPT_ASSERT((TransformConcept<Translate>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<Scale>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<Rotate>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<HShear>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<VShear>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<Affine>)); // Affine is also a transform
+#endif
+
+ // check inter-transform multiplication
+ Affine m;
+ Translate t(Translate::identity());
+ Scale s(Scale::identity());
+ Rotate r(Rotate::identity());
+ HShear h(HShear::identity());
+ VShear v(VShear::identity());
+
+ // notice that the first column is always the same and enumerates all transform types,
+ // while the second one changes to each transform type in turn.
+ m = t * t; m = t * s; m = t * r; m = t * h; m = t * v;
+ m = s * t; m = s * s; m = s * r; m = s * h; m = s * v;
+ m = r * t; m = r * s; m = r * r; m = r * h; m = r * v;
+ m = h * t; m = h * s; m = h * r; m = h * h; m = h * v;
+ m = v * t; m = v * s; m = v * r; m = v * h; m = v * v;
}
}
diff --git a/src/2geom/transforms.h b/src/2geom/transforms.h
index 1d8d87da3..b8db82f14 100644
--- a/src/2geom/transforms.h
+++ b/src/2geom/transforms.h
@@ -1,11 +1,12 @@
/**
- * \file
- * \brief Transforms should be applied left to right. scale * translate means: first scale, then translate.
- *
+ * @file
+ * @brief Affine transformation classes
+ *//*
* Authors:
- * ? <?@?.?>
+ * ? <?@?.?>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
*
- * Copyright ?-? authors
+ * Copyright ?-2009 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -29,132 +30,235 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
- *
*/
#ifndef SEEN_Geom_TRANSFORMS_H
#define SEEN_Geom_TRANSFORMS_H
-#include <2geom/matrix.h>
+#include <2geom/forward.h>
+#include <2geom/affine.h>
#include <cmath>
namespace Geom {
+/** @brief Type requirements for transforms.
+ * @ingroup Concepts */
template <typename T>
struct TransformConcept {
T t;
- Matrix m;
+ Affine m;
Point p;
+ bool bool_;
void constraints() {
m = t; //implicit conversion
- t = t.inverse();
+ m *= t;
+ m = m * t;
+ m = t * m;
+ p *= t;
p = p * t;
+ p = t * p;
+ t *= t;
t = t * t;
+ t = pow(t, 3);
+ p /= t; // multiplication by inverse
+ p = p / t;
+ bool_ = (t == t);
+ bool_ = (t != t);
+ t = T::identity();
+ t = t.inverse();
}
};
+/** @brief Base template for transforms. */
+template <typename T>
+class TransformOperations
+ : boost::equality_comparable< T
+ , boost::multipliable< T
+ > >
+{
+public:
+ template <typename T2>
+ Affine operator*(T2 const &t) const {
+ Affine ret(*static_cast<T const*>(this)); ret *= t; return ret;
+ }
+};
-class Rotate;
-class Translate {
- private:
- Translate();
+/** @brief Integer exponentiation for transforms.
+ * Negative exponents will yield the corresponding power of the inverse. This function
+ * can also be applied to matrices.
+ * @param t Affine or transform to exponantiate
+ * @param n Exponent
+ * @return \f$A^n\f$ if @a n is positive, \f$(A^{-1})^n\f$ if negative, identity if zero.
+ * @ingroup Transforms */
+template <typename T>
+T pow(T const &t, int n) {
+ if (n == 0) return T::identity();
+ T result(T::identity());
+ T x(n < 0 ? t.inverse() : t);
+ if (n < 0) n = -n;
+ while ( n ) { // binary exponentiation - fast
+ if ( n & 1 ) { result *= x; --n; }
+ x *= x; n /= 2;
+ }
+ return result;
+}
+
+/** @brief Translation by a vector.
+ * @ingroup Transforms */
+class Translate
+ : public TransformOperations< Translate >
+{
+ Translate() : vec(0, 0) {}
Point vec;
- public:
+public:
+ /** @brief Construct a translation from its vector. */
explicit Translate(Point const &p) : vec(p) {}
- explicit Translate(Coord const x, Coord const y) : vec(x, y) {}
- inline operator Matrix() const { return Matrix(1, 0, 0, 1, vec[X], vec[Y]); }
+ /** @brief Construct a translation from its coordinates. */
+ explicit Translate(Coord x, Coord y) : vec(x, y) {}
- inline Coord operator[](Dim2 const dim) const { return vec[dim]; }
- inline Coord operator[](unsigned const dim) const { return vec[dim]; }
- inline bool operator==(Translate const &o) const { return vec == o.vec; }
- inline bool operator!=(Translate const &o) const { return vec != o.vec; }
+ operator Affine() const { Affine ret(1, 0, 0, 1, vec[X], vec[Y]); return ret; }
+ Coord operator[](Dim2 dim) const { return vec[dim]; }
+ Coord operator[](unsigned dim) const { return vec[dim]; }
+ Translate &operator*=(Translate const &o) { vec += o.vec; return *this; }
+ bool operator==(Translate const &o) const { return vec == o.vec; }
- inline Translate inverse() const { return Translate(-vec); }
+ /** @brief Get the inverse translation. */
+ Translate inverse() const { return Translate(-vec); }
+ /** @brief Get a translation that doesn't do anything. */
+ static Translate identity() { Translate ret; return ret; }
- friend Point operator*(Point const &v, Translate const &t);
- inline Translate operator*(Translate const &b) const { return Translate(vec + b.vec); }
-
- friend Matrix operator*(Translate const &t, Rotate const &r);
+ friend class Point;
};
-inline Point operator*(Point const &v, Translate const &t) { return v + t.vec; }
-
-class Scale {
- private:
+/** @brief Scaling from the origin.
+ * During scaling, the point (0,0) will not move. To obtain a scale with a different
+ * invariant point, combine with translation to the origin and back.
+ * @ingroup Transforms */
+class Scale
+ : public TransformOperations< Scale >
+{
Point vec;
- Scale();
- public:
+ Scale() : vec(1, 1) {}
+public:
explicit Scale(Point const &p) : vec(p) {}
- Scale(Coord const x, Coord const y) : vec(x, y) {}
- explicit Scale(Coord const s) : vec(s, s) {}
- inline operator Matrix() const { return Matrix(vec[X], 0, 0, vec[Y], 0, 0); }
+ Scale(Coord x, Coord y) : vec(x, y) {}
+ explicit Scale(Coord s) : vec(s, s) {}
+ inline operator Affine() const { Affine ret(vec[X], 0, 0, vec[Y], 0, 0); return ret; }
- inline Coord operator[](Dim2 const d) const { return vec[d]; }
- inline Coord operator[](unsigned const d) const { return vec[d]; }
+ Coord operator[](Dim2 d) const { return vec[d]; }
+ Coord operator[](unsigned d) const { return vec[d]; }
//TODO: should we keep these mutators? add them to the other transforms?
- inline Coord &operator[](Dim2 const d) { return vec[d]; }
- inline Coord &operator[](unsigned const d) { return vec[d]; }
- inline bool operator==(Scale const &o) const { return vec == o.vec; }
- inline bool operator!=(Scale const &o) const { return vec != o.vec; }
+ Coord &operator[](Dim2 d) { return vec[d]; }
+ Coord &operator[](unsigned d) { return vec[d]; }
+ Scale &operator*=(Scale const &b) { vec[X] *= b[X]; vec[Y] *= b[Y]; return *this; }
+ bool operator==(Scale const &o) const { return vec == o.vec; }
+ Scale inverse() const { return Scale(1./vec[0], 1./vec[1]); }
+ static Scale identity() { Scale ret; return ret; }
- inline Scale inverse() const { return Scale(1./vec[0], 1./vec[1]); }
-
- friend Point operator*(Point const &v, Translate const &t);
- inline Scale operator*(Scale const &b) const { return Scale(vec[X]*b[X], vec[Y]*b[Y]); }
+ friend class Point;
};
-inline Point operator*(Point const &p, Scale const &s) { return Point(p[X] * s[X], p[Y] * s[Y]); }
-
-/** Notionally an Geom::Matrix corresponding to rotation about the origin.
- Behaves like Geom::Matrix for multiplication.
-**/
-class Rotate {
- private:
- Rotate() {}
+/** @brief Rotation around the origin.
+ * Combine with translations to the origin and back to get a rotation around a different point.
+ * @ingroup Transforms */
+class Rotate
+ : public TransformOperations< Rotate >
+{
+ Rotate() : vec(1, 0) {}
Point vec;
- public:
- explicit Rotate(Coord theta) : vec(std::cos(theta), std::sin(theta)) {}
- Rotate(Point const &p) {Point v = p; v.normalize(); vec = v;} //TODO: UGLY!
+public:
+ /** @brief Construct a rotation from its angle in radians.
+ * Positive arguments correspond to counter-clockwise rotations (if Y grows upwards). */
+ explicit Rotate(Coord theta) : vec(Point::polar(theta)) {}
+ /** @brief Construct a rotation from its characteristic vector. */
+ explicit Rotate(Point const &p) : vec(unit_vector(p)) {}
+ /** @brief Construct a rotation from the coordinates of its characteristic vector. */
explicit Rotate(Coord x, Coord y) { Rotate(Point(x, y)); }
- inline operator Matrix() const { return Matrix(vec[X], vec[Y], -vec[Y], vec[X], 0, 0); }
+ operator Affine() const { Affine ret(vec[X], vec[Y], -vec[Y], vec[X], 0, 0); return ret; }
- inline Point vector() const { return vec; }
- inline Coord operator[](Dim2 const dim) const { return vec[dim]; }
- inline Coord operator[](unsigned const dim) const { return vec[dim]; }
- inline bool operator==(Rotate const &o) const { return vec == o.vec; }
- inline bool operator!=(Rotate const &o) const { return vec != o.vec; }
-
- inline Rotate inverse() const {
+ /** @brief Get the characteristic vector of the rotation.
+ * @return A vector that would be obtained by applying this transform to the X versor. */
+ Point vector() const { return vec; }
+ Coord operator[](Dim2 dim) const { return vec[dim]; }
+ Coord operator[](unsigned dim) const { return vec[dim]; }
+ Rotate &operator*=(Rotate const &o) { vec *= o; return *this; }
+ bool operator==(Rotate const &o) const { return vec == o.vec; }
+ Rotate inverse() const {
Rotate r;
r.vec = Point(vec[X], -vec[Y]);
return r;
}
+ /** @brief Get a 0-degree rotation. */
+ static Rotate identity() { Rotate ret; return ret; }
+ /** @brief Construct a rotation from its angle in degrees.
+ * Positive arguments correspond to counter-clockwise rotations (if Y grows upwards). */
static Rotate from_degrees(Coord deg) {
Coord rad = (deg / 180.0) * M_PI;
return Rotate(rad);
}
- friend Point operator*(Point const &v, Rotate const &r);
- inline Rotate operator*(Rotate const &b) const { return Rotate(vec * b); }
+ friend class Point;
};
-inline Point operator*(Point const &v, Rotate const &r) { return v ^ r.vec; }
+/** @brief Common base for shearing transforms.
+ * @ingroup Transforms */
+template <typename S>
+class ShearBase
+ : public TransformOperations< S >
+{
+protected:
+ Coord f;
+ ShearBase(Coord _f) : f(_f) {}
+public:
+ Coord factor() const { return f; }
+ void setFactor(Coord nf) { f = nf; }
+ S &operator*=(S const &s) { f += s.f; return *static_cast<S const*>(this); }
+ bool operator==(S const &s) const { return f == s.f; }
+ S inverse() const { return S(-f); }
+ static S identity() { return S(0); }
-Matrix operator*(Translate const &t, Scale const &s);
-Matrix operator*(Translate const &t, Rotate const &r);
+ friend class Point;
+ friend class Affine;
+};
-Matrix operator*(Scale const &s, Translate const &t);
-Matrix operator*(Scale const &s, Matrix const &m);
+/** @brief Horizontal shearing.
+ * Points on the X axis will not move. Combine with translations to get a shear
+ * with a different invariant line.
+ * @ingroup Transforms */
+class HShear
+ : public ShearBase<HShear>
+{
+public:
+ explicit HShear(Coord h) : ShearBase<HShear>(h) {}
+ operator Affine() const { Affine ret(1, 0, f, 1, 0, 0); return ret; }
+};
-Matrix operator*(Matrix const &m, Translate const &t);
-Matrix operator*(Matrix const &m, Scale const &s);
-Matrix operator*(Matrix const &m, Rotate const &r);
-Matrix operator*(Matrix const &m1, Matrix const &m2);
+/** @brief Vertical shearing.
+ * Points on the Y axis will not move. Combine with translations to get a shear
+ * with a different invariant line.
+ * @ingroup Transforms */
+class VShear
+ : public ShearBase<VShear>
+{
+public:
+ explicit VShear(Coord h) : ShearBase<VShear>(h) {}
+ operator Affine() const { Affine ret(1, f, 0, 1, 0, 0); return ret; }
+};
-Translate pow(Translate const &t, int n);
-Scale pow(Scale const &t, int n);
-Rotate pow(Rotate t, int n);
-Matrix pow(Matrix t, int n);
+/** @brief Specialization of exponentiation for Scale.
+ * @relates Scale */
+template<>
+inline Scale pow(Scale const &s, int n) {
+ Scale ret(::pow(s[X], n), ::pow(s[Y], n));
+ return ret;
+}
+/** @brief Specialization of exponentiation for Translate.
+ * @relates Translate */
+template<>
+inline Translate pow(Translate const &t, int n) {
+ Translate ret(t[X] * n, t[Y] * n);
+ return ret;
+}
//TODO: matrix to trans/scale/rotate
diff --git a/src/2geom/utils.h b/src/2geom/utils.h
index dcadc8431..31468a204 100644
--- a/src/2geom/utils.h
+++ b/src/2geom/utils.h
@@ -33,7 +33,7 @@
*
*/
-#include <cmath>
+#include <2geom/math-utils.h>
#include <vector>
namespace Geom {
@@ -41,45 +41,6 @@ namespace Geom {
// proper logical xor
inline bool logical_xor (bool a, bool b) { return (a || b) && !(a && b); }
-/** Sign function - indicates the sign of a numeric type. -1 indicates negative, 1 indicates
- * positive, and 0 indicates, well, 0. Mathsy people will know this is basically the derivative
- * of abs, except for the fact that it is defined on 0.
- */
-template <class T> inline int sgn(const T& x) {return (x < 0 ? -1 : (x > 0 ? 1 : 0) );}
-
-template <class T> inline T sqr(const T& x) {return x * x;}
-template <class T> inline T cube(const T& x) {return x * x * x;}
-
-/** Between function - returns true if a number x is within a range. The values delimiting the
- * range and the number must have the same type.
- */
-template <class T> inline const T& between (const T& min, const T& max, const T& x)
- { return min < x && max > x; }
-
-/** Returns x rounded to the nearest integer. It is unspecified what happens
- * if x is half way between two integers: we may in future use rint/round
- * on platforms that have them.
- */
-inline double round(double const x) { return std::floor(x + .5); }
-
-/** Returns x rounded to the nearest \a places decimal places.
-
- Implemented in terms of round, i.e. we make no guarantees as to what happens if x is
- half way between two rounded numbers.
-
- Note: places is the number of decimal places without using scientific (e) notation, not the
- number of significant figures. This function may not be suitable for values of x whose
- magnitude is so far from 1 that one would want to use scientific (e) notation.
-
- places may be negative: e.g. places = -2 means rounding to a multiple of .01
-**/
-inline double decimal_round(double const x, int const places) {
- //TODO: possibly implement with modulus instead?
- double const multiplier = std::pow(10.0, places);
- return round( x * multiplier ) / multiplier;
-}
-
-
void binomial_coefficients(std::vector<size_t>& bc, size_t n);
}
diff --git a/src/arc-context.cpp b/src/arc-context.cpp
index 1c480ecbc..76b064f06 100644
--- a/src/arc-context.cpp
+++ b/src/arc-context.cpp
@@ -447,7 +447,7 @@ static void sp_arc_drag(SPArcContext *ac, Geom::Point pt, guint state)
Geom::Point c = r.midpoint();
if (!ctrl_save) {
if (fabs(dir[Geom::X]) > 1E-6 && fabs(dir[Geom::Y]) > 1E-6) {
- Geom::Matrix const i2d ((ac->item)->i2d_affine ());
+ Geom::Affine const i2d ((ac->item)->i2d_affine ());
Geom::Point new_dir = pt * i2d - c;
new_dir[Geom::X] *= dir[Geom::Y] / dir[Geom::X];
double lambda = new_dir.length() / dir[Geom::Y];
diff --git a/src/box3d.cpp b/src/box3d.cpp
index d51df9df3..cc3280150 100644
--- a/src/box3d.cpp
+++ b/src/box3d.cpp
@@ -49,7 +49,7 @@ static void box3d_update(SPObject *object, SPCtx *ctx, guint flags);
static Inkscape::XML::Node *box3d_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
static gchar *box3d_description(SPItem *item);
-static Geom::Matrix box3d_set_transform(SPItem *item, Geom::Matrix const &xform);
+static Geom::Affine box3d_set_transform(SPItem *item, Geom::Affine const &xform);
static void box3d_convert_to_guides(SPItem *item);
static void box3d_ref_changed(SPObject *old_ref, SPObject *ref, SPBox3D *box);
@@ -335,15 +335,15 @@ void box3d_position_set(SPBox3D *box)
}
}
-static Geom::Matrix
-box3d_set_transform(SPItem *item, Geom::Matrix const &xform)
+static Geom::Affine
+box3d_set_transform(SPItem *item, Geom::Affine const &xform)
{
SPBox3D *box = SP_BOX3D(item);
// We don't apply the transform to the box directly but instead to its perspective (which is
// done in sp_selection_apply_affine). Here we only adjust strokes, patterns, etc.
- Geom::Matrix ret(Geom::Matrix(xform).without_translation());
+ Geom::Affine ret(Geom::Affine(xform).withoutTranslation());
gdouble const sw = hypot(ret[0], ret[1]);
gdouble const sh = hypot(ret[2], ret[3]);
@@ -390,7 +390,7 @@ box3d_get_corner_screen (SPBox3D const *box, guint id, bool item_coords) {
if (!box3d_get_perspective(box)) {
return Geom::Point (NR_HUGE, NR_HUGE);
}
- Geom::Matrix const i2d (SP_ITEM(box)->i2d_affine ());
+ Geom::Affine const i2d (SP_ITEM(box)->i2d_affine ());
if (item_coords) {
return box3d_get_perspective(box)->perspective_impl->tmat.image(proj_corner).affine() * i2d.inverse();
} else {
@@ -414,7 +414,7 @@ box3d_get_center_screen (SPBox3D *box) {
if (!box3d_get_perspective(box)) {
return Geom::Point (NR_HUGE, NR_HUGE);
}
- Geom::Matrix const i2d (SP_ITEM(box)->i2d_affine ());
+ Geom::Affine const i2d (SP_ITEM(box)->i2d_affine ());
return box3d_get_perspective(box)->perspective_impl->tmat.image(proj_center).affine() * i2d.inverse();
}
diff --git a/src/conn-avoid-ref.cpp b/src/conn-avoid-ref.cpp
index 21ef2deab..410090e22 100644
--- a/src/conn-avoid-ref.cpp
+++ b/src/conn-avoid-ref.cpp
@@ -390,7 +390,7 @@ Geom::Point SPAvoidRef::getConnectionPointPos(const int type, const int id)
{
g_assert(item);
Geom::Point pos;
- const Geom::Matrix& transform = item->i2doc_affine();
+ const Geom::Affine& transform = item->i2doc_affine();
if ( type == ConnPointDefault )
{
@@ -475,7 +475,7 @@ static std::vector<Geom::Point> approxCurveWithPoints(SPCurve *curve)
return poly_points;
}
-static std::vector<Geom::Point> approxItemWithPoints(SPItem const *item, const Geom::Matrix& item_transform)
+static std::vector<Geom::Point> approxItemWithPoints(SPItem const *item, const Geom::Affine& item_transform)
{
// The structure to hold the output
std::vector<Geom::Point> poly_points;
@@ -512,7 +512,7 @@ static Avoid::Polygon avoid_item_poly(SPItem const *item)
g_assert(desktop != NULL);
double spacing = desktop->namedview->connector_spacing;
- Geom::Matrix itd_mat = item->i2doc_affine();
+ Geom::Affine itd_mat = item->i2doc_affine();
std::vector<Geom::Point> hull_points;
hull_points = approxItemWithPoints(item, itd_mat);
@@ -525,15 +525,15 @@ static Avoid::Polygon avoid_item_poly(SPItem const *item)
Geom::Line hull_edge(hull[-1], hull[0]);
Geom::Line prev_parallel_hull_edge;
- prev_parallel_hull_edge.origin(hull_edge.origin()+hull_edge.versor().ccw()*spacing);
- prev_parallel_hull_edge.versor(hull_edge.versor());
+ prev_parallel_hull_edge.setOrigin(hull_edge.origin()+hull_edge.versor().ccw()*spacing);
+ prev_parallel_hull_edge.setVersor(hull_edge.versor());
int hull_size = hull.boundary.size();
for (int i = 0; i < hull_size; ++i)
{
- hull_edge.setBy2Points(hull[i], hull[i+1]);
+ hull_edge.setPoints(hull[i], hull[i+1]);
Geom::Line parallel_hull_edge;
- parallel_hull_edge.origin(hull_edge.origin()+hull_edge.versor().ccw()*spacing);
- parallel_hull_edge.versor(hull_edge.versor());
+ parallel_hull_edge.setOrigin(hull_edge.origin()+hull_edge.versor().ccw()*spacing);
+ parallel_hull_edge.setVersor(hull_edge.versor());
// determine the intersection point
@@ -578,7 +578,7 @@ GSList *get_avoided_items(GSList *list, SPObject *from, SPDesktop *desktop,
}
-void avoid_item_move(Geom::Matrix const */*mp*/, SPItem *moved_item)
+void avoid_item_move(Geom::Affine const */*mp*/, SPItem *moved_item)
{
Avoid::ShapeRef *shapeRef = moved_item->avoidRef->shapeRef;
g_assert(shapeRef);
diff --git a/src/conn-avoid-ref.h b/src/conn-avoid-ref.h
index 5dff8dd38..eaf479e37 100644
--- a/src/conn-avoid-ref.h
+++ b/src/conn-avoid-ref.h
@@ -65,7 +65,7 @@ private:
extern GSList *get_avoided_items(GSList *list, SPObject *from,
SPDesktop *desktop, bool initialised = true);
-extern void avoid_item_move(Geom::Matrix const *mp, SPItem *moved_item);
+extern void avoid_item_move(Geom::Affine const *mp, SPItem *moved_item);
extern void init_avoided_shape_geometry(SPDesktop *desktop);
static const double defaultConnSpacing = 3.0;
diff --git a/src/connector-context.cpp b/src/connector-context.cpp
index f4b202451..ac39831b7 100644
--- a/src/connector-context.cpp
+++ b/src/connector-context.cpp
@@ -977,8 +977,8 @@ connector_handle_motion_notify(SPConnectorContext *const cc, GdkEventMotion cons
m.unSetup();
// Update the hidden path
- Geom::Matrix i2d = (cc->clickeditem)->i2d_affine();
- Geom::Matrix d2i = i2d.inverse();
+ Geom::Affine i2d = (cc->clickeditem)->i2d_affine();
+ Geom::Affine d2i = i2d.inverse();
SPPath *path = SP_PATH(cc->clickeditem);
SPCurve *curve = path->original_curve ? path->original_curve : path->curve;
if (cc->clickedhandle == cc->endpt_handle[0]) {
@@ -1203,7 +1203,7 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval)
// Obtain original position
ConnectionPoint const& cp = cc->connpthandles[cc->selected_handle];
SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc);
- const Geom::Matrix& i2doc = (cc->active_shape)->i2doc_affine();
+ const Geom::Affine& i2doc = (cc->active_shape)->i2doc_affine();
sp_knot_set_position(cc->selected_handle, cp.pos * i2doc * desktop->doc2dt(), 0);
cc->state = SP_CONNECTOR_CONTEXT_IDLE;
desktop->messageStack()->flash( Inkscape::NORMAL_MESSAGE,
@@ -1607,7 +1607,7 @@ endpt_handler(SPKnot */*knot*/, GdkEvent *event, SPConnectorContext *cc)
// Show the red path for dragging.
cc->red_curve = SP_PATH(cc->clickeditem)->original_curve ? SP_PATH(cc->clickeditem)->original_curve->copy() : SP_PATH(cc->clickeditem)->curve->copy();
- Geom::Matrix i2d = (cc->clickeditem)->i2d_affine();
+ Geom::Affine i2d = (cc->clickeditem)->i2d_affine();
cc->red_curve->transform(i2d);
sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), cc->red_curve);
@@ -1766,7 +1766,7 @@ cc_set_active_conn(SPConnectorContext *cc, SPItem *item)
g_assert( SP_IS_PATH(item) );
SPCurve *curve = SP_PATH(item)->original_curve ? SP_PATH(item)->original_curve : SP_PATH(item)->curve;
- Geom::Matrix i2d = item->i2d_affine();
+ Geom::Affine i2d = item->i2d_affine();
if (cc->active_conn == item)
{
diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp
index c580d6767..b8de8aadc 100644
--- a/src/desktop-style.cpp
+++ b/src/desktop-style.cpp
@@ -121,7 +121,7 @@ sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines)
// Scale the style by the inverse of the accumulated parent transform in the paste context.
{
- Geom::Matrix const local(SP_ITEM(o)->i2doc_affine());
+ Geom::Affine const local(SP_ITEM(o)->i2doc_affine());
double const ex(local.descrim());
if ( ( ex != 0. )
&& ( ex != 1. ) ) {
@@ -420,7 +420,7 @@ stroke_average_width (GSList const *objects)
if (!SP_IS_ITEM (l->data))
continue;
- Geom::Matrix i2d = SP_ITEM(l->data)->i2d_affine();
+ Geom::Affine i2d = SP_ITEM(l->data)->i2d_affine();
SPObject *object = SP_OBJECT(l->data);
@@ -714,7 +714,7 @@ objects_query_strokewidth (GSList *objects, SPStyle *style_res)
noneSet &= style->stroke.isNone();
- Geom::Matrix i2d = SP_ITEM(obj)->i2d_affine();
+ Geom::Affine i2d = SP_ITEM(obj)->i2d_affine();
double sw = style->stroke_width.computed * i2d.descrim();
if (prev_sw != -1 && fabs(sw - prev_sw) > 1e-3)
@@ -932,7 +932,7 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res)
if (!style) continue;
texts ++;
- size += style->font_size.computed * Geom::Matrix(SP_ITEM(obj)->i2d_affine()).descrim(); /// \todo FIXME: we assume non-% units here
+ size += style->font_size.computed * Geom::Affine(SP_ITEM(obj)->i2d_affine()).descrim(); /// \todo FIXME: we assume non-% units here
if (style->letter_spacing.normal) {
if (!different && (letterspacing_prev == 0 || letterspacing_prev == letterspacing))
@@ -1380,7 +1380,7 @@ objects_query_blur (GSList *objects, SPStyle *style_res)
if (!style) continue;
if (!SP_IS_ITEM(obj)) continue;
- Geom::Matrix i2d = SP_ITEM(obj)->i2d_affine();
+ Geom::Affine i2d = SP_ITEM(obj)->i2d_affine();
items ++;
diff --git a/src/desktop.cpp b/src/desktop.cpp
index bfde0ee92..b382a1d91 100644
--- a/src/desktop.cpp
+++ b/src/desktop.cpp
@@ -1159,7 +1159,7 @@ SPDesktop::scroll_to_point (Geom::Point const &p, gdouble autoscrollspeed)
if (!(p[X] > dbox.min()[X] && p[X] < dbox.max()[X]) ||
!(p[Y] > dbox.min()[Y] && p[Y] < dbox.max()[Y]) ) {
- Geom::Point const s_w( p * (Geom::Matrix)_d2w );
+ Geom::Point const s_w( p * (Geom::Affine)_d2w );
gdouble x_to;
if (p[X] < dbox.min()[X])
@@ -1754,7 +1754,7 @@ _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop)
}
}
-Geom::Matrix SPDesktop::w2d() const
+Geom::Affine SPDesktop::w2d() const
{
return _w2d;
}
@@ -1769,12 +1769,12 @@ Geom::Point SPDesktop::d2w(Geom::Point const &p) const
return p * _d2w;
}
-Geom::Matrix SPDesktop::doc2dt() const
+Geom::Affine SPDesktop::doc2dt() const
{
return _doc2dt;
}
-Geom::Matrix SPDesktop::dt2doc() const
+Geom::Affine SPDesktop::dt2doc() const
{
// doc2dt is its own inverse
return _doc2dt;
diff --git a/src/desktop.h b/src/desktop.h
index 957c3b342..8f89df418 100644
--- a/src/desktop.h
+++ b/src/desktop.h
@@ -31,7 +31,7 @@
#include <gtk/gtktypeutils.h>
#include <sigc++/sigc++.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <2geom/rect.h>
#include "ui/view/view.h"
@@ -312,11 +312,11 @@ public:
void fullscreen();
void focusMode(bool mode = true);
- Geom::Matrix w2d() const; //transformation from window to desktop coordinates (used for zooming)
+ Geom::Affine w2d() const; //transformation from window to desktop coordinates (used for zooming)
Geom::Point w2d(Geom::Point const &p) const;
Geom::Point d2w(Geom::Point const &p) const;
- Geom::Matrix doc2dt() const;
- Geom::Matrix dt2doc() const;
+ Geom::Affine doc2dt() const;
+ Geom::Affine dt2doc() const;
Geom::Point doc2dt(Geom::Point const &p) const;
Geom::Point dt2doc(Geom::Point const &p) const;
@@ -335,9 +335,9 @@ private:
Inkscape::Application *_inkscape;
Inkscape::MessageContext *_guides_message_context;
bool _active;
- Geom::Matrix _w2d;
- Geom::Matrix _d2w;
- Geom::Matrix _doc2dt;
+ Geom::Affine _w2d;
+ Geom::Affine _d2w;
+ Geom::Affine _doc2dt;
bool grids_visible; /* don't set this variable directly, use the method below */
void set_grids_visible(bool visible);
diff --git a/src/dialogs/clonetiler.cpp b/src/dialogs/clonetiler.cpp
index 8045675b4..bd5be5be5 100644
--- a/src/dialogs/clonetiler.cpp
+++ b/src/dialogs/clonetiler.cpp
@@ -196,7 +196,7 @@ enum {
};
-static Geom::Matrix
+static Geom::Affine
clonetiler_get_transform (
// symmetry group
@@ -287,7 +287,7 @@ clonetiler_get_transform (
if ( shifty_exp != 1.0 ) shiftj = pow( shiftj, shifty_exp );
// Final shift
- Geom::Matrix rect_translate (Geom::Translate (w * shifti, h * shiftj));
+ Geom::Affine rect_translate (Geom::Translate (w * shifti, h * shiftj));
// Rotation (in degrees) ------------
double delta_rotationi = 0.0;
@@ -370,25 +370,25 @@ clonetiler_get_transform (
// Calculate transformation matrices, translating back to "center of tile" (rotation center) before transforming
- Geom::Matrix drot_c = Geom::Translate(-cx, -cy) * Geom::Rotate (M_PI*dr/180) * Geom::Translate(cx, cy);
+ Geom::Affine drot_c = Geom::Translate(-cx, -cy) * Geom::Rotate (M_PI*dr/180) * Geom::Translate(cx, cy);
- Geom::Matrix dscale_c = Geom::Translate(-cx, -cy) * Geom::Scale (scalex, scaley) * Geom::Translate(cx, cy);
+ Geom::Affine dscale_c = Geom::Translate(-cx, -cy) * Geom::Scale (scalex, scaley) * Geom::Translate(cx, cy);
- Geom::Matrix d_s_r = dscale_c * drot_c;
+ Geom::Affine d_s_r = dscale_c * drot_c;
- Geom::Matrix rotate_180_c = Geom::Translate(-cx, -cy) * Geom::Rotate (M_PI) * Geom::Translate(cx, cy);
+ Geom::Affine rotate_180_c = Geom::Translate(-cx, -cy) * Geom::Rotate (M_PI) * Geom::Translate(cx, cy);
- Geom::Matrix rotate_90_c = Geom::Translate(-cx, -cy) * Geom::Rotate (-M_PI/2) * Geom::Translate(cx, cy);
- Geom::Matrix rotate_m90_c = Geom::Translate(-cx, -cy) * Geom::Rotate ( M_PI/2) * Geom::Translate(cx, cy);
+ Geom::Affine rotate_90_c = Geom::Translate(-cx, -cy) * Geom::Rotate (-M_PI/2) * Geom::Translate(cx, cy);
+ Geom::Affine rotate_m90_c = Geom::Translate(-cx, -cy) * Geom::Rotate ( M_PI/2) * Geom::Translate(cx, cy);
- Geom::Matrix rotate_120_c = Geom::Translate(-cx, -cy) * Geom::Rotate (-2*M_PI/3) * Geom::Translate(cx, cy);
- Geom::Matrix rotate_m120_c = Geom::Translate(-cx, -cy) * Geom::Rotate ( 2*M_PI/3) * Geom::Translate(cx, cy);
+ Geom::Affine rotate_120_c = Geom::Translate(-cx, -cy) * Geom::Rotate (-2*M_PI/3) * Geom::Translate(cx, cy);
+ Geom::Affine rotate_m120_c = Geom::Translate(-cx, -cy) * Geom::Rotate ( 2*M_PI/3) * Geom::Translate(cx, cy);
- Geom::Matrix rotate_60_c = Geom::Translate(-cx, -cy) * Geom::Rotate (-M_PI/3) * Geom::Translate(cx, cy);
- Geom::Matrix rotate_m60_c = Geom::Translate(-cx, -cy) * Geom::Rotate ( M_PI/3) * Geom::Translate(cx, cy);
+ Geom::Affine rotate_60_c = Geom::Translate(-cx, -cy) * Geom::Rotate (-M_PI/3) * Geom::Translate(cx, cy);
+ Geom::Affine rotate_m60_c = Geom::Translate(-cx, -cy) * Geom::Rotate ( M_PI/3) * Geom::Translate(cx, cy);
- Geom::Matrix flip_x = Geom::Translate(-cx, -cy) * Geom::Scale (-1, 1) * Geom::Translate(cx, cy);
- Geom::Matrix flip_y = Geom::Translate(-cx, -cy) * Geom::Scale (1, -1) * Geom::Translate(cx, cy);
+ Geom::Affine flip_x = Geom::Translate(-cx, -cy) * Geom::Scale (-1, 1) * Geom::Translate(cx, cy);
+ Geom::Affine flip_y = Geom::Translate(-cx, -cy) * Geom::Scale (1, -1) * Geom::Translate(cx, cy);
// Create tile with required symmetry
@@ -513,9 +513,9 @@ clonetiler_get_transform (
case TILE_P4:
{
- Geom::Matrix ori (Geom::Translate ((w + h) * pow((i/2), shiftx_exp) + dx, (h + w) * pow((j/2), shifty_exp) + dy));
- Geom::Matrix dia1 (Geom::Translate (w/2 + h/2, -h/2 + w/2));
- Geom::Matrix dia2 (Geom::Translate (-w/2 + h/2, h/2 + w/2));
+ Geom::Affine ori (Geom::Translate ((w + h) * pow((i/2), shiftx_exp) + dx, (h + w) * pow((j/2), shifty_exp) + dy));
+ Geom::Affine dia1 (Geom::Translate (w/2 + h/2, -h/2 + w/2));
+ Geom::Affine dia2 (Geom::Translate (-w/2 + h/2, h/2 + w/2));
if (j % 2 == 0) {
if (i % 2 == 0) {
return d_s_r * ori;
@@ -535,9 +535,9 @@ clonetiler_get_transform (
case TILE_P4M:
{
double max = MAX(w, h);
- Geom::Matrix ori (Geom::Translate ((max + max) * pow((i/4), shiftx_exp) + dx, (max + max) * pow((j/2), shifty_exp) + dy));
- Geom::Matrix dia1 (Geom::Translate ( w/2 - h/2, h/2 - w/2));
- Geom::Matrix dia2 (Geom::Translate (-h/2 + w/2, w/2 - h/2));
+ Geom::Affine ori (Geom::Translate ((max + max) * pow((i/4), shiftx_exp) + dx, (max + max) * pow((j/2), shifty_exp) + dy));
+ Geom::Affine dia1 (Geom::Translate ( w/2 - h/2, h/2 - w/2));
+ Geom::Affine dia2 (Geom::Translate (-h/2 + w/2, w/2 - h/2));
if (j % 2 == 0) {
if (i % 4 == 0) {
return d_s_r * ori;
@@ -565,9 +565,9 @@ clonetiler_get_transform (
case TILE_P4G:
{
double max = MAX(w, h);
- Geom::Matrix ori (Geom::Translate ((max + max) * pow((i/4), shiftx_exp) + dx, (max + max) * pow(j, shifty_exp) + dy));
- Geom::Matrix dia1 (Geom::Translate ( w/2 + h/2, h/2 - w/2));
- Geom::Matrix dia2 (Geom::Translate (-h/2 + w/2, w/2 + h/2));
+ Geom::Affine ori (Geom::Translate ((max + max) * pow((i/4), shiftx_exp) + dx, (max + max) * pow(j, shifty_exp) + dy));
+ Geom::Affine dia1 (Geom::Translate ( w/2 + h/2, h/2 - w/2));
+ Geom::Affine dia2 (Geom::Translate (-h/2 + w/2, w/2 + h/2));
if (((i/4) + j) % 2 == 0) {
if (i % 4 == 0) {
return d_s_r * ori;
@@ -596,20 +596,20 @@ clonetiler_get_transform (
{
double width;
double height;
- Geom::Matrix dia1;
- Geom::Matrix dia2;
+ Geom::Affine dia1;
+ Geom::Affine dia2;
if (w > h) {
width = w + w * cos60;
height = 2 * w * sin60;
- dia1 = Geom::Matrix (Geom::Translate (w/2 + w/2 * cos60, -(w/2 * sin60)));
- dia2 = dia1 * Geom::Matrix (Geom::Translate (0, 2 * (w/2 * sin60)));
+ dia1 = Geom::Affine (Geom::Translate (w/2 + w/2 * cos60, -(w/2 * sin60)));
+ dia2 = dia1 * Geom::Affine (Geom::Translate (0, 2 * (w/2 * sin60)));
} else {
width = h * cos (M_PI/6);
height = h;
- dia1 = Geom::Matrix (Geom::Translate (h/2 * cos30, -(h/2 * sin30)));
- dia2 = dia1 * Geom::Matrix (Geom::Translate (0, h/2));
+ dia1 = Geom::Affine (Geom::Translate (h/2 * cos30, -(h/2 * sin30)));
+ dia2 = dia1 * Geom::Affine (Geom::Translate (0, h/2));
}
- Geom::Matrix ori (Geom::Translate (width * pow((2*(i/3) + j%2), shiftx_exp) + dx, (height/2) * pow(j, shifty_exp) + dy));
+ Geom::Affine ori (Geom::Translate (width * pow((2*(i/3) + j%2), shiftx_exp) + dx, (height/2) * pow(j, shifty_exp) + dy));
if (i % 3 == 0) {
return d_s_r * ori;
} else if (i % 3 == 1) {
@@ -622,23 +622,23 @@ clonetiler_get_transform (
case TILE_P31M:
{
- Geom::Matrix ori;
- Geom::Matrix dia1;
- Geom::Matrix dia2;
- Geom::Matrix dia3;
- Geom::Matrix dia4;
+ Geom::Affine ori;
+ Geom::Affine dia1;
+ Geom::Affine dia2;
+ Geom::Affine dia3;
+ Geom::Affine dia4;
if (w > h) {
- ori = Geom::Matrix(Geom::Translate (w * pow((i/6) + 0.5*(j%2), shiftx_exp) + dx, (w * cos30) * pow(j, shifty_exp) + dy));
- dia1 = Geom::Matrix (Geom::Translate (0, h/2) * Geom::Translate (w/2, 0) * Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (-h/2 * cos30, -h/2 * sin30) );
- dia2 = dia1 * Geom::Matrix (Geom::Translate (h * cos30, h * sin30));
- dia3 = dia2 * Geom::Matrix (Geom::Translate (0, 2 * (w/2 * sin60 - h/2 * sin30)));
- dia4 = dia3 * Geom::Matrix (Geom::Translate (-h * cos30, h * sin30));
+ ori = Geom::Affine(Geom::Translate (w * pow((i/6) + 0.5*(j%2), shiftx_exp) + dx, (w * cos30) * pow(j, shifty_exp) + dy));
+ dia1 = Geom::Affine (Geom::Translate (0, h/2) * Geom::Translate (w/2, 0) * Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (-h/2 * cos30, -h/2 * sin30) );
+ dia2 = dia1 * Geom::Affine (Geom::Translate (h * cos30, h * sin30));
+ dia3 = dia2 * Geom::Affine (Geom::Translate (0, 2 * (w/2 * sin60 - h/2 * sin30)));
+ dia4 = dia3 * Geom::Affine (Geom::Translate (-h * cos30, h * sin30));
} else {
- ori = Geom::Matrix (Geom::Translate (2*h * cos30 * pow((i/6 + 0.5*(j%2)), shiftx_exp) + dx, (2*h - h * sin30) * pow(j, shifty_exp) + dy));
- dia1 = Geom::Matrix (Geom::Translate (0, -h/2) * Geom::Translate (h/2 * cos30, h/2 * sin30));
- dia2 = dia1 * Geom::Matrix (Geom::Translate (h * cos30, h * sin30));
- dia3 = dia2 * Geom::Matrix (Geom::Translate (0, h/2));
- dia4 = dia3 * Geom::Matrix (Geom::Translate (-h * cos30, h * sin30));
+ ori = Geom::Affine (Geom::Translate (2*h * cos30 * pow((i/6 + 0.5*(j%2)), shiftx_exp) + dx, (2*h - h * sin30) * pow(j, shifty_exp) + dy));
+ dia1 = Geom::Affine (Geom::Translate (0, -h/2) * Geom::Translate (h/2 * cos30, h/2 * sin30));
+ dia2 = dia1 * Geom::Affine (Geom::Translate (h * cos30, h * sin30));
+ dia3 = dia2 * Geom::Affine (Geom::Translate (0, h/2));
+ dia4 = dia3 * Geom::Affine (Geom::Translate (-h * cos30, h * sin30));
}
if (i % 6 == 0) {
return d_s_r * ori;
@@ -660,26 +660,26 @@ clonetiler_get_transform (
{
double width;
double height;
- Geom::Matrix dia1;
- Geom::Matrix dia2;
- Geom::Matrix dia3;
- Geom::Matrix dia4;
+ Geom::Affine dia1;
+ Geom::Affine dia2;
+ Geom::Affine dia3;
+ Geom::Affine dia4;
if (w > h) {
width = w + w * cos60;
height = 2 * w * sin60;
- dia1 = Geom::Matrix (Geom::Translate (0, h/2) * Geom::Translate (w/2, 0) * Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (-h/2 * cos30, -h/2 * sin30) );
- dia2 = dia1 * Geom::Matrix (Geom::Translate (h * cos30, h * sin30));
- dia3 = dia2 * Geom::Matrix (Geom::Translate (0, 2 * (w/2 * sin60 - h/2 * sin30)));
- dia4 = dia3 * Geom::Matrix (Geom::Translate (-h * cos30, h * sin30));
+ dia1 = Geom::Affine (Geom::Translate (0, h/2) * Geom::Translate (w/2, 0) * Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (-h/2 * cos30, -h/2 * sin30) );
+ dia2 = dia1 * Geom::Affine (Geom::Translate (h * cos30, h * sin30));
+ dia3 = dia2 * Geom::Affine (Geom::Translate (0, 2 * (w/2 * sin60 - h/2 * sin30)));
+ dia4 = dia3 * Geom::Affine (Geom::Translate (-h * cos30, h * sin30));
} else {
width = 2 * h * cos (M_PI/6);
height = 2 * h;
- dia1 = Geom::Matrix (Geom::Translate (0, -h/2) * Geom::Translate (h/2 * cos30, h/2 * sin30));
- dia2 = dia1 * Geom::Matrix (Geom::Translate (h * cos30, h * sin30));
- dia3 = dia2 * Geom::Matrix (Geom::Translate (0, h/2));
- dia4 = dia3 * Geom::Matrix (Geom::Translate (-h * cos30, h * sin30));
+ dia1 = Geom::Affine (Geom::Translate (0, -h/2) * Geom::Translate (h/2 * cos30, h/2 * sin30));
+ dia2 = dia1 * Geom::Affine (Geom::Translate (h * cos30, h * sin30));
+ dia3 = dia2 * Geom::Affine (Geom::Translate (0, h/2));
+ dia4 = dia3 * Geom::Affine (Geom::Translate (-h * cos30, h * sin30));
}
- Geom::Matrix ori (Geom::Translate (width * pow((2*(i/6) + j%2), shiftx_exp) + dx, (height/2) * pow(j, shifty_exp) + dy));
+ Geom::Affine ori (Geom::Translate (width * pow((2*(i/6) + j%2), shiftx_exp) + dx, (height/2) * pow(j, shifty_exp) + dy));
if (i % 6 == 0) {
return d_s_r * ori;
} else if (i % 6 == 1) {
@@ -698,24 +698,24 @@ clonetiler_get_transform (
case TILE_P6:
{
- Geom::Matrix ori;
- Geom::Matrix dia1;
- Geom::Matrix dia2;
- Geom::Matrix dia3;
- Geom::Matrix dia4;
- Geom::Matrix dia5;
+ Geom::Affine ori;
+ Geom::Affine dia1;
+ Geom::Affine dia2;
+ Geom::Affine dia3;
+ Geom::Affine dia4;
+ Geom::Affine dia5;
if (w > h) {
- ori = Geom::Matrix(Geom::Translate (w * pow((2*(i/6) + (j%2)), shiftx_exp) + dx, (2*w * sin60) * pow(j, shifty_exp) + dy));
- dia1 = Geom::Matrix (Geom::Translate (w/2 * cos60, -w/2 * sin60));
- dia2 = dia1 * Geom::Matrix (Geom::Translate (w/2, 0));
- dia3 = dia2 * Geom::Matrix (Geom::Translate (w/2 * cos60, w/2 * sin60));
- dia4 = dia3 * Geom::Matrix (Geom::Translate (-w/2 * cos60, w/2 * sin60));
- dia5 = dia4 * Geom::Matrix (Geom::Translate (-w/2, 0));
+ ori = Geom::Affine(Geom::Translate (w * pow((2*(i/6) + (j%2)), shiftx_exp) + dx, (2*w * sin60) * pow(j, shifty_exp) + dy));
+ dia1 = Geom::Affine (Geom::Translate (w/2 * cos60, -w/2 * sin60));
+ dia2 = dia1 * Geom::Affine (Geom::Translate (w/2, 0));
+ dia3 = dia2 * Geom::Affine (Geom::Translate (w/2 * cos60, w/2 * sin60));
+ dia4 = dia3 * Geom::Affine (Geom::Translate (-w/2 * cos60, w/2 * sin60));
+ dia5 = dia4 * Geom::Affine (Geom::Translate (-w/2, 0));
} else {
- ori = Geom::Matrix(Geom::Translate (2*h * cos30 * pow((i/6 + 0.5*(j%2)), shiftx_exp) + dx, (h + h * sin30) * pow(j, shifty_exp) + dy));
- dia1 = Geom::Matrix (Geom::Translate (-w/2, -h/2) * Geom::Translate (h/2 * cos30, -h/2 * sin30) * Geom::Translate (w/2 * cos60, w/2 * sin60));
- dia2 = dia1 * Geom::Matrix (Geom::Translate (-w/2 * cos60, -w/2 * sin60) * Geom::Translate (h/2 * cos30, -h/2 * sin30) * Geom::Translate (h/2 * cos30, h/2 * sin30) * Geom::Translate (-w/2 * cos60, w/2 * sin60));
- dia3 = dia2 * Geom::Matrix (Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (h/2 * cos30, h/2 * sin30) * Geom::Translate (-w/2, h/2));
+ ori = Geom::Affine(Geom::Translate (2*h * cos30 * pow((i/6 + 0.5*(j%2)), shiftx_exp) + dx, (h + h * sin30) * pow(j, shifty_exp) + dy));
+ dia1 = Geom::Affine (Geom::Translate (-w/2, -h/2) * Geom::Translate (h/2 * cos30, -h/2 * sin30) * Geom::Translate (w/2 * cos60, w/2 * sin60));
+ dia2 = dia1 * Geom::Affine (Geom::Translate (-w/2 * cos60, -w/2 * sin60) * Geom::Translate (h/2 * cos30, -h/2 * sin30) * Geom::Translate (h/2 * cos30, h/2 * sin30) * Geom::Translate (-w/2 * cos60, w/2 * sin60));
+ dia3 = dia2 * Geom::Affine (Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (h/2 * cos30, h/2 * sin30) * Geom::Translate (-w/2, h/2));
dia4 = dia3 * dia1.inverse();
dia5 = dia3 * dia2.inverse();
}
@@ -738,28 +738,28 @@ clonetiler_get_transform (
case TILE_P6M:
{
- Geom::Matrix ori;
- Geom::Matrix dia1, dia2, dia3, dia4, dia5, dia6, dia7, dia8, dia9, dia10;
+ Geom::Affine ori;
+ Geom::Affine dia1, dia2, dia3, dia4, dia5, dia6, dia7, dia8, dia9, dia10;
if (w > h) {
- ori = Geom::Matrix(Geom::Translate (w * pow((2*(i/12) + (j%2)), shiftx_exp) + dx, (2*w * sin60) * pow(j, shifty_exp) + dy));
- dia1 = Geom::Matrix (Geom::Translate (w/2, h/2) * Geom::Translate (-w/2 * cos60, -w/2 * sin60) * Geom::Translate (-h/2 * cos30, h/2 * sin30));
- dia2 = dia1 * Geom::Matrix (Geom::Translate (h * cos30, -h * sin30));
- dia3 = dia2 * Geom::Matrix (Geom::Translate (-h/2 * cos30, h/2 * sin30) * Geom::Translate (w * cos60, 0) * Geom::Translate (-h/2 * cos30, -h/2 * sin30));
- dia4 = dia3 * Geom::Matrix (Geom::Translate (h * cos30, h * sin30));
- dia5 = dia4 * Geom::Matrix (Geom::Translate (-h/2 * cos30, -h/2 * sin30) * Geom::Translate (-w/2 * cos60, w/2 * sin60) * Geom::Translate (w/2, -h/2));
- dia6 = dia5 * Geom::Matrix (Geom::Translate (0, h));
+ ori = Geom::Affine(Geom::Translate (w * pow((2*(i/12) + (j%2)), shiftx_exp) + dx, (2*w * sin60) * pow(j, shifty_exp) + dy));
+ dia1 = Geom::Affine (Geom::Translate (w/2, h/2) * Geom::Translate (-w/2 * cos60, -w/2 * sin60) * Geom::Translate (-h/2 * cos30, h/2 * sin30));
+ dia2 = dia1 * Geom::Affine (Geom::Translate (h * cos30, -h * sin30));
+ dia3 = dia2 * Geom::Affine (Geom::Translate (-h/2 * cos30, h/2 * sin30) * Geom::Translate (w * cos60, 0) * Geom::Translate (-h/2 * cos30, -h/2 * sin30));
+ dia4 = dia3 * Geom::Affine (Geom::Translate (h * cos30, h * sin30));
+ dia5 = dia4 * Geom::Affine (Geom::Translate (-h/2 * cos30, -h/2 * sin30) * Geom::Translate (-w/2 * cos60, w/2 * sin60) * Geom::Translate (w/2, -h/2));
+ dia6 = dia5 * Geom::Affine (Geom::Translate (0, h));
dia7 = dia6 * dia1.inverse();
dia8 = dia6 * dia2.inverse();
dia9 = dia6 * dia3.inverse();
dia10 = dia6 * dia4.inverse();
} else {
- ori = Geom::Matrix(Geom::Translate (4*h * cos30 * pow((i/12 + 0.5*(j%2)), shiftx_exp) + dx, (2*h + 2*h * sin30) * pow(j, shifty_exp) + dy));
- dia1 = Geom::Matrix (Geom::Translate (-w/2, -h/2) * Geom::Translate (h/2 * cos30, -h/2 * sin30) * Geom::Translate (w/2 * cos60, w/2 * sin60));
- dia2 = dia1 * Geom::Matrix (Geom::Translate (h * cos30, -h * sin30));
- dia3 = dia2 * Geom::Matrix (Geom::Translate (-w/2 * cos60, -w/2 * sin60) * Geom::Translate (h * cos30, 0) * Geom::Translate (-w/2 * cos60, w/2 * sin60));
- dia4 = dia3 * Geom::Matrix (Geom::Translate (h * cos30, h * sin30));
- dia5 = dia4 * Geom::Matrix (Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (h/2 * cos30, h/2 * sin30) * Geom::Translate (-w/2, h/2));
- dia6 = dia5 * Geom::Matrix (Geom::Translate (0, h));
+ ori = Geom::Affine(Geom::Translate (4*h * cos30 * pow((i/12 + 0.5*(j%2)), shiftx_exp) + dx, (2*h + 2*h * sin30) * pow(j, shifty_exp) + dy));
+ dia1 = Geom::Affine (Geom::Translate (-w/2, -h/2) * Geom::Translate (h/2 * cos30, -h/2 * sin30) * Geom::Translate (w/2 * cos60, w/2 * sin60));
+ dia2 = dia1 * Geom::Affine (Geom::Translate (h * cos30, -h * sin30));
+ dia3 = dia2 * Geom::Affine (Geom::Translate (-w/2 * cos60, -w/2 * sin60) * Geom::Translate (h * cos30, 0) * Geom::Translate (-w/2 * cos60, w/2 * sin60));
+ dia4 = dia3 * Geom::Affine (Geom::Translate (h * cos30, h * sin30));
+ dia5 = dia4 * Geom::Affine (Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (h/2 * cos30, h/2 * sin30) * Geom::Translate (-w/2, h/2));
+ dia6 = dia5 * Geom::Affine (Geom::Translate (0, h));
dia7 = dia6 * dia1.inverse();
dia8 = dia6 * dia2.inverse();
dia9 = dia6 * dia3.inverse();
@@ -870,7 +870,7 @@ clonetiler_trace_pick (Geom::Rect box)
if (!trace_arena)
return 0;
- Geom::Matrix t(Geom::Scale(trace_zoom, trace_zoom));
+ Geom::Affine t(Geom::Scale(trace_zoom, trace_zoom));
nr_arena_item_set_transform(trace_root, &t);
NRGC gc(NULL);
gc.transform.setIdentity();
@@ -1041,7 +1041,7 @@ clonetiler_remove( GtkWidget */*widget*/, void *, bool do_undo = true )
}
static Geom::Rect
-transform_rect( Geom::Rect const &r, Geom::Matrix const &m)
+transform_rect( Geom::Rect const &r, Geom::Affine const &m)
{
using Geom::X;
using Geom::Y;
@@ -1263,7 +1263,7 @@ clonetiler_apply( GtkWidget */*widget*/, void * )
// Note: We create a clone at 0,0 too, right over the original, in case our clones are colored
// Get transform from symmetry, shift, scale, rotation
- Geom::Matrix t = clonetiler_get_transform (type, i, j, center[Geom::X], center[Geom::Y], w, h,
+ Geom::Affine t = clonetiler_get_transform (type, i, j, center[Geom::X], center[Geom::Y], w, h,
shiftx_per_i, shifty_per_i,
shiftx_per_j, shifty_per_j,
shiftx_rand, shifty_rand,
diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp
index fb7ca9d78..f3e1b0f0c 100644
--- a/src/display/canvas-arena.cpp
+++ b/src/display/canvas-arena.cpp
@@ -29,7 +29,7 @@ static void sp_canvas_arena_class_init(SPCanvasArenaClass *klass);
static void sp_canvas_arena_init(SPCanvasArena *group);
static void sp_canvas_arena_destroy(GtkObject *object);
-static void sp_canvas_arena_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+static void sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf);
static double sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
static gint sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event);
@@ -134,7 +134,7 @@ sp_canvas_arena_destroy (GtkObject *object)
}
static void
-sp_canvas_arena_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags)
+sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
{
SPCanvasArena *arena = SP_CANVAS_ARENA (item);
diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp
index 550fd3559..845c4e077 100644
--- a/src/display/canvas-axonomgrid.cpp
+++ b/src/display/canvas-axonomgrid.cpp
@@ -511,7 +511,7 @@ CanvasAxonomGrid::updateWidgets()
void
-CanvasAxonomGrid::Update (Geom::Matrix const &affine, unsigned int /*flags*/)
+CanvasAxonomGrid::Update (Geom::Affine const &affine, unsigned int /*flags*/)
{
ow = origin * affine;
sw = Geom::Point(fabs(affine[0]),fabs(affine[3]));
diff --git a/src/display/canvas-axonomgrid.h b/src/display/canvas-axonomgrid.h
index 58185e2e6..282524c74 100644
--- a/src/display/canvas-axonomgrid.h
+++ b/src/display/canvas-axonomgrid.h
@@ -34,7 +34,7 @@ public:
CanvasAxonomGrid(SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument * in_doc);
virtual ~CanvasAxonomGrid();
- void Update (Geom::Matrix const &affine, unsigned int flags);
+ void Update (Geom::Affine const &affine, unsigned int flags);
void Render (SPCanvasBuf *buf);
void readRepr();
diff --git a/src/display/canvas-bpath.cpp b/src/display/canvas-bpath.cpp
index f8a8ef22c..725a1d0ff 100644
--- a/src/display/canvas-bpath.cpp
+++ b/src/display/canvas-bpath.cpp
@@ -34,7 +34,7 @@ static void sp_canvas_bpath_class_init (SPCanvasBPathClass *klass);
static void sp_canvas_bpath_init (SPCanvasBPath *path);
static void sp_canvas_bpath_destroy (GtkObject *object);
-static void sp_canvas_bpath_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+static void sp_canvas_bpath_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_canvas_bpath_render (SPCanvasItem *item, SPCanvasBuf *buf);
static double sp_canvas_bpath_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
@@ -103,7 +103,7 @@ sp_canvas_bpath_destroy (GtkObject *object)
}
static void
-sp_canvas_bpath_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags)
+sp_canvas_bpath_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
{
SPCanvasBPath *cbp = SP_CANVAS_BPATH (item);
diff --git a/src/display/canvas-bpath.h b/src/display/canvas-bpath.h
index 0760baef6..7f8b75dfe 100644
--- a/src/display/canvas-bpath.h
+++ b/src/display/canvas-bpath.h
@@ -67,7 +67,7 @@ struct SPCanvasBPath {
/* Line def */
SPCurve *curve;
- Geom::Matrix affine;
+ Geom::Affine affine;
/* Fill attributes */
guint32 fill_rgba;
diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp
index 5892e1dc7..79bfc31ad 100644
--- a/src/display/canvas-grid.cpp
+++ b/src/display/canvas-grid.cpp
@@ -52,7 +52,7 @@ static void grid_canvasitem_class_init (GridCanvasItemClass *klass);
static void grid_canvasitem_init (GridCanvasItem *grid);
static void grid_canvasitem_destroy (GtkObject *object);
-static void grid_canvasitem_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+static void grid_canvasitem_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void grid_canvasitem_render (SPCanvasItem *item, SPCanvasBuf *buf);
static SPCanvasItemClass * parent_class;
@@ -124,7 +124,7 @@ grid_canvasitem_render (SPCanvasItem * item, SPCanvasBuf * buf)
}
static void
-grid_canvasitem_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags)
+grid_canvasitem_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
{
GridCanvasItem *gridcanvasitem = INKSCAPE_GRID_CANVASITEM (item);
@@ -803,7 +803,7 @@ CanvasXYGrid::updateWidgets()
void
-CanvasXYGrid::Update (Geom::Matrix const &affine, unsigned int /*flags*/)
+CanvasXYGrid::Update (Geom::Affine const &affine, unsigned int /*flags*/)
{
ow = origin * affine;
sw = spacing * affine;
diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h
index b8f313948..f386fe05e 100644
--- a/src/display/canvas-grid.h
+++ b/src/display/canvas-grid.h
@@ -79,7 +79,7 @@ public:
GridCanvasItem * createCanvasItem(SPDesktop * desktop);
- virtual void Update (Geom::Matrix const &affine, unsigned int flags) = 0;
+ virtual void Update (Geom::Affine const &affine, unsigned int flags) = 0;
virtual void Render (SPCanvasBuf *buf) = 0;
virtual void readRepr() = 0;
@@ -129,7 +129,7 @@ public:
CanvasXYGrid(SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument * in_doc);
virtual ~CanvasXYGrid();
- void Update (Geom::Matrix const &affine, unsigned int flags);
+ void Update (Geom::Affine const &affine, unsigned int flags);
void Render (SPCanvasBuf *buf);
void readRepr();
diff --git a/src/display/canvas-text.cpp b/src/display/canvas-text.cpp
index e2bc09679..70196b307 100644
--- a/src/display/canvas-text.cpp
+++ b/src/display/canvas-text.cpp
@@ -31,7 +31,7 @@ static void sp_canvastext_class_init (SPCanvasTextClass *klass);
static void sp_canvastext_init (SPCanvasText *canvastext);
static void sp_canvastext_destroy (GtkObject *object);
-static void sp_canvastext_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+static void sp_canvastext_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_canvastext_render (SPCanvasItem *item, SPCanvasBuf *buf);
static SPCanvasItemClass *parent_class_ct;
@@ -133,7 +133,7 @@ sp_canvastext_render (SPCanvasItem *item, SPCanvasBuf *buf)
}
static void
-sp_canvastext_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags)
+sp_canvastext_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
{
SPCanvasText *cl = SP_CANVASTEXT (item);
diff --git a/src/display/canvas-text.h b/src/display/canvas-text.h
index cc194ccc4..d8bd86b7d 100644
--- a/src/display/canvas-text.h
+++ b/src/display/canvas-text.h
@@ -31,7 +31,7 @@ struct SPCanvasText : public SPCanvasItem {
gchar* text;
Geom::Point s;
- Geom::Matrix affine;
+ Geom::Affine affine;
double fontsize;
double anchor_x;
double anchor_y;
diff --git a/src/display/curve.cpp b/src/display/curve.cpp
index 303d1bb4d..5c18324eb 100644
--- a/src/display/curve.cpp
+++ b/src/display/curve.cpp
@@ -180,7 +180,7 @@ SPCurve::split() const
* Transform all paths in curve using matrix.
*/
void
-SPCurve::transform(Geom::Matrix const &m)
+SPCurve::transform(Geom::Affine const &m)
{
_pathv *= m;
}
diff --git a/src/display/curve.h b/src/display/curve.h
index e6387a9f0..ec828e674 100644
--- a/src/display/curve.h
+++ b/src/display/curve.h
@@ -67,7 +67,7 @@ public:
void closepath_current();
void backspace();
- void transform(Geom::Matrix const &m);
+ void transform(Geom::Affine const &m);
void stretch_endpoints(Geom::Point const &, Geom::Point const &);
void move_endpoints(Geom::Point const &, Geom::Point const &);
void last_point_additive_move(Geom::Point const & p);
diff --git a/src/display/gnome-canvas-acetate.cpp b/src/display/gnome-canvas-acetate.cpp
index c257f1f92..b86892e32 100644
--- a/src/display/gnome-canvas-acetate.cpp
+++ b/src/display/gnome-canvas-acetate.cpp
@@ -20,7 +20,7 @@ static void sp_canvas_acetate_class_init (SPCanvasAcetateClass *klass);
static void sp_canvas_acetate_init (SPCanvasAcetate *acetate);
static void sp_canvas_acetate_destroy (GtkObject *object);
-static void sp_canvas_acetate_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+static void sp_canvas_acetate_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static double sp_canvas_acetate_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
static SPCanvasItemClass *parent_class;
@@ -81,7 +81,7 @@ sp_canvas_acetate_destroy (GtkObject *object)
}
static void
-sp_canvas_acetate_update( SPCanvasItem *item, Geom::Matrix const &/*affine*/, unsigned int /*flags*/ )
+sp_canvas_acetate_update( SPCanvasItem *item, Geom::Affine const &/*affine*/, unsigned int /*flags*/ )
{
item->x1 = -G_MAXINT;
item->y1 = -G_MAXINT;
diff --git a/src/display/guideline.cpp b/src/display/guideline.cpp
index ce1289faf..bebec2852 100644
--- a/src/display/guideline.cpp
+++ b/src/display/guideline.cpp
@@ -24,7 +24,7 @@ static void sp_guideline_class_init(SPGuideLineClass *c);
static void sp_guideline_init(SPGuideLine *guideline);
static void sp_guideline_destroy(GtkObject *object);
-static void sp_guideline_update(SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+static void sp_guideline_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf);
static double sp_guideline_point(SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
@@ -183,7 +183,7 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf)
}
}
-static void sp_guideline_update(SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags)
+static void sp_guideline_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
{
SPGuideLine *gl = SP_GUIDELINE(item);
@@ -243,8 +243,8 @@ SPCanvasItem *sp_guideline_new(SPCanvasGroup *parent, Geom::Point point_on_line,
void sp_guideline_set_position(SPGuideLine *gl, Geom::Point point_on_line)
{
- sp_canvas_item_affine_absolute(SP_CANVAS_ITEM (gl), Geom::Matrix(Geom::Translate(point_on_line)));
- sp_canvas_item_affine_absolute(SP_CANVAS_ITEM (gl->origin), Geom::Matrix(Geom::Translate(point_on_line)));
+ sp_canvas_item_affine_absolute(SP_CANVAS_ITEM (gl), Geom::Affine(Geom::Translate(point_on_line)));
+ sp_canvas_item_affine_absolute(SP_CANVAS_ITEM (gl->origin), Geom::Affine(Geom::Translate(point_on_line)));
}
void sp_guideline_set_normal(SPGuideLine *gl, Geom::Point normal_to_line)
diff --git a/src/display/inkscape-cairo.cpp b/src/display/inkscape-cairo.cpp
index fdbd49727..4fc492ba8 100644
--- a/src/display/inkscape-cairo.cpp
+++ b/src/display/inkscape-cairo.cpp
@@ -22,7 +22,7 @@
#include <2geom/pathvector.h>
#include <2geom/bezier-curve.h>
#include <2geom/hvlinesegment.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <2geom/point.h>
#include <2geom/path.h>
#include <2geom/transforms.h>
@@ -73,7 +73,7 @@ nr_create_cairo_context (NRRectL *area, NRPixBlock *pb)
* If optimize_stroke == false, the view Rect is not used.
*/
static void
-feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Matrix const & trans, Geom::Rect view, bool optimize_stroke)
+feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Affine const & trans, Geom::Rect view, bool optimize_stroke)
{
if( is_straight_curve(c) )
{
@@ -163,7 +163,7 @@ feed_path_to_cairo (cairo_t *ct, Geom::Path const &path)
/** Feeds path-creating calls to the cairo context translating them from the Path, with the given transform and shift */
static void
-feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width)
+feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width)
{
if (!area)
return;
@@ -174,9 +174,9 @@ feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Matrix trans, Geo
Geom::Point shift = area->min();
Geom::Rect view = *area;
view.expandBy (stroke_width);
- view = view * (Geom::Matrix)Geom::Translate(-shift);
+ view = view * (Geom::Affine)Geom::Translate(-shift);
// Pass transformation to feed_curve, so that we don't need to create a whole new path.
- Geom::Matrix transshift(trans * Geom::Translate(-shift));
+ Geom::Affine transshift(trans * Geom::Translate(-shift));
Geom::Point initial = path.initialPoint() * transshift;
cairo_move_to(ct, initial[0], initial[1] );
@@ -211,7 +211,7 @@ feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Matrix trans, Geo
/** Feeds path-creating calls to the cairo context translating them from the PathVector, with the given transform and shift
* One must have done cairo_new_path(ct); before calling this function. */
void
-feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width)
+feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width)
{
if (!area)
return;
diff --git a/src/display/inkscape-cairo.h b/src/display/inkscape-cairo.h
index 0b3c99a7f..4133661fe 100644
--- a/src/display/inkscape-cairo.h
+++ b/src/display/inkscape-cairo.h
@@ -21,7 +21,7 @@ class SPCanvasBuf;
cairo_t *nr_create_cairo_context_canvasbuf (NRRectL *area, SPCanvasBuf *b);
cairo_t *nr_create_cairo_context (NRRectL *area, NRPixBlock *pb);
-void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width);
+void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width);
void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv);
#endif
diff --git a/src/display/nr-3dutils.cpp b/src/display/nr-3dutils.cpp
index de97c2e04..c5e7b4c1b 100644
--- a/src/display/nr-3dutils.cpp
+++ b/src/display/nr-3dutils.cpp
@@ -137,7 +137,7 @@ void compute_surface_normal(Fvector &N, gdouble ss, NRPixBlock *in, int i, int j
//std::cout << "(" << N[X_3D] << ", " << N[Y_3D] << ", " << N[Z_3D] << ")" << std::endl;
}
-void convert_coord(gdouble &x, gdouble &y, gdouble &z, Geom::Matrix const &trans) {
+void convert_coord(gdouble &x, gdouble &y, gdouble &z, Geom::Affine const &trans) {
Point p = Point(x, y);
p *= trans;
x = p[Geom::X];
diff --git a/src/display/nr-3dutils.h b/src/display/nr-3dutils.h
index 01138cf1f..56bed6ba2 100644
--- a/src/display/nr-3dutils.h
+++ b/src/display/nr-3dutils.h
@@ -94,7 +94,7 @@ void compute_surface_normal(Fvector &N, gdouble ss, NRPixBlock *in, int i, int j
* \param z a reference to a z coordinate
* \param z a reference to a transformation matrix
*/
-void convert_coord(gdouble &x, gdouble &y, gdouble &z, Geom::Matrix const &trans);
+void convert_coord(gdouble &x, gdouble &y, gdouble &z, Geom::Affine const &trans);
} /* namespace NR */
diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp
index fb7f57272..440a87012 100644
--- a/src/display/nr-arena-glyphs.cpp
+++ b/src/display/nr-arena-glyphs.cpp
@@ -18,7 +18,7 @@
#endif
#include <libnr/nr-blit.h>
#include <libnr/nr-convert2geom.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include "../style.h"
#include "nr-arena.h"
#include "nr-arena-glyphs.h"
@@ -143,7 +143,7 @@ nr_arena_glyphs_update(NRArenaItem *item, NRRectL */*area*/, NRGC *gc, guint /*s
float const scale = gc->transform.descrim();
if (!glyphs->style->fill.isNone()) {
- Geom::Matrix t;
+ Geom::Affine t;
t = glyphs->g_transform * gc->transform;
glyphs->x = t[4];
glyphs->y = t[5];
@@ -165,7 +165,7 @@ nr_arena_glyphs_update(NRArenaItem *item, NRRectL */*area*/, NRGC *gc, guint /*s
if (!glyphs->style->stroke.isNone()) {
/* Build state data */
- Geom::Matrix t;
+ Geom::Affine t;
t = glyphs->g_transform * gc->transform;
glyphs->x = t[4];
glyphs->y = t[5];
@@ -252,7 +252,7 @@ nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, gdouble delta, unsigned i
}
void
-nr_arena_glyphs_set_path(NRArenaGlyphs *glyphs, SPCurve */*curve*/, unsigned int /*lieutenant*/, font_instance *font, gint glyph, Geom::Matrix const *transform)
+nr_arena_glyphs_set_path(NRArenaGlyphs *glyphs, SPCurve */*curve*/, unsigned int /*lieutenant*/, font_instance *font, gint glyph, Geom::Affine const *transform)
{
nr_return_if_fail(glyphs != NULL);
nr_return_if_fail(NR_IS_ARENA_GLYPHS(glyphs));
@@ -463,7 +463,7 @@ nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPi
Geom::PathVector const * pathv = g->font->PathVector(g->glyph);
cairo_new_path(ct);
- Geom::Matrix transform = g->g_transform * group->ctm;
+ Geom::Affine transform = g->g_transform * group->ctm;
feed_pathvector_to_cairo (ct, *pathv, transform, to_2geom((pb->area).upgrade()), false, 0);
cairo_fill(ct);
pb->empty = FALSE;
@@ -613,7 +613,7 @@ nr_arena_glyphs_group_clear(NRArenaGlyphsGroup *sg)
}
void
-nr_arena_glyphs_group_add_component(NRArenaGlyphsGroup *sg, font_instance *font, int glyph, Geom::Matrix const &transform)
+nr_arena_glyphs_group_add_component(NRArenaGlyphsGroup *sg, font_instance *font, int glyph, Geom::Affine const &transform)
{
NRArenaGroup *group;
diff --git a/src/display/nr-arena-glyphs.h b/src/display/nr-arena-glyphs.h
index 1d15fef81..d04fdb4dc 100644
--- a/src/display/nr-arena-glyphs.h
+++ b/src/display/nr-arena-glyphs.h
@@ -33,7 +33,7 @@ NRType nr_arena_glyphs_get_type (void);
struct NRArenaGlyphs : public NRArenaItem {
/* Glyphs data */
SPStyle *style;
- Geom::Matrix g_transform;
+ Geom::Affine g_transform;
font_instance *font;
gint glyph;
@@ -41,7 +41,7 @@ struct NRArenaGlyphs : public NRArenaItem {
raster_font *sfont;
float x, y;
-// Geom::Matrix cached_tr;
+// Geom::Affine cached_tr;
// Shape *cached_shp;
// bool cached_shp_dirty;
// bool cached_style_dirty;
@@ -62,7 +62,7 @@ struct NRArenaGlyphsClass {
void nr_arena_glyphs_set_path ( NRArenaGlyphs *glyphs,
SPCurve *curve, unsigned int lieutenant,
font_instance *font, int glyph,
- Geom::Matrix const *transform );
+ Geom::Affine const *transform );
void nr_arena_glyphs_set_style (NRArenaGlyphs *glyphs, SPStyle *style);
/* Integrated group of component glyphss */
@@ -100,7 +100,7 @@ struct NRArenaGlyphsGroupClass {
void nr_arena_glyphs_group_clear (NRArenaGlyphsGroup *group);
-void nr_arena_glyphs_group_add_component (NRArenaGlyphsGroup *group, font_instance *font, int glyph, Geom::Matrix const &transform);
+void nr_arena_glyphs_group_add_component (NRArenaGlyphsGroup *group, font_instance *font, int glyph, Geom::Affine const &transform);
void nr_arena_glyphs_group_set_style (NRArenaGlyphsGroup *group, SPStyle *style);
diff --git a/src/display/nr-arena-group.cpp b/src/display/nr-arena-group.cpp
index e339fe5a7..6c6043b2c 100644
--- a/src/display/nr-arena-group.cpp
+++ b/src/display/nr-arena-group.cpp
@@ -271,13 +271,13 @@ nr_arena_group_set_transparent (NRArenaGroup *group, unsigned int transparent)
group->transparent = transparent;
}
-void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Matrix const &t)
+void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const &t)
{
- Geom::Matrix nt(t);
+ Geom::Affine nt(t);
nr_arena_group_set_child_transform(group, &nt);
}
-void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Matrix const *t)
+void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const *t)
{
if (!t) t = &GEOM_MATRIX_IDENTITY;
diff --git a/src/display/nr-arena-group.h b/src/display/nr-arena-group.h
index 4579d068f..58394643c 100644
--- a/src/display/nr-arena-group.h
+++ b/src/display/nr-arena-group.h
@@ -26,7 +26,7 @@ struct NRArenaGroup : public NRArenaItem{
unsigned int transparent : 1;
NRArenaItem *children;
NRArenaItem *last;
- Geom::Matrix child_transform;
+ Geom::Affine child_transform;
SPStyle *style;
static NRArenaGroup *create(NRArena *arena) {
@@ -42,8 +42,8 @@ struct NRArenaGroupClass {
void nr_arena_group_set_transparent(NRArenaGroup *group, unsigned int transparent);
-void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Matrix const &t);
-void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Matrix const *t);
+void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const &t);
+void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const *t);
void nr_arena_group_set_style(NRArenaGroup *group, SPStyle *style);
#endif
diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp
index 4132ada78..6539ae4d2 100644
--- a/src/display/nr-arena-image.cpp
+++ b/src/display/nr-arena-image.cpp
@@ -108,7 +108,7 @@ nr_arena_image_finalize (NRObject *object)
static unsigned int
nr_arena_image_update( NRArenaItem *item, NRRectL */*area*/, NRGC *gc, unsigned int /*state*/, unsigned int /*reset*/ )
{
- Geom::Matrix grid2px;
+ Geom::Affine grid2px;
// clear old bbox
nr_arena_item_request_render(item);
@@ -180,7 +180,7 @@ nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL */*area*/, NRPixB
NRArenaImage *image = NR_ARENA_IMAGE (item);
- Geom::Matrix d2s;
+ Geom::Affine d2s;
d2s[0] = b2i[0];
d2s[1] = b2i[1];
diff --git a/src/display/nr-arena-image.h b/src/display/nr-arena-image.h
index 48ebc5bd0..c8d1525dc 100644
--- a/src/display/nr-arena-image.h
+++ b/src/display/nr-arena-image.h
@@ -34,7 +34,7 @@ struct NRArenaImage : public NRArenaItem {
Geom::Point c00, c01, c11, c10; // all 4 corners of the image, for outline mode rect
/* From GRID to PIXELS */
- Geom::Matrix grid2px;
+ Geom::Affine grid2px;
SPStyle *style;
diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp
index 5598efa32..c74e2baa0 100644
--- a/src/display/nr-arena-item.cpp
+++ b/src/display/nr-arena-item.cpp
@@ -735,14 +735,14 @@ nr_arena_item_append_child (NRArenaItem *parent, NRArenaItem *child)
}
void
-nr_arena_item_set_transform (NRArenaItem *item, Geom::Matrix const &transform)
+nr_arena_item_set_transform (NRArenaItem *item, Geom::Affine const &transform)
{
- Geom::Matrix const t (transform);
+ Geom::Affine const t (transform);
nr_arena_item_set_transform (item, &t);
}
void
-nr_arena_item_set_transform (NRArenaItem *item, Geom::Matrix const *transform)
+nr_arena_item_set_transform (NRArenaItem *item, Geom::Affine const *transform)
{
nr_return_if_fail (item != NULL);
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
@@ -750,8 +750,8 @@ nr_arena_item_set_transform (NRArenaItem *item, Geom::Matrix const *transform)
if (!transform && !item->transform)
return;
- const Geom::Matrix *md = (item->transform) ? item->transform : &GEOM_MATRIX_IDENTITY;
- const Geom::Matrix *ms = (transform) ? transform : &GEOM_MATRIX_IDENTITY;
+ const Geom::Affine *md = (item->transform) ? item->transform : &GEOM_MATRIX_IDENTITY;
+ const Geom::Affine *ms = (transform) ? transform : &GEOM_MATRIX_IDENTITY;
if (!Geom::matrix_equalp(*md, *ms, NR_EPSILON)) {
nr_arena_item_request_render (item);
@@ -760,7 +760,7 @@ nr_arena_item_set_transform (NRArenaItem *item, Geom::Matrix const *transform)
item->transform = NULL;
} else {
if (!item->transform)
- item->transform = new (GC::ATOMIC) Geom::Matrix ();
+ item->transform = new (GC::ATOMIC) Geom::Affine ();
*item->transform = *transform;
}
nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
diff --git a/src/display/nr-arena-item.h b/src/display/nr-arena-item.h
index d1b157775..ff9965b85 100644
--- a/src/display/nr-arena-item.h
+++ b/src/display/nr-arena-item.h
@@ -52,7 +52,7 @@
#define NR_ARENA_ITEM_RENDER_NO_CACHE (1 << 0)
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <libnr/nr-rect-l.h>
#include <libnr/nr-pixblock.h>
#include <libnr/nr-object.h>
@@ -64,7 +64,7 @@
struct NRGC {
NRGC(NRGC const *p) : parent(p) {}
NRGC const *parent;
- Geom::Matrix transform;
+ Geom::Affine transform;
};
struct NRArenaItem : public NRObject {
@@ -95,7 +95,7 @@ struct NRArenaItem : public NRObject {
* specified in SVG standard. Required by filters. */
Geom::OptRect item_bbox;
/* Our affine */
- Geom::Matrix *transform;
+ Geom::Affine *transform;
/* Clip item */
NRArenaItem *clip;
/* Mask item */
@@ -109,7 +109,7 @@ struct NRArenaItem : public NRObject {
void *data;
/* Current Transformation Matrix */
- Geom::Matrix ctm;
+ Geom::Affine ctm;
/* These hold background buffer state for filter rendering */
NRPixBlock *background_pb;
@@ -171,8 +171,8 @@ NRArenaItem *nr_arena_item_unparent (NRArenaItem *item);
void nr_arena_item_append_child (NRArenaItem *parent, NRArenaItem *child);
-void nr_arena_item_set_transform(NRArenaItem *item, Geom::Matrix const &transform);
-void nr_arena_item_set_transform(NRArenaItem *item, Geom::Matrix const *transform);
+void nr_arena_item_set_transform(NRArenaItem *item, Geom::Affine const &transform);
+void nr_arena_item_set_transform(NRArenaItem *item, Geom::Affine const *transform);
void nr_arena_item_set_opacity (NRArenaItem *item, double opacity);
void nr_arena_item_set_sensitive (NRArenaItem *item, unsigned int sensitive);
void nr_arena_item_set_visible (NRArenaItem *item, unsigned int visible);
diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp
index 6f38fd97d..1f516c066 100644
--- a/src/display/nr-arena-shape.cpp
+++ b/src/display/nr-arena-shape.cpp
@@ -401,8 +401,8 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
return NR_ARENA_ITEM_STATE_ALL;
}
-int matrix_is_isometry(Geom::Matrix p) {
- Geom::Matrix tp;
+int matrix_is_isometry(Geom::Affine p) {
+ Geom::Affine tp;
// transposition
tp[0]=p[0];
tp[1]=p[2];
@@ -410,7 +410,7 @@ int matrix_is_isometry(Geom::Matrix p) {
tp[3]=p[3];
for (int i = 4; i < 6; i++) // shut valgrind up :)
tp[i] = p[i] = 0;
- Geom::Matrix isom = tp*p; // A^T * A = adjunct?
+ Geom::Affine isom = tp*p; // A^T * A = adjunct?
// Is the adjunct nearly an identity function?
if (isom.isTranslation(0.01)) {
// the transformation is an isometry -> no need to recompute
@@ -453,7 +453,7 @@ nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, NRRectL *area, bool fo
if ((shape->_fill.paint.type() != NRArenaShape::Paint::NONE || force_shape) &&
has_inner_area(shape->curve->get_pathvector()) ) {
- Geom::Matrix cached_to_new = Geom::identity();
+ Geom::Affine cached_to_new = Geom::identity();
int isometry = 0;
if ( shape->cached_fill ) {
if (shape->cached_fctm == gc->transform) {
@@ -472,7 +472,7 @@ nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, NRRectL *area, bool fo
Path* thePath=new Path;
Shape* theShape=new Shape;
{
- Geom::Matrix tempMat(gc->transform);
+ Geom::Affine tempMat(gc->transform);
thePath->LoadPathVector(shape->curve->get_pathvector(), tempMat, true);
}
@@ -562,7 +562,7 @@ nr_arena_shape_update_stroke(NRArenaShape *shape,NRGC* gc, NRRectL *area)
width = style_width;
}
- Geom::Matrix cached_to_new = Geom::identity();
+ Geom::Affine cached_to_new = Geom::identity();
int isometry = 0;
if ( shape->cached_stroke ) {
@@ -586,7 +586,7 @@ nr_arena_shape_update_stroke(NRArenaShape *shape,NRGC* gc, NRRectL *area)
Path* thePath = new Path;
Shape* theShape = new Shape;
{
- Geom::Matrix tempMat( gc->transform );
+ Geom::Affine tempMat( gc->transform );
thePath->LoadPathVector(shape->curve->get_pathvector(), tempMat, true);
}
diff --git a/src/display/nr-arena-shape.h b/src/display/nr-arena-shape.h
index d484615a9..e00993901 100644
--- a/src/display/nr-arena-shape.h
+++ b/src/display/nr-arena-shape.h
@@ -112,7 +112,7 @@ struct NRArenaShape : public NRArenaItem {
SPStyle *style;
NRRect paintbox;
/* State data */
- Geom::Matrix ctm;
+ Geom::Affine ctm;
SPPainter *fill_painter;
SPPainter *stroke_painter;
@@ -135,8 +135,8 @@ struct NRArenaShape : public NRArenaItem {
// polygon to get the *_shp polygon. Otherwise, recompute so this
// works fine for translation and rotation, but not scaling and
// skewing
- Geom::Matrix cached_fctm;
- Geom::Matrix cached_sctm;
+ Geom::Affine cached_fctm;
+ Geom::Affine cached_sctm;
NRRectL cached_farea;
NRRectL cached_sarea;
bool cached_fpartialy;
diff --git a/src/display/nr-filter-colormatrix.cpp b/src/display/nr-filter-colormatrix.cpp
index 7d0792325..54d5dfd69 100644
--- a/src/display/nr-filter-colormatrix.cpp
+++ b/src/display/nr-filter-colormatrix.cpp
@@ -195,7 +195,7 @@ int FilterColorMatrix::render(FilterSlot &slot, FilterUnits const &/*units*/) {
return 0;
}
-void FilterColorMatrix::area_enlarge(NRRectL &/*area*/, Geom::Matrix const &/*trans*/)
+void FilterColorMatrix::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/)
{
}
diff --git a/src/display/nr-filter-colormatrix.h b/src/display/nr-filter-colormatrix.h
index 8507f8a63..7a2395f5d 100644
--- a/src/display/nr-filter-colormatrix.h
+++ b/src/display/nr-filter-colormatrix.h
@@ -35,7 +35,7 @@ public:
virtual ~FilterColorMatrix();
virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
virtual void set_type(FilterColorMatrixType type);
virtual void set_value(gdouble value);
virtual void set_values(std::vector<gdouble> &values);
diff --git a/src/display/nr-filter-component-transfer.cpp b/src/display/nr-filter-component-transfer.cpp
index 2b6f0c722..3fe8cbf4a 100644
--- a/src/display/nr-filter-component-transfer.cpp
+++ b/src/display/nr-filter-component-transfer.cpp
@@ -198,7 +198,7 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units
return 0;
}
-void FilterComponentTransfer::area_enlarge(NRRectL &/*area*/, Geom::Matrix const &/*trans*/)
+void FilterComponentTransfer::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/)
{
}
diff --git a/src/display/nr-filter-component-transfer.h b/src/display/nr-filter-component-transfer.h
index 2fda2692a..65b4d4079 100644
--- a/src/display/nr-filter-component-transfer.h
+++ b/src/display/nr-filter-component-transfer.h
@@ -36,7 +36,7 @@ public:
virtual ~FilterComponentTransfer();
virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
FilterComponentTransferType type[4];
std::vector<gdouble> tableValues[4];
diff --git a/src/display/nr-filter-convolve-matrix.cpp b/src/display/nr-filter-convolve-matrix.cpp
index 4b88aa929..f5cc7175a 100644
--- a/src/display/nr-filter-convolve-matrix.cpp
+++ b/src/display/nr-filter-convolve-matrix.cpp
@@ -246,7 +246,7 @@ void FilterConvolveMatrix::set_preserveAlpha(bool pa){
preserveAlpha = pa;
}
-void FilterConvolveMatrix::area_enlarge(NRRectL &area, Geom::Matrix const &/*trans*/)
+void FilterConvolveMatrix::area_enlarge(NRRectL &area, Geom::Affine const &/*trans*/)
{
//Seems to me that since this filter's operation is resolution dependent,
// some spurious pixels may still appear at the borders when low zooming or rotating. Needs a better fix.
diff --git a/src/display/nr-filter-convolve-matrix.h b/src/display/nr-filter-convolve-matrix.h
index 846ef5685..50d97f1a0 100644
--- a/src/display/nr-filter-convolve-matrix.h
+++ b/src/display/nr-filter-convolve-matrix.h
@@ -35,7 +35,7 @@ public:
virtual ~FilterConvolveMatrix();
virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
virtual FilterTraits get_input_traits();
void set_targetY(int coord);
diff --git a/src/display/nr-filter-diffuselighting.cpp b/src/display/nr-filter-diffuselighting.cpp
index 7443039f6..8e764f6d4 100644
--- a/src/display/nr-filter-diffuselighting.cpp
+++ b/src/display/nr-filter-diffuselighting.cpp
@@ -62,7 +62,7 @@ int FilterDiffuseLighting::render(FilterSlot &slot, FilterUnits const &units) {
int dx = 1; //TODO setup
int dy = 1; //TODO setup
//surface scale
- Geom::Matrix trans = units.get_matrix_primitiveunits2pb();
+ Geom::Affine trans = units.get_matrix_primitiveunits2pb();
gdouble ss = surfaceScale * trans[0];
gdouble kd = diffuseConstant; //diffuse lighting constant
@@ -168,7 +168,7 @@ int FilterDiffuseLighting::render(FilterSlot &slot, FilterUnits const &units) {
return 0;
}
-void FilterDiffuseLighting::area_enlarge(NRRectL &area, Geom::Matrix const &trans)
+void FilterDiffuseLighting::area_enlarge(NRRectL &area, Geom::Affine const &trans)
{
// TODO: support kernelUnitLength
double scalex = std::fabs(trans[0]) + std::fabs(trans[1]);
diff --git a/src/display/nr-filter-diffuselighting.h b/src/display/nr-filter-diffuselighting.h
index 5141d0b61..8dc7a1818 100644
--- a/src/display/nr-filter-diffuselighting.h
+++ b/src/display/nr-filter-diffuselighting.h
@@ -42,7 +42,7 @@ public:
static FilterPrimitive *create();
virtual ~FilterDiffuseLighting();
virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
virtual FilterTraits get_input_traits();
private:
diff --git a/src/display/nr-filter-displacement-map.cpp b/src/display/nr-filter-displacement-map.cpp
index 863927f4b..d71a691ef 100644
--- a/src/display/nr-filter-displacement-map.cpp
+++ b/src/display/nr-filter-displacement-map.cpp
@@ -190,7 +190,7 @@ int FilterDisplacementMap::render(FilterSlot &slot, FilterUnits const &units) {
bool map_premultiplied = (map->mode == NR_PIXBLOCK_MODE_R8G8B8A8P);
bool data_premultiplied = (out->mode == NR_PIXBLOCK_MODE_R8G8B8A8P);
- Geom::Matrix trans = units.get_matrix_primitiveunits2pb();
+ Geom::Affine trans = units.get_matrix_primitiveunits2pb();
double scalex = scale * trans.expansionX();
double scaley = scale * trans.expansionY();
@@ -237,7 +237,7 @@ void FilterDisplacementMap::set_channel_selector(int s, FilterDisplacementMapCha
if (s == 1) Ychannel = channel;
}
-void FilterDisplacementMap::area_enlarge(NRRectL &area, Geom::Matrix const &trans)
+void FilterDisplacementMap::area_enlarge(NRRectL &area, Geom::Affine const &trans)
{
//I assume scale is in user coordinates (?!?)
//FIXME: trans should be multiplied by some primitiveunits2user, shouldn't it?
diff --git a/src/display/nr-filter-displacement-map.h b/src/display/nr-filter-displacement-map.h
index e76e47fec..1dad1873a 100644
--- a/src/display/nr-filter-displacement-map.h
+++ b/src/display/nr-filter-displacement-map.h
@@ -32,7 +32,7 @@ public:
virtual void set_scale(double s);
virtual void set_channel_selector(int s, FilterDisplacementMapChannelSelector channel);
virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
virtual FilterTraits get_input_traits();
private:
diff --git a/src/display/nr-filter-flood.cpp b/src/display/nr-filter-flood.cpp
index 3f4951dd6..ca073cfd8 100644
--- a/src/display/nr-filter-flood.cpp
+++ b/src/display/nr-filter-flood.cpp
@@ -87,7 +87,7 @@ void FilterFlood::set_icc(SVGICCColor *icc_color) {
icc = icc_color;
}
-void FilterFlood::area_enlarge(NRRectL &/*area*/, Geom::Matrix const &/*trans*/)
+void FilterFlood::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/)
{
}
diff --git a/src/display/nr-filter-flood.h b/src/display/nr-filter-flood.h
index b11fa117d..ebb7d4506 100644
--- a/src/display/nr-filter-flood.h
+++ b/src/display/nr-filter-flood.h
@@ -30,7 +30,7 @@ public:
virtual void set_color(guint32 c);
virtual void set_icc(SVGICCColor *icc_color);
virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
private:
double opacity;
guint32 color;
diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp
index 5cfaab54d..3f7bea35d 100644
--- a/src/display/nr-filter-gaussian.cpp
+++ b/src/display/nr-filter-gaussian.cpp
@@ -33,7 +33,7 @@
#include "display/nr-filter-units.h"
#include "libnr/nr-blit.h"
#include "libnr/nr-pixblock.h"
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include "util/fixed_point.h"
#include "preferences.h"
@@ -582,7 +582,7 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units)
nr_blit_pixblock_pixblock(in, original_in);
}
- Geom::Matrix trans = units.get_matrix_primitiveunits2pb();
+ Geom::Affine trans = units.get_matrix_primitiveunits2pb();
// Some common constants
int const width_org = in->area.x1-in->area.x0, height_org = in->area.y1-in->area.y0;
@@ -847,7 +847,7 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units)
return 0;
}
-void FilterGaussian::area_enlarge(NRRectL &area, Geom::Matrix const &trans)
+void FilterGaussian::area_enlarge(NRRectL &area, Geom::Affine const &trans)
{
int area_x = _effect_area_scr(_deviation_x * trans.expansionX());
int area_y = _effect_area_scr(_deviation_y * trans.expansionY());
diff --git a/src/display/nr-filter-gaussian.h b/src/display/nr-filter-gaussian.h
index 1dcb07d67..87d74ac63 100644
--- a/src/display/nr-filter-gaussian.h
+++ b/src/display/nr-filter-gaussian.h
@@ -39,7 +39,7 @@ public:
virtual ~FilterGaussian();
virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Matrix const &m);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &m);
virtual FilterTraits get_input_traits();
/**
diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp
index 9a39168c2..cc6dc18fa 100644
--- a/src/display/nr-filter-image.cpp
+++ b/src/display/nr-filter-image.cpp
@@ -85,7 +85,7 @@ int FilterImage::render(FilterSlot &slot, FilterUnits const &units) {
NRGC gc(NULL);
/* Update to renderable state */
double sf = 1.0;
- Geom::Matrix t(Geom::Scale(sf, sf));
+ Geom::Affine t(Geom::Scale(sf, sf));
nr_arena_item_set_transform(ai, &t);
gc.transform.setIdentity();
nr_arena_item_invoke_update( ai, NULL, &gc,
@@ -166,7 +166,7 @@ int FilterImage::render(FilterSlot &slot, FilterUnits const &units) {
// Get the object bounding box. Image is placed with respect to box.
// Array values: 0: width; 3: height; 4: -x; 5: -y.
- Geom::Matrix object_bbox = units.get_matrix_user2filterunits().inverse();
+ Geom::Affine object_bbox = units.get_matrix_user2filterunits().inverse();
// feImage is suppose to use the same parameters as a normal SVG image.
// If a width or height is set to zero, the image is not suppose to be displayed.
@@ -181,8 +181,8 @@ int FilterImage::render(FilterSlot &slot, FilterUnits const &units) {
int coordx,coordy;
unsigned char *out_data = NR_PIXBLOCK_PX(out);
- Geom::Matrix unit_trans = units.get_matrix_primitiveunits2pb().inverse();
- Geom::Matrix d2s = Geom::Translate(x0, y0) * unit_trans * Geom::Translate(object_bbox[4]-feImageX, object_bbox[5]-feImageY) * Geom::Scale(scaleX, scaleY);
+ Geom::Affine unit_trans = units.get_matrix_primitiveunits2pb().inverse();
+ Geom::Affine d2s = Geom::Translate(x0, y0) * unit_trans * Geom::Translate(object_bbox[4]-feImageX, object_bbox[5]-feImageY) * Geom::Scale(scaleX, scaleY);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int nr_arena_image_x_sample = prefs->getInt("/options/bitmapoversample/value", 1);
diff --git a/src/display/nr-filter-morphology.cpp b/src/display/nr-filter-morphology.cpp
index 6902bacc6..ceb2a2b9d 100644
--- a/src/display/nr-filter-morphology.cpp
+++ b/src/display/nr-filter-morphology.cpp
@@ -51,7 +51,7 @@ int FilterMorphology::render(FilterSlot &slot, FilterUnits const &units) {
free_in_on_exit = true;
}
- Geom::Matrix p2pb = units.get_matrix_primitiveunits2pb();
+ Geom::Affine p2pb = units.get_matrix_primitiveunits2pb();
int const xradius = (int)round(this->xradius * p2pb.expansionX());
int const yradius = (int)round(this->yradius * p2pb.expansionY());
@@ -112,7 +112,7 @@ int FilterMorphology::render(FilterSlot &slot, FilterUnits const &units) {
return 0;
}
-void FilterMorphology::area_enlarge(NRRectL &area, Geom::Matrix const &trans)
+void FilterMorphology::area_enlarge(NRRectL &area, Geom::Affine const &trans)
{
int const enlarge_x = (int)std::ceil(this->xradius * (std::fabs(trans[0]) + std::fabs(trans[1])));
int const enlarge_y = (int)std::ceil(this->yradius * (std::fabs(trans[2]) + std::fabs(trans[3])));
diff --git a/src/display/nr-filter-morphology.h b/src/display/nr-filter-morphology.h
index 867a6a391..c8d8b2f50 100644
--- a/src/display/nr-filter-morphology.h
+++ b/src/display/nr-filter-morphology.h
@@ -32,7 +32,7 @@ public:
virtual ~FilterMorphology();
virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
virtual FilterTraits get_input_traits();
void set_operator(FilterMorphologyOperator &o);
void set_xradius(double x);
diff --git a/src/display/nr-filter-offset.cpp b/src/display/nr-filter-offset.cpp
index bee73c998..7c924b7b7 100644
--- a/src/display/nr-filter-offset.cpp
+++ b/src/display/nr-filter-offset.cpp
@@ -43,7 +43,7 @@ int FilterOffset::render(FilterSlot &slot, FilterUnits const &units) {
NRPixBlock *out = new NRPixBlock;
- Geom::Matrix trans = units.get_matrix_primitiveunits2pb();
+ Geom::Affine trans = units.get_matrix_primitiveunits2pb();
Geom::Point offset(dx, dy);
offset *= trans;
offset[X] -= trans[4];
@@ -74,7 +74,7 @@ void FilterOffset::set_dy(double amount) {
dy = amount;
}
-void FilterOffset::area_enlarge(NRRectL &area, Geom::Matrix const &trans)
+void FilterOffset::area_enlarge(NRRectL &area, Geom::Affine const &trans)
{
Geom::Point offset(dx, dy);
offset *= trans;
diff --git a/src/display/nr-filter-offset.h b/src/display/nr-filter-offset.h
index 7c2b33742..a78450e17 100644
--- a/src/display/nr-filter-offset.h
+++ b/src/display/nr-filter-offset.h
@@ -27,7 +27,7 @@ public:
virtual ~FilterOffset();
virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
void set_dx(double amount);
void set_dy(double amount);
diff --git a/src/display/nr-filter-primitive.cpp b/src/display/nr-filter-primitive.cpp
index f79af8bd8..f53ff4a7f 100644
--- a/src/display/nr-filter-primitive.cpp
+++ b/src/display/nr-filter-primitive.cpp
@@ -37,7 +37,7 @@ FilterPrimitive::~FilterPrimitive()
// Nothing to do here
}
-void FilterPrimitive::area_enlarge(NRRectL &/*area*/, Geom::Matrix const &/*m*/)
+void FilterPrimitive::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*m*/)
{
// This doesn't need to do anything by default
}
diff --git a/src/display/nr-filter-primitive.h b/src/display/nr-filter-primitive.h
index 87fe21f31..7639a9d1d 100644
--- a/src/display/nr-filter-primitive.h
+++ b/src/display/nr-filter-primitive.h
@@ -44,7 +44,7 @@ public:
virtual ~FilterPrimitive();
virtual int render(FilterSlot &slot, FilterUnits const &units) = 0;
- virtual void area_enlarge(NRRectL &area, Geom::Matrix const &m);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &m);
/**
* Sets the input slot number 'slot' to be used as input in rendering
diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp
index 96e2a92e9..b019b194f 100644
--- a/src/display/nr-filter-slot.cpp
+++ b/src/display/nr-filter-slot.cpp
@@ -151,7 +151,7 @@ NRPixBlock *FilterSlot::get(int slot_nr)
void FilterSlot::get_final(int slot_nr, NRPixBlock *result) {
NRPixBlock *final_usr = get(slot_nr);
- Geom::Matrix trans = units.get_matrix_pb2display();
+ Geom::Affine trans = units.get_matrix_pb2display();
int size = (result->area.x1 - result->area.x0)
* (result->area.y1 - result->area.y0)
@@ -188,7 +188,7 @@ void FilterSlot::set(int slot_nr, NRPixBlock *pb, bool takeOwnership)
assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slots[index].number == slot_nr);
if (slot_nr == NR_FILTER_SOURCEGRAPHIC || slot_nr == NR_FILTER_BACKGROUNDIMAGE) {
- Geom::Matrix trans = units.get_matrix_display2pb();
+ Geom::Affine trans = units.get_matrix_display2pb();
if (fabs(trans[1]) > 1e-6 || fabs(trans[2]) > 1e-6) {
NRPixBlock *trans_pb = new NRPixBlock;
int x0 = pb->area.x0;
diff --git a/src/display/nr-filter-specularlighting.cpp b/src/display/nr-filter-specularlighting.cpp
index 354695dd7..8ecee24e6 100644
--- a/src/display/nr-filter-specularlighting.cpp
+++ b/src/display/nr-filter-specularlighting.cpp
@@ -80,7 +80,7 @@ int FilterSpecularLighting::render(FilterSlot &slot, FilterUnits const &units) {
int dx = 1; //TODO setup
int dy = 1; //TODO setup
//surface scale
- Geom::Matrix trans = units.get_matrix_primitiveunits2pb();
+ Geom::Affine trans = units.get_matrix_primitiveunits2pb();
gdouble ss = surfaceScale * trans[0];
gdouble ks = specularConstant; //diffuse lighting constant
NR::Fvector L, N, LC, H;
@@ -188,7 +188,7 @@ int FilterSpecularLighting::render(FilterSlot &slot, FilterUnits const &units) {
return 0;
}
-void FilterSpecularLighting::area_enlarge(NRRectL &area, Geom::Matrix const &trans)
+void FilterSpecularLighting::area_enlarge(NRRectL &area, Geom::Affine const &trans)
{
// TODO: support kernelUnitLength
double scalex = std::fabs(trans[0]) + std::fabs(trans[1]);
diff --git a/src/display/nr-filter-specularlighting.h b/src/display/nr-filter-specularlighting.h
index 5d31b09f1..a5d29588a 100644
--- a/src/display/nr-filter-specularlighting.h
+++ b/src/display/nr-filter-specularlighting.h
@@ -43,7 +43,7 @@ public:
static FilterPrimitive *create();
virtual ~FilterSpecularLighting();
virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
virtual FilterTraits get_input_traits();
private:
diff --git a/src/display/nr-filter-tile.cpp b/src/display/nr-filter-tile.cpp
index 8eca6b18f..b1ca5d191 100644
--- a/src/display/nr-filter-tile.cpp
+++ b/src/display/nr-filter-tile.cpp
@@ -53,7 +53,7 @@ int FilterTile::render(FilterSlot &slot, FilterUnits const &/*units*/) {
return 0;
}
-void FilterTile::area_enlarge(NRRectL &/*area*/, Geom::Matrix const &/*trans*/)
+void FilterTile::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/)
{
}
diff --git a/src/display/nr-filter-tile.h b/src/display/nr-filter-tile.h
index 505fb9948..4a2a0dddc 100644
--- a/src/display/nr-filter-tile.h
+++ b/src/display/nr-filter-tile.h
@@ -27,7 +27,7 @@ public:
virtual ~FilterTile();
virtual int render(FilterSlot &slot, FilterUnits const &units);
- virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans);
+ virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans);
virtual FilterTraits get_input_traits();
};
diff --git a/src/display/nr-filter-turbulence.cpp b/src/display/nr-filter-turbulence.cpp
index dde92c0a5..a91de0460 100644
--- a/src/display/nr-filter-turbulence.cpp
+++ b/src/display/nr-filter-turbulence.cpp
@@ -87,7 +87,7 @@ void FilterTurbulence::render_area(NRPixBlock *pix, NR::IRect &full_area, Filter
const int bbox_x1 = full_area.max()[NR::X];
const int bbox_y1 = full_area.max()[NR::Y];
- Geom::Matrix unit_trans = units.get_matrix_primitiveunits2pb().inverse();
+ Geom::Affine unit_trans = units.get_matrix_primitiveunits2pb().inverse();
double point[2];
diff --git a/src/display/nr-filter-units.cpp b/src/display/nr-filter-units.cpp
index 4cf165800..b1c475c41 100644
--- a/src/display/nr-filter-units.cpp
+++ b/src/display/nr-filter-units.cpp
@@ -35,7 +35,7 @@ FilterUnits::FilterUnits(SPFilterUnits const filterUnits, SPFilterUnits const pr
paraller_axis(false), automatic_resolution(true)
{}
-void FilterUnits::set_ctm(Geom::Matrix const &ctm) {
+void FilterUnits::set_ctm(Geom::Affine const &ctm) {
this->ctm = ctm;
}
@@ -63,12 +63,12 @@ void FilterUnits::set_automatic_resolution(bool const automatic) {
automatic_resolution = automatic;
}
-Geom::Matrix FilterUnits::get_matrix_user2pb() const {
+Geom::Affine FilterUnits::get_matrix_user2pb() const {
g_assert(resolution_x > 0);
g_assert(resolution_y > 0);
g_assert(filter_area);
- Geom::Matrix u2pb = ctm;
+ Geom::Affine u2pb = ctm;
if (paraller_axis || !automatic_resolution) {
u2pb[0] = resolution_x / (filter_area->max()[X] - filter_area->min()[X]);
@@ -82,9 +82,9 @@ Geom::Matrix FilterUnits::get_matrix_user2pb() const {
return u2pb;
}
-Geom::Matrix FilterUnits::get_matrix_units2pb(SPFilterUnits units) const {
+Geom::Affine FilterUnits::get_matrix_units2pb(SPFilterUnits units) const {
if ( item_bbox && (units == SP_FILTER_UNITS_OBJECTBOUNDINGBOX) ) {
- Geom::Matrix u2pb = get_matrix_user2pb();
+ Geom::Affine u2pb = get_matrix_user2pb();
Geom::Point origo(item_bbox->min());
origo *= u2pb;
Geom::Point i_end(item_bbox->max()[X], item_bbox->min()[Y]);
@@ -106,31 +106,31 @@ Geom::Matrix FilterUnits::get_matrix_units2pb(SPFilterUnits units) const {
return get_matrix_user2pb();
} else {
g_warning("Error in Inkscape::Filters::FilterUnits::get_matrix_units2pb: unrecognized unit type (%d)", units);
- return Geom::Matrix();
+ return Geom::Affine();
}
}
-Geom::Matrix FilterUnits::get_matrix_filterunits2pb() const {
+Geom::Affine FilterUnits::get_matrix_filterunits2pb() const {
return get_matrix_units2pb(filterUnits);
}
-Geom::Matrix FilterUnits::get_matrix_primitiveunits2pb() const {
+Geom::Affine FilterUnits::get_matrix_primitiveunits2pb() const {
return get_matrix_units2pb(primitiveUnits);
}
-Geom::Matrix FilterUnits::get_matrix_display2pb() const {
- Geom::Matrix d2pb = ctm.inverse();
+Geom::Affine FilterUnits::get_matrix_display2pb() const {
+ Geom::Affine d2pb = ctm.inverse();
d2pb *= get_matrix_user2pb();
return d2pb;
}
-Geom::Matrix FilterUnits::get_matrix_pb2display() const {
- Geom::Matrix pb2d = get_matrix_user2pb().inverse();
+Geom::Affine FilterUnits::get_matrix_pb2display() const {
+ Geom::Affine pb2d = get_matrix_user2pb().inverse();
pb2d *= ctm;
return pb2d;
}
-Geom::Matrix FilterUnits::get_matrix_user2units(SPFilterUnits units) const {
+Geom::Affine FilterUnits::get_matrix_user2units(SPFilterUnits units) const {
if (item_bbox && units == SP_FILTER_UNITS_OBJECTBOUNDINGBOX) {
/* No need to worry about rotations: bounding box coordinates
* always have base vectors paraller with userspace coordinates */
@@ -139,22 +139,22 @@ Geom::Matrix FilterUnits::get_matrix_user2units(SPFilterUnits units) const {
double scale_x = 1.0 / (max[X] - min[X]);
double scale_y = 1.0 / (max[Y] - min[Y]);
//return Geom::Translate(min) * Geom::Scale(scale_x,scale_y); ?
- return Geom::Matrix(scale_x, 0,
+ return Geom::Affine(scale_x, 0,
0, scale_y,
min[X] * scale_x, min[Y] * scale_y);
} else if (units == SP_FILTER_UNITS_USERSPACEONUSE) {
return Geom::identity();
} else {
g_warning("Error in Inkscape::Filters::FilterUnits::get_matrix_user2units: unrecognized unit type (%d)", units);
- return Geom::Matrix();
+ return Geom::Affine();
}
}
-Geom::Matrix FilterUnits::get_matrix_user2filterunits() const {
+Geom::Affine FilterUnits::get_matrix_user2filterunits() const {
return get_matrix_user2units(filterUnits);
}
-Geom::Matrix FilterUnits::get_matrix_user2primitiveunits() const {
+Geom::Affine FilterUnits::get_matrix_user2primitiveunits() const {
return get_matrix_user2units(primitiveUnits);
}
@@ -162,7 +162,7 @@ NR::IRect FilterUnits::get_pixblock_filterarea_paraller() const {
g_assert(filter_area);
int min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN;
- Geom::Matrix u2pb = get_matrix_user2pb();
+ Geom::Affine u2pb = get_matrix_user2pb();
for (int i = 0 ; i < 4 ; i++) {
Geom::Point p = filter_area->corner(i);
diff --git a/src/display/nr-filter-units.h b/src/display/nr-filter-units.h
index 2a64b1afc..9a0d8ea83 100644
--- a/src/display/nr-filter-units.h
+++ b/src/display/nr-filter-units.h
@@ -16,7 +16,7 @@
#include "libnr/nr-matrix.h"
#include "libnr/nr-rect.h"
#include "libnr/nr-rect-l.h"
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <2geom/rect.h>
namespace Inkscape {
@@ -31,7 +31,7 @@ public:
* Sets the current transformation matrix, i.e. transformation matrix
* from object's user coordinates to screen coordinates
*/
- void set_ctm(Geom::Matrix const &ctm);
+ void set_ctm(Geom::Affine const &ctm);
/**
* Sets the resolution, the filter should be rendered with.
@@ -64,39 +64,39 @@ public:
/**
* Gets the user coordinates to pixblock coordinates transformation matrix.
*/
- Geom::Matrix get_matrix_user2pb() const;
+ Geom::Affine get_matrix_user2pb() const;
/**
* Gets the filterUnits to pixblock coordinates transformation matrix.
*/
- Geom::Matrix get_matrix_filterunits2pb() const;
+ Geom::Affine get_matrix_filterunits2pb() const;
/**
* Gets the primitiveUnits to pixblock coordinates transformation matrix.
*/
- Geom::Matrix get_matrix_primitiveunits2pb() const;
+ Geom::Affine get_matrix_primitiveunits2pb() const;
/**
* Gets the display coordinates to pixblock coordinates transformation
* matrix.
*/
- Geom::Matrix get_matrix_display2pb() const;
+ Geom::Affine get_matrix_display2pb() const;
/**
* Gets the pixblock coordinates to display coordinates transformation
* matrix
*/
- Geom::Matrix get_matrix_pb2display() const;
+ Geom::Affine get_matrix_pb2display() const;
/**
* Gets the user coordinates to filterUnits transformation matrix.
*/
- Geom::Matrix get_matrix_user2filterunits() const;
+ Geom::Affine get_matrix_user2filterunits() const;
/**
* Gets the user coordinates to primitiveUnits transformation matrix.
*/
- Geom::Matrix get_matrix_user2primitiveunits() const;
+ Geom::Affine get_matrix_user2primitiveunits() const;
/**
* Returns the filter area in pixblock coordinates.
@@ -108,14 +108,14 @@ public:
FilterUnits& operator=(FilterUnits const &other);
private:
- Geom::Matrix get_matrix_units2pb(SPFilterUnits units) const;
- Geom::Matrix get_matrix_user2units(SPFilterUnits units) const;
+ Geom::Affine get_matrix_units2pb(SPFilterUnits units) const;
+ Geom::Affine get_matrix_user2units(SPFilterUnits units) const;
SPFilterUnits filterUnits, primitiveUnits;
double resolution_x, resolution_y;
bool paraller_axis;
bool automatic_resolution;
- Geom::Matrix ctm;
+ Geom::Affine ctm;
Geom::OptRect item_bbox;
Geom::OptRect filter_area;
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index 5ff9d2da5..ea9b4f7da 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -43,7 +43,7 @@
#include "display/nr-arena-item.h"
#include "libnr/nr-pixblock.h"
#include "libnr/nr-blit.h"
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <2geom/rect.h>
#include "svg/svg-length.h"
#include "sp-filter-units.h"
@@ -139,7 +139,7 @@ int Filter::render(NRArenaItem const *item, NRPixBlock *pb)
FilterQuality const filterquality = (FilterQuality)item->arena->filterquality;
int const blurquality = item->arena->blurquality;
- Geom::Matrix trans = item->ctm;
+ Geom::Affine trans = item->ctm;
FilterSlot slot(_slot_count, item);
slot.set_quality(filterquality);
slot.set_blurquality(blurquality);
@@ -508,7 +508,7 @@ int Filter::_resolution_limit(FilterQuality const quality) const {
}
std::pair<double,double> Filter::_filter_resolution(
- Geom::Rect const &area, Geom::Matrix const &trans,
+ Geom::Rect const &area, Geom::Affine const &trans,
FilterQuality const filterquality) const
{
std::pair<double,double> resolution;
diff --git a/src/display/nr-filter.h b/src/display/nr-filter.h
index a7cf932b1..23acea99f 100644
--- a/src/display/nr-filter.h
+++ b/src/display/nr-filter.h
@@ -201,7 +201,7 @@ private:
void _common_init();
int _resolution_limit(FilterQuality const quality) const;
std::pair<double,double> _filter_resolution(Geom::Rect const &area,
- Geom::Matrix const &trans,
+ Geom::Affine const &trans,
FilterQuality const q) const;
};
diff --git a/src/display/nr-light.cpp b/src/display/nr-light.cpp
index a8a31734d..74d83da70 100644
--- a/src/display/nr-light.cpp
+++ b/src/display/nr-light.cpp
@@ -43,7 +43,7 @@ void DistantLight::light_components(NR::Fvector &lc) {
lc[LIGHT_BLUE] = NR_RGBA32_B(color);
}
-PointLight::PointLight(SPFePointLight *light, guint32 lighting_color, const Geom::Matrix &trans) {
+PointLight::PointLight(SPFePointLight *light, guint32 lighting_color, const Geom::Affine &trans) {
color = lighting_color;
l_x = light->x;
l_y = light->y;
@@ -66,7 +66,7 @@ void PointLight::light_components(NR::Fvector &lc) {
lc[LIGHT_BLUE] = NR_RGBA32_B(color);
}
-SpotLight::SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Geom::Matrix &trans) {
+SpotLight::SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Geom::Affine &trans) {
gdouble p_x, p_y, p_z;
color = lighting_color;
l_x = light->x;
diff --git a/src/display/nr-light.h b/src/display/nr-light.h
index 65c341a7e..49130cc4e 100644
--- a/src/display/nr-light.h
+++ b/src/display/nr-light.h
@@ -68,7 +68,7 @@ class PointLight {
* employed in the sp light object) and current coordinate (those
* employed in the rendering)
*/
- PointLight(SPFePointLight *light, guint32 lighting_color, const Geom::Matrix &trans);
+ PointLight(SPFePointLight *light, guint32 lighting_color, const Geom::Affine &trans);
virtual ~PointLight();
/**
* Computes the light vector of the distant light at point (x,y,z).
@@ -108,7 +108,7 @@ class SpotLight {
* employed in the sp light object) and current coordinate (those
* employed in the rendering)
*/
- SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Geom::Matrix &trans);
+ SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Geom::Affine &trans);
virtual ~SpotLight();
/**
diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp
index 2b724246a..62d52b04b 100644
--- a/src/display/nr-svgfonts.cpp
+++ b/src/display/nr-svgfonts.cpp
@@ -253,7 +253,7 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t */*scaled_font*/,
// Geom::Scale s(1.0/((SPFont*) node->parent)->horiz_adv_x);
Geom::Scale s(1.0/1000);//TODO: use here the units-per-em attribute?
//This matrix flips the glyph vertically
- Geom::Matrix m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0));
+ Geom::Affine m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0));
//then we offset it
// pathv += Geom::Point(Geom::Coord(0),Geom::Coord(-((SPFont*) node->parent)->horiz_adv_x));
pathv += Geom::Point(Geom::Coord(0),Geom::Coord(-1000));//TODO: use here the units-per-em attribute?
diff --git a/src/display/pixblock-scaler.cpp b/src/display/pixblock-scaler.cpp
index c9df0c833..5af5230d8 100644
--- a/src/display/pixblock-scaler.cpp
+++ b/src/display/pixblock-scaler.cpp
@@ -70,7 +70,7 @@ inline static void _check_index(NRPixBlock const * const pb, int const location,
}
static void scale_bicubic_rgba(NRPixBlock *to, NRPixBlock *from,
- Geom::Matrix const &trans)
+ Geom::Affine const &trans)
{
if (NR_PIXBLOCK_BPP(from) != 4 || NR_PIXBLOCK_BPP(to) != 4) {
g_warning("A non-32-bpp image passed to scale_bicubic_rgba: scaling aborted.");
@@ -203,7 +203,7 @@ static void scale_bicubic_rgba(NRPixBlock *to, NRPixBlock *from,
}
void scale_bicubic_alpha(NRPixBlock *to, NRPixBlock *from,
- Geom::Matrix const &trans)
+ Geom::Affine const &trans)
{
if (NR_PIXBLOCK_BPP(from) != 1 || NR_PIXBLOCK_BPP(to) != 1) {
g_warning("A non-8-bpp image passed to scale_bicubic_alpha: scaling aborted.");
@@ -275,7 +275,7 @@ void scale_bicubic_alpha(NRPixBlock *to, NRPixBlock *from,
}
}
-void scale_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans)
+void scale_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans)
{
if (NR_PIXBLOCK_BPP(to) == 4 && NR_PIXBLOCK_BPP(from) == 4) {
scale_bicubic_rgba(to, from, trans);
diff --git a/src/display/pixblock-scaler.h b/src/display/pixblock-scaler.h
index f7cbcb0be..ff9613ab8 100644
--- a/src/display/pixblock-scaler.h
+++ b/src/display/pixblock-scaler.h
@@ -23,7 +23,7 @@ namespace NR {
* Source pixblock is not modified in process.
* Only works for 32-bpp images.
*/
-void scale_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans);
+void scale_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans);
} /* namespace NR */
diff --git a/src/display/pixblock-transform.cpp b/src/display/pixblock-transform.cpp
index 78324434a..5d5b8a9cf 100644
--- a/src/display/pixblock-transform.cpp
+++ b/src/display/pixblock-transform.cpp
@@ -23,7 +23,7 @@ using std::floor;
#include "libnr/nr-blit.h"
#include "libnr/nr-pixblock.h"
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
namespace NR {
@@ -48,7 +48,7 @@ inline void _check_index(NRPixBlock const * const pb, int const location, int co
}
}
-void transform_nearest(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans)
+void transform_nearest(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans)
{
if (NR_PIXBLOCK_BPP(from) != 4 || NR_PIXBLOCK_BPP(to) != 4) {
g_warning("A non-32-bpp image passed to transform_nearest: scaling aborted.");
@@ -70,7 +70,7 @@ void transform_nearest(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &tra
int to_width = to->area.x1 - to->area.x0;
int to_height = to->area.y1 - to->area.y0;
- Geom::Matrix itrans = trans.inverse();
+ Geom::Affine itrans = trans.inverse();
// Loop through every pixel of destination image, a line at a time
for (int to_y = 0 ; to_y < to_height ; to_y++) {
@@ -133,7 +133,7 @@ inline static double sample(double const a, double const b,
return sum;
}
-void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans)
+void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans)
{
if (NR_PIXBLOCK_BPP(from) != 4 || NR_PIXBLOCK_BPP(to) != 4) {
g_warning("A non-32-bpp image passed to transform_bicubic: scaling aborted.");
@@ -160,7 +160,7 @@ void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &tra
int to_width = to->area.x1 - to->area.x0;
int to_height = to->area.y1 - to->area.y0;
- Geom::Matrix itrans = trans.inverse();
+ Geom::Affine itrans = trans.inverse();
// Loop through every pixel of destination image, a line at a time
for (int to_y = 0 ; to_y < to_height ; to_y++) {
diff --git a/src/display/pixblock-transform.h b/src/display/pixblock-transform.h
index 6c322835c..b73435fdf 100644
--- a/src/display/pixblock-transform.h
+++ b/src/display/pixblock-transform.h
@@ -17,8 +17,8 @@
namespace NR {
-void transform_nearest(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans);
-void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans);
+void transform_nearest(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans);
+void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans);
} /* namespace NR */
diff --git a/src/display/sodipodi-ctrl.cpp b/src/display/sodipodi-ctrl.cpp
index a63f570cf..202fc206e 100644
--- a/src/display/sodipodi-ctrl.cpp
+++ b/src/display/sodipodi-ctrl.cpp
@@ -32,7 +32,7 @@ static void sp_ctrl_init (SPCtrl *ctrl);
static void sp_ctrl_destroy (GtkObject *object);
static void sp_ctrl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);
-static void sp_ctrl_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+static void sp_ctrl_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf);
static double sp_ctrl_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
@@ -210,7 +210,7 @@ sp_ctrl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
}
static void
-sp_ctrl_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags)
+sp_ctrl_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
{
SPCtrl *ctrl;
gint x, y;
@@ -552,7 +552,7 @@ sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf)
void SPCtrl::moveto (Geom::Point const p) {
if (p != _point) {
- sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (this), Geom::Matrix(Geom::Translate (p)));
+ sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (this), Geom::Affine(Geom::Translate (p)));
_moved = true;
}
_point = p;
diff --git a/src/display/sodipodi-ctrlrect.cpp b/src/display/sodipodi-ctrlrect.cpp
index 6d9c40858..380039798 100644
--- a/src/display/sodipodi-ctrlrect.cpp
+++ b/src/display/sodipodi-ctrlrect.cpp
@@ -30,7 +30,7 @@ static void sp_ctrlrect_class_init(SPCtrlRectClass *c);
static void sp_ctrlrect_init(CtrlRect *ctrlrect);
static void sp_ctrlrect_destroy(GtkObject *object);
-static void sp_ctrlrect_update(SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+static void sp_ctrlrect_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_ctrlrect_render(SPCanvasItem *item, SPCanvasBuf *buf);
static SPCanvasItemClass *parent_class;
@@ -160,7 +160,7 @@ static void sp_ctrlrect_render(SPCanvasItem *item, SPCanvasBuf *buf)
}
-static void sp_ctrlrect_update(SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags)
+static void sp_ctrlrect_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
{
SP_CTRLRECT(item)->update(affine, flags);
}
@@ -220,7 +220,7 @@ void CtrlRect::render(SPCanvasBuf *buf)
}
-void CtrlRect::update(Geom::Matrix const &affine, unsigned int flags)
+void CtrlRect::update(Geom::Affine const &affine, unsigned int flags)
{
if (((SPCanvasItemClass *) parent_class)->update) {
((SPCanvasItemClass *) parent_class)->update(this, affine, flags);
diff --git a/src/display/sodipodi-ctrlrect.h b/src/display/sodipodi-ctrlrect.h
index 9ecba47c8..2ba73a4c9 100644
--- a/src/display/sodipodi-ctrlrect.h
+++ b/src/display/sodipodi-ctrlrect.h
@@ -39,7 +39,7 @@ public:
void setDashed(bool d);
void render(SPCanvasBuf *buf);
- void update(Geom::Matrix const &affine, unsigned int flags);
+ void update(Geom::Affine const &affine, unsigned int flags);
private:
void _requestUpdate();
diff --git a/src/display/sp-canvas-item.h b/src/display/sp-canvas-item.h
index 1ae2ff2d1..cc0bdfc77 100644
--- a/src/display/sp-canvas-item.h
+++ b/src/display/sp-canvas-item.h
@@ -52,14 +52,14 @@ struct SPCanvasItem : public GtkObject {
double x1, y1, x2, y2;
Geom::Rect bounds;
- Geom::Matrix xform;
+ Geom::Affine xform;
};
/**
* The vtable of an SPCanvasItem.
*/
struct _SPCanvasItemClass : public GtkObjectClass {
- void (* update) (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+ void (* update) (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
void (* render) (SPCanvasItem *item, SPCanvasBuf *buf);
double (* point) (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
@@ -74,7 +74,7 @@ G_END_DECLS
#define sp_canvas_item_set gtk_object_set
-void sp_canvas_item_affine_absolute(SPCanvasItem *item, Geom::Matrix const &aff);
+void sp_canvas_item_affine_absolute(SPCanvasItem *item, Geom::Affine const &aff);
void sp_canvas_item_raise(SPCanvasItem *item, int positions);
void sp_canvas_item_lower(SPCanvasItem *item, int positions);
@@ -84,7 +84,7 @@ void sp_canvas_item_hide(SPCanvasItem *item);
int sp_canvas_item_grab(SPCanvasItem *item, unsigned int event_mask, GdkCursor *cursor, guint32 etime);
void sp_canvas_item_ungrab(SPCanvasItem *item, guint32 etime);
-Geom::Matrix sp_canvas_item_i2w_affine(SPCanvasItem const *item);
+Geom::Affine sp_canvas_item_i2w_affine(SPCanvasItem const *item);
void sp_canvas_item_grab_focus(SPCanvasItem *item);
diff --git a/src/display/sp-canvas-util.cpp b/src/display/sp-canvas-util.cpp
index af80eed44..7eac32e2d 100644
--- a/src/display/sp-canvas-util.cpp
+++ b/src/display/sp-canvas-util.cpp
@@ -14,7 +14,7 @@
#include <string.h> // for memset
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include "libnr/nr-pixops.h"
#include "sp-canvas-item.h"
#include "sp-canvas-util.h"
@@ -77,7 +77,7 @@ sp_canvas_clear_buffer (SPCanvasBuf *buf)
}
}
-Geom::Matrix sp_canvas_item_i2p_affine (SPCanvasItem * item)
+Geom::Affine sp_canvas_item_i2p_affine (SPCanvasItem * item)
{
g_assert (item != NULL); /* this may be overly zealous - it is
* plausible that this gets called
@@ -86,7 +86,7 @@ Geom::Matrix sp_canvas_item_i2p_affine (SPCanvasItem * item)
return item->xform;
}
-Geom::Matrix sp_canvas_item_i2i_affine (SPCanvasItem * from, SPCanvasItem * to)
+Geom::Affine sp_canvas_item_i2i_affine (SPCanvasItem * from, SPCanvasItem * to)
{
g_assert (from != NULL);
g_assert (to != NULL);
@@ -94,7 +94,7 @@ Geom::Matrix sp_canvas_item_i2i_affine (SPCanvasItem * from, SPCanvasItem * to)
return sp_canvas_item_i2w_affine(from) * sp_canvas_item_i2w_affine(to).inverse();
}
-void sp_canvas_item_set_i2w_affine (SPCanvasItem * item, Geom::Matrix const &i2w)
+void sp_canvas_item_set_i2w_affine (SPCanvasItem * item, Geom::Affine const &i2w)
{
g_assert (item != NULL);
diff --git a/src/display/sp-canvas-util.h b/src/display/sp-canvas-util.h
index 639163a28..f0aa15cb9 100644
--- a/src/display/sp-canvas-util.h
+++ b/src/display/sp-canvas-util.h
@@ -28,15 +28,15 @@ sp_canvas_clear_buffer (SPCanvasBuf * buf);
/* get i2p (item to parent) affine transformation as general 6-element array */
-Geom::Matrix sp_canvas_item_i2p_affine (SPCanvasItem * item);
+Geom::Affine sp_canvas_item_i2p_affine (SPCanvasItem * item);
/* get i2i (item to item) affine transformation as general 6-element array */
-Geom::Matrix sp_canvas_item_i2i_affine (SPCanvasItem * from, SPCanvasItem * to);
+Geom::Affine sp_canvas_item_i2i_affine (SPCanvasItem * from, SPCanvasItem * to);
/* set item affine matrix to achieve given i2w matrix */
-void sp_canvas_item_set_i2w_affine (SPCanvasItem * item, Geom::Matrix const & aff);
+void sp_canvas_item_set_i2w_affine (SPCanvasItem * item, Geom::Affine const & aff);
void sp_canvas_item_move_to_z (SPCanvasItem * item, gint z);
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index fc68bcfc0..caf1ecbcc 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -30,7 +30,7 @@
#include <helper/recthull.h>
#include "display/sp-canvas.h"
#include "display/sp-canvas-group.h"
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include "libnr/nr-convex-hull.h"
#include "preferences.h"
#include "inkscape.h"
@@ -171,7 +171,7 @@ sp_canvas_item_init (SPCanvasItem *item)
// that should be initially invisible; examples of such items: node handles, the CtrlRect
// used for rubberbanding, path outline, etc.
item->flags |= SP_CANVAS_ITEM_VISIBLE;
- item->xform = Geom::Matrix(Geom::identity());
+ item->xform = Geom::Affine(Geom::identity());
}
/**
@@ -284,10 +284,10 @@ sp_canvas_item_dispose (GObject *object)
* NB! affine is parent2canvas.
*/
static void
-sp_canvas_item_invoke_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags)
+sp_canvas_item_invoke_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
{
/* Apply the child item's transform */
- Geom::Matrix child_affine = item->xform * affine;
+ Geom::Affine child_affine = item->xform * affine;
/* apply object flags to child flags */
int child_flags = flags & ~SP_CANVAS_UPDATE_REQUESTED;
@@ -331,7 +331,7 @@ sp_canvas_item_invoke_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **a
* @affine: An affine transformation matrix.
*/
void
-sp_canvas_item_affine_absolute (SPCanvasItem *item, Geom::Matrix const &affine)
+sp_canvas_item_affine_absolute (SPCanvasItem *item, Geom::Affine const &affine)
{
item->xform = affine;
@@ -598,11 +598,11 @@ sp_canvas_item_ungrab (SPCanvasItem *item, guint32 etime)
* Returns the product of all transformation matrices from the root item down
* to the item.
*/
-Geom::Matrix sp_canvas_item_i2w_affine(SPCanvasItem const *item)
+Geom::Affine sp_canvas_item_i2w_affine(SPCanvasItem const *item)
{
g_assert (SP_IS_CANVAS_ITEM (item)); // should we get this?
- Geom::Matrix affine = Geom::identity();
+ Geom::Affine affine = Geom::identity();
while (item) {
affine *= item->xform;
@@ -697,7 +697,7 @@ static void sp_canvas_group_class_init (SPCanvasGroupClass *klass);
static void sp_canvas_group_init (SPCanvasGroup *group);
static void sp_canvas_group_destroy (GtkObject *object);
-static void sp_canvas_group_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+static void sp_canvas_group_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static double sp_canvas_group_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
static void sp_canvas_group_render (SPCanvasItem *item, SPCanvasBuf *buf);
@@ -782,7 +782,7 @@ sp_canvas_group_destroy (GtkObject *object)
* Update handler for canvas groups
*/
static void
-sp_canvas_group_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags)
+sp_canvas_group_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
{
SPCanvasGroup const *group = SP_CANVAS_GROUP (item);
Geom::RectHull corners(Geom::Point(0, 0));
diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h
index 9c8b19982..7ecbe0451 100644
--- a/src/display/sp-canvas.h
+++ b/src/display/sp-canvas.h
@@ -35,7 +35,7 @@
#include <glibmm/ustring.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <libnr/nr-rect-l.h>
#include <2geom/rect.h>
diff --git a/src/display/sp-ctrlline.cpp b/src/display/sp-ctrlline.cpp
index 0ef23812e..ef71c0a16 100644
--- a/src/display/sp-ctrlline.cpp
+++ b/src/display/sp-ctrlline.cpp
@@ -33,7 +33,7 @@ static void sp_ctrlline_class_init (SPCtrlLineClass *klass);
static void sp_ctrlline_init (SPCtrlLine *ctrlline);
static void sp_ctrlline_destroy (GtkObject *object);
-static void sp_ctrlline_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+static void sp_ctrlline_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_ctrlline_render (SPCanvasItem *item, SPCanvasBuf *buf);
static SPCanvasItemClass *parent_class;
@@ -123,7 +123,7 @@ sp_ctrlline_render (SPCanvasItem *item, SPCanvasBuf *buf)
}
static void
-sp_ctrlline_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags)
+sp_ctrlline_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
{
SPCtrlLine *cl = SP_CTRLLINE (item);
diff --git a/src/display/sp-ctrlline.h b/src/display/sp-ctrlline.h
index a13907a70..e69c478fb 100644
--- a/src/display/sp-ctrlline.h
+++ b/src/display/sp-ctrlline.h
@@ -26,7 +26,7 @@ struct SPCtrlLine : public SPCanvasItem{
SPItem *item; // the item to which this line belongs in some sense; may be NULL for some users
guint32 rgba;
Geom::Point s, e;
- Geom::Matrix affine;
+ Geom::Affine affine;
};
struct SPCtrlLineClass : public SPCanvasItemClass{};
diff --git a/src/display/sp-ctrlpoint.cpp b/src/display/sp-ctrlpoint.cpp
index ba40192a9..9f2ecb937 100644
--- a/src/display/sp-ctrlpoint.cpp
+++ b/src/display/sp-ctrlpoint.cpp
@@ -25,7 +25,7 @@ static void sp_ctrlpoint_class_init (SPCtrlPointClass *klass);
static void sp_ctrlpoint_init (SPCtrlPoint *ctrlpoint);
static void sp_ctrlpoint_destroy (GtkObject *object);
-static void sp_ctrlpoint_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+static void sp_ctrlpoint_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_ctrlpoint_render (SPCanvasItem *item, SPCanvasBuf *buf);
static SPCanvasItemClass *parent_class;
@@ -110,7 +110,7 @@ sp_ctrlpoint_render (SPCanvasItem *item, SPCanvasBuf *buf)
}
static void
-sp_ctrlpoint_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags)
+sp_ctrlpoint_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
{
SPCtrlPoint *cp = SP_CTRLPOINT (item);
diff --git a/src/display/sp-ctrlpoint.h b/src/display/sp-ctrlpoint.h
index 1b7b7ba1e..b98d48f67 100644
--- a/src/display/sp-ctrlpoint.h
+++ b/src/display/sp-ctrlpoint.h
@@ -24,7 +24,7 @@ struct SPCtrlPoint : public SPCanvasItem {
SPItem *item; // the item to which this line belongs in some sense; may be NULL for some users
guint32 rgba;
Geom::Point pt;
- Geom::Matrix affine;
+ Geom::Affine affine;
double radius;
};
struct SPCtrlPointClass : public SPCanvasItemClass{};
diff --git a/src/display/sp-ctrlquadr.cpp b/src/display/sp-ctrlquadr.cpp
index c29aecb96..1ed8d62b8 100644
--- a/src/display/sp-ctrlquadr.cpp
+++ b/src/display/sp-ctrlquadr.cpp
@@ -21,7 +21,7 @@
struct SPCtrlQuadr : public SPCanvasItem{
guint32 rgba;
Geom::Point p1, p2, p3, p4;
- Geom::Matrix affine;
+ Geom::Affine affine;
};
struct SPCtrlQuadrClass : public SPCanvasItemClass{};
@@ -30,7 +30,7 @@ static void sp_ctrlquadr_class_init (SPCtrlQuadrClass *klass);
static void sp_ctrlquadr_init (SPCtrlQuadr *ctrlquadr);
static void sp_ctrlquadr_destroy (GtkObject *object);
-static void sp_ctrlquadr_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags);
+static void sp_ctrlquadr_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_ctrlquadr_render (SPCanvasItem *item, SPCanvasBuf *buf);
static SPCanvasItemClass *parent_class;
@@ -136,7 +136,7 @@ sp_ctrlquadr_render (SPCanvasItem *item, SPCanvasBuf *buf)
static void
-sp_ctrlquadr_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags)
+sp_ctrlquadr_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags)
{
SPCtrlQuadr *cq = SP_CTRLQUADR (item);
diff --git a/src/draw-context.cpp b/src/draw-context.cpp
index 62ae67336..182d4fca4 100644
--- a/src/draw-context.cpp
+++ b/src/draw-context.cpp
@@ -820,7 +820,7 @@ void spdc_create_single_dot(SPEventContext *ec, Geom::Point const &pt, char cons
current stroke width, multiplied by the amount specified in the preferences */
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- Geom::Matrix const i2d (item->i2d_affine ());
+ Geom::Affine const i2d (item->i2d_affine ());
Geom::Point pp = pt;
double rad = 0.5 * prefs->getDouble(tool_path + "/dot-size", 3.0);
if (event_state & GDK_MOD1_MASK) {
diff --git a/src/dropper-context.cpp b/src/dropper-context.cpp
index b7344889f..a2515c5f0 100644
--- a/src/dropper-context.cpp
+++ b/src/dropper-context.cpp
@@ -216,9 +216,9 @@ static gint sp_dropper_context_root_handler(SPEventContext *event_context, GdkEv
}
Geom::Point const cd = desktop->w2d(dc->centre);
- Geom::Matrix const w2dt = desktop->w2d();
+ Geom::Affine const w2dt = desktop->w2d();
const double scale = rw * w2dt.descrim();
- Geom::Matrix const sm( Geom::Scale(scale, scale) * Geom::Translate(cd) );
+ Geom::Affine const sm( Geom::Scale(scale, scale) * Geom::Translate(cd) );
sp_canvas_item_affine_absolute(dc->area, sm);
sp_canvas_item_show(dc->area);
diff --git a/src/dyna-draw-context.cpp b/src/dyna-draw-context.cpp
index 7d0c7ee91..6f0898d43 100644
--- a/src/dyna-draw-context.cpp
+++ b/src/dyna-draw-context.cpp
@@ -583,7 +583,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
Geom::Point hatch_unit_vector(0,0);
Geom::Point nearest(0,0);
Geom::Point pointer(0,0);
- Geom::Matrix motion_to_curve(Geom::identity());
+ Geom::Affine motion_to_curve(Geom::identity());
if (event->motion.state & GDK_CONTROL_MASK) { // hatching - sense the item
@@ -780,21 +780,21 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
if (dc->hatch_spacing == 0 && hatch_dist != 0) {
// Haven't set spacing yet: gray, center free, update radius live
Geom::Point c = desktop->w2d(motion_w);
- Geom::Matrix const sm (Geom::Scale(hatch_dist, hatch_dist) * Geom::Translate(c));
+ Geom::Affine const sm (Geom::Scale(hatch_dist, hatch_dist) * Geom::Translate(c));
sp_canvas_item_affine_absolute(dc->hatch_area, sm);
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0x7f7f7fff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
sp_canvas_item_show(dc->hatch_area);
} else if (dc->dragging && !dc->hatch_escaped) {
// Tracking: green, center snapped, fixed radius
Geom::Point c = motion_dt;
- Geom::Matrix const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c));
+ Geom::Affine const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c));
sp_canvas_item_affine_absolute(dc->hatch_area, sm);
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0x00FF00ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
sp_canvas_item_show(dc->hatch_area);
} else if (dc->dragging && dc->hatch_escaped) {
// Tracking escaped: red, center free, fixed radius
Geom::Point c = motion_dt;
- Geom::Matrix const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c));
+ Geom::Affine const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c));
sp_canvas_item_affine_absolute(dc->hatch_area, sm);
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0xFF0000ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
@@ -803,7 +803,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
// Not drawing but spacing set: gray, center snapped, fixed radius
Geom::Point c = (nearest + dc->hatch_spacing * hatch_unit_vector) * motion_to_curve.inverse();
if (!IS_NAN(c[Geom::X]) && !IS_NAN(c[Geom::Y])) {
- Geom::Matrix const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c));
+ Geom::Affine const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c));
sp_canvas_item_affine_absolute(dc->hatch_area, sm);
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0x7f7f7fff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
sp_canvas_item_show(dc->hatch_area);
diff --git a/src/extension/implementation/implementation.cpp b/src/extension/implementation/implementation.cpp
index a8533a427..b1b671026 100644
--- a/src/extension/implementation/implementation.cpp
+++ b/src/extension/implementation/implementation.cpp
@@ -148,7 +148,7 @@ Implementation::finish(Inkscape::Extension::Print */*module*/)
/* Rendering methods */
unsigned int
-Implementation::bind(Inkscape::Extension::Print */*module*/, Geom::Matrix const */*transform*/, float /*opacity*/)
+Implementation::bind(Inkscape::Extension::Print */*module*/, Geom::Affine const */*transform*/, float /*opacity*/)
{
return 0;
}
@@ -166,14 +166,14 @@ Implementation::comment(Inkscape::Extension::Print */*module*/, char const */*co
}
unsigned int
-Implementation::fill(Inkscape::Extension::Print */*module*/, Geom::PathVector const &/*pathv*/, Geom::Matrix const */*ctm*/, SPStyle const */*style*/,
+Implementation::fill(Inkscape::Extension::Print */*module*/, Geom::PathVector const &/*pathv*/, Geom::Affine const */*ctm*/, SPStyle const */*style*/,
NRRect const */*pbox*/, NRRect const */*dbox*/, NRRect const */*bbox*/)
{
return 0;
}
unsigned int
-Implementation::stroke(Inkscape::Extension::Print */*module*/, Geom::PathVector const &/*pathv*/, Geom::Matrix const */*transform*/, SPStyle const */*style*/,
+Implementation::stroke(Inkscape::Extension::Print */*module*/, Geom::PathVector const &/*pathv*/, Geom::Affine const */*transform*/, SPStyle const */*style*/,
NRRect const */*pbox*/, NRRect const */*dbox*/, NRRect const */*bbox*/)
{
return 0;
@@ -181,7 +181,7 @@ Implementation::stroke(Inkscape::Extension::Print */*module*/, Geom::PathVector
unsigned int
Implementation::image(Inkscape::Extension::Print */*module*/, unsigned char */*px*/, unsigned int /*w*/, unsigned int /*h*/, unsigned int /*rs*/,
- Geom::Matrix const */*transform*/, SPStyle const */*style*/)
+ Geom::Affine const */*transform*/, SPStyle const */*style*/)
{
return 0;
}
diff --git a/src/extension/implementation/implementation.h b/src/extension/implementation/implementation.h
index 9de70dce7..bf584b401 100644
--- a/src/extension/implementation/implementation.h
+++ b/src/extension/implementation/implementation.h
@@ -100,20 +100,20 @@ public:
/* ----- Rendering methods ----- */
virtual unsigned bind(Inkscape::Extension::Print *module,
- Geom::Matrix const *transform,
+ Geom::Affine const *transform,
float opacity);
virtual unsigned release(Inkscape::Extension::Print *module);
virtual unsigned comment(Inkscape::Extension::Print *module, const char * comment);
virtual unsigned fill(Inkscape::Extension::Print *module,
Geom::PathVector const &pathv,
- Geom::Matrix const *ctm,
+ Geom::Affine const *ctm,
SPStyle const *style,
NRRect const *pbox,
NRRect const *dbox,
NRRect const *bbox);
virtual unsigned stroke(Inkscape::Extension::Print *module,
Geom::PathVector const &pathv,
- Geom::Matrix const *transform,
+ Geom::Affine const *transform,
SPStyle const *style,
NRRect const *pbox,
NRRect const *dbox,
@@ -123,7 +123,7 @@ public:
unsigned int w,
unsigned int h,
unsigned int rs,
- Geom::Matrix const *transform,
+ Geom::Affine const *transform,
SPStyle const *style);
virtual unsigned text(Inkscape::Extension::Print *module,
char const *text,
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index b68105b30..cfbceab05 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -626,7 +626,7 @@ CairoRenderContext::popLayer(void)
// copy over the correct CTM
// It must be stored in item_transform of current state after pushState.
- Geom::Matrix item_transform;
+ Geom::Affine item_transform;
if (_state->parent_has_userspace)
item_transform = getParentState()->transform * _state->item_transform;
else
@@ -908,7 +908,7 @@ CairoRenderContext::finish(void)
}
void
-CairoRenderContext::transform(Geom::Matrix const *transform)
+CairoRenderContext::transform(Geom::Affine const *transform)
{
g_assert( _is_valid );
@@ -921,7 +921,7 @@ CairoRenderContext::transform(Geom::Matrix const *transform)
}
void
-CairoRenderContext::setTransform(Geom::Matrix const *transform)
+CairoRenderContext::setTransform(Geom::Affine const *transform)
{
g_assert( _is_valid );
@@ -932,7 +932,7 @@ CairoRenderContext::setTransform(Geom::Matrix const *transform)
}
void
-CairoRenderContext::getTransform(Geom::Matrix *copy) const
+CairoRenderContext::getTransform(Geom::Affine *copy) const
{
g_assert( _is_valid );
@@ -947,12 +947,12 @@ CairoRenderContext::getTransform(Geom::Matrix *copy) const
}
void
-CairoRenderContext::getParentTransform(Geom::Matrix *copy) const
+CairoRenderContext::getParentTransform(Geom::Affine *copy) const
{
g_assert( _is_valid );
CairoRenderState *parent_state = getParentState();
- memcpy(copy, &parent_state->transform, sizeof(Geom::Matrix));
+ memcpy(copy, &parent_state->transform, sizeof(Geom::Affine));
}
void
@@ -1001,7 +1001,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
SPPattern *pat = SP_PATTERN (paintserver);
- Geom::Matrix ps2user, pcs2dev;
+ Geom::Affine ps2user, pcs2dev;
ps2user = Geom::identity();
pcs2dev = Geom::identity();
@@ -1015,7 +1015,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
TRACE(("%f x %f pattern\n", width, height));
if (pbox && pattern_patternUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
- //Geom::Matrix bbox2user (pbox->x1 - pbox->x0, 0.0, 0.0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0);
+ //Geom::Affine bbox2user (pbox->x1 - pbox->x0, 0.0, 0.0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0);
bbox_width_scaler = pbox->x1 - pbox->x0;
bbox_height_scaler = pbox->y1 - pbox->y0;
ps2user[4] = x * bbox_width_scaler + pbox->x0;
@@ -1028,7 +1028,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
}
// apply pattern transformation
- Geom::Matrix pattern_transform(pattern_patternTransform(pat));
+ Geom::Affine pattern_transform(pattern_patternTransform(pat));
ps2user *= pattern_transform;
Geom::Point ori (ps2user[4], ps2user[5]);
@@ -1150,7 +1150,7 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain
Geom::Point p2 (lg->x2.computed, lg->y2.computed);
if (pbox && SP_GRADIENT(lg)->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
// convert to userspace
- Geom::Matrix bbox2user(pbox->x1 - pbox->x0, 0, 0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0);
+ Geom::Affine bbox2user(pbox->x1 - pbox->x0, 0, 0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0);
p1 *= bbox2user;
p2 *= bbox2user;
}
@@ -1413,7 +1413,7 @@ CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle con
bool
CairoRenderContext::renderImage(guchar *px, unsigned int w, unsigned int h, unsigned int rs,
- Geom::Matrix const *image_transform, SPStyle const *style)
+ Geom::Affine const *image_transform, SPStyle const *style)
{
g_assert( _is_valid );
@@ -1550,7 +1550,7 @@ CairoRenderContext::_showGlyphs(cairo_t *cr, PangoFont *font, std::vector<CairoG
}
bool
-CairoRenderContext::renderGlyphtext(PangoFont *font, Geom::Matrix const *font_matrix,
+CairoRenderContext::renderGlyphtext(PangoFont *font, Geom::Affine const *font_matrix,
std::vector<CairoGlyphInfo> const &glyphtext, SPStyle const *style)
{
// create a cairo_font_face from PangoFont
@@ -1668,7 +1668,7 @@ CairoRenderContext::_concatTransform(cairo_t *cr, double xx, double yx, double x
}
void
-CairoRenderContext::_initCairoMatrix(cairo_matrix_t *matrix, Geom::Matrix const *transform)
+CairoRenderContext::_initCairoMatrix(cairo_matrix_t *matrix, Geom::Affine const *transform)
{
matrix->xx = (*transform)[0];
matrix->yx = (*transform)[1];
@@ -1679,7 +1679,7 @@ CairoRenderContext::_initCairoMatrix(cairo_matrix_t *matrix, Geom::Matrix const
}
void
-CairoRenderContext::_concatTransform(cairo_t *cr, Geom::Matrix const *transform)
+CairoRenderContext::_concatTransform(cairo_t *cr, Geom::Affine const *transform)
{
_concatTransform(cr, (*transform)[0], (*transform)[1],
(*transform)[2], (*transform)[3],
diff --git a/src/extension/internal/cairo-render-context.h b/src/extension/internal/cairo-render-context.h
index 73ee585ce..d663a82fd 100644
--- a/src/extension/internal/cairo-render-context.h
+++ b/src/extension/internal/cairo-render-context.h
@@ -53,12 +53,12 @@ struct CairoRenderState {
unsigned int parent_has_userspace : 1; // whether the parent's ctm should be applied
float opacity;
bool has_filtereffect;
- Geom::Matrix item_transform; // this item's item->transform, for correct clipping
+ Geom::Affine item_transform; // this item's item->transform, for correct clipping
SPClipPath *clip_path;
SPMask* mask;
- Geom::Matrix transform; // the CTM
+ Geom::Affine transform; // the CTM
};
class CairoRenderContext {
@@ -127,10 +127,10 @@ public:
CairoRenderState *getParentState(void) const;
void setStateForStyle(SPStyle const *style);
- void transform(Geom::Matrix const *transform);
- void setTransform(Geom::Matrix const *transform);
- void getTransform(Geom::Matrix *copy) const;
- void getParentTransform(Geom::Matrix *copy) const;
+ void transform(Geom::Affine const *transform);
+ void setTransform(Geom::Affine const *transform);
+ void getTransform(Geom::Affine *copy) const;
+ void getParentTransform(Geom::Affine *copy) const;
/* Clipping methods */
void addClipPath(Geom::PathVector const &pv, SPIEnum const *fill_rule);
@@ -139,8 +139,8 @@ public:
/* Rendering methods */
bool renderPathVector(Geom::PathVector const & pathv, SPStyle const *style, NRRect const *pbox);
bool renderImage(unsigned char *px, unsigned int w, unsigned int h, unsigned int rs,
- Geom::Matrix const *image_transform, SPStyle const *style);
- bool renderGlyphtext(PangoFont *font, Geom::Matrix const *font_matrix,
+ Geom::Affine const *image_transform, SPStyle const *style);
+ bool renderGlyphtext(PangoFont *font, Geom::Affine const *font_matrix,
std::vector<CairoGlyphInfo> const &glyphtext, SPStyle const *style);
/* More general rendering methods will have to be added (like fill, stroke) */
@@ -191,9 +191,9 @@ protected:
void _setFillStyle(SPStyle const *style, NRRect const *pbox);
void _setStrokeStyle(SPStyle const *style, NRRect const *pbox);
- void _initCairoMatrix(cairo_matrix_t *matrix, Geom::Matrix const *transform);
+ void _initCairoMatrix(cairo_matrix_t *matrix, Geom::Affine const *transform);
void _concatTransform(cairo_t *cr, double xx, double yx, double xy, double yy, double x0, double y0);
- void _concatTransform(cairo_t *cr, Geom::Matrix const *transform);
+ void _concatTransform(cairo_t *cr, Geom::Affine const *transform);
GHashTable *font_table;
static void font_data_free(gpointer data);
diff --git a/src/extension/internal/cairo-renderer-pdf-out.cpp b/src/extension/internal/cairo-renderer-pdf-out.cpp
index 8406e2a3b..6527a646b 100644
--- a/src/extension/internal/cairo-renderer-pdf-out.cpp
+++ b/src/extension/internal/cairo-renderer-pdf-out.cpp
@@ -37,7 +37,7 @@
#include "sp-item.h"
#include "sp-root.h"
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
namespace Inkscape {
namespace Extension {
diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp
index bc3c6c484..015b3b2cb 100644
--- a/src/extension/internal/cairo-renderer.cpp
+++ b/src/extension/internal/cairo-renderer.cpp
@@ -157,7 +157,7 @@ static void sp_image_render(SPItem *item, CairoRenderContext *ctx);
static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx);
static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx);
-static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Matrix tr, SPStyle* style, CairoRenderContext *ctx)
+static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Affine tr, SPStyle* style, CairoRenderContext *ctx)
{
bool render = true;
if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
@@ -170,8 +170,8 @@ static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Matr
if (render) {
SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker));
- tr = (Geom::Matrix)marker_item->transform * (Geom::Matrix)marker->c2p * tr;
- Geom::Matrix old_tr = marker_item->transform;
+ tr = (Geom::Affine)marker_item->transform * (Geom::Affine)marker->c2p * tr;
+ Geom::Affine old_tr = marker_item->transform;
marker_item->transform = tr;
ctx->getRenderer()->renderItem (ctx, marker_item);
marker_item->transform = old_tr;
@@ -199,7 +199,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
if ( shape->marker[i] ) {
SPMarker* marker = SP_MARKER (shape->marker[i]);
- Geom::Matrix tr;
+ Geom::Affine tr;
if (marker->orient_auto) {
tr = sp_shape_marker_get_transform_at_start(pathv.begin()->front());
} else {
@@ -217,7 +217,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
if ( path_it != pathv.begin()
&& ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there
{
- Geom::Matrix tr;
+ Geom::Affine tr;
if (marker->orient_auto) {
tr = sp_shape_marker_get_transform_at_start(path_it->front());
} else {
@@ -234,7 +234,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
/* Put marker between curve_it1 and curve_it2.
* Loop to end_default (so including closing segment), because when a path is closed,
* there should be a midpoint marker between last segment and closing straight line segment */
- Geom::Matrix tr;
+ Geom::Affine tr;
if (marker->orient_auto) {
tr = sp_shape_marker_get_transform(*curve_it1, *curve_it2);
} else {
@@ -250,7 +250,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
// END position
if ( path_it != (pathv.end()-1) && !path_it->empty()) {
Geom::Curve const &lastcurve = path_it->back_default();
- Geom::Matrix tr;
+ Geom::Affine tr;
if (marker->orient_auto) {
tr = sp_shape_marker_get_transform_at_end(lastcurve);
} else {
@@ -274,7 +274,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx)
}
Geom::Curve const &lastcurve = path_last[index];
- Geom::Matrix tr;
+ Geom::Affine tr;
if (marker->orient_auto) {
tr = sp_shape_marker_get_transform_at_end(lastcurve);
} else {
@@ -309,7 +309,7 @@ static void sp_use_render(SPItem *item, CairoRenderContext *ctx)
CairoRenderer *renderer = ctx->getRenderer();
if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) {
- Geom::Matrix tp(Geom::Translate(use->x.computed, use->y.computed));
+ Geom::Affine tp(Geom::Translate(use->x.computed, use->y.computed));
ctx->pushState();
ctx->transform(&tp);
translated = true;
@@ -368,7 +368,7 @@ static void sp_image_render(SPItem *item, CairoRenderContext *ctx)
Geom::Translate tp(x, y);
Geom::Scale s(width / (double)w, height / (double)h);
- Geom::Matrix t(s * tp);
+ Geom::Affine t(s * tp);
ctx->renderImage (px, w, h, rs, &t, SP_OBJECT_STYLE (item));
}
@@ -385,7 +385,7 @@ static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx)
// apply viewbox if set
if (0 /*symbol->viewBox_set*/) {
- Geom::Matrix vb2user;
+ Geom::Affine vb2user;
double x, y, width, height;
double view_width, view_height;
x = 0.0;
@@ -423,7 +423,7 @@ static void sp_root_render(SPItem *item, CairoRenderContext *ctx)
ctx->pushState();
renderer->setStateForItem(ctx, item);
- Geom::Matrix tempmat (root->c2p);
+ Geom::Affine tempmat (root->c2p);
ctx->transform(&tempmat);
sp_group_render(item, ctx);
ctx->popState();
@@ -492,12 +492,12 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx)
// Calculate the matrix that will be applied to the image so that it exactly overlaps the source objects
// Matix to put bitmap in correct place on document
- Geom::Matrix t_on_document = (Geom::Matrix)(Geom::Scale (scale_x, -scale_y)) *
- (Geom::Matrix)(Geom::Translate (shift_x, shift_y));
+ Geom::Affine t_on_document = (Geom::Affine)(Geom::Scale (scale_x, -scale_y)) *
+ (Geom::Affine)(Geom::Translate (shift_x, shift_y));
// ctx matrix already includes item transformation. We must substract.
- Geom::Matrix t_item = item->i2d_affine ();
- Geom::Matrix t = t_on_document * t_item.inverse();
+ Geom::Affine t_item = item->i2d_affine ();
+ Geom::Affine t = t_on_document * t_item.inverse();
// Do the export
SPDocument *document = SP_OBJECT(item)->document;
@@ -570,7 +570,7 @@ CairoRenderer::setStateForItem(CairoRenderContext *ctx, SPItem const *item)
CairoRenderState *state = ctx->getCurrentState();
state->clip_path = item->clip_ref->getObject();
state->mask = item->mask_ref->getObject();
- state->item_transform = Geom::Matrix (item->transform);
+ state->item_transform = Geom::Affine (item->transform);
// If parent_has_userspace is true the parent state's transform
// has to be used for the mask's/clippath's context.
@@ -601,7 +601,7 @@ CairoRenderer::renderItem(CairoRenderContext *ctx, SPItem *item)
state->merge_opacity = FALSE;
ctx->pushLayer();
}
- Geom::Matrix tempmat (item->transform);
+ Geom::Affine tempmat (item->transform);
ctx->transform(&tempmat);
sp_item_invoke_render(item, ctx);
@@ -652,7 +652,7 @@ CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool page
if (ctx->_vector_based_target)
high *= PT_PER_PX;
- Geom::Matrix tp(Geom::Translate(-d.x0 * (ctx->_vector_based_target ? PX_PER_PT : 1.0),
+ Geom::Affine tp(Geom::Translate(-d.x0 * (ctx->_vector_based_target ? PX_PER_PT : 1.0),
(d.y1 - high) * (ctx->_vector_based_target ? PX_PER_PT : 1.0)));
ctx->transform(&tp);
}
@@ -674,11 +674,11 @@ CairoRenderer::applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp)
CairoRenderContext::CairoRenderMode saved_mode = ctx->getRenderMode();
ctx->setRenderMode(CairoRenderContext::RENDER_MODE_CLIP);
- Geom::Matrix saved_ctm;
+ Geom::Affine saved_ctm;
if (cp->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
//SP_PRINT_DRECT("clipd", cp->display->bbox);
NRRect clip_bbox(cp->display->bbox);
- Geom::Matrix t(Geom::Scale(clip_bbox.x1 - clip_bbox.x0, clip_bbox.y1 - clip_bbox.y0));
+ Geom::Affine t(Geom::Scale(clip_bbox.x1 - clip_bbox.x0, clip_bbox.y1 - clip_bbox.y0));
t[4] = clip_bbox.x0;
t[5] = clip_bbox.y0;
t *= ctx->getCurrentState()->transform;
@@ -693,7 +693,7 @@ CairoRenderer::applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp)
SPItem *item = SP_ITEM(child);
// combine transform of the item in clippath and the item using clippath:
- Geom::Matrix tempmat (item->transform);
+ Geom::Affine tempmat (item->transform);
tempmat = tempmat * (ctx->getCurrentState()->item_transform);
// render this item in clippath
@@ -730,7 +730,7 @@ CairoRenderer::applyMask(CairoRenderContext *ctx, SPMask const *mask)
NRRect mask_bbox(mask->display->bbox);
// TODO: should the bbox be transformed if maskUnits != userSpaceOnUse ?
if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
- Geom::Matrix t(Geom::Scale(mask_bbox.x1 - mask_bbox.x0, mask_bbox.y1 - mask_bbox.y0));
+ Geom::Affine t(Geom::Scale(mask_bbox.x1 - mask_bbox.x0, mask_bbox.y1 - mask_bbox.y0));
t[4] = mask_bbox.x0;
t[5] = mask_bbox.y0;
t *= ctx->getCurrentState()->transform;
diff --git a/src/extension/internal/emf-win32-print.cpp b/src/extension/internal/emf-win32-print.cpp
index e1ef77ae5..503a13d09 100644
--- a/src/extension/internal/emf-win32-print.cpp
+++ b/src/extension/internal/emf-win32-print.cpp
@@ -310,7 +310,7 @@ PrintEmfWin32::destroy_brush()
void
-PrintEmfWin32::create_pen(SPStyle const *style, const Geom::Matrix &transform)
+PrintEmfWin32::create_pen(SPStyle const *style, const Geom::Affine &transform)
{
if (style) {
float rgb[3];
@@ -459,12 +459,12 @@ PrintEmfWin32::flush_fill()
}
unsigned int
-PrintEmfWin32::bind(Inkscape::Extension::Print * /*mod*/, Geom::Matrix const *transform, float /*opacity*/)
+PrintEmfWin32::bind(Inkscape::Extension::Print * /*mod*/, Geom::Affine const *transform, float /*opacity*/)
{
- Geom::Matrix tr = *transform;
+ Geom::Affine tr = *transform;
if (m_tr_stack.size()) {
- Geom::Matrix tr_top = m_tr_stack.top();
+ Geom::Affine tr_top = m_tr_stack.top();
m_tr_stack.push(tr * tr_top);
} else {
m_tr_stack.push(tr);
@@ -482,12 +482,12 @@ PrintEmfWin32::release(Inkscape::Extension::Print * /*mod*/)
unsigned int
PrintEmfWin32::fill(Inkscape::Extension::Print * /*mod*/,
- Geom::PathVector const &pathv, Geom::Matrix const * /*transform*/, SPStyle const *style,
+ Geom::PathVector const &pathv, Geom::Affine const * /*transform*/, SPStyle const *style,
NRRect const * /*pbox*/, NRRect const * /*dbox*/, NRRect const * /*bbox*/)
{
if (!hdc) return 0;
- Geom::Matrix tf = m_tr_stack.top();
+ Geom::Affine tf = m_tr_stack.top();
flush_fill(); // flush any pending fills
@@ -511,12 +511,12 @@ PrintEmfWin32::fill(Inkscape::Extension::Print * /*mod*/,
unsigned int
PrintEmfWin32::stroke (Inkscape::Extension::Print * /*mod*/,
- Geom::PathVector const &pathv, const Geom::Matrix * /*transform*/, const SPStyle *style,
+ Geom::PathVector const &pathv, const Geom::Affine * /*transform*/, const SPStyle *style,
const NRRect * /*pbox*/, const NRRect * /*dbox*/, const NRRect * /*bbox*/)
{
if (!hdc) return 0;
- Geom::Matrix tf = m_tr_stack.top();
+ Geom::Affine tf = m_tr_stack.top();
stroke_and_fill = ( pathv == fill_pathv );
@@ -550,7 +550,7 @@ PrintEmfWin32::stroke (Inkscape::Extension::Print * /*mod*/,
bool
-PrintEmfWin32::print_simple_shape(Geom::PathVector const &pathv, const Geom::Matrix &transform)
+PrintEmfWin32::print_simple_shape(Geom::PathVector const &pathv, const Geom::Affine &transform)
{
Geom::PathVector pv = pathv_to_linear_and_cubic_beziers( pathv * transform );
@@ -746,7 +746,7 @@ PrintEmfWin32::print_simple_shape(Geom::PathVector const &pathv, const Geom::Mat
}
unsigned int
-PrintEmfWin32::print_pathv(Geom::PathVector const &pathv, const Geom::Matrix &transform)
+PrintEmfWin32::print_pathv(Geom::PathVector const &pathv, const Geom::Affine &transform)
{
simple_shape = print_simple_shape(pathv, transform);
@@ -863,7 +863,7 @@ PrintEmfWin32::text(Inkscape::Extension::Print * /*mod*/, char const *text, Geom
if (!hdc) return 0;
HFONT hfont = NULL;
- Geom::Matrix tf = m_tr_stack.top();
+ Geom::Affine tf = m_tr_stack.top();
double rot = 1800.0*std::atan2(tf[1], tf[0])/M_PI; // 0.1 degree rotation
#ifdef USE_PANGO_WIN32
diff --git a/src/extension/internal/emf-win32-print.h b/src/extension/internal/emf-win32-print.h
index a0f26abb5..a9f639bcd 100644
--- a/src/extension/internal/emf-win32-print.h
+++ b/src/extension/internal/emf-win32-print.h
@@ -38,15 +38,15 @@ class PrintEmfWin32 : public Inkscape::Extension::Implementation::Implementation
HBRUSH hbrush, hbrushOld;
HPEN hpen, hpenOld;
- std::stack<Geom::Matrix> m_tr_stack;
+ std::stack<Geom::Affine> m_tr_stack;
Geom::PathVector fill_pathv;
- Geom::Matrix fill_transform;
+ Geom::Affine fill_transform;
bool stroke_and_fill;
bool fill_only;
bool simple_shape;
- unsigned int print_pathv (Geom::PathVector const &pathv, const Geom::Matrix &transform);
- bool print_simple_shape (Geom::PathVector const &pathv, const Geom::Matrix &transform);
+ unsigned int print_pathv (Geom::PathVector const &pathv, const Geom::Affine &transform);
+ bool print_simple_shape (Geom::PathVector const &pathv, const Geom::Affine &transform);
public:
PrintEmfWin32 (void);
@@ -59,13 +59,13 @@ public:
virtual unsigned int finish (Inkscape::Extension::Print * module);
/* Rendering methods */
- virtual unsigned int bind(Inkscape::Extension::Print *module, Geom::Matrix const *transform, float opacity);
+ virtual unsigned int bind(Inkscape::Extension::Print *module, Geom::Affine const *transform, float opacity);
virtual unsigned int release(Inkscape::Extension::Print *module);
virtual unsigned int fill (Inkscape::Extension::Print * module,
- Geom::PathVector const &pathv, const Geom::Matrix *ctm, const SPStyle *style,
+ Geom::PathVector const &pathv, const Geom::Affine *ctm, const SPStyle *style,
const NRRect *pbox, const NRRect *dbox, const NRRect *bbox);
virtual unsigned int stroke (Inkscape::Extension::Print * module,
- Geom::PathVector const &pathv, const Geom::Matrix *transform, const SPStyle *style,
+ Geom::PathVector const &pathv, const Geom::Affine *transform, const SPStyle *style,
const NRRect *pbox, const NRRect *dbox, const NRRect *bbox);
virtual unsigned int comment(Inkscape::Extension::Print *module, const char * comment);
virtual unsigned int text(Inkscape::Extension::Print *module, char const *text,
@@ -79,7 +79,7 @@ protected:
void destroy_brush();
- void create_pen(SPStyle const *style, const Geom::Matrix &transform);
+ void create_pen(SPStyle const *style, const Geom::Affine &transform);
void destroy_pen();
diff --git a/src/extension/internal/javafx-out.cpp b/src/extension/internal/javafx-out.cpp
index 7098027c7..5902c3ad0 100644
--- a/src/extension/internal/javafx-out.cpp
+++ b/src/extension/internal/javafx-out.cpp
@@ -494,7 +494,7 @@ bool JavaFXOutput::doCurve(SPItem *item, const String &id)
// convert the path to only lineto's and cubic curveto's:
Geom::Scale yflip(1.0, -1.0);
- Geom::Matrix tf = item->i2d_affine() * yflip;
+ Geom::Affine tf = item->i2d_affine() * yflip;
Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() * tf );
//Count the NR_CURVETOs/LINETOs (including closing line segment)
@@ -636,7 +636,7 @@ bool JavaFXOutput::doCurve(SPItem *item, const String &id)
// convert the path to only lineto's and cubic curveto's:
Geom::Scale yflip(1.0, -1.0);
- Geom::Matrix tf = item->i2d_affine() * yflip;
+ Geom::Affine tf = item->i2d_affine() * yflip;
Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() * tf );
//Count the NR_CURVETOs/LINETOs (including closing line segment)
diff --git a/src/extension/internal/latex-pstricks.cpp b/src/extension/internal/latex-pstricks.cpp
index 44b64c5f8..e09e7c024 100644
--- a/src/extension/internal/latex-pstricks.cpp
+++ b/src/extension/internal/latex-pstricks.cpp
@@ -164,12 +164,12 @@ PrintLatex::finish (Inkscape::Extension::Print *mod)
}
unsigned int
-PrintLatex::bind(Inkscape::Extension::Print *mod, Geom::Matrix const *transform, float opacity)
+PrintLatex::bind(Inkscape::Extension::Print *mod, Geom::Affine const *transform, float opacity)
{
- Geom::Matrix tr = *transform;
+ Geom::Affine tr = *transform;
if(m_tr_stack.size()){
- Geom::Matrix tr_top = m_tr_stack.top();
+ Geom::Affine tr_top = m_tr_stack.top();
m_tr_stack.push(tr * tr_top);
}else
m_tr_stack.push(tr);
@@ -194,7 +194,7 @@ unsigned int PrintLatex::comment (Inkscape::Extension::Print * module,
unsigned int
PrintLatex::fill(Inkscape::Extension::Print *mod,
- Geom::PathVector const &pathv, Geom::Matrix const *transform, SPStyle const *style,
+ Geom::PathVector const &pathv, Geom::Affine const *transform, SPStyle const *style,
NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
{
if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
@@ -227,7 +227,7 @@ PrintLatex::fill(Inkscape::Extension::Print *mod,
}
unsigned int
-PrintLatex::stroke (Inkscape::Extension::Print *mod, Geom::PathVector const &pathv, const Geom::Matrix *transform, const SPStyle *style,
+PrintLatex::stroke (Inkscape::Extension::Print *mod, Geom::PathVector const &pathv, const Geom::Affine *transform, const SPStyle *style,
const NRRect *pbox, const NRRect *dbox, const NRRect *bbox)
{
if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
@@ -236,7 +236,7 @@ PrintLatex::stroke (Inkscape::Extension::Print *mod, Geom::PathVector const &pat
Inkscape::SVGOStringStream os;
float rgb[3];
float stroke_opacity;
- Geom::Matrix tr_stack = m_tr_stack.top();
+ Geom::Affine tr_stack = m_tr_stack.top();
double const scale = tr_stack.descrim();
os.setf(std::ios::fixed);
@@ -277,13 +277,13 @@ PrintLatex::stroke (Inkscape::Extension::Print *mod, Geom::PathVector const &pat
// FIXME: why is 'transform' argument not used?
void
-PrintLatex::print_pathvector(SVGOStringStream &os, Geom::PathVector const &pathv_in, const Geom::Matrix * /*transform*/)
+PrintLatex::print_pathvector(SVGOStringStream &os, Geom::PathVector const &pathv_in, const Geom::Affine * /*transform*/)
{
if (pathv_in.empty())
return;
-// Geom::Matrix tf=*transform; // why was this here?
- Geom::Matrix tf_stack=m_tr_stack.top(); // and why is transform argument not used?
+// Geom::Affine tf=*transform; // why was this here?
+ Geom::Affine tf_stack=m_tr_stack.top(); // and why is transform argument not used?
Geom::PathVector pathv = pathv_in * tf_stack; // generates new path, which is a bit slow, but this doesn't have to be performance optimized
os << "\\newpath\n";
diff --git a/src/extension/internal/latex-pstricks.h b/src/extension/internal/latex-pstricks.h
index a33e169e8..64b0de474 100644
--- a/src/extension/internal/latex-pstricks.h
+++ b/src/extension/internal/latex-pstricks.h
@@ -31,9 +31,9 @@ class PrintLatex : public Inkscape::Extension::Implementation::Implementation {
float _height;
FILE * _stream;
- std::stack<Geom::Matrix> m_tr_stack;
+ std::stack<Geom::Affine> m_tr_stack;
- void print_pathvector(SVGOStringStream &os, Geom::PathVector const &pathv_in, const Geom::Matrix * /*transform*/);
+ void print_pathvector(SVGOStringStream &os, Geom::PathVector const &pathv_in, const Geom::Affine * /*transform*/);
void print_2geomcurve(SVGOStringStream &os, Geom::Curve const & c );
public:
@@ -47,12 +47,12 @@ public:
virtual unsigned int finish (Inkscape::Extension::Print * module);
/* Rendering methods */
- virtual unsigned int bind(Inkscape::Extension::Print *module, Geom::Matrix const *transform, float opacity);
+ virtual unsigned int bind(Inkscape::Extension::Print *module, Geom::Affine const *transform, float opacity);
virtual unsigned int release(Inkscape::Extension::Print *module);
- virtual unsigned int fill (Inkscape::Extension::Print * module, Geom::PathVector const &pathv, const Geom::Matrix *ctm, const SPStyle *style,
+ virtual unsigned int fill (Inkscape::Extension::Print * module, Geom::PathVector const &pathv, const Geom::Affine *ctm, const SPStyle *style,
const NRRect *pbox, const NRRect *dbox, const NRRect *bbox);
- virtual unsigned int stroke (Inkscape::Extension::Print * module, Geom::PathVector const &pathv, const Geom::Matrix *transform, const SPStyle *style,
+ virtual unsigned int stroke (Inkscape::Extension::Print * module, Geom::PathVector const &pathv, const Geom::Affine *transform, const SPStyle *style,
const NRRect *pbox, const NRRect *dbox, const NRRect *bbox);
virtual unsigned int comment(Inkscape::Extension::Print *module, const char * comment);
bool textToPath (Inkscape::Extension::Print * ext);
diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp
index fd99afe31..3c4bb5c92 100644
--- a/src/extension/internal/latex-text-renderer.cpp
+++ b/src/extension/internal/latex-text-renderer.cpp
@@ -246,7 +246,7 @@ LaTeXTextRenderer::sp_use_render(SPItem *item)
SPUse *use = SP_USE(item);
if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) {
- Geom::Matrix tp(Geom::Translate(use->x.computed, use->y.computed));
+ Geom::Affine tp(Geom::Translate(use->x.computed, use->y.computed));
push_transform(tp);
translated = true;
}
@@ -311,8 +311,8 @@ LaTeXTextRenderer::sp_text_render(SPItem *item)
}
// get rotation
- Geom::Matrix i2doc = item->i2doc_affine();
- Geom::Matrix wotransl = i2doc.without_translation();
+ Geom::Affine i2doc = item->i2doc_affine();
+ Geom::Affine wotransl = i2doc.withoutTranslation();
double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis());
bool has_rotation = !Geom::are_near(degrees,0.);
@@ -412,8 +412,8 @@ Flowing in rectangle is possible, not in arb shape.
}
// get rotation
- Geom::Matrix i2doc = item->i2doc_affine();
- Geom::Matrix wotransl = i2doc.without_translation();
+ Geom::Affine i2doc = item->i2doc_affine();
+ Geom::Affine wotransl = i2doc.withoutTranslation();
double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis());
bool has_rotation = !Geom::are_near(degrees,0.);
@@ -543,17 +543,17 @@ LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem *
return true;
}
-Geom::Matrix const &
+Geom::Affine const &
LaTeXTextRenderer::transform()
{
return _transform_stack.top();
}
void
-LaTeXTextRenderer::push_transform(Geom::Matrix const &tr)
+LaTeXTextRenderer::push_transform(Geom::Affine const &tr)
{
if(_transform_stack.size()){
- Geom::Matrix tr_top = _transform_stack.top();
+ Geom::Affine tr_top = _transform_stack.top();
_transform_stack.push(tr * tr_top);
} else {
_transform_stack.push(tr);
diff --git a/src/extension/internal/latex-text-renderer.h b/src/extension/internal/latex-text-renderer.h
index e4bbd94ed..2259427d6 100644
--- a/src/extension/internal/latex-text-renderer.h
+++ b/src/extension/internal/latex-text-renderer.h
@@ -18,7 +18,7 @@
#endif
#include "extension/extension.h"
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <stack>
class SPItem;
@@ -51,10 +51,10 @@ protected:
bool _pdflatex; /** true if ouputting for pdfLaTeX*/
- void push_transform(Geom::Matrix const &transform);
- Geom::Matrix const & transform();
+ void push_transform(Geom::Affine const &transform);
+ Geom::Affine const & transform();
void pop_transform();
- std::stack<Geom::Matrix> _transform_stack;
+ std::stack<Geom::Affine> _transform_stack;
void writePreamble();
void writePostamble();
diff --git a/src/extension/internal/odf.cpp b/src/extension/internal/odf.cpp
index b5c842a40..6a350ab48 100644
--- a/src/extension/internal/odf.cpp
+++ b/src/extension/internal/odf.cpp
@@ -259,7 +259,7 @@ private:
* NOTE:
* This class is ported almost verbatim from the public domain
* JAMA Matrix package. It is modified to handle only 3x3 matrices
- * and our Geom::Matrix affine transform class. We give full
+ * and our Geom::Affine affine transform class. We give full
* attribution to them, along with many thanks. JAMA can be found at:
* http://math.nist.gov/javanumerics/jama
*
@@ -921,7 +921,7 @@ static Glib::ustring getExtension(const Glib::ustring &fname)
}
-static Glib::ustring formatTransform(Geom::Matrix &tf)
+static Glib::ustring formatTransform(Geom::Affine &tf)
{
Glib::ustring str;
if (!tf.isIdentity())
@@ -943,16 +943,16 @@ static Glib::ustring formatTransform(Geom::Matrix &tf)
* Get the general transform from SVG pixels to
* ODF cm
*/
-static Geom::Matrix getODFTransform(const SPItem *item)
+static Geom::Affine getODFTransform(const SPItem *item)
{
//### Get SVG-to-ODF transform
- Geom::Matrix tf (item->i2d_affine());
+ Geom::Affine tf (item->i2d_affine());
//Flip Y into document coordinates
double doc_height = SP_ACTIVE_DOCUMENT->getHeight();
- Geom::Matrix doc2dt_tf = Geom::Matrix(Geom::Scale(1.0, -1.0));
- doc2dt_tf = doc2dt_tf * Geom::Matrix(Geom::Translate(0, doc_height));
+ Geom::Affine doc2dt_tf = Geom::Affine(Geom::Scale(1.0, -1.0));
+ doc2dt_tf = doc2dt_tf * Geom::Affine(Geom::Translate(0, doc_height));
tf = tf * doc2dt_tf;
- tf = tf * Geom::Matrix(Geom::Scale(pxToCm));
+ tf = tf * Geom::Affine(Geom::Scale(pxToCm));
return tf;
}
@@ -970,10 +970,10 @@ static Geom::OptRect getODFBoundingBox(const SPItem *item)
if (bbox_temp) {
bbox = *bbox_temp;
double doc_height = SP_ACTIVE_DOCUMENT->getHeight();
- Geom::Matrix doc2dt_tf = Geom::Matrix(Geom::Scale(1.0, -1.0));
- doc2dt_tf = doc2dt_tf * Geom::Matrix(Geom::Translate(0, doc_height));
+ Geom::Affine doc2dt_tf = Geom::Affine(Geom::Scale(1.0, -1.0));
+ doc2dt_tf = doc2dt_tf * Geom::Affine(Geom::Translate(0, doc_height));
bbox = *bbox * doc2dt_tf;
- bbox = *bbox * Geom::Matrix(Geom::Scale(pxToCm));
+ bbox = *bbox * Geom::Affine(Geom::Scale(pxToCm));
}
return bbox;
}
@@ -984,10 +984,10 @@ static Geom::OptRect getODFBoundingBox(const SPItem *item)
* Get the transform for an item, correcting for
* handedness reversal
*/
-static Geom::Matrix getODFItemTransform(const SPItem *item)
+static Geom::Affine getODFItemTransform(const SPItem *item)
{
- Geom::Matrix itemTransform (Geom::Scale(1, -1));
- itemTransform = itemTransform * (Geom::Matrix)item->transform;
+ Geom::Affine itemTransform (Geom::Scale(1, -1));
+ itemTransform = itemTransform * (Geom::Affine)item->transform;
itemTransform = itemTransform * Geom::Scale(1, -1);
return itemTransform;
}
@@ -997,7 +997,7 @@ static Geom::Matrix getODFItemTransform(const SPItem *item)
/**
* Get some fun facts from the transform
*/
-static void analyzeTransform(Geom::Matrix &tf,
+static void analyzeTransform(Geom::Affine &tf,
double &rotate, double &/*xskew*/, double &/*yskew*/,
double &xscale, double &yscale)
{
@@ -1087,7 +1087,7 @@ OdfOutput::preprocess(ZipFile &zf, Inkscape::XML::Node *node)
}
SPItem *item = SP_ITEM(reprobj);
//### Get SVG-to-ODF transform
- Geom::Matrix tf = getODFTransform(item);
+ Geom::Affine tf = getODFTransform(item);
if (nodeName == "image" || nodeName == "svg:image")
{
@@ -1487,7 +1487,7 @@ bool OdfOutput::writeStyle(ZipFile &zf)
*/
static int
writePath(Writer &outs, Geom::PathVector const &pathv,
- Geom::Matrix const &tf, double xoff, double yoff)
+ Geom::Affine const &tf, double xoff, double yoff)
{
using Geom::X;
using Geom::Y;
@@ -1638,7 +1638,7 @@ bool OdfOutput::processStyle(Writer &outs, SPItem *item,
bool OdfOutput::processGradient(Writer &outs, SPItem *item,
- const Glib::ustring &id, Geom::Matrix &/*tf*/)
+ const Glib::ustring &id, Geom::Affine &/*tf*/)
{
if (!item)
return false;
@@ -1864,7 +1864,7 @@ bool OdfOutput::writeTree(Writer &couts, Writer &souts,
Glib::ustring id = getAttribute(node, "id");
//### Get SVG-to-ODF transform
- Geom::Matrix tf = getODFTransform(item);
+ Geom::Affine tf = getODFTransform(item);
//### Get ODF bounding box params for item
Geom::OptRect bbox = getODFBoundingBox(item);
@@ -1960,7 +1960,7 @@ bool OdfOutput::writeTree(Writer &couts, Writer &souts,
iwidth = xscale * iwidth;
iheight = yscale * iheight;
- Geom::Matrix itemTransform = getODFItemTransform(item);
+ Geom::Affine itemTransform = getODFItemTransform(item);
Glib::ustring itemTransformString = formatTransform(itemTransform);
diff --git a/src/extension/internal/odf.h b/src/extension/internal/odf.h
index 9ad261098..2a6f7799f 100644
--- a/src/extension/internal/odf.h
+++ b/src/extension/internal/odf.h
@@ -317,7 +317,7 @@ private:
bool processStyle(Writer &outs, SPItem *item, const Glib::ustring &id);
bool processGradient(Writer &outs, SPItem *item,
- const Glib::ustring &id, Geom::Matrix &tf);
+ const Glib::ustring &id, Geom::Affine &tf);
bool writeStyleHeader(Writer &outs);
diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp
index 8b414239a..8d7c95560 100644
--- a/src/extension/internal/pdfinput/svg-builder.cpp
+++ b/src/extension/internal/pdfinput/svg-builder.cpp
@@ -247,7 +247,7 @@ static gchar *svgConvertGfxRGB(GfxRGB *color) {
static void svgSetTransform(Inkscape::XML::Node *node, double c0, double c1,
double c2, double c3, double c4, double c5) {
- Geom::Matrix matrix(c0, c1, c2, c3, c4, c5);
+ Geom::Affine matrix(c0, c1, c2, c3, c4, c5);
gchar *transform_text = sp_svg_transform_write(matrix);
node->setAttribute("transform", transform_text);
g_free(transform_text);
@@ -544,7 +544,7 @@ void SvgBuilder::setClipPath(GfxState *state, bool even_odd) {
* \return true on success; false on invalid transformation
*/
bool SvgBuilder::getTransform(double *transform) {
- Geom::Matrix svd;
+ Geom::Affine svd;
gchar const *tr = _container->attribute("transform");
bool valid = sp_svg_transform_read(tr, &svd);
if (valid) {
@@ -634,7 +634,7 @@ gchar *SvgBuilder::_createTilingPattern(GfxTilingPattern *tiling_pattern,
Inkscape::XML::Node *pattern_node = _xml_doc->createElement("svg:pattern");
// Set pattern transform matrix
double *p2u = tiling_pattern->getMatrix();
- Geom::Matrix pat_matrix(p2u[0], p2u[1], p2u[2], p2u[3], p2u[4], p2u[5]);
+ Geom::Affine pat_matrix(p2u[0], p2u[1], p2u[2], p2u[3], p2u[4], p2u[5]);
gchar *transform_text = sp_svg_transform_write(pat_matrix);
pattern_node->setAttribute("patternTransform", transform_text);
g_free(transform_text);
@@ -732,10 +732,10 @@ gchar *SvgBuilder::_createGradient(GfxShading *shading, double *matrix, bool for
gradient->setAttribute("gradientUnits", "userSpaceOnUse");
// If needed, flip the gradient transform around the y axis
if (matrix) {
- Geom::Matrix pat_matrix(matrix[0], matrix[1], matrix[2], matrix[3],
+ Geom::Affine pat_matrix(matrix[0], matrix[1], matrix[2], matrix[3],
matrix[4], matrix[5]);
if ( !for_shading && _is_top_level ) {
- Geom::Matrix flip(1.0, 0.0, 0.0, -1.0, 0.0, _height * PT_PER_PX);
+ Geom::Affine flip(1.0, 0.0, 0.0, -1.0, 0.0, _height * PT_PER_PX);
pat_matrix *= flip;
}
gchar *transform_text = sp_svg_transform_write(pat_matrix);
@@ -1149,7 +1149,7 @@ void SvgBuilder::updateTextMatrix(GfxState *state) {
max_scale = h_scale;
}
// Calculate new text matrix
- Geom::Matrix new_text_matrix(text_matrix[0] * state->getHorizScaling(),
+ Geom::Affine new_text_matrix(text_matrix[0] * state->getHorizScaling(),
text_matrix[1] * state->getHorizScaling(),
-text_matrix[2], -text_matrix[3],
0.0, 0.0);
@@ -1184,7 +1184,7 @@ void SvgBuilder::_flushText() {
Inkscape::XML::Node *text_node = _xml_doc->createElement("svg:text");
// Set text matrix
- Geom::Matrix text_transform(_text_matrix);
+ Geom::Affine text_transform(_text_matrix);
text_transform[4] = first_glyph.position[0];
text_transform[5] = first_glyph.position[1];
gchar *transform = sp_svg_transform_write(text_transform);
@@ -1719,7 +1719,7 @@ void SvgBuilder::addMaskedImage(GfxState *state, Stream *str, int width, int hei
mask_image_node->setAttribute("transform", NULL);
mask_node->appendChild(mask_image_node);
// Scale the mask to the size of the image
- Geom::Matrix mask_transform((double)width, 0.0, 0.0, (double)height, 0.0, 0.0);
+ Geom::Affine mask_transform((double)width, 0.0, 0.0, (double)height, 0.0, 0.0);
gchar *transform_text = sp_svg_transform_write(mask_transform);
mask_node->setAttribute("maskTransform", transform_text);
g_free(transform_text);
diff --git a/src/extension/internal/pdfinput/svg-builder.h b/src/extension/internal/pdfinput/svg-builder.h
index f0062bbe6..47e5d7735 100644
--- a/src/extension/internal/pdfinput/svg-builder.h
+++ b/src/extension/internal/pdfinput/svg-builder.h
@@ -27,7 +27,7 @@ namespace Inkscape {
}
#include <2geom/point.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <glibmm/ustring.h>
#include "CharTypes.h"
@@ -212,7 +212,7 @@ private:
char *_font_specification;
double _font_scaling;
bool _need_font_update;
- Geom::Matrix _text_matrix;
+ Geom::Affine _text_matrix;
Geom::Point _text_position;
std::vector<SvgGlyph> _glyphs; // Added characters
bool _in_text_object; // Whether we are inside a text object
diff --git a/src/extension/internal/pov-out.cpp b/src/extension/internal/pov-out.cpp
index a130b6923..b5389bad3 100644
--- a/src/extension/internal/pov-out.cpp
+++ b/src/extension/internal/pov-out.cpp
@@ -301,7 +301,7 @@ bool PovOutput::doCurve(SPItem *item, const String &id)
povShapes.push_back(shapeInfo); //passed all tests. save the info
// convert the path to only lineto's and cubic curveto's:
- Geom::Matrix tf = item->i2d_affine();
+ Geom::Affine tf = item->i2d_affine();
Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() * tf );
/*
diff --git a/src/extension/internal/win32.cpp b/src/extension/internal/win32.cpp
index 8b4ff13c8..537c91a2c 100644
--- a/src/extension/internal/win32.cpp
+++ b/src/extension/internal/win32.cpp
@@ -293,7 +293,7 @@ PrintWin32::finish (Inkscape::Extension::Print *mod)
scaley = dpiY / 72.0;
// We simply map document 0,0 to physical page 0,0
- Geom::Matrix affine = Geom::Scale(scalex / 1.25, scaley / 1.25);
+ Geom::Affine affine = Geom::Scale(scalex / 1.25, scaley / 1.25);
nr_arena_item_set_transform (mod->root, affine);
diff --git a/src/extension/internal/win32.h b/src/extension/internal/win32.h
index 02790a231..4a913bb05 100644
--- a/src/extension/internal/win32.h
+++ b/src/extension/internal/win32.h
@@ -70,11 +70,11 @@ public:
/* Rendering methods */
/*
- virtual unsigned int bind (Inkscape::Extension::Print * module, const Geom::Matrix *transform, float opacity);
+ virtual unsigned int bind (Inkscape::Extension::Print * module, const Geom::Affine *transform, float opacity);
virtual unsigned int release (Inkscape::Extension::Print * module);
virtual unsigned int comment (Inkscape::Extension::Print * module, const char * comment);
virtual unsigned int image (Inkscape::Extension::Print * module, unsigned char *px, unsigned int w, unsigned int h, unsigned int rs,
- const Geom::Matrix *transform, const SPStyle *style);
+ const Geom::Affine *transform, const SPStyle *style);
*/
};
diff --git a/src/extension/print.cpp b/src/extension/print.cpp
index 2d4177d60..ad8c4c38d 100644
--- a/src/extension/print.cpp
+++ b/src/extension/print.cpp
@@ -61,7 +61,7 @@ Print::finish (void)
}
unsigned int
-Print::bind (const Geom::Matrix *transform, float opacity)
+Print::bind (const Geom::Affine *transform, float opacity)
{
return imp->bind (this, transform, opacity);
}
@@ -79,14 +79,14 @@ Print::comment (const char * comment)
}
unsigned int
-Print::fill (Geom::PathVector const &pathv, const Geom::Matrix *ctm, const SPStyle *style,
+Print::fill (Geom::PathVector const &pathv, const Geom::Affine *ctm, const SPStyle *style,
const NRRect *pbox, const NRRect *dbox, const NRRect *bbox)
{
return imp->fill (this, pathv, ctm, style, pbox, dbox, bbox);
}
unsigned int
-Print::stroke (Geom::PathVector const &pathv, const Geom::Matrix *transform, const SPStyle *style,
+Print::stroke (Geom::PathVector const &pathv, const Geom::Affine *transform, const SPStyle *style,
const NRRect *pbox, const NRRect *dbox, const NRRect *bbox)
{
return imp->stroke (this, pathv, transform, style, pbox, dbox, bbox);
@@ -94,7 +94,7 @@ Print::stroke (Geom::PathVector const &pathv, const Geom::Matrix *transform, con
unsigned int
Print::image (unsigned char *px, unsigned int w, unsigned int h, unsigned int rs,
- const Geom::Matrix *transform, const SPStyle *style)
+ const Geom::Affine *transform, const SPStyle *style)
{
return imp->image (this, px, w, h, rs, transform, style);
}
diff --git a/src/extension/print.h b/src/extension/print.h
index 0f0435c0f..d5218aed8 100644
--- a/src/extension/print.h
+++ b/src/extension/print.h
@@ -41,18 +41,18 @@ public:
unsigned int finish (void);
/* Rendering methods */
- unsigned int bind (Geom::Matrix const *transform,
+ unsigned int bind (Geom::Affine const *transform,
float opacity);
unsigned int release (void);
unsigned int comment (const char * comment);
unsigned int fill (Geom::PathVector const &pathv,
- Geom::Matrix const *ctm,
+ Geom::Affine const *ctm,
SPStyle const *style,
NRRect const *pbox,
NRRect const *dbox,
NRRect const *bbox);
unsigned int stroke (Geom::PathVector const &pathv,
- Geom::Matrix const *transform,
+ Geom::Affine const *transform,
SPStyle const *style,
NRRect const *pbox,
NRRect const *dbox,
@@ -61,7 +61,7 @@ public:
unsigned int w,
unsigned int h,
unsigned int rs,
- Geom::Matrix const *transform,
+ Geom::Affine const *transform,
SPStyle const *style);
unsigned int text (char const *text,
Geom::Point p,
diff --git a/src/file.cpp b/src/file.cpp
index bde985ea5..c041cb262 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -1039,7 +1039,7 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri,
// preserve parent and viewBox transformations
// c2p is identity matrix at this point unless ensureUpToDate is called
doc->ensureUpToDate();
- Geom::Matrix affine = SP_ROOT(doc->getRoot())->c2p * SP_ITEM(place_to_insert)->i2doc_affine().inverse();
+ Geom::Affine affine = SP_ROOT(doc->getRoot())->c2p * SP_ITEM(place_to_insert)->i2doc_affine().inverse();
sp_selection_apply_affine(selection, desktop->dt2doc() * affine * desktop->doc2dt(), true, false);
// move to mouse pointer
diff --git a/src/filter-chemistry.cpp b/src/filter-chemistry.cpp
index d6900b1f6..742ac7261 100644
--- a/src/filter-chemistry.cpp
+++ b/src/filter-chemistry.cpp
@@ -329,7 +329,7 @@ new_filter_simple_from_item (SPDocument *document, SPItem *item, const char *mod
width = height = 0;
}
- Geom::Matrix i2d (item->i2d_affine () );
+ Geom::Affine i2d (item->i2d_affine () );
return (new_filter_blend_gaussian_blur (document, mode, radius, i2d.descrim(), i2d.expansionX(), i2d.expansionY(), width, height));
}
@@ -364,7 +364,7 @@ SPFilter *modify_filter_gaussian_blur_from_item(SPDocument *document, SPItem *it
}
// Determine the required standard deviation value
- Geom::Matrix i2d (item->i2d_affine ());
+ Geom::Affine i2d (item->i2d_affine ());
double expansion = i2d.descrim();
double stdDeviation = radius;
if (expansion != 0)
diff --git a/src/flood-context.cpp b/src/flood-context.cpp
index dd26782a3..4bec2f292 100644
--- a/src/flood-context.cpp
+++ b/src/flood-context.cpp
@@ -395,7 +395,7 @@ inline static bool check_if_pixel_is_paintable(guchar *px, unsigned char *trace_
* \param transform The transform to apply to the final SVG path.
* \param union_with_selection If true, merge the final SVG path with the current selection.
*/
-static void do_trace(bitmap_coords_info bci, guchar *trace_px, SPDesktop *desktop, Geom::Matrix transform, unsigned int min_x, unsigned int max_x, unsigned int min_y, unsigned int max_y, bool union_with_selection) {
+static void do_trace(bitmap_coords_info bci, guchar *trace_px, SPDesktop *desktop, Geom::Affine transform, unsigned int min_x, unsigned int max_x, unsigned int min_y, unsigned int max_y, bool union_with_selection) {
SPDocument *document = sp_desktop_document(desktop);
unsigned char *trace_t;
@@ -490,10 +490,10 @@ static void do_trace(bitmap_coords_info bci, guchar *trace_px, SPDesktop *deskto
SP_ITEM(reprobj)->doWriteTransform(pathRepr, transform, NULL);
// premultiply the item transform by the accumulated parent transform in the paste layer
- Geom::Matrix local (SP_GROUP(desktop->currentLayer())->i2doc_affine());
+ Geom::Affine local (SP_GROUP(desktop->currentLayer())->i2doc_affine());
if (!local.isIdentity()) {
gchar const *t_str = pathRepr->attribute("transform");
- Geom::Matrix item_t (Geom::identity());
+ Geom::Affine item_t (Geom::identity());
if (t_str)
sp_svg_transform_read(t_str, &item_t);
item_t *= local.inverse();
@@ -806,7 +806,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even
origin[Geom::Y] = origin[Geom::Y] + (screen.height() * ((1 - padding) / 2));
Geom::Scale scale(zoom_scale, zoom_scale);
- Geom::Matrix affine = scale * Geom::Translate(-origin * scale);
+ Geom::Affine affine = scale * Geom::Translate(-origin * scale);
/* Create ArenaItems and set transform */
NRArenaItem *root = SP_ITEM(document->getRoot())->invoke_show( arena, dkey, SP_ITEM_SHOW_DISPLAY);
@@ -1115,7 +1115,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even
Geom::Point min_start = Geom::Point(min_x, min_y);
affine = scale * Geom::Translate(-origin * scale - min_start);
- Geom::Matrix inverted_affine = Geom::Matrix(affine).inverse();
+ Geom::Affine inverted_affine = Geom::Affine(affine).inverse();
do_trace(bci, trace_px, desktop, inverted_affine, min_x, max_x, min_y, max_y, union_with_selection);
diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp
index fb5dab648..d99a57208 100644
--- a/src/gradient-chemistry.cpp
+++ b/src/gradient-chemistry.cpp
@@ -317,7 +317,7 @@ SPGradient *sp_gradient_reset_to_userspace(SPGradient *gr, SPItem *item)
sp_repr_set_svg_double(repr, "r", width/2);
// we want it to be elliptic, not circular
- Geom::Matrix squeeze = Geom::Translate (-center) *
+ Geom::Affine squeeze = Geom::Translate (-center) *
Geom::Scale(1, height/width) *
Geom::Translate (center);
@@ -365,10 +365,10 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar
// calculate the bbox of the item
SP_OBJECT_DOCUMENT(item)->ensureUpToDate();
- Geom::Matrix bbox2user;
+ Geom::Affine bbox2user;
Geom::OptRect bbox = item->getBounds(Geom::identity()); // we need "true" bbox without item_i2d_affine
if ( bbox ) {
- bbox2user = Geom::Matrix(bbox->dimensions()[Geom::X], 0,
+ bbox2user = Geom::Affine(bbox->dimensions()[Geom::X], 0,
0, bbox->dimensions()[Geom::Y],
bbox->min()[Geom::X], bbox->min()[Geom::Y]);
} else {
@@ -390,7 +390,7 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar
* gradient vector in user space due to application of the non-uniform scaling
* transformation from bounding box space to user space.
*/
- Geom::Matrix skew = bbox2user;
+ Geom::Affine skew = bbox2user;
double exp = skew.descrim();
skew[0] /= exp;
skew[1] /= exp;
@@ -409,7 +409,7 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar
// Matrix to convert points to userspace coords; postmultiply by inverse of skew so
// as to cancel it out when it's applied to the gradient during rendering
- Geom::Matrix point_convert = bbox2user * skew.inverse();
+ Geom::Affine point_convert = bbox2user * skew.inverse();
if (SP_IS_RADIALGRADIENT(gr)) {
SPRadialGradient *rg = SP_RADIALGRADIENT(gr);
@@ -462,7 +462,7 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar
return gr;
}
-void sp_gradient_transform_multiply(SPGradient *gradient, Geom::Matrix postmul, bool set)
+void sp_gradient_transform_multiply(SPGradient *gradient, Geom::Affine postmul, bool set)
{
#ifdef SP_GR_VERBOSE
g_message("sp_gradient_transform_multiply(%p, , %d)", gradient, set);
@@ -791,7 +791,7 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i,
gradient = sp_gradient_convert_to_userspace (gradient, item, fill_or_stroke? "fill" : "stroke");
- Geom::Matrix i2d (item->i2d_affine ());
+ Geom::Affine i2d (item->i2d_affine ());
Geom::Point p = p_w * i2d.inverse();
p *= (gradient->gradientTransform).inverse();
// now p is in gradient's original coordinates
@@ -864,7 +864,7 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i,
// prevent setting a radius too close to the center
return;
}
- Geom::Matrix new_transform;
+ Geom::Affine new_transform;
bool transform_set = false;
switch (point_type) {
@@ -899,12 +899,12 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i,
double move_angle = Geom::atan2(p_w - c_w) - r1_angle;
double move_stretch = Geom::L2(p_w - c_w) / Geom::L2(r1_w - c_w);
- Geom::Matrix move = Geom::Matrix (Geom::Translate (-c_w)) *
- Geom::Matrix (Geom::Rotate(-r1_angle)) *
- Geom::Matrix (Geom::Scale(move_stretch, scale? move_stretch : 1)) *
- Geom::Matrix (Geom::Rotate(r1_angle)) *
- Geom::Matrix (Geom::Rotate(move_angle)) *
- Geom::Matrix (Geom::Translate (c_w));
+ Geom::Affine move = Geom::Affine (Geom::Translate (-c_w)) *
+ Geom::Affine (Geom::Rotate(-r1_angle)) *
+ Geom::Affine (Geom::Scale(move_stretch, scale? move_stretch : 1)) *
+ Geom::Affine (Geom::Rotate(r1_angle)) *
+ Geom::Affine (Geom::Rotate(move_angle)) *
+ Geom::Affine (Geom::Translate (c_w));
new_transform = gradient->gradientTransform * i2d * move * i2d.inverse();
transform_set = true;
@@ -918,12 +918,12 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i,
double move_angle = Geom::atan2(p_w - c_w) - r2_angle;
double move_stretch = Geom::L2(p_w - c_w) / Geom::L2(r2_w - c_w);
- Geom::Matrix move = Geom::Matrix (Geom::Translate (-c_w)) *
- Geom::Matrix (Geom::Rotate(-r2_angle)) *
- Geom::Matrix (Geom::Scale(move_stretch, scale? move_stretch : 1)) *
- Geom::Matrix (Geom::Rotate(r2_angle)) *
- Geom::Matrix (Geom::Rotate(move_angle)) *
- Geom::Matrix (Geom::Translate (c_w));
+ Geom::Affine move = Geom::Affine (Geom::Translate (-c_w)) *
+ Geom::Affine (Geom::Rotate(-r2_angle)) *
+ Geom::Affine (Geom::Scale(move_stretch, scale? move_stretch : 1)) *
+ Geom::Affine (Geom::Rotate(r2_angle)) *
+ Geom::Affine (Geom::Rotate(move_angle)) *
+ Geom::Affine (Geom::Translate (c_w));
new_transform = gradient->gradientTransform * i2d * move * i2d.inverse();
transform_set = true;
@@ -1067,12 +1067,12 @@ Geom::Point sp_item_gradient_get_coords(SPItem *item, guint point_type, guint po
SP_OBJECT_DOCUMENT(item)->ensureUpToDate();
Geom::OptRect bbox = item->getBounds(Geom::identity()); // we need "true" bbox without item_i2d_affine
if (bbox) {
- p *= Geom::Matrix(bbox->dimensions()[Geom::X], 0,
+ p *= Geom::Affine(bbox->dimensions()[Geom::X], 0,
0, bbox->dimensions()[Geom::Y],
bbox->min()[Geom::X], bbox->min()[Geom::Y]);
}
}
- p *= Geom::Matrix(gradient->gradientTransform) * (Geom::Matrix)item->i2d_affine();
+ p *= Geom::Affine(gradient->gradientTransform) * (Geom::Affine)item->i2d_affine();
return from_2geom(p);
}
diff --git a/src/gradient-chemistry.h b/src/gradient-chemistry.h
index 5e4a7b337..e0d9a1f46 100644
--- a/src/gradient-chemistry.h
+++ b/src/gradient-chemistry.h
@@ -64,7 +64,7 @@ guint32 average_color (guint32 c1, guint32 c2, gdouble p = 0.5);
SPStop *sp_vector_add_stop (SPGradient *vector, SPStop* prev_stop, SPStop* next_stop, gfloat offset);
-void sp_gradient_transform_multiply (SPGradient *gradient, Geom::Matrix postmul, bool set);
+void sp_gradient_transform_multiply (SPGradient *gradient, Geom::Affine postmul, bool set);
SPGradient * sp_item_gradient (SPItem *item, bool fill_or_stroke);
void sp_item_gradient_set_coords (SPItem *item, guint point_type, guint point_i, Geom::Point p_desk, bool fill_or_stroke, bool write_repr, bool scale);
diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp
index cc9064451..4bf56f6c1 100644
--- a/src/helper/geom.cpp
+++ b/src/helper/geom.cpp
@@ -40,8 +40,8 @@ cubic_bbox (Geom::Coord x000, Geom::Coord y000, Geom::Coord x001, Geom::Coord y0
{
Geom::Coord a, b, c, D;
- bbox[0].extendTo(x111);
- bbox[1].extendTo(y111);
+ bbox[0].expandTo(x111);
+ bbox[1].expandTo(y111);
// It already contains (x000,y000) and (x111,y111)
// All points of the Bezier lie in the convex hull of (x000,y000), (x001,y001), (x011,y011) and (x111,y111)
@@ -83,7 +83,7 @@ cubic_bbox (Geom::Coord x000, Geom::Coord y000, Geom::Coord x001, Geom::Coord y0
if ((s > 0.0) && (s < 1.0)) {
t = 1.0 - s;
xttt = s * s * s * x000 + 3 * s * s * t * x001 + 3 * s * t * t * x011 + t * t * t * x111;
- bbox[0].extendTo(xttt);
+ bbox[0].expandTo(xttt);
}
}
} else {
@@ -97,13 +97,13 @@ cubic_bbox (Geom::Coord x000, Geom::Coord y000, Geom::Coord x001, Geom::Coord y0
if ((s > 0.0) && (s < 1.0)) {
t = 1.0 - s;
xttt = s * s * s * x000 + 3 * s * s * t * x001 + 3 * s * t * t * x011 + t * t * t * x111;
- bbox[0].extendTo(xttt);
+ bbox[0].expandTo(xttt);
}
s = (-b - d) / (2 * a);
if ((s > 0.0) && (s < 1.0)) {
t = 1.0 - s;
xttt = s * s * s * x000 + 3 * s * s * t * x001 + 3 * s * t * t * x011 + t * t * t * x111;
- bbox[0].extendTo(xttt);
+ bbox[0].expandTo(xttt);
}
}
}
@@ -122,7 +122,7 @@ cubic_bbox (Geom::Coord x000, Geom::Coord y000, Geom::Coord x001, Geom::Coord y0
if ((s > 0.0) && (s < 1.0)) {
t = 1.0 - s;
yttt = s * s * s * y000 + 3 * s * s * t * y001 + 3 * s * t * t * y011 + t * t * t * y111;
- bbox[1].extendTo(yttt);
+ bbox[1].expandTo(yttt);
}
}
} else {
@@ -136,13 +136,13 @@ cubic_bbox (Geom::Coord x000, Geom::Coord y000, Geom::Coord x001, Geom::Coord y0
if ((s > 0.0) && (s < 1.0)) {
t = 1.0 - s;
yttt = s * s * s * y000 + 3 * s * s * t * y001 + 3 * s * t * t * y011 + t * t * t * y111;
- bbox[1].extendTo(yttt);
+ bbox[1].expandTo(yttt);
}
s = (-b - d) / (2 * a);
if ((s > 0.0) && (s < 1.0)) {
t = 1.0 - s;
yttt = s * s * s * y000 + 3 * s * s * t * y001 + 3 * s * t * t * y011 + t * t * t * y111;
- bbox[1].extendTo(yttt);
+ bbox[1].expandTo(yttt);
}
}
}
@@ -150,14 +150,14 @@ cubic_bbox (Geom::Coord x000, Geom::Coord y000, Geom::Coord x001, Geom::Coord y0
}
Geom::OptRect
-bounds_fast_transformed(Geom::PathVector const & pv, Geom::Matrix const & t)
+bounds_fast_transformed(Geom::PathVector const & pv, Geom::Affine const & t)
{
return bounds_exact_transformed(pv, t); //use this as it is faster for now! :)
// return Geom::bounds_fast(pv * t);
}
Geom::OptRect
-bounds_exact_transformed(Geom::PathVector const & pv, Geom::Matrix const & t)
+bounds_exact_transformed(Geom::PathVector const & pv, Geom::Affine const & t)
{
if (pv.empty())
return Geom::OptRect();
@@ -354,7 +354,7 @@ geom_cubic_bbox_wind_distance (Geom::Coord x000, Geom::Coord y000,
}
static void
-geom_curve_bbox_wind_distance(Geom::Curve const & c, Geom::Matrix const &m,
+geom_curve_bbox_wind_distance(Geom::Curve const & c, Geom::Affine const &m,
Geom::Point const &pt,
Geom::Rect *bbox, int *wind, Geom::Coord *dist,
Geom::Coord tolerance, Geom::Rect const *viewbox,
@@ -417,7 +417,7 @@ geom_curve_bbox_wind_distance(Geom::Curve const & c, Geom::Matrix const &m,
Returns bounding box in *bbox if bbox!=NULL.
*/
void
-pathv_matrix_point_bbox_wind_distance (Geom::PathVector const & pathv, Geom::Matrix const &m, Geom::Point const &pt,
+pathv_matrix_point_bbox_wind_distance (Geom::PathVector const & pathv, Geom::Affine const &m, Geom::Point const &pt,
Geom::Rect *bbox, int *wind, Geom::Coord *dist,
Geom::Coord tolerance, Geom::Rect const *viewbox)
{
@@ -507,7 +507,7 @@ void round_rectangle_outwards(Geom::Rect & rect) {
namespace Geom {
-bool transform_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord const epsilon) {
+bool transform_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon) {
return
NR_DF_TEST_CLOSE(m0[0], m1[0], epsilon) &&
NR_DF_TEST_CLOSE(m0[1], m1[1], epsilon) &&
@@ -516,12 +516,12 @@ bool transform_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coor
}
-bool translate_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord const epsilon) {
+bool translate_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon) {
return NR_DF_TEST_CLOSE(m0[4], m1[4], epsilon) && NR_DF_TEST_CLOSE(m0[5], m1[5], epsilon);
}
-bool matrix_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord const epsilon) {
+bool matrix_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon) {
return transform_equalp(m0, m1, epsilon) && translate_equalp(m0, m1, epsilon);
}
@@ -530,7 +530,7 @@ bool matrix_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord c
The following predefined objects are for reference
and comparison.
*/
-Geom::Matrix GEOM_MATRIX_IDENTITY = Geom::identity();
+Geom::Affine GEOM_MATRIX_IDENTITY = Geom::identity();
/*
Local Variables:
diff --git a/src/helper/geom.h b/src/helper/geom.h
index 73f95794f..b1015b185 100644
--- a/src/helper/geom.h
+++ b/src/helper/geom.h
@@ -16,10 +16,10 @@
#include <libnr/nr-forward.h>
#include <libnr/nr-coord.h>
-Geom::OptRect bounds_fast_transformed(Geom::PathVector const & pv, Geom::Matrix const & t);
-Geom::OptRect bounds_exact_transformed(Geom::PathVector const & pv, Geom::Matrix const & t);
+Geom::OptRect bounds_fast_transformed(Geom::PathVector const & pv, Geom::Affine const & t);
+Geom::OptRect bounds_exact_transformed(Geom::PathVector const & pv, Geom::Affine const & t);
-void pathv_matrix_point_bbox_wind_distance ( Geom::PathVector const & pathv, Geom::Matrix const &m, Geom::Point const &pt,
+void pathv_matrix_point_bbox_wind_distance ( Geom::PathVector const & pathv, Geom::Affine const &m, Geom::Point const &pt,
Geom::Rect *bbox, int *wind, Geom::Coord *dist,
Geom::Coord tolerance, Geom::Rect const *viewbox);
@@ -31,12 +31,12 @@ void round_rectangle_outwards(Geom::Rect & rect);
The following predefined objects are for reference
and comparison. They are defined in helper/geom.cpp
*/
-extern Geom::Matrix GEOM_MATRIX_IDENTITY;
+extern Geom::Affine GEOM_MATRIX_IDENTITY;
namespace Geom{
-bool transform_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord const epsilon);
-bool translate_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord const epsilon);
-bool matrix_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord const epsilon);
+bool transform_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon);
+bool translate_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon);
+bool matrix_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon);
}
#endif // INKSCAPE_HELPER_GEOM_H
diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp
index 7ce5c7dd2..acd2568af 100644
--- a/src/helper/pixbuf-ops.cpp
+++ b/src/helper/pixbuf-ops.cpp
@@ -132,7 +132,7 @@ sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/,
origin[Geom::Y] = origin[Geom::Y] + (screen[Geom::Y].extent() * ((1 - padding) / 2));
Geom::Scale scale( (xdpi / PX_PER_IN), (ydpi / PX_PER_IN));
- Geom::Matrix affine = scale * Geom::Translate(-origin * scale);
+ Geom::Affine affine = scale * Geom::Translate(-origin * scale);
/* Create ArenaItems and set transform */
NRArenaItem *root = SP_ITEM(doc->getRoot())->invoke_show( arena, dkey, SP_ITEM_SHOW_DISPLAY);
diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp
index d3fe2771f..2df543c6d 100644
--- a/src/helper/png-write.cpp
+++ b/src/helper/png-write.cpp
@@ -442,7 +442,7 @@ sp_export_png_file(SPDocument *doc, gchar const *filename,
* (2) a[5] = -a[3] * y1
*/
- Geom::Matrix const affine(Geom::Translate(translation)
+ Geom::Affine const affine(Geom::Translate(translation)
* Geom::Scale(width / area.width(),
height / area.height()));
diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp
index 005ca24c7..81d845e99 100644
--- a/src/knot-holder-entity.cpp
+++ b/src/knot-holder-entity.cpp
@@ -25,7 +25,7 @@
#include "snap.h"
#include "desktop.h"
#include "sp-namedview.h"
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <2geom/transforms.h>
int KnotHolderEntity::counter = 0;
@@ -76,7 +76,7 @@ KnotHolderEntity::~KnotHolderEntity()
void
KnotHolderEntity::update_knot()
{
- Geom::Matrix const i2d(item->i2d_affine());
+ Geom::Affine const i2d(item->i2d_affine());
Geom::Point dp(knot_get() * i2d);
@@ -88,7 +88,7 @@ KnotHolderEntity::update_knot()
Geom::Point
KnotHolderEntity::snap_knot_position(Geom::Point const &p)
{
- Geom::Matrix const i2d (item->i2d_affine());
+ Geom::Affine const i2d (item->i2d_affine());
Geom::Point s = p * i2d;
SnapManager &m = desktop->namedview->snap_manager;
@@ -102,7 +102,7 @@ KnotHolderEntity::snap_knot_position(Geom::Point const &p)
Geom::Point
KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::SnapConstraint const &constraint)
{
- Geom::Matrix const i2d (item->i2d_affine());
+ Geom::Affine const i2d (item->i2d_affine());
Geom::Point s = p * i2d;
SnapManager &m = desktop->namedview->snap_manager;
@@ -125,13 +125,13 @@ KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape:
static gdouble sp_pattern_extract_theta(SPPattern *pat)
{
- Geom::Matrix transf = pat->patternTransform;
+ Geom::Affine transf = pat->patternTransform;
return Geom::atan2(transf.xAxis());
}
static Geom::Point sp_pattern_extract_scale(SPPattern *pat)
{
- Geom::Matrix transf = pat->patternTransform;
+ Geom::Affine transf = pat->patternTransform;
return Geom::Point( transf.expansionX(), transf.expansionY() );
}
@@ -158,7 +158,7 @@ PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &ori
if (state) {
Geom::Point const q = p_snapped - sp_pattern_extract_trans(pat);
- item->adjust_pattern(Geom::Matrix(Geom::Translate(q)));
+ item->adjust_pattern(Geom::Affine(Geom::Translate(q)));
}
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
@@ -181,7 +181,7 @@ PatternKnotHolderEntityAngle::knot_get()
Geom::Point delta = Geom::Point(x,y);
Geom::Point scale = sp_pattern_extract_scale(pat);
gdouble theta = sp_pattern_extract_theta(pat);
- delta = delta * Geom::Matrix(Geom::Scale(scale))*Geom::Matrix(Geom::Rotate(theta));
+ delta = delta * Geom::Affine(Geom::Scale(scale))*Geom::Affine(Geom::Rotate(theta));
delta = delta + sp_pattern_extract_trans(pat);
return delta;
}
@@ -204,7 +204,7 @@ PatternKnotHolderEntityAngle::knot_set(Geom::Point const &p, Geom::Point const &
// get the scale from the current transform so we can keep it.
Geom::Point scl = sp_pattern_extract_scale(pat);
- Geom::Matrix rot = Geom::Matrix(Geom::Scale(scl)) * Geom::Matrix(Geom::Rotate(theta));
+ Geom::Affine rot = Geom::Affine(Geom::Scale(scl)) * Geom::Affine(Geom::Rotate(theta));
Geom::Point const t = sp_pattern_extract_trans(pat);
rot[4] = t[Geom::X];
rot[5] = t[Geom::Y];
@@ -237,7 +237,7 @@ PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const &
scl = Geom::Scale(d[Geom::X] / pat_x, d[Geom::Y] / pat_y);
}
- Geom::Matrix rot = (Geom::Matrix)scl * Geom::Rotate(theta);
+ Geom::Affine rot = (Geom::Affine)scl * Geom::Rotate(theta);
Geom::Point const t = sp_pattern_extract_trans(pat);
rot[4] = t[Geom::X];
@@ -255,7 +255,7 @@ PatternKnotHolderEntityScale::knot_get()
gdouble x = pattern_width(pat);
gdouble y = pattern_height(pat);
Geom::Point delta = Geom::Point(x,y);
- Geom::Matrix a = pat->patternTransform;
+ Geom::Affine a = pat->patternTransform;
a[4] = 0;
a[5] = 0;
delta = delta * a;
diff --git a/src/knotholder.cpp b/src/knotholder.cpp
index f5e28618e..5ff42a7c6 100644
--- a/src/knotholder.cpp
+++ b/src/knotholder.cpp
@@ -85,7 +85,7 @@ KnotHolder::~KnotHolder() {
void
KnotHolder::update_knots()
{
- Geom::Matrix const i2d(item->i2d_affine());
+ Geom::Affine const i2d(item->i2d_affine());
for(std::list<KnotHolderEntity *>::iterator i = entity.begin(); i != entity.end(); ++i) {
KnotHolderEntity *e = *i;
diff --git a/src/libnr/nr-convert2geom.h b/src/libnr/nr-convert2geom.h
index b4bca3516..2f87632fb 100644
--- a/src/libnr/nr-convert2geom.h
+++ b/src/libnr/nr-convert2geom.h
@@ -12,7 +12,7 @@
#include <libnr/nr-matrix.h>
#include <libnr/nr-rect.h>
#include <libnr/nr-point.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <2geom/d2.h>
#include <2geom/transforms.h>
#include <2geom/point.h>
@@ -24,11 +24,11 @@ inline NR::Point from_2geom(Geom::Point const & _pt) {
return NR::Point(_pt[0], _pt[1]);
}
-inline Geom::Matrix to_2geom(NR::Matrix const & mat) {
- Geom::Matrix mat2geom(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
+inline Geom::Affine to_2geom(NR::Matrix const & mat) {
+ Geom::Affine mat2geom(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
return mat2geom;
}
-inline NR::Matrix from_2geom(Geom::Matrix const & mat) {
+inline NR::Matrix from_2geom(Geom::Affine const & mat) {
NR::Matrix mat2geom(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
return mat2geom;
}
diff --git a/src/libnr/nr-matrix.h b/src/libnr/nr-matrix.h
index 206ff18b6..5d62dfafe 100644
--- a/src/libnr/nr-matrix.h
+++ b/src/libnr/nr-matrix.h
@@ -25,7 +25,7 @@
#include <libnr/nr-rotate.h>
#include <libnr/nr-scale.h>
#include <libnr/nr-translate.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
namespace NR {
@@ -78,7 +78,7 @@ class Matrix {
}
- Matrix(Geom::Matrix const &m) {
+ Matrix(Geom::Affine const &m) {
NR::Coord *dest = _c;
*dest++ = m[0];
@@ -231,8 +231,8 @@ class Matrix {
return _c[i];
}
- inline operator Geom::Matrix() const {
- return Geom::Matrix(_c[0], _c[1], _c[2], _c[3], _c[4], _c[5]);
+ inline operator Geom::Affine() const {
+ return Geom::Affine(_c[0], _c[1], _c[2], _c[3], _c[4], _c[5]);
}
/**
diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp
index bdf700346..6ba6440de 100644
--- a/src/libnrtype/FontInstance.cpp
+++ b/src/libnrtype/FontInstance.cpp
@@ -794,7 +794,7 @@ double font_instance::Advance(int glyph_id,bool vertical)
}
-raster_font* font_instance::RasterFont(const Geom::Matrix &trs, double stroke_width, bool vertical, JoinType stroke_join, ButtType stroke_cap, float /*miter_limit*/)
+raster_font* font_instance::RasterFont(const Geom::Affine &trs, double stroke_width, bool vertical, JoinType stroke_join, ButtType stroke_cap, float /*miter_limit*/)
{
font_style nStyle;
nStyle.transform=trs;
diff --git a/src/libnrtype/Layout-TNG-OutIter.cpp b/src/libnrtype/Layout-TNG-OutIter.cpp
index 0682e3570..4d461a486 100644
--- a/src/libnrtype/Layout-TNG-OutIter.cpp
+++ b/src/libnrtype/Layout-TNG-OutIter.cpp
@@ -343,7 +343,7 @@ Geom::Rect Layout::characterBoundingBox(iterator const &it, double *rotation) co
return Geom::Rect(top_left, bottom_right);
}
-std::vector<Geom::Point> Layout::createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Matrix const &transform) const
+std::vector<Geom::Point> Layout::createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Affine const &transform) const
{
std::vector<Geom::Point> quads;
unsigned char_index;
@@ -398,7 +398,7 @@ std::vector<Geom::Point> Layout::createSelectionShape(iterator const &it_start,
continue;
Geom::Point center_of_rotation((top_left[Geom::X] + bottom_right[Geom::X]) * 0.5,
top_left[Geom::Y] + _spans[span_index].line_height.ascent);
- Geom::Matrix total_transform = Geom::Translate(-center_of_rotation) * Geom::Rotate(char_rotation) * Geom::Translate(center_of_rotation) * transform;
+ Geom::Affine total_transform = Geom::Translate(-center_of_rotation) * Geom::Rotate(char_rotation) * Geom::Translate(center_of_rotation) * transform;
for(int i = 0; i < 4; i ++)
quads.push_back(char_box.corner(i) * total_transform);
}
diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp
index 10be0fc51..0d4d19a42 100644
--- a/src/libnrtype/Layout-TNG-Output.cpp
+++ b/src/libnrtype/Layout-TNG-Output.cpp
@@ -66,7 +66,7 @@ void Layout::LineHeight::max(LineHeight const &other)
if (other.leading > leading) leading = other.leading;
}
-void Layout::_getGlyphTransformMatrix(int glyph_index, Geom::Matrix *matrix) const
+void Layout::_getGlyphTransformMatrix(int glyph_index, Geom::Affine *matrix) const
{
Span const &span = _glyphs[glyph_index].span(this);
double sin_rotation = sin(_glyphs[glyph_index].rotation);
@@ -97,7 +97,7 @@ void Layout::show(NRArenaGroup *in_arena, NRRect const *paintbox) const
nr_arena_glyphs_group_set_style(nr_group, text_source->style);
while (glyph_index < (int)_glyphs.size() && _characters[_glyphs[glyph_index].in_character].in_span == span_index) {
if (_characters[_glyphs[glyph_index].in_character].in_glyph != -1) {
- Geom::Matrix glyph_matrix;
+ Geom::Affine glyph_matrix;
_getGlyphTransformMatrix(glyph_index, &glyph_matrix);
nr_arena_glyphs_group_add_component(nr_group, _spans[span_index].font, _glyphs[glyph_index].glyph, glyph_matrix);
}
@@ -108,7 +108,7 @@ void Layout::show(NRArenaGroup *in_arena, NRRect const *paintbox) const
nr_arena_item_request_update(NR_ARENA_ITEM(in_arena), NR_ARENA_ITEM_STATE_ALL, FALSE);
}
-void Layout::getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform, int start, int length) const
+void Layout::getBoundingBox(NRRect *bounding_box, Geom::Affine const &transform, int start, int length) const
{
for (unsigned glyph_index = 0 ; glyph_index < _glyphs.size() ; glyph_index++) {
if (_characters[_glyphs[glyph_index].in_character].in_glyph == -1) continue;
@@ -119,9 +119,9 @@ void Layout::getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform,
if ((int) _glyphs[glyph_index].in_character > start + length) continue;
}
// this could be faster
- Geom::Matrix glyph_matrix;
+ Geom::Affine glyph_matrix;
_getGlyphTransformMatrix(glyph_index, &glyph_matrix);
- Geom::Matrix total_transform = glyph_matrix;
+ Geom::Affine total_transform = glyph_matrix;
total_transform *= transform;
if(_glyphs[glyph_index].span(this).font) {
Geom::OptRect glyph_rect = _glyphs[glyph_index].span(this).font->BBox(_glyphs[glyph_index].glyph);
@@ -146,11 +146,11 @@ void Layout::getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform,
void Layout::print(SPPrintContext *ctx,
NRRect const *pbox, NRRect const *dbox, NRRect const *bbox,
- Geom::Matrix const &ctm) const
+ Geom::Affine const &ctm) const
{
if (_input_stream.empty()) return;
- Geom::Matrix ctm_2geom(ctm);
+ Geom::Affine ctm_2geom(ctm);
Direction block_progression = _blockProgression();
bool text_to_path = ctx->module->textToPath();
for (unsigned glyph_index = 0 ; glyph_index < _glyphs.size() ; ) {
@@ -161,7 +161,7 @@ void Layout::print(SPPrintContext *ctx,
glyph_index++;
continue;
}
- Geom::Matrix glyph_matrix;
+ Geom::Affine glyph_matrix;
Span const &span = _spans[_characters[_glyphs[glyph_index].in_character].in_span];
InputStreamTextSource const *text_source = static_cast<InputStreamTextSource const *>(_input_stream[span.in_input_stream_item]);
if (text_to_path || _path_fitted) {
@@ -177,7 +177,7 @@ void Layout::print(SPPrintContext *ctx,
glyph_index++;
} else {
Geom::Point g_pos(0,0); // all strings are output at (0,0) because we do the translation using the matrix
- glyph_matrix = Geom::Scale(1.0, -1.0) * (Geom::Matrix)Geom::Rotate(_glyphs[glyph_index].rotation);
+ glyph_matrix = Geom::Scale(1.0, -1.0) * (Geom::Affine)Geom::Rotate(_glyphs[glyph_index].rotation);
if (block_progression == LEFT_TO_RIGHT || block_progression == RIGHT_TO_LEFT) {
glyph_matrix[4] = span.line(this).baseline_y + span.baseline_shift;
// since we're outputting character codes, not glyphs, we want the character x
@@ -237,7 +237,7 @@ void Layout::showGlyphs(CairoRenderContext *ctx) const
Span const &span = _spans[_characters[_glyphs[glyph_index].in_character].in_span];
InputStreamTextSource const *text_source = static_cast<InputStreamTextSource const *>(_input_stream[span.in_input_stream_item]);
- Geom::Matrix glyph_matrix;
+ Geom::Affine glyph_matrix;
_getGlyphTransformMatrix(glyph_index, &glyph_matrix);
if (clip_mode) {
Geom::PathVector const *pathv = span.font->PathVector(_glyphs[glyph_index].glyph);
@@ -250,7 +250,7 @@ void Layout::showGlyphs(CairoRenderContext *ctx) const
continue;
}
- Geom::Matrix font_matrix = glyph_matrix;
+ Geom::Affine font_matrix = glyph_matrix;
font_matrix[4] = 0;
font_matrix[5] = 0;
@@ -292,7 +292,7 @@ void Layout::showGlyphs(CairoRenderContext *ctx) const
&& _characters[_glyphs[glyph_index].in_character].in_span == this_span_index);
// remove vertical flip
- Geom::Matrix flip_matrix;
+ Geom::Affine flip_matrix;
flip_matrix.setIdentity();
flip_matrix[3] = -1.0;
font_matrix = flip_matrix * font_matrix;
@@ -547,7 +547,7 @@ SPCurve *Layout::convertToCurves(iterator const &from_glyph, iterator const &to_
GSList *cc = NULL;
for (int glyph_index = from_glyph._glyph_index ; glyph_index < to_glyph._glyph_index ; glyph_index++) {
- Geom::Matrix glyph_matrix;
+ Geom::Affine glyph_matrix;
Span const &span = _glyphs[glyph_index].span(this);
_getGlyphTransformMatrix(glyph_index, &glyph_matrix);
@@ -576,7 +576,7 @@ SPCurve *Layout::convertToCurves(iterator const &from_glyph, iterator const &to_
return curve;
}
-void Layout::transform(Geom::Matrix const &transform)
+void Layout::transform(Geom::Affine const &transform)
{
// this is all massively oversimplified
// I can't actually think of anybody who'll want to use it at the moment, so it'll stay simple
diff --git a/src/libnrtype/Layout-TNG-Scanline-Makers.cpp b/src/libnrtype/Layout-TNG-Scanline-Makers.cpp
index 1bfde1f2d..7144f3876 100644
--- a/src/libnrtype/Layout-TNG-Scanline-Makers.cpp
+++ b/src/libnrtype/Layout-TNG-Scanline-Makers.cpp
@@ -85,9 +85,9 @@ Layout::ShapeScanlineMaker::ShapeScanlineMaker(Shape const *shape, Layout::Direc
_shape_needs_freeing = true;
temp_rotated_shape->Copy(const_cast<Shape*>(shape));
switch (block_progression) {
- case BOTTOM_TO_TOP: temp_rotated_shape->Transform(Geom::Matrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0)); break; // reflect about x axis
- case LEFT_TO_RIGHT: temp_rotated_shape->Transform(Geom::Matrix(0.0, 1.0, 1.0, 0.0, 0.0, 0.0)); break; // reflect about y=x
- case RIGHT_TO_LEFT: temp_rotated_shape->Transform(Geom::Matrix(0.0, -1.0, 1.0, 0.0, 0.0, 0.0)); break; // reflect about y=-x
+ case BOTTOM_TO_TOP: temp_rotated_shape->Transform(Geom::Affine(1.0, 0.0, 0.0, -1.0, 0.0, 0.0)); break; // reflect about x axis
+ case LEFT_TO_RIGHT: temp_rotated_shape->Transform(Geom::Affine(0.0, 1.0, 1.0, 0.0, 0.0, 0.0)); break; // reflect about y=x
+ case RIGHT_TO_LEFT: temp_rotated_shape->Transform(Geom::Affine(0.0, -1.0, 1.0, 0.0, 0.0, 0.0)); break; // reflect about y=-x
default: break;
}
_rotated_shape = new Shape;
diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h
index ae2b9ae9a..5ed922969 100644
--- a/src/libnrtype/Layout-TNG.h
+++ b/src/libnrtype/Layout-TNG.h
@@ -18,7 +18,7 @@
#include <libnr/nr-rotate-ops.h>
#include <libnr/nr-rect.h>
#include <2geom/d2.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <glibmm/ustring.h>
#include <pango/pango-break.h>
#include <algorithm>
@@ -337,7 +337,7 @@ public:
\param transform The transform to be applied to the entire object
prior to calculating its bounds.
*/
- void getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform, int start = -1, int length = -1) const;
+ void getBoundingBox(NRRect *bounding_box, Geom::Affine const &transform, int start = -1, int length = -1) const;
/** Sends all the glyphs to the given print context.
\param ctx I have
@@ -346,7 +346,7 @@ public:
\param bbox parameters
\param ctm do yet
*/
- void print(SPPrintContext *ctx, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox, Geom::Matrix const &ctm) const;
+ void print(SPPrintContext *ctx, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox, Geom::Affine const &ctm) const;
#ifdef HAVE_CAIRO_PDF
/** Renders all the glyphs to the given Cairo rendering context.
@@ -380,7 +380,7 @@ public:
/** Apply the given transform to all the output presently stored in
this object. This only transforms the glyph positions, The glyphs
themselves will not be transformed. */
- void transform(Geom::Matrix const &transform);
+ void transform(Geom::Affine const &transform);
//@}
@@ -501,7 +501,7 @@ public:
\a start to \a end and returns the union of these boxes. The return value
is a list of zero or more quadrilaterals specified by a group of four
points for each, thus size() is always a multiple of four. */
- std::vector<Geom::Point> createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Matrix const &transform) const;
+ std::vector<Geom::Point> createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Affine const &transform) const;
/** Returns true if \a it points to a character which is a valid cursor
position, as defined by Pango. */
@@ -746,7 +746,7 @@ private:
/** gets the overall matrix that transforms the given glyph from local
space to world space. */
- void _getGlyphTransformMatrix(int glyph_index, Geom::Matrix *matrix) const;
+ void _getGlyphTransformMatrix(int glyph_index, Geom::Affine *matrix) const;
// loads of functions to drill down the object tree, all of them
// annoyingly similar and all of them requiring predicate functors.
diff --git a/src/libnrtype/font-instance.h b/src/libnrtype/font-instance.h
index d52bd723f..33085858b 100644
--- a/src/libnrtype/font-instance.h
+++ b/src/libnrtype/font-instance.h
@@ -68,7 +68,7 @@ public:
Geom::OptRect BBox(int glyph_id);
// creates a rasterfont for the given style
- raster_font* RasterFont(Geom::Matrix const &trs, double stroke_width,
+ raster_font* RasterFont(Geom::Affine const &trs, double stroke_width,
bool vertical = false, JoinType stroke_join = join_straight,
ButtType stroke_cap = butt_straight, float miter_limit = 4.0);
// the dashes array in iStyle is copied
diff --git a/src/libnrtype/font-style.h b/src/libnrtype/font-style.h
index 20f03df86..abfac2737 100644
--- a/src/libnrtype/font-style.h
+++ b/src/libnrtype/font-style.h
@@ -1,7 +1,7 @@
#ifndef SEEN_LIBNRTYPE_FONT_STYLE_H
#define SEEN_LIBNRTYPE_FONT_STYLE_H
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <livarot/LivarotDefs.h>
#include <livarot/livarot-forward.h>
@@ -9,7 +9,7 @@
// Different raster styles.
struct font_style {
- Geom::Matrix transform; // the ctm. contains the font-size
+ Geom::Affine transform; // the ctm. contains the font-size
bool vertical; // should be rendered vertically or not?
// good font support would take the glyph alternates for vertical mode, when present
double stroke_width; // if 0, the glyph is filled; otherwise stroked
diff --git a/src/livarot/Path.cpp b/src/livarot/Path.cpp
index 66ec87274..1c04dbfb1 100644
--- a/src/livarot/Path.cpp
+++ b/src/livarot/Path.cpp
@@ -700,7 +700,7 @@ void Path::PointAndTangentAt(int piece, double at, Geom::Point &pos, Geom::Point
}
}
-void Path::Transform(const Geom::Matrix &trans)
+void Path::Transform(const Geom::Affine &trans)
{
for (std::vector<PathDescr*>::iterator i = descr_cmd.begin(); i != descr_cmd.end(); i++) {
(*i)->transform(trans);
diff --git a/src/livarot/Path.h b/src/livarot/Path.h
index 19b1ab48c..b8041c63a 100644
--- a/src/livarot/Path.h
+++ b/src/livarot/Path.h
@@ -178,12 +178,12 @@ public:
void DashPolylineFromStyle(SPStyle *style, float scale, float min_len);
//utilitaire pour inkscape
- void LoadPath(Geom::Path const &path, Geom::Matrix const &tr, bool doTransformation, bool append = false);
- void LoadPathVector(Geom::PathVector const &pv, Geom::Matrix const &tr, bool doTransformation);
+ void LoadPath(Geom::Path const &path, Geom::Affine const &tr, bool doTransformation, bool append = false);
+ void LoadPathVector(Geom::PathVector const &pv, Geom::Affine const &tr, bool doTransformation);
void LoadPathVector(Geom::PathVector const &pv);
Geom::PathVector* MakePathVector();
- void Transform(const Geom::Matrix &trans);
+ void Transform(const Geom::Affine &trans);
// decompose le chemin en ses sous-chemin
// killNoSurf=true -> oublie les chemins de surface nulle
diff --git a/src/livarot/PathCutting.cpp b/src/livarot/PathCutting.cpp
index c279eb449..ba81864a8 100644
--- a/src/livarot/PathCutting.cpp
+++ b/src/livarot/PathCutting.cpp
@@ -24,7 +24,7 @@
#include "libnr/nr-convert2geom.h"
#include <2geom/pathvector.h>
#include <2geom/point.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <2geom/sbasis-to-bezier.h>
#include <2geom/curves.h>
#include "../display/canvas-bpath.h"
@@ -400,9 +400,9 @@ void Path::AddCurve(Geom::Curve const &c)
}
else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::SVGEllipticalArc const *>(&c)) {
ArcTo( svg_elliptical_arc->finalPoint(),
- svg_elliptical_arc->ray(0), svg_elliptical_arc->ray(1),
- svg_elliptical_arc->rotation_angle(), /// \todo check that this parameter is in radians (rotation_angle returns the angle in radians!)
- svg_elliptical_arc->large_arc_flag(), !svg_elliptical_arc->sweep_flag() );
+ svg_elliptical_arc->ray(Geom::X), svg_elliptical_arc->ray(Geom::Y),
+ svg_elliptical_arc->rotationAngle(), /// \todo check that this parameter is in radians (rotation_angle returns the angle in radians!)
+ svg_elliptical_arc->largeArc(), !svg_elliptical_arc->sweep() );
} else {
//this case handles sbasis as well as all other curve types
Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
@@ -416,7 +416,7 @@ void Path::AddCurve(Geom::Curve const &c)
/** append is false by default: it means that the path should be resetted. If it is true, the path is not resetted and Geom::Path will be appended as a new path
*/
-void Path::LoadPath(Geom::Path const &path, Geom::Matrix const &tr, bool doTransformation, bool append)
+void Path::LoadPath(Geom::Path const &path, Geom::Affine const &tr, bool doTransformation, bool append)
{
if (!append) {
SetBackData (false);
@@ -449,10 +449,10 @@ void Path::LoadPath(Geom::Path const &path, Geom::Matrix const &tr, bool doTran
void Path::LoadPathVector(Geom::PathVector const &pv)
{
- LoadPathVector(pv, Geom::Matrix(), false);
+ LoadPathVector(pv, Geom::Affine(), false);
}
-void Path::LoadPathVector(Geom::PathVector const &pv, Geom::Matrix const &tr, bool doTransformation)
+void Path::LoadPathVector(Geom::PathVector const &pv, Geom::Affine const &tr, bool doTransformation)
{
SetBackData (false);
Reset();
diff --git a/src/livarot/PathSimplify.cpp b/src/livarot/PathSimplify.cpp
index c04979fe9..7b04f028a 100644
--- a/src/livarot/PathSimplify.cpp
+++ b/src/livarot/PathSimplify.cpp
@@ -252,7 +252,7 @@ bool Path::FitCubic(Geom::Point const &start, PathDescrCubicTo &res,
Geom::Point const end = res.p;
// la matrice tNN
- Geom::Matrix M(0, 0, 0, 0, 0, 0);
+ Geom::Affine M(0, 0, 0, 0, 0, 0);
for (int i = 1; i < nbPt - 1; i++) {
M[0] += N13(tk[i]) * N13(tk[i]);
M[1] += N23(tk[i]) * N13(tk[i]);
@@ -267,7 +267,7 @@ bool Path::FitCubic(Geom::Point const &start, PathDescrCubicTo &res,
return false;
}
- Geom::Matrix const iM = M.inverse();
+ Geom::Affine const iM = M.inverse();
M = iM;
// phase 1: abcisses
diff --git a/src/livarot/Shape.h b/src/livarot/Shape.h
index 44dd43a4a..5649ff9e4 100644
--- a/src/livarot/Shape.h
+++ b/src/livarot/Shape.h
@@ -288,9 +288,9 @@ public:
// create a graph that is an offseted version of the graph "of"
// the offset is dec, with joins between edges of type "join" (see LivarotDefs.h)
// the result is NOT a polygon; you need a subsequent call to ConvertToShape to get a real polygon
- int MakeOffset(Shape *of, double dec, JoinType join, double miter, bool do_profile=false, double cx = 0, double cy = 0, double radius = 0, Geom::Matrix *i2doc = NULL);
+ int MakeOffset(Shape *of, double dec, JoinType join, double miter, bool do_profile=false, double cx = 0, double cy = 0, double radius = 0, Geom::Affine *i2doc = NULL);
- int MakeTweak (int mode, Shape *a, double dec, JoinType join, double miter, bool do_profile, Geom::Point c, Geom::Point vector, double radius, Geom::Matrix *i2doc);
+ int MakeTweak (int mode, Shape *a, double dec, JoinType join, double miter, bool do_profile, Geom::Point c, Geom::Point vector, double radius, Geom::Affine *i2doc);
int PtWinding(const Geom::Point px) const; // plus rapide
int Winding(const Geom::Point px) const;
@@ -314,7 +314,7 @@ public:
void QuickScan(float &pos, int &curP, float to, FillRule directed, BitLigne* line, float step);
void QuickScan(float &pos, int &curP, float to, AlphaLigne* line, float step);
- void Transform(Geom::Matrix const &tr)
+ void Transform(Geom::Affine const &tr)
{for(std::vector<dg_point>::iterator it=_pts.begin();it!=_pts.end();it++) it->x*=tr;}
std::vector<back_data> ebData;
diff --git a/src/livarot/ShapeMisc.cpp b/src/livarot/ShapeMisc.cpp
index d6ca8c533..7d23913c3 100644
--- a/src/livarot/ShapeMisc.cpp
+++ b/src/livarot/ShapeMisc.cpp
@@ -528,7 +528,7 @@ Shape::ConvertToFormeNested (Path * dest, int nbP, Path * *orig, int wildPath,in
int
-Shape::MakeTweak (int mode, Shape *a, double power, JoinType join, double miter, bool do_profile, Geom::Point c, Geom::Point vector, double radius, Geom::Matrix *i2doc)
+Shape::MakeTweak (int mode, Shape *a, double power, JoinType join, double miter, bool do_profile, Geom::Point c, Geom::Point vector, double radius, Geom::Affine *i2doc)
{
Reset (0, 0);
MakeBackData(a->_has_back_data);
@@ -639,7 +639,7 @@ Shape::MakeTweak (int mode, Shape *a, double power, JoinType join, double miter,
Geom::Point this_vec(0,0);
if (mode == tweak_mode_push) {
- Geom::Matrix tovec (*i2doc);
+ Geom::Affine tovec (*i2doc);
tovec[4] = tovec[5] = 0;
tovec = tovec.inverse();
this_vec = this_power * (vector * tovec) ;
@@ -718,7 +718,7 @@ Shape::MakeTweak (int mode, Shape *a, double power, JoinType join, double miter,
// you gotta be very careful with the join, as anything but the right one will fuck everything up
// see PathStroke.cpp for the "right" joins
int
-Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_profile, double cx, double cy, double radius, Geom::Matrix *i2doc)
+Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_profile, double cx, double cy, double radius, Geom::Affine *i2doc)
{
Reset (0, 0);
MakeBackData(a->_has_back_data);
diff --git a/src/livarot/ShapeSweep.cpp b/src/livarot/ShapeSweep.cpp
index 00a0dd9a0..a0b9dac1d 100644
--- a/src/livarot/ShapeSweep.cpp
+++ b/src/livarot/ShapeSweep.cpp
@@ -2605,7 +2605,7 @@ Shape::TesteIntersection (Shape * ils, Shape * irs, int ilb, int irb,
usvs = irs->pData[rSt].rx - ils->pData[lSt].rx;
// pas sur de l'ordre des coefs de m
- Geom::Matrix m(ldir[0], ldir[1],
+ Geom::Affine m(ldir[0], ldir[1],
rdir[0], rdir[1],
0, 0);
double det = m.det();
diff --git a/src/livarot/path-description.cpp b/src/livarot/path-description.cpp
index 9ecfb99d6..95bd192d5 100644
--- a/src/livarot/path-description.cpp
+++ b/src/livarot/path-description.cpp
@@ -11,7 +11,7 @@ void PathDescrMoveTo::dumpSVG(Inkscape::SVGOStringStream& s, Geom::Point const &
s << "M " << p[Geom::X] << " " << p[Geom::Y] << " ";
}
-void PathDescrMoveTo::transform(Geom::Matrix const& t)
+void PathDescrMoveTo::transform(Geom::Affine const& t)
{
p = p * t;
}
@@ -32,7 +32,7 @@ PathDescr *PathDescrLineTo::clone() const
return new PathDescrLineTo(*this);
}
-void PathDescrLineTo::transform(Geom::Matrix const& t)
+void PathDescrLineTo::transform(Geom::Affine const& t)
{
p = p * t;
}
@@ -48,7 +48,7 @@ PathDescr *PathDescrBezierTo::clone() const
return new PathDescrBezierTo(*this);
}
-void PathDescrBezierTo::transform(Geom::Matrix const& t)
+void PathDescrBezierTo::transform(Geom::Affine const& t)
{
p = p * t;
}
@@ -64,7 +64,7 @@ PathDescr *PathDescrIntermBezierTo::clone() const
return new PathDescrIntermBezierTo(*this);
}
-void PathDescrIntermBezierTo::transform(Geom::Matrix const& t)
+void PathDescrIntermBezierTo::transform(Geom::Affine const& t)
{
p = p * t;
}
@@ -100,9 +100,9 @@ void PathDescrCubicTo::dump(std::ostream &s) const
<< end[Geom::X] << " " << end[Geom::Y] << " ";
}
-void PathDescrCubicTo::transform(Geom::Matrix const& t)
+void PathDescrCubicTo::transform(Geom::Affine const& t)
{
- Geom::Matrix tr = t;
+ Geom::Affine tr = t;
tr[4] = tr[5] = 0;
start = start * tr;
end = end * tr;
@@ -127,7 +127,7 @@ PathDescr *PathDescrArcTo::clone() const
return new PathDescrArcTo(*this);
}
-void PathDescrArcTo::transform(Geom::Matrix const& t)
+void PathDescrArcTo::transform(Geom::Affine const& t)
{
p = p * t;
}
diff --git a/src/livarot/path-description.h b/src/livarot/path-description.h
index 68088c27c..1d0dfb57e 100644
--- a/src/livarot/path-description.h
+++ b/src/livarot/path-description.h
@@ -37,7 +37,7 @@ struct PathDescr
virtual void dumpSVG(Inkscape::SVGOStringStream &/*s*/, Geom::Point const &/*last*/) const {}
virtual PathDescr *clone() const = 0;
- virtual void transform(Geom::Matrix const &/*t*/) {}
+ virtual void transform(Geom::Affine const &/*t*/) {}
virtual void dump(std::ostream &/*s*/) const {}
int flags; // most notably contains the path command no
@@ -53,7 +53,7 @@ struct PathDescrMoveTo : public PathDescr
void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const;
PathDescr *clone() const;
- void transform(Geom::Matrix const &t);
+ void transform(Geom::Affine const &t);
void dump(std::ostream &s) const;
Geom::Point p;
@@ -66,7 +66,7 @@ struct PathDescrLineTo : public PathDescr
void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const;
PathDescr *clone() const;
- void transform(Geom::Matrix const &t);
+ void transform(Geom::Affine const &t);
void dump(std::ostream &s) const;
Geom::Point p;
@@ -79,7 +79,7 @@ struct PathDescrBezierTo : public PathDescr
: PathDescr(descr_bezierto), p(pp), nb(n) {}
PathDescr *clone() const;
- void transform(Geom::Matrix const &t);
+ void transform(Geom::Affine const &t);
void dump(std::ostream &s) const;
Geom::Point p; // the endpoint's coordinates
@@ -95,7 +95,7 @@ struct PathDescrIntermBezierTo : public PathDescr
: PathDescr(descr_interm_bezier), p(pp) {}
PathDescr *clone() const;
- void transform(Geom::Matrix const &t);
+ void transform(Geom::Affine const &t);
void dump(std::ostream &s) const;
Geom::Point p; // control point coordinates
@@ -109,7 +109,7 @@ struct PathDescrCubicTo : public PathDescr
void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const;
PathDescr *clone() const;
- void transform(Geom::Matrix const &t);
+ void transform(Geom::Affine const &t);
void dump(std::ostream &s) const;
Geom::Point p;
@@ -125,7 +125,7 @@ struct PathDescrArcTo : public PathDescr
void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const;
PathDescr *clone() const;
- void transform(Geom::Matrix const &t);
+ void transform(Geom::Affine const &t);
void dump(std::ostream &s) const;
Geom::Point p;
diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp
index 3ea57de23..f59a38fac 100644
--- a/src/live_effects/effect.cpp
+++ b/src/live_effects/effect.cpp
@@ -38,7 +38,7 @@
#include <exception>
#include <2geom/sbasis-to-bezier.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <2geom/pathvector.h>
// include effects:
@@ -668,7 +668,7 @@ Effect::resetDefaults(SPItem * /*item*/)
}
void
-Effect::transform_multiply(Geom::Matrix const& postmul, bool set)
+Effect::transform_multiply(Geom::Affine const& postmul, bool set)
{
// cycle through all parameters. Most parameters will not need transformation, but path and point params do.
for (std::vector<Parameter *>::iterator it = param_vector.begin(); it != param_vector.end(); it++) {
diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h
index 6acba000c..7fe4e9348 100644
--- a/src/live_effects/effect.h
+++ b/src/live_effects/effect.h
@@ -92,7 +92,7 @@ public:
virtual void resetDefaults(SPItem * item);
/// /todo: is this method really necessary? it causes UI inconsistensies... (johan)
- virtual void transform_multiply(Geom::Matrix const& postmul, bool set);
+ virtual void transform_multiply(Geom::Affine const& postmul, bool set);
// /TODO: providesKnotholder() is currently used as an indicator of whether a nodepath is
// created for an item or not. When we allow both at the same time, this needs rethinking!
diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp
index dac34c5d4..38869cb97 100644
--- a/src/live_effects/lpe-copy_rotate.cpp
+++ b/src/live_effects/lpe-copy_rotate.cpp
@@ -101,12 +101,12 @@ LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & p
Piecewise<D2<SBasis> > output;
- Matrix pre = Translate(-origin) * Rotate(-deg_to_rad(starting_angle));
+ Affine pre = Translate(-origin) * Rotate(-deg_to_rad(starting_angle));
for (int i = 0; i < num_copies; ++i) {
// I first suspected the minus sign to be a bug in 2geom but it is
// likely due to SVG's choice of coordinate system orientation (max)
Rotate rot(-deg_to_rad(rotation_angle * i));
- Matrix t = pre * rot * Translate(origin);
+ Affine t = pre * rot * Translate(origin);
output.concat(pwd2_in * t);
}
diff --git a/src/live_effects/lpe-curvestitch.cpp b/src/live_effects/lpe-curvestitch.cpp
index 75218705c..80221e7b8 100644
--- a/src/live_effects/lpe-curvestitch.cpp
+++ b/src/live_effects/lpe-curvestitch.cpp
@@ -27,7 +27,7 @@
#include <2geom/bezier-to-sbasis.h>
#include <2geom/sbasis-to-bezier.h>
#include <2geom/d2.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include "ui/widget/scalar.h"
#include "libnr/nr-values.h"
@@ -120,7 +120,7 @@ LPECurveStitch::doEffect_path (std::vector<Geom::Path> const & path_in)
scaling_y = prop_scale;
}
- Matrix transform;
+ Affine transform;
transform.setXAxis( (end-start) / scaling );
transform.setYAxis( rot90(unit_vector(end-start)) * scaling_y);
transform.setTranslation( start );
@@ -195,7 +195,7 @@ LPECurveStitch::resetDefaults(SPItem * item)
* special casing is probably needed, because rotation should not be propagated to the strokepath.
*/
void
-LPECurveStitch::transform_multiply(Geom::Matrix const& postmul, bool set)
+LPECurveStitch::transform_multiply(Geom::Affine const& postmul, bool set)
{
// only take translations into account
if (postmul.isTranslation()) {
@@ -203,7 +203,7 @@ LPECurveStitch::transform_multiply(Geom::Matrix const& postmul, bool set)
} else if (!scale_y_rel.get_value()) {
// this basically means that for this transformation, the result should be the same as normal scaling the result path
// don't know how to do this yet.
-// Geom::Matrix new_postmul;
+// Geom::Affine new_postmul;
//new_postmul.setIdentity();
// new_postmul.setTranslation(postmul.translation());
// Effect::transform_multiply(new_postmul, set);
diff --git a/src/live_effects/lpe-curvestitch.h b/src/live_effects/lpe-curvestitch.h
index 8a8e43f2c..f46f2a5d2 100644
--- a/src/live_effects/lpe-curvestitch.h
+++ b/src/live_effects/lpe-curvestitch.h
@@ -32,7 +32,7 @@ public:
virtual void resetDefaults(SPItem * item);
- virtual void transform_multiply(Geom::Matrix const& postmul, bool set);
+ virtual void transform_multiply(Geom::Affine const& postmul, bool set);
private:
PathParam strokepath;
diff --git a/src/live_effects/lpe-dynastroke.cpp b/src/live_effects/lpe-dynastroke.cpp
index 0c97d50f0..97d49d83d 100644
--- a/src/live_effects/lpe-dynastroke.cpp
+++ b/src/live_effects/lpe-dynastroke.cpp
@@ -166,12 +166,12 @@ LPEDynastroke::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & p
std::cout<<"ellptic pen\n";
//FIXME: roundness=0???
double c = cos(angle_rad), s = sin(angle_rad);
- Matrix rot,slant;
- rot = Matrix(c, -s, s, c, 0, 0 );
- slant = Matrix(double(width)*roundness, 0, 0, double(width), 0, 0 );
+ Affine rot,slant;
+ rot = Affine(c, -s, s, c, 0, 0 );
+ slant = Affine(double(width)*roundness, 0, 0, double(width), 0, 0 );
Piecewise<D2<SBasis> > nn = unitVector(v * ( rot * slant ) );
- slant = Matrix( 0,-roundness, 1, 0, 0, 0 );
- rot = Matrix(-s, -c, c, -s, 0, 0 );
+ slant = Affine( 0,-roundness, 1, 0, 0, 0 );
+ rot = Affine(-s, -c, c, -s, 0, 0 );
nn = nn * (slant * rot );
n1 = nn*double(width);
diff --git a/src/live_effects/lpe-knot.cpp b/src/live_effects/lpe-knot.cpp
index fef4e1f87..e45515a8e 100644
--- a/src/live_effects/lpe-knot.cpp
+++ b/src/live_effects/lpe-knot.cpp
@@ -95,7 +95,7 @@ findShadowedTime(Geom::Path const &patha, std::vector<Geom::Point> const &pt_and
Point N = T.cw();
Point A = pt_and_dir[0]-3*width*T, B = A+6*width*T;
- Matrix mat = from_basis( T, N, pt_and_dir[0] );
+ Affine mat = from_basis( T, N, pt_and_dir[0] );
mat = mat.inverse();
Path p = patha * mat;
@@ -611,7 +611,7 @@ LPEKnot::addCanvasIndicators(SPLPEItem */*lpeitem*/, std::vector<Geom::PathVecto
svgd = "M 10,0 C 10,5.52 5.52,10 0,10 -5.52,10 -10,5.52 -10,0 c 0,-5.52 4.48,-10 10,-10 5.52,0 10,4.48 10,10 z";
}
PathVector pathv = sp_svg_read_pathv(svgd);
- pathv *= Matrix(r,0,0,r,0,0);
+ pathv *= Affine(r,0,0,r,0,0);
pathv+=switcher;
hp_vec.push_back(pathv);
}
diff --git a/src/live_effects/lpe-mirror_symmetry.cpp b/src/live_effects/lpe-mirror_symmetry.cpp
index 1af2ed6ca..dec8c9216 100644
--- a/src/live_effects/lpe-mirror_symmetry.cpp
+++ b/src/live_effects/lpe-mirror_symmetry.cpp
@@ -20,7 +20,7 @@
#include <2geom/path.h>
#include <2geom/transforms.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
namespace Inkscape {
namespace LivePathEffect {
@@ -46,7 +46,7 @@ LPEMirrorSymmetry::doOnApply (SPLPEItem *lpeitem)
using namespace Geom;
SPItem *item = SP_ITEM(lpeitem);
- Geom::Matrix t = item->i2d_affine();
+ Geom::Affine t = item->i2d_affine();
Geom::Rect bbox = *item->getBounds(t); // fixme: what happens if getBounds does not return a valid rect?
Point A(bbox.left(), bbox.bottom());
@@ -74,15 +74,15 @@ LPEMirrorSymmetry::doEffect_path (std::vector<Geom::Path> const & path_in)
Geom::Point A(mline.front().initialPoint());
Geom::Point B(mline.back().finalPoint());
- Geom::Matrix m1(1.0, 0.0, 0.0, 1.0, A[0], A[1]);
+ Geom::Affine m1(1.0, 0.0, 0.0, 1.0, A[0], A[1]);
double hyp = Geom::distance(A, B);
double c = (B[0] - A[0]) / hyp; // cos(alpha)
double s = (B[1] - A[1]) / hyp; // sin(alpha)
- Geom::Matrix m2(c, -s, s, c, 0.0, 0.0);
- Geom::Matrix sca(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
+ Geom::Affine m2(c, -s, s, c, 0.0, 0.0);
+ Geom::Affine sca(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
- Geom::Matrix m = m1.inverse() * m2;
+ Geom::Affine m = m1.inverse() * m2;
m = m * sca;
m = m * m2.inverse();
m = m * m1;
diff --git a/src/live_effects/lpe-patternalongpath.cpp b/src/live_effects/lpe-patternalongpath.cpp
index 36f257333..bbcf9b1c3 100644
--- a/src/live_effects/lpe-patternalongpath.cpp
+++ b/src/live_effects/lpe-patternalongpath.cpp
@@ -230,7 +230,7 @@ LPEPatternAlongPath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > con
}
void
-LPEPatternAlongPath::transform_multiply(Geom::Matrix const& postmul, bool set)
+LPEPatternAlongPath::transform_multiply(Geom::Affine const& postmul, bool set)
{
// overriding the Effect class default method, disabling transform forwarding to the parameters.
diff --git a/src/live_effects/lpe-patternalongpath.h b/src/live_effects/lpe-patternalongpath.h
index 1c02f2c08..f48281090 100644
--- a/src/live_effects/lpe-patternalongpath.h
+++ b/src/live_effects/lpe-patternalongpath.h
@@ -32,7 +32,7 @@ public:
virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
- virtual void transform_multiply(Geom::Matrix const& postmul, bool set);
+ virtual void transform_multiply(Geom::Affine const& postmul, bool set);
PathParam pattern;
private:
diff --git a/src/live_effects/lpe-rough-hatches.cpp b/src/live_effects/lpe-rough-hatches.cpp
index 76456cd87..055b63661 100644
--- a/src/live_effects/lpe-rough-hatches.cpp
+++ b/src/live_effects/lpe-rough-hatches.cpp
@@ -28,7 +28,7 @@
#include <2geom/bezier-to-sbasis.h>
#include <2geom/sbasis-to-bezier.h>
#include <2geom/d2.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include "ui/widget/scalar.h"
#include "libnr/nr-values.h"
@@ -309,12 +309,12 @@ LPERoughHatches::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const &
}
Point transformed_org = direction.getOrigin();
Piecewise<SBasis> tilter;//used to bend the hatches
- Matrix bend_mat;//used to bend the hatches
+ Affine bend_mat;//used to bend the hatches
if (do_bend.get_value()){
Point bend_dir = -rot90(unit_vector(bender.getVector()));
double bend_amount = L2(bender.getVector());
- bend_mat = Matrix(-bend_dir[Y], bend_dir[X], bend_dir[X], bend_dir[Y],0,0);
+ bend_mat = Affine(-bend_dir[Y], bend_dir[X], bend_dir[X], bend_dir[Y],0,0);
transformed_pwd2_in = transformed_pwd2_in * bend_mat;
tilter = Piecewise<SBasis>(shift(Linear(-bend_amount),1));
OptRect bbox = bounds_exact( transformed_pwd2_in );
@@ -325,7 +325,7 @@ LPERoughHatches::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const &
}
hatch_dist = Geom::L2(direction.getVector())/5;
Point hatches_dir = rot90(unit_vector(direction.getVector()));
- Matrix mat(-hatches_dir[Y], hatches_dir[X], hatches_dir[X], hatches_dir[Y],0,0);
+ Affine mat(-hatches_dir[Y], hatches_dir[X], hatches_dir[X], hatches_dir[Y],0,0);
transformed_pwd2_in = transformed_pwd2_in * mat;
transformed_org *= mat;
diff --git a/src/live_effects/lpe-sketch.cpp b/src/live_effects/lpe-sketch.cpp
index f03bac811..9488da84a 100644
--- a/src/live_effects/lpe-sketch.cpp
+++ b/src/live_effects/lpe-sketch.cpp
@@ -343,7 +343,7 @@ LPESketch::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_
//TODO: put this 4 as a parameter in the UI...
//TODO: what if with v=0?
double l = tgtlength*(1-tgtlength_rdm)/v_t.length();
- double r = pow(v_t.length(),3)/cross(a_t,v_t);
+ double r = std::pow(v_t.length(),3)/cross(a_t,v_t);
r = sqrt((2*fabs(r)-tgtscale)*tgtscale)/v_t.length();
l=(r<l)?r:l;
//collect the tgt segment into output.
diff --git a/src/live_effects/lpe-spiro.cpp b/src/live_effects/lpe-spiro.cpp
index 7c8262af6..54554ebb2 100644
--- a/src/live_effects/lpe-spiro.cpp
+++ b/src/live_effects/lpe-spiro.cpp
@@ -9,7 +9,7 @@
#include "display/curve.h"
#include <typeinfo>
#include <2geom/pathvector.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <2geom/bezier-curve.h>
#include <2geom/hvlinesegment.h>
#include <2geom/isnan.h>
diff --git a/src/live_effects/lpe-vonkoch.cpp b/src/live_effects/lpe-vonkoch.cpp
index f52ee9f69..56d66d137 100644
--- a/src/live_effects/lpe-vonkoch.cpp
+++ b/src/live_effects/lpe-vonkoch.cpp
@@ -88,25 +88,25 @@ LPEVonKoch::doEffect_path (std::vector<Geom::Path> const & path_in)
}
//Collect transform matrices.
- Matrix m0;
+ Affine m0;
Geom::Path refpath = ref_path.get_pathvector().front();
Point A = refpath.pointAt(0);
Point B = refpath.pointAt(refpath.size());
Point u = B-A;
- m0 = Matrix(u[X], u[Y],-u[Y], u[X], A[X], A[Y]);
+ m0 = Affine(u[X], u[Y],-u[Y], u[X], A[X], A[Y]);
//FIXME: a path is used as ref instead of 2 points to work around path/point param incompatibility bug.
//Point u = refB-refA;
- //m0 = Matrix(u[X], u[Y],-u[Y], u[X], refA[X], refA[Y]);
+ //m0 = Affine(u[X], u[Y],-u[Y], u[X], refA[X], refA[Y]);
m0 = m0.inverse();
- std::vector<Matrix> transforms;
+ std::vector<Affine> transforms;
for (unsigned i=0; i<generating_path.size(); i++){
- Matrix m;
+ Affine m;
if(generating_path[i].size()==1){
Point p = generating_path[i].pointAt(0);
Point u = generating_path[i].pointAt(1)-p;
- m = Matrix(u[X], u[Y],-u[Y], u[X], p[X], p[Y]);
+ m = Affine(u[X], u[Y],-u[Y], u[X], p[X], p[Y]);
m = m0*m;
transforms.push_back(m);
}else if(generating_path[i].size()>=2){
@@ -118,7 +118,7 @@ LPEVonKoch::doEffect_path (std::vector<Geom::Path> const & path_in)
v[X] = -u[Y]*sign;
v[Y] = u[X]*sign;
}
- m = Matrix(u[X], u[Y],v[X], v[Y], p[X], p[Y]);
+ m = Affine(u[X], u[Y],v[X], v[Y], p[X], p[Y]);
m = m0*m;
transforms.push_back(m);
}
@@ -133,16 +133,16 @@ LPEVonKoch::doEffect_path (std::vector<Geom::Path> const & path_in)
for (unsigned k = 0; k < path_in.size(); k++){
path_in_complexity+=path_in[k].size();
}
- double complexity = pow(transforms.size(),nbgenerations)*path_in_complexity;
+ double complexity = std::pow(transforms.size(),nbgenerations)*path_in_complexity;
if (drawall.get_value()){
int k = transforms.size();
if(k>1){
- complexity = (pow(k,nbgenerations+1)-1)/(k-1)*path_in_complexity;
+ complexity = (std::pow(k,nbgenerations+1)-1)/(k-1)*path_in_complexity;
}else{
complexity = nbgenerations*k*path_in_complexity;
}
}else{
- complexity = pow(transforms.size(),nbgenerations)*path_in_complexity;
+ complexity = std::pow(transforms.size(),nbgenerations)*path_in_complexity;
}
if (complexity > double(maxComplexity)){
g_warning("VonKoch lpe's output too complex. Effect bypassed.");
@@ -288,8 +288,8 @@ LPEVonKoch::resetDefaults(SPItem * item)
refpaths.push_back(path);
ref_path.set_new_value(refpaths, true);
- paths.push_back(path * Matrix(1./3,0,0,1./3, A[X]*2./3, A[Y]*2./3 + boundingbox_Y.extent()/2));
- paths.push_back(path * Matrix(1./3,0,0,1./3, B[X]*2./3, B[Y]*2./3 + boundingbox_Y.extent()/2));
+ paths.push_back(path * Affine(1./3,0,0,1./3, A[X]*2./3, A[Y]*2./3 + boundingbox_Y.extent()/2));
+ paths.push_back(path * Affine(1./3,0,0,1./3, B[X]*2./3, B[Y]*2./3 + boundingbox_Y.extent()/2));
generator.set_new_value(paths, true);
//FIXME: a path is used as ref instead of 2 points to work around path/point param incompatibility bug.
@@ -300,8 +300,8 @@ LPEVonKoch::resetDefaults(SPItem * item)
//std::vector<Geom::Path> paths;
//Geom::Path path = Geom::Path( (Point) refA);
//path.appendNew<Geom::LineSegment>( (Point) refB );
- //paths.push_back(path * Matrix(1./3,0,0,1./3, refA[X]*2./3, refA[Y]*2./3 + boundingbox_Y.extent()/2));
- //paths.push_back(path * Matrix(1./3,0,0,1./3, refB[X]*2./3, refB[Y]*2./3 + boundingbox_Y.extent()/2));
+ //paths.push_back(path * Affine(1./3,0,0,1./3, refA[X]*2./3, refA[Y]*2./3 + boundingbox_Y.extent()/2));
+ //paths.push_back(path * Affine(1./3,0,0,1./3, refB[X]*2./3, refB[Y]*2./3 + boundingbox_Y.extent()/2));
//paths.push_back(path);
//generator.set_new_value(paths, true);
}
diff --git a/src/live_effects/lpegroupbbox.cpp b/src/live_effects/lpegroupbbox.cpp
index e6fc95f86..2678509a4 100644
--- a/src/live_effects/lpegroupbbox.cpp
+++ b/src/live_effects/lpegroupbbox.cpp
@@ -28,7 +28,7 @@ GroupBBoxEffect::original_bbox(SPLPEItem *lpeitem, bool absolute)
// Get item bounding box
SPItem* item = SP_ITEM(lpeitem);
- Geom::Matrix transform;
+ Geom::Affine transform;
if (absolute) {
transform = item->i2doc_affine();
}
diff --git a/src/live_effects/parameter/parameter.h b/src/live_effects/parameter/parameter.h
index ff878e717..cee10bc70 100644
--- a/src/live_effects/parameter/parameter.h
+++ b/src/live_effects/parameter/parameter.h
@@ -67,7 +67,7 @@ public:
virtual void param_editOncanvas(SPItem * /*item*/, SPDesktop * /*dt*/) {};
virtual void param_setup_nodepath(Inkscape::NodePath::Path */*np*/) {};
- virtual void param_transform_multiply(Geom::Matrix const& /*postmul*/, bool /*set*/) {};
+ virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/) {};
Glib::ustring param_key;
Inkscape::UI::Widget::Registry * param_wr;
diff --git a/src/live_effects/parameter/path.cpp b/src/live_effects/parameter/path.cpp
index 8d9b2376f..d652dfd0c 100644
--- a/src/live_effects/parameter/path.cpp
+++ b/src/live_effects/parameter/path.cpp
@@ -235,7 +235,7 @@ PathParam::addCanvasIndicators(SPLPEItem */*lpeitem*/, std::vector<Geom::PathVec
* Only applies transform when not referring to other path!
*/
void
-PathParam::param_transform_multiply(Geom::Matrix const& postmul, bool /*set*/)
+PathParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/)
{
// only apply transform when not referring to other path
if (!href) {
diff --git a/src/live_effects/parameter/path.h b/src/live_effects/parameter/path.h
index 23ad51417..e3d3901cc 100644
--- a/src/live_effects/parameter/path.h
+++ b/src/live_effects/parameter/path.h
@@ -49,7 +49,7 @@ public:
virtual void param_setup_nodepath(Inkscape::NodePath::Path *np);
virtual void addCanvasIndicators(SPLPEItem *lpeitem, std::vector<Geom::PathVector> &hp_vec);
- virtual void param_transform_multiply(Geom::Matrix const& /*postmul*/, bool /*set*/);
+ virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/);
sigc::signal <void> signal_path_pasted;
sigc::signal <void> signal_path_changed;
diff --git a/src/live_effects/parameter/point.cpp b/src/live_effects/parameter/point.cpp
index e7abb70ea..550a8517c 100644
--- a/src/live_effects/parameter/point.cpp
+++ b/src/live_effects/parameter/point.cpp
@@ -84,7 +84,7 @@ PointParam::param_newWidget(Gtk::Tooltips * /*tooltips*/)
param_effect->getSPDoc() ) );
// TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP)
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- Geom::Matrix transf = desktop->doc2dt();
+ Geom::Affine transf = desktop->doc2dt();
pointwdg->setTransform(transf);
pointwdg->setValue( *this );
pointwdg->clearProgrammatically();
@@ -114,7 +114,7 @@ PointParam::param_set_and_write_new_value (Geom::Point newpoint)
}
void
-PointParam::param_transform_multiply(Geom::Matrix const& postmul, bool /*set*/)
+PointParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/)
{
param_set_and_write_new_value( (*this) * postmul );
}
diff --git a/src/live_effects/parameter/point.h b/src/live_effects/parameter/point.h
index ec61fcd88..2d4e942c0 100644
--- a/src/live_effects/parameter/point.h
+++ b/src/live_effects/parameter/point.h
@@ -45,7 +45,7 @@ public:
void param_set_and_write_new_value(Geom::Point newpoint);
- virtual void param_transform_multiply(Geom::Matrix const& /*postmul*/, bool /*set*/);
+ virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/);
void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);
diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp
index c20980193..9d43e8447 100644
--- a/src/live_effects/parameter/powerstrokepointarray.cpp
+++ b/src/live_effects/parameter/powerstrokepointarray.cpp
@@ -55,7 +55,7 @@ PowerStrokePointArrayParam::param_newWidget(Gtk::Tooltips * /*tooltips*/)
param_effect->getSPDoc() ) );
// TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP)
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- Geom::Matrix transf = desktop->doc2dt();
+ Geom::Affine transf = desktop->doc2dt();
pointwdg->setTransform(transf);
pointwdg->setValue( *this );
pointwdg->clearProgrammatically();
@@ -71,7 +71,7 @@ PowerStrokePointArrayParam::param_newWidget(Gtk::Tooltips * /*tooltips*/)
void
-PowerStrokePointArrayParam::param_transform_multiply(Geom::Matrix const& postmul, bool /*set*/)
+PowerStrokePointArrayParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/)
{
// param_set_and_write_new_value( (*this) * postmul );
}
diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h
index 06d406dfe..d984a7de5 100644
--- a/src/live_effects/parameter/powerstrokepointarray.h
+++ b/src/live_effects/parameter/powerstrokepointarray.h
@@ -36,7 +36,7 @@ public:
virtual Gtk::Widget * param_newWidget(Gtk::Tooltips * tooltips);
- virtual void param_transform_multiply(Geom::Matrix const& /*postmul*/, bool /*set*/);
+ virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/);
void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);
diff --git a/src/live_effects/parameter/vector.cpp b/src/live_effects/parameter/vector.cpp
index 5496b52f2..9086ab376 100644
--- a/src/live_effects/parameter/vector.cpp
+++ b/src/live_effects/parameter/vector.cpp
@@ -112,9 +112,9 @@ VectorParam::set_and_write_new_values(Geom::Point const &new_origin, Geom::Point
}
void
-VectorParam::param_transform_multiply(Geom::Matrix const& postmul, bool /*set*/)
+VectorParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/)
{
- set_and_write_new_values( origin * postmul, vector * postmul.without_translation() );
+ set_and_write_new_values( origin * postmul, vector * postmul.withoutTranslation() );
}
diff --git a/src/live_effects/parameter/vector.h b/src/live_effects/parameter/vector.h
index a4c29d317..cb7094b7f 100644
--- a/src/live_effects/parameter/vector.h
+++ b/src/live_effects/parameter/vector.h
@@ -48,7 +48,7 @@ public:
void set_and_write_new_values(Geom::Point const &new_origin, Geom::Point const &new_vector);
- virtual void param_transform_multiply(Geom::Matrix const &postmul, bool set);
+ virtual void param_transform_multiply(Geom::Affine const &postmul, bool set);
void set_vector_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);
void set_origin_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);
diff --git a/src/lpe-tool-context.cpp b/src/lpe-tool-context.cpp
index f25949296..d4c795656 100644
--- a/src/lpe-tool-context.cpp
+++ b/src/lpe-tool-context.cpp
@@ -426,7 +426,7 @@ lpetool_context_reset_limiting_bbox(SPLPEToolContext *lc)
Geom::Point A, B;
lpetool_get_limiting_bbox_corners(document, A, B);
- Geom::Matrix doc2dt(lc->desktop->doc2dt());
+ Geom::Affine doc2dt(lc->desktop->doc2dt());
A *= doc2dt;
B *= doc2dt;
diff --git a/src/marker.cpp b/src/marker.cpp
index 0ec92a1ff..efbe27680 100644
--- a/src/marker.cpp
+++ b/src/marker.cpp
@@ -24,7 +24,7 @@
#include "libnr/nr-scale-matrix-ops.h"
#include "libnr/nr-translate-matrix-ops.h"
#include "libnr/nr-convert2geom.h"
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include "svg/svg.h"
#include "display/nr-arena-group.h"
#include "xml/repr.h"
@@ -50,7 +50,7 @@ static Inkscape::XML::Node *sp_marker_write (SPObject *object, Inkscape::XML::Do
static NRArenaItem *sp_marker_private_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
static void sp_marker_private_hide (SPItem *item, unsigned int key);
-static void sp_marker_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+static void sp_marker_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static void sp_marker_print (SPItem *item, SPPrintContext *ctx);
static void sp_marker_view_remove (SPMarker *marker, SPMarkerView *view, unsigned int destroyitems);
@@ -463,7 +463,7 @@ sp_marker_update (SPObject *object, SPCtx *ctx, guint flags)
for (v = marker->views; v != NULL; v = v->next) {
for (unsigned i = 0 ; i < v->items.size() ; i++) {
if (v->items[i]) {
- Geom::Matrix tmp = marker->c2p;
+ Geom::Affine tmp = marker->c2p;
nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->items[i]), &tmp);
}
}
@@ -557,7 +557,7 @@ sp_marker_private_hide (SPItem */*item*/, unsigned int /*key*/)
* This routine is disabled to break propagation.
*/
static void
-sp_marker_bbox(SPItem const *, NRRect *, Geom::Matrix const &, unsigned const)
+sp_marker_bbox(SPItem const *, NRRect *, Geom::Affine const &, unsigned const)
{
/* Break propagation */
}
@@ -619,7 +619,7 @@ sp_marker_show_dimension (SPMarker *marker, unsigned int key, unsigned int size)
NRArenaItem *
sp_marker_show_instance ( SPMarker *marker, NRArenaItem *parent,
unsigned int key, unsigned int pos,
- Geom::Matrix const &base, float linewidth)
+ Geom::Affine const &base, float linewidth)
{
for (SPMarkerView *v = marker->views; v != NULL; v = v->next) {
if (v->key == key) {
@@ -635,12 +635,12 @@ sp_marker_show_instance ( SPMarker *marker, NRArenaItem *parent,
/* fixme: Position (Lauris) */
nr_arena_item_add_child (parent, v->items[pos], NULL);
/* nr_arena_item_unref (v->items[pos]); */
- Geom::Matrix tmp = marker->c2p;
+ Geom::Affine tmp = marker->c2p;
nr_arena_group_set_child_transform((NRArenaGroup *) v->items[pos], &tmp);
}
}
if (v->items[pos]) {
- Geom::Matrix m;
+ Geom::Affine m;
if (marker->orient_auto) {
m = base;
} else {
@@ -710,7 +710,7 @@ sp_marker_view_remove (SPMarker *marker, SPMarkerView *view, unsigned int destro
delete view;
}
-const gchar *generate_marker(GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Matrix /*transform*/, Geom::Matrix move)
+const gchar *generate_marker(GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine /*transform*/, Geom::Affine move)
{
Inkscape::XML::Document *xml_doc = document->getReprDoc();
Inkscape::XML::Node *defsrepr = SP_DOCUMENT_DEFS(document)->getRepr();
@@ -735,7 +735,7 @@ const gchar *generate_marker(GSList *reprs, Geom::Rect bounds, SPDocument *docum
Inkscape::XML::Node *node = (Inkscape::XML::Node *)(i->data);
SPItem *copy = SP_ITEM(mark_object->appendChildRepr(node));
- Geom::Matrix dup_transform;
+ Geom::Affine dup_transform;
if (!sp_svg_transform_read (node->attribute("transform"), &dup_transform))
dup_transform = Geom::identity();
dup_transform *= move;
diff --git a/src/marker.h b/src/marker.h
index f2d74a3a6..09461b3a1 100644
--- a/src/marker.h
+++ b/src/marker.h
@@ -27,7 +27,7 @@ class SPMarkerClass;
class SPMarkerView;
#include <2geom/rect.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include "svg/svg-length.h"
#include "enums.h"
#include "sp-item-group.h"
@@ -61,7 +61,7 @@ struct SPMarker : public SPGroup {
unsigned int aspect_clip : 1;
/* Child to parent additional transform */
- Geom::Matrix c2p;
+ Geom::Affine c2p;
/* Private views */
SPMarkerView *views;
@@ -87,9 +87,9 @@ protected:
void sp_marker_show_dimension (SPMarker *marker, unsigned int key, unsigned int size);
NRArenaItem *sp_marker_show_instance (SPMarker *marker, NRArenaItem *parent,
unsigned int key, unsigned int pos,
- Geom::Matrix const &base, float linewidth);
+ Geom::Affine const &base, float linewidth);
void sp_marker_hide (SPMarker *marker, unsigned int key);
-const gchar *generate_marker (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Matrix transform, Geom::Matrix move);
+const gchar *generate_marker (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move);
#endif
diff --git a/src/object-edit.cpp b/src/object-edit.cpp
index 27e75afab..a683500c0 100644
--- a/src/object-edit.cpp
+++ b/src/object-edit.cpp
@@ -481,7 +481,7 @@ Box3DKnotHolderEntity::knot_set_generic(SPItem *item, unsigned int knot_id, Geom
g_assert(item != NULL);
SPBox3D *box = SP_BOX3D(item);
- Geom::Matrix const i2d (item->i2d_affine ());
+ Geom::Affine const i2d (item->i2d_affine ());
Box3D::Axis movement;
if ((knot_id < 4) != (state & GDK_SHIFT_MASK)) {
@@ -657,7 +657,7 @@ Box3DKnotHolderEntityCenter::knot_set(Geom::Point const &new_pos, Geom::Point co
Geom::Point const s = snap_knot_position(new_pos);
SPBox3D *box = SP_BOX3D(item);
- Geom::Matrix const i2d (item->i2d_affine ());
+ Geom::Affine const i2d (item->i2d_affine ());
box3d_set_center (SP_BOX3D(item), s * i2d, origin * i2d, !(state & GDK_SHIFT_MASK) ? Box3D::XY : Box3D::Z,
state & GDK_CONTROL_MASK);
diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp
index 43651f002..e123173a5 100644
--- a/src/object-snapper.cpp
+++ b/src/object-snapper.cpp
@@ -84,7 +84,7 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent,
bool const &first_point,
Geom::Rect const &bbox_to_snap,
bool const clip_or_mask,
- Geom::Matrix const additional_affine) const // transformation of the item being clipped / masked
+ Geom::Affine const additional_affine) const // transformation of the item being clipped / masked
{
if (!ThisSnapperMightSnap()) {
return;
@@ -198,7 +198,7 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapSourceType const &t,
}
for (std::vector<SnapCandidateItem>::const_iterator i = _candidates->begin(); i != _candidates->end(); i++) {
- //Geom::Matrix i2doc(Geom::identity());
+ //Geom::Affine i2doc(Geom::identity());
SPItem *root_item = (*i).item;
if (SP_IS_USE((*i).item)) {
root_item = sp_use_root(SP_USE((*i).item));
@@ -378,7 +378,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/,
for (std::vector<SnapCandidateItem>::const_iterator i = _candidates->begin(); i != _candidates->end(); i++) {
/* Transform the requested snap point to this item's coordinates */
- Geom::Matrix i2doc(Geom::identity());
+ Geom::Affine i2doc(Geom::identity());
SPItem *root_item = NULL;
/* We might have a clone at hand, so make sure we get the root item */
if (SP_IS_USE((*i).item)) {
diff --git a/src/object-snapper.h b/src/object-snapper.h
index 6bde3dd39..6e3cc620f 100644
--- a/src/object-snapper.h
+++ b/src/object-snapper.h
@@ -71,7 +71,7 @@ private:
bool const &first_point,
Geom::Rect const &bbox_to_snap,
bool const _clip_or_mask,
- Geom::Matrix const additional_affine) const;
+ Geom::Affine const additional_affine) const;
void _snapNodes(SnappedConstraints &sc,
Inkscape::SnapCandidatePoint const &p, // in desktop coordinates
diff --git a/src/persp3d.cpp b/src/persp3d.cpp
index 74208444b..fbd782294 100644
--- a/src/persp3d.cpp
+++ b/src/persp3d.cpp
@@ -385,7 +385,7 @@ persp3d_update_with_point (Persp3DImpl *persp_impl, Proj::Axis const axis, Proj:
}
void
-persp3d_apply_affine_transformation (Persp3D *persp, Geom::Matrix const &xform) {
+persp3d_apply_affine_transformation (Persp3D *persp, Geom::Affine const &xform) {
persp->perspective_impl->tmat *= xform;
persp3d_update_box_reprs(persp);
SP_OBJECT(persp)->updateRepr(SP_OBJECT_WRITE_EXT);
diff --git a/src/persp3d.h b/src/persp3d.h
index 44b6d2435..db4971635 100644
--- a/src/persp3d.h
+++ b/src/persp3d.h
@@ -74,7 +74,7 @@ void persp3d_toggle_VP (Persp3D *persp, Proj::Axis axis, bool set_undo = true);
void persp3d_toggle_VPs (std::list<Persp3D *>, Proj::Axis axis);
void persp3d_set_VP_state (Persp3D *persp, Proj::Axis axis, Proj::VPState state);
void persp3d_rotate_VP (Persp3D *persp, Proj::Axis axis, double angle, bool alt_pressed); // angle is in degrees
-void persp3d_apply_affine_transformation (Persp3D *persp, Geom::Matrix const &xform);
+void persp3d_apply_affine_transformation (Persp3D *persp, Geom::Affine const &xform);
void persp3d_add_box (Persp3D *persp, SPBox3D *box);
void persp3d_remove_box (Persp3D *persp, SPBox3D *box);
diff --git a/src/print.cpp b/src/print.cpp
index e0601aa33..fe52ea6dd 100644
--- a/src/print.cpp
+++ b/src/print.cpp
@@ -27,14 +27,14 @@
/* Identity typedef */
-unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Matrix const &transform, float opacity)
+unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Affine const &transform, float opacity)
{
- Geom::Matrix const ntransform(transform);
+ Geom::Affine const ntransform(transform);
return sp_print_bind(ctx, &ntransform, opacity);
}
unsigned int
-sp_print_bind(SPPrintContext *ctx, Geom::Matrix const *transform, float opacity)
+sp_print_bind(SPPrintContext *ctx, Geom::Affine const *transform, float opacity)
{
return ctx->module->bind(transform, opacity);
}
@@ -52,14 +52,14 @@ sp_print_comment(SPPrintContext *ctx, char const *comment)
}
unsigned int
-sp_print_fill(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Matrix const *ctm, SPStyle const *style,
+sp_print_fill(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Affine const *ctm, SPStyle const *style,
NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
{
return ctx->module->fill(pathv, ctm, style, pbox, dbox, bbox);
}
unsigned int
-sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Matrix const *ctm, SPStyle const *style,
+sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Affine const *ctm, SPStyle const *style,
NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
{
return ctx->module->stroke(pathv, ctm, style, pbox, dbox, bbox);
@@ -68,7 +68,7 @@ sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Matrix
unsigned int
sp_print_image_R8G8B8A8_N(SPPrintContext *ctx,
guchar *px, unsigned int w, unsigned int h, unsigned int rs,
- Geom::Matrix const *transform, SPStyle const *style)
+ Geom::Affine const *transform, SPStyle const *style)
{
return ctx->module->image(px, w, h, rs, transform, style);
}
diff --git a/src/print.h b/src/print.h
index f566d4e31..70361fb14 100644
--- a/src/print.h
+++ b/src/print.h
@@ -21,18 +21,18 @@ struct SPPrintContext {
Inkscape::Extension::Print *module;
};
-unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Matrix const &transform, float opacity);
-unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Matrix const *transform, float opacity);
+unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Affine const &transform, float opacity);
+unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Affine const *transform, float opacity);
unsigned int sp_print_release(SPPrintContext *ctx);
unsigned int sp_print_comment(SPPrintContext *ctx, char const *comment);
-unsigned int sp_print_fill(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Matrix const *ctm, SPStyle const *style,
+unsigned int sp_print_fill(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Affine const *ctm, SPStyle const *style,
NRRect const *pbox, NRRect const *dbox, NRRect const *bbox);
-unsigned int sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Matrix const *transform, SPStyle const *style,
+unsigned int sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Affine const *transform, SPStyle const *style,
NRRect const *pbox, NRRect const *dbox, NRRect const *bbox);
unsigned int sp_print_image_R8G8B8A8_N(SPPrintContext *ctx,
guchar *px, unsigned int w, unsigned int h, unsigned int rs,
- Geom::Matrix const *transform, SPStyle const *style);
+ Geom::Affine const *transform, SPStyle const *style);
unsigned int sp_print_text(SPPrintContext *ctx, char const *text, Geom::Point p,
SPStyle const *style);
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index d63ee7e83..9acacf7d5 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -216,7 +216,7 @@ void SelectionHelper::selectPrev(SPDesktop *dt)
* Copies repr and its inherited css style elements, along with the accumulated transform 'full_t',
* then prepends the copy to 'clip'.
*/
-void sp_selection_copy_one(Inkscape::XML::Node *repr, Geom::Matrix full_t, GSList **clip, Inkscape::XML::Document* xml_doc)
+void sp_selection_copy_one(Inkscape::XML::Node *repr, Geom::Affine full_t, GSList **clip, Inkscape::XML::Document* xml_doc)
{
Inkscape::XML::Node *copy = repr->duplicate(xml_doc);
@@ -261,10 +261,10 @@ GSList *sp_selection_paste_impl(SPDocument *doc, SPObject *parent, GSList **clip
Inkscape::XML::Node *copy = repr->duplicate(xml_doc);
// premultiply the item transform by the accumulated parent transform in the paste layer
- Geom::Matrix local(SP_ITEM(parent)->i2doc_affine());
+ Geom::Affine local(SP_ITEM(parent)->i2doc_affine());
if (!local.isIdentity()) {
gchar const *t_str = copy->attribute("transform");
- Geom::Matrix item_t(Geom::identity());
+ Geom::Affine item_t(Geom::identity());
if (t_str)
sp_svg_transform_read(t_str, &item_t);
item_t *= local.inverse();
@@ -591,7 +591,7 @@ void sp_selection_group_impl(GSList *p, Inkscape::XML::Node *group, Inkscape::XM
// At this point, current may already have no item, due to its being a clone whose original is already moved away
// So we copy it artificially calculating the transform from its repr->attr("transform") and the parent transform
gchar const *t_str = current->attribute("transform");
- Geom::Matrix item_t(Geom::identity());
+ Geom::Affine item_t(Geom::identity());
if (t_str)
sp_svg_transform_read(t_str, &item_t);
item_t *= SP_ITEM(doc->getObjectByRepr(current->parent()))->i2doc_affine();
@@ -1303,7 +1303,7 @@ value of set_i2d==false is only used by seltrans when it's dragging objects live
that case, items are already in the new position, but the repr is in the old, and this function
then simply updates the repr from item->transform.
*/
-void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix const &affine, bool set_i2d, bool compensate)
+void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d, bool compensate)
{
if (selection->isEmpty())
return;
@@ -1403,26 +1403,26 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons
SP_OBJECT(item)->readAttr( "transform" );
// calculate the matrix we need to apply to the clone to cancel its induced transform from its original
- Geom::Matrix parent2dt = SP_ITEM(SP_OBJECT_PARENT(item))->i2d_affine();
- Geom::Matrix t = parent2dt * affine * parent2dt.inverse();
- Geom::Matrix t_inv = t.inverse();
- Geom::Matrix result = t_inv * item->transform * t;
+ Geom::Affine parent2dt = SP_ITEM(SP_OBJECT_PARENT(item))->i2d_affine();
+ Geom::Affine t = parent2dt * affine * parent2dt.inverse();
+ Geom::Affine t_inv = t.inverse();
+ Geom::Affine result = t_inv * item->transform * t;
if ((prefs_parallel || prefs_unmoved) && affine.isTranslation()) {
// we need to cancel out the move compensation, too
// find out the clone move, same as in sp_use_move_compensate
- Geom::Matrix parent = sp_use_get_parent_transform(SP_USE(item));
- Geom::Matrix clone_move = parent.inverse() * t * parent;
+ Geom::Affine parent = sp_use_get_parent_transform(SP_USE(item));
+ Geom::Affine clone_move = parent.inverse() * t * parent;
if (prefs_parallel) {
- Geom::Matrix move = result * clone_move * t_inv;
+ Geom::Affine move = result * clone_move * t_inv;
item->doWriteTransform(SP_OBJECT_REPR(item), move, &move, compensate);
} else if (prefs_unmoved) {
//if (SP_IS_USE(sp_use_get_original(SP_USE(item))))
// clone_move = Geom::identity();
- Geom::Matrix move = result * clone_move;
+ Geom::Affine move = result * clone_move;
item->doWriteTransform(SP_OBJECT_REPR(item), move, &t, compensate);
}
@@ -1433,7 +1433,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons
} else {
if (set_i2d) {
- item->set_i2d_affine(item->i2d_affine() * (Geom::Matrix)affine);
+ item->set_i2d_affine(item->i2d_affine() * (Geom::Affine)affine);
}
item->doWriteTransform(SP_OBJECT_REPR(item), item->transform, NULL, compensate);
}
@@ -1483,7 +1483,7 @@ sp_selection_scale_absolute(Inkscape::Selection *selection,
y1 - y0);
Geom::Scale const scale( newSize * Geom::Scale(bbox->dimensions()).inverse() );
Geom::Translate const o2n(x0, y0);
- Geom::Matrix const final( p2o * scale * o2n );
+ Geom::Affine const final( p2o * scale * o2n );
sp_selection_apply_affine(selection, final);
}
@@ -1509,7 +1509,7 @@ void sp_selection_scale_relative(Inkscape::Selection *selection, Geom::Point con
Geom::Translate const n2d(-align);
Geom::Translate const d2n(align);
- Geom::Matrix const final( n2d * scale * d2n );
+ Geom::Affine const final( n2d * scale * d2n );
sp_selection_apply_affine(selection, final);
}
@@ -1519,7 +1519,7 @@ sp_selection_rotate_relative(Inkscape::Selection *selection, Geom::Point const &
Geom::Translate const d2n(center);
Geom::Translate const n2d(-center);
Geom::Rotate const rotate(Geom::Rotate::from_degrees(angle_degrees));
- Geom::Matrix const final( Geom::Matrix(n2d) * rotate * d2n );
+ Geom::Affine const final( Geom::Affine(n2d) * rotate * d2n );
sp_selection_apply_affine(selection, final);
}
@@ -1528,21 +1528,21 @@ sp_selection_skew_relative(Inkscape::Selection *selection, Geom::Point const &al
{
Geom::Translate const d2n(align);
Geom::Translate const n2d(-align);
- Geom::Matrix const skew(1, dy,
+ Geom::Affine const skew(1, dy,
dx, 1,
0, 0);
- Geom::Matrix const final( n2d * skew * d2n );
+ Geom::Affine const final( n2d * skew * d2n );
sp_selection_apply_affine(selection, final);
}
void sp_selection_move_relative(Inkscape::Selection *selection, Geom::Point const &move, bool compensate)
{
- sp_selection_apply_affine(selection, Geom::Matrix(Geom::Translate(move)), true, compensate);
+ sp_selection_apply_affine(selection, Geom::Affine(Geom::Translate(move)), true, compensate);
}
void sp_selection_move_relative(Inkscape::Selection *selection, double dx, double dy)
{
- sp_selection_apply_affine(selection, Geom::Matrix(Geom::Translate(dx, dy)));
+ sp_selection_apply_affine(selection, Geom::Affine(Geom::Translate(dx, dy)));
}
/**
@@ -2291,7 +2291,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply)
// calculate the transform to be applied to objects to move them to 0,0
Geom::Point move_p = Geom::Point(0, doc->getHeight()) - *c;
move_p[Geom::Y] = -move_p[Geom::Y];
- Geom::Matrix move = Geom::Matrix(Geom::Translate(move_p));
+ Geom::Affine move = Geom::Affine(Geom::Translate(move_p));
GSList *items = g_slist_copy((GSList *) selection->itemList());
@@ -2300,7 +2300,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply)
// bottommost object, after sorting
SPObject *parent = SP_OBJECT_PARENT(items->data);
- Geom::Matrix parent_transform(SP_ITEM(parent)->i2doc_affine());
+ Geom::Affine parent_transform(SP_ITEM(parent)->i2doc_affine());
// remember the position of the first item
gint pos = SP_OBJECT_REPR(items->data)->position();
@@ -2331,7 +2331,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply)
prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
gchar const *mark_id = generate_marker(repr_copies, bounds, doc,
- ( Geom::Matrix(Geom::Translate(desktop->dt2doc(
+ ( Geom::Affine(Geom::Translate(desktop->dt2doc(
Geom::Point(r->min()[Geom::X],
r->max()[Geom::Y]))))
* parent_transform.inverse() ),
@@ -2415,7 +2415,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply)
// calculate the transform to be applied to objects to move them to 0,0
Geom::Point move_p = Geom::Point(0, doc->getHeight()) - (r->min() + Geom::Point(0, r->dimensions()[Geom::Y]));
move_p[Geom::Y] = -move_p[Geom::Y];
- Geom::Matrix move = Geom::Matrix(Geom::Translate(move_p));
+ Geom::Affine move = Geom::Affine(Geom::Translate(move_p));
GSList *items = g_slist_copy((GSList *) selection->itemList());
@@ -2424,7 +2424,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply)
// bottommost object, after sorting
SPObject *parent = SP_OBJECT_PARENT(items->data);
- Geom::Matrix parent_transform(SP_ITEM(parent)->i2doc_affine());
+ Geom::Affine parent_transform(SP_ITEM(parent)->i2doc_affine());
// remember the position of the first item
gint pos = SP_OBJECT_REPR(items->data)->position();
@@ -2456,7 +2456,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply)
prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
gchar const *pat_id = pattern_tile(repr_copies, bounds, doc,
- ( Geom::Matrix(Geom::Translate(desktop->dt2doc(Geom::Point(r->min()[Geom::X],
+ ( Geom::Affine(Geom::Translate(desktop->dt2doc(Geom::Point(r->min()[Geom::X],
r->max()[Geom::Y]))))
* to_2geom(parent_transform.inverse()) ),
parent_transform * move);
@@ -2534,7 +2534,7 @@ void sp_selection_untile(SPDesktop *desktop)
SPPattern *pattern = pattern_getroot(SP_PATTERN(server));
- Geom::Matrix pat_transform = to_2geom(pattern_patternTransform(SP_PATTERN(server)));
+ Geom::Affine pat_transform = to_2geom(pattern_patternTransform(SP_PATTERN(server)));
pat_transform *= item->transform;
for (SPObject *child = pattern->firstChild() ; child != NULL; child = child->next ) {
@@ -2547,7 +2547,7 @@ void sp_selection_untile(SPDesktop *desktop)
// this is needed to make sure the new item has curve (simply requestDisplayUpdate does not work)
doc->ensureUpToDate();
- Geom::Matrix transform( i->transform * pat_transform );
+ Geom::Affine transform( i->transform * pat_transform );
i->doWriteTransform(SP_OBJECT_REPR(i), transform);
new_select = g_slist_prepend(new_select, i);
@@ -2758,8 +2758,8 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
}
// Calculate the matrix that will be applied to the image so that it exactly overlaps the source objects
- Geom::Matrix eek(SP_ITEM(parent_object)->i2d_affine());
- Geom::Matrix t;
+ Geom::Affine eek(SP_ITEM(parent_object)->i2d_affine());
+ Geom::Affine t;
double shift_x = bbox.x0;
double shift_y = bbox.y1;
@@ -2974,7 +2974,7 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_
SPItem *item = reinterpret_cast<SPItem *>(i->data);
// inverted object transform should be applied to a mask object,
// as mask is calculated in user space (after applying transform)
- Geom::Matrix maskTransform(item->transform.inverse());
+ Geom::Affine maskTransform(item->transform.inverse());
GSList *mask_items_dup = NULL;
for (GSList *mask_item = mask_items; NULL != mask_item; mask_item = mask_item->next) {
@@ -3142,7 +3142,7 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) {
items_to_select = g_slist_prepend(items_to_select, mask_item);
// transform mask, so it is moved the same spot where mask was applied
- Geom::Matrix transform(mask_item->transform);
+ Geom::Affine transform(mask_item->transform);
transform *= (*it).second->transform;
mask_item->doWriteTransform(SP_OBJECT_REPR(mask_item), transform);
}
diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h
index 65d1ba296..b3d64ae8e 100644
--- a/src/selection-chemistry.h
+++ b/src/selection-chemistry.h
@@ -93,7 +93,7 @@ void sp_selection_paste_size_separately(SPDesktop *desktop, bool apply_x, bool a
void sp_selection_to_next_layer( SPDesktop *desktop, bool suppressDone = false );
void sp_selection_to_prev_layer( SPDesktop *desktop, bool suppressDone = false );
-void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix const &affine, bool set_i2d = true, bool compensate = true);
+void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d = true, bool compensate = true);
void sp_selection_remove_transform (SPDesktop *desktop);
void sp_selection_scale_absolute (Inkscape::Selection *selection, double x0, double x1, double y0, double y1);
void sp_selection_scale_relative(Inkscape::Selection *selection, Geom::Point const &align, Geom::Scale const &scale);
diff --git a/src/selection.cpp b/src/selection.cpp
index 9cef87076..79a71afbd 100644
--- a/src/selection.cpp
+++ b/src/selection.cpp
@@ -394,7 +394,7 @@ NRRect *Selection::boundsInDocument(NRRect *bbox, SPItem::BBoxType type) const {
for ( GSList const *iter=items ; iter != NULL ; iter = iter->next ) {
SPItem *item=SP_ITEM(iter->data);
- Geom::Matrix i2doc(item->i2doc_affine());
+ Geom::Affine i2doc(item->i2doc_affine());
item->invoke_bbox( bbox, i2doc, FALSE, type);
}
diff --git a/src/seltrans.cpp b/src/seltrans.cpp
index b1d184986..848c0836a 100644
--- a/src/seltrans.cpp
+++ b/src/seltrans.cpp
@@ -419,18 +419,18 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s
g_return_if_fail(_stamp_cache == NULL);
}
-void Inkscape::SelTrans::transform(Geom::Matrix const &rel_affine, Geom::Point const &norm)
+void Inkscape::SelTrans::transform(Geom::Affine const &rel_affine, Geom::Point const &norm)
{
g_return_if_fail(_grabbed);
g_return_if_fail(!_empty);
- Geom::Matrix const affine( Geom::Translate(-norm) * rel_affine * Geom::Translate(norm) );
+ Geom::Affine const affine( Geom::Translate(-norm) * rel_affine * Geom::Translate(norm) );
if (_show == SHOW_CONTENT) {
// update the content
for (unsigned i = 0; i < _items.size(); i++) {
SPItem &item = *_items[i];
- Geom::Matrix const &prev_transform = _items_affines[i];
+ Geom::Affine const &prev_transform = _items_affines[i];
item.set_i2d_affine(prev_transform * affine);
}
} else {
@@ -509,10 +509,10 @@ void Inkscape::SelTrans::ungrab()
if (_current_relative_affine.isTranslation()) {
DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
_("Move"));
- } else if (_current_relative_affine.without_translation().isScale()) {
+ } else if (_current_relative_affine.withoutTranslation().isScale()) {
DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
_("Scale"));
- } else if (_current_relative_affine.without_translation().isRotation()) {
+ } else if (_current_relative_affine.withoutTranslation().isRotation()) {
DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
_("Rotate"));
} else {
@@ -584,10 +584,10 @@ void Inkscape::SelTrans::stamp()
SPItem *copy_item = (SPItem *) sp_desktop_document(_desktop)->getObjectByRepr(copy_repr);
- Geom::Matrix const *new_affine;
+ Geom::Affine const *new_affine;
if (_show == SHOW_OUTLINE) {
- Geom::Matrix const i2d(original_item->i2d_affine());
- Geom::Matrix const i2dnew( i2d * _current_relative_affine );
+ Geom::Affine const i2d(original_item->i2d_affine());
+ Geom::Affine const i2dnew( i2d * _current_relative_affine );
copy_item->set_i2d_affine(i2dnew);
new_affine = &copy_item->transform;
} else {
@@ -1520,7 +1520,7 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state)
}
}
- Geom::Matrix const move((Geom::Translate(dxy)));
+ Geom::Affine const move((Geom::Translate(dxy)));
Geom::Point const norm(0, 0);
transform(move, norm);
@@ -1557,7 +1557,7 @@ Geom::Point Inkscape::SelTrans::_getGeomHandlePos(Geom::Point const &visual_hand
// Calculate the absolute affine while taking into account the scaling of the stroke width
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
bool transform_stroke = prefs->getBool("/options/transform/stroke", true);
- Geom::Matrix abs_affine = get_scale_transform_with_stroke (*_bbox, _strokewidth, transform_stroke,
+ Geom::Affine abs_affine = get_scale_transform_with_stroke (*_bbox, _strokewidth, transform_stroke,
new_bbox.min()[Geom::X], new_bbox.min()[Geom::Y], new_bbox.max()[Geom::X], new_bbox.max()[Geom::Y]);
// Calculate the scaled geometrical bbox
@@ -1591,7 +1591,7 @@ Geom::Scale Inkscape::calcScaleFactors(Geom::Point const &initial_point, Geom::P
// Only for scaling/stretching
Geom::Point Inkscape::SelTrans::_calcAbsAffineDefault(Geom::Scale const default_scale)
{
- Geom::Matrix abs_affine = Geom::Translate(-_origin) * Geom::Matrix(default_scale) * Geom::Translate(_origin);
+ Geom::Affine abs_affine = Geom::Translate(-_origin) * Geom::Affine(default_scale) * Geom::Translate(_origin);
Geom::Point new_bbox_min = _approximate_bbox->min() * abs_affine;
Geom::Point new_bbox_max = _approximate_bbox->max() * abs_affine;
@@ -1614,7 +1614,7 @@ Geom::Point Inkscape::SelTrans::_calcAbsAffineDefault(Geom::Scale const default_
// Only for scaling/stretching
Geom::Point Inkscape::SelTrans::_calcAbsAffineGeom(Geom::Scale const geom_scale)
{
- _relative_affine = Geom::Matrix(geom_scale);
+ _relative_affine = Geom::Affine(geom_scale);
_absolute_affine = Geom::Translate(-_origin_for_specpoints) * _relative_affine * Geom::Translate(_origin_for_specpoints);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
diff --git a/src/seltrans.h b/src/seltrans.h
index bb26aa2cb..d1a99f9d3 100644
--- a/src/seltrans.h
+++ b/src/seltrans.h
@@ -17,7 +17,7 @@
#include <sigc++/sigc++.h>
#include <2geom/point.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <2geom/rect.h>
#include "knot.h"
#include "forward.h"
@@ -55,7 +55,7 @@ public:
void resetState();
void setCenter(Geom::Point const &p);
void grab(Geom::Point const &p, gdouble x, gdouble y, bool show_handles, bool translating);
- void transform(Geom::Matrix const &rel_affine, Geom::Point const &norm);
+ void transform(Geom::Affine const &rel_affine, Geom::Point const &norm);
void ungrab();
void stamp();
void moveTo(Geom::Point const &xy, guint state);
@@ -114,7 +114,7 @@ private:
std::vector<SPItem *> _items;
std::vector<SPItem const *> _items_const;
- std::vector<Geom::Matrix> _items_affines;
+ std::vector<Geom::Affine> _items_affines;
std::vector<Geom::Point> _items_centers;
std::vector<Inkscape::SnapCandidatePoint> _snap_points;
@@ -139,9 +139,9 @@ private:
Geom::OptRect _geometric_bbox;
gdouble _strokewidth;
- Geom::Matrix _current_relative_affine;
- Geom::Matrix _absolute_affine;
- Geom::Matrix _relative_affine;
+ Geom::Affine _current_relative_affine;
+ Geom::Affine _absolute_affine;
+ Geom::Affine _relative_affine;
/* According to Merriam - Webster's online dictionary
* Affine: a transformation (as a translation, a rotation, or a uniform stretching) that carries straight
* lines into straight lines and parallel lines into parallel lines but may alter distance between points
diff --git a/src/snap-candidate.h b/src/snap-candidate.h
index 772800be5..236f2497d 100644
--- a/src/snap-candidate.h
+++ b/src/snap-candidate.h
@@ -82,7 +82,7 @@ private:
class SnapCandidateItem
{
public:
- SnapCandidateItem(SPItem* item, bool clip_or_mask, Geom::Matrix additional_affine)
+ SnapCandidateItem(SPItem* item, bool clip_or_mask, Geom::Affine additional_affine)
: item(item), clip_or_mask(clip_or_mask), additional_affine(additional_affine) {}
~SnapCandidateItem() {};
@@ -93,7 +93,7 @@ public:
* the transformation of the clipping path or mask itself, but also the transformation of
* the object to which the clip or mask is being applied; that transformation is stored here
*/
- Geom::Matrix additional_affine;
+ Geom::Affine additional_affine;
}
;
diff --git a/src/snapped-curve.cpp b/src/snapped-curve.cpp
index 5deb4c449..25bde8105 100644
--- a/src/snapped-curve.cpp
+++ b/src/snapped-curve.cpp
@@ -56,7 +56,7 @@ Inkscape::SnappedCurve::~SnappedCurve()
{
}
-Inkscape::SnappedPoint Inkscape::SnappedCurve::intersect(SnappedCurve const &curve, Geom::Point const &p, Geom::Matrix dt2doc) const
+Inkscape::SnappedPoint Inkscape::SnappedCurve::intersect(SnappedCurve const &curve, Geom::Point const &p, Geom::Affine dt2doc) const
{
// Calculate the intersections of two curves, which are both within snapping range, and
// return only the closest intersection
@@ -125,7 +125,7 @@ bool getClosestCurve(std::list<Inkscape::SnappedCurve> const &list, Inkscape::Sn
}
// search for the closest intersection of two snapped curves, which are both member of the same collection
-bool getClosestIntersectionCS(std::list<Inkscape::SnappedCurve> const &list, Geom::Point const &p, Inkscape::SnappedPoint &result, Geom::Matrix dt2doc)
+bool getClosestIntersectionCS(std::list<Inkscape::SnappedCurve> const &list, Geom::Point const &p, Inkscape::SnappedPoint &result, Geom::Affine dt2doc)
{
bool success = false;
diff --git a/src/snapped-curve.h b/src/snapped-curve.h
index 595f84411..ed04576df 100644
--- a/src/snapped-curve.h
+++ b/src/snapped-curve.h
@@ -26,7 +26,7 @@ public:
SnappedCurve();
SnappedCurve(Geom::Point const &snapped_point, int num_path, int num_segm, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, bool const &fully_constrained, Geom::Curve const *curve, SnapSourceType source, long source_num, SnapTargetType target, Geom::OptRect target_bbox);
~SnappedCurve();
- Inkscape::SnappedPoint intersect(SnappedCurve const &curve, Geom::Point const &p, Geom::Matrix dt2doc) const; //intersect with another SnappedCurve
+ Inkscape::SnappedPoint intersect(SnappedCurve const &curve, Geom::Point const &p, Geom::Affine dt2doc) const; //intersect with another SnappedCurve
private:
Geom::Curve const *_curve;
@@ -37,7 +37,7 @@ private:
}
bool getClosestCurve(std::list<Inkscape::SnappedCurve> const &list, Inkscape::SnappedCurve &result);
-bool getClosestIntersectionCS(std::list<Inkscape::SnappedCurve> const &list, Geom::Point const &p, Inkscape::SnappedPoint &result, Geom::Matrix dt2doc);
+bool getClosestIntersectionCS(std::list<Inkscape::SnappedCurve> const &list, Geom::Point const &p, Inkscape::SnappedPoint &result, Geom::Affine dt2doc);
#endif /* !SEEN_SNAPPEDCURVE_H */
diff --git a/src/sp-clippath.cpp b/src/sp-clippath.cpp
index 16368b9c6..4e6f41a70 100644
--- a/src/sp-clippath.cpp
+++ b/src/sp-clippath.cpp
@@ -187,7 +187,7 @@ void SPClipPath::update(SPObject *object, SPCtx *ctx, guint flags)
SPClipPath *cp = SP_CLIPPATH(object);
for (SPClipPathView *v = cp->display; v != NULL; v = v->next) {
if (cp->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
- Geom::Matrix t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0));
+ Geom::Affine t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0));
t[4] = v->bbox.x0;
t[5] = v->bbox.y0;
nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), &t);
@@ -254,7 +254,7 @@ NRArenaItem *SPClipPath::show(NRArena *arena, unsigned int key)
}
if (clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
- Geom::Matrix t(Geom::Scale(display->bbox.x1 - display->bbox.x0, display->bbox.y1 - display->bbox.y0));
+ Geom::Affine t(Geom::Scale(display->bbox.x1 - display->bbox.x0, display->bbox.y1 - display->bbox.y0));
t[4] = display->bbox.x0;
t[5] = display->bbox.y0;
nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), &t);
@@ -297,7 +297,7 @@ void SPClipPath::setBBox(unsigned int key, NRRect *bbox)
}
}
-void SPClipPath::getBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/)
+void SPClipPath::getBBox(NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/)
{
SPObject *i = 0;
for (i = firstChild(); i && !SP_IS_ITEM(i); i = i->getNext()) {
@@ -306,13 +306,13 @@ void SPClipPath::getBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned c
return;
}
- SP_ITEM(i)->invoke_bbox_full( bbox, Geom::Matrix(SP_ITEM(i)->transform) * transform, SPItem::GEOMETRIC_BBOX, FALSE);
+ SP_ITEM(i)->invoke_bbox_full( bbox, Geom::Affine(SP_ITEM(i)->transform) * transform, SPItem::GEOMETRIC_BBOX, FALSE);
SPObject *i_start = i;
while (i != NULL) {
if (i != i_start) {
NRRect i_box;
- SP_ITEM(i)->invoke_bbox_full( &i_box, Geom::Matrix(SP_ITEM(i)->transform) * transform, SPItem::GEOMETRIC_BBOX, FALSE);
+ SP_ITEM(i)->invoke_bbox_full( &i_box, Geom::Affine(SP_ITEM(i)->transform) * transform, SPItem::GEOMETRIC_BBOX, FALSE);
nr_rect_d_union (bbox, bbox, &i_box);
}
i = i->getNext();
@@ -355,7 +355,7 @@ sp_clippath_view_list_remove(SPClipPathView *list, SPClipPathView *view)
}
// Create a mask element (using passed elements), add it to <defs>
-const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Matrix const* applyTransform)
+const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform)
{
Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document));
@@ -372,7 +372,7 @@ const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Matr
SPItem *item = SP_ITEM(clip_path_object->appendChildRepr(node));
if (NULL != applyTransform) {
- Geom::Matrix transform (item->transform);
+ Geom::Affine transform (item->transform);
transform *= (*applyTransform);
item->doWriteTransform(SP_OBJECT_REPR(item), transform);
}
diff --git a/src/sp-clippath.h b/src/sp-clippath.h
index a622df1f6..d3c650ca6 100644
--- a/src/sp-clippath.h
+++ b/src/sp-clippath.h
@@ -37,14 +37,14 @@ public:
unsigned int clipPathUnits : 1;
SPClipPathView *display;
- static const gchar *create(GSList *reprs, SPDocument *document, Geom::Matrix const* applyTransform);
+ static const gchar *create(GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform);
static GType sp_clippath_get_type(void);
NRArenaItem *show(NRArena *arena, unsigned int key);
void hide(unsigned int key);
void setBBox(unsigned int key, NRRect *bbox);
- void getBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+ void getBBox(NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
private:
static void init(SPClipPath *clippath);
diff --git a/src/sp-conn-end-pair.cpp b/src/sp-conn-end-pair.cpp
index 5bce1a4f8..3cc022c39 100644
--- a/src/sp-conn-end-pair.cpp
+++ b/src/sp-conn-end-pair.cpp
@@ -90,7 +90,7 @@ sp_conn_end_pair_build(SPObject *object)
static void
-avoid_conn_transformed(Geom::Matrix const */*mp*/, SPItem *moved_item)
+avoid_conn_transformed(Geom::Affine const */*mp*/, SPItem *moved_item)
{
SPPath *path = SP_PATH(moved_item);
if (path->connEndPair.isAutoRoutingConn()) {
@@ -217,7 +217,7 @@ SPConnEndPair::getEndpoints(Geom::Point endPts[]) const {
SPCurve *curve = _path->original_curve ? _path->original_curve : _path->curve;
SPItem *h2attItem[2];
getAttachedItems(h2attItem);
- Geom::Matrix i2d = SP_ITEM(_path)->i2doc_affine();
+ Geom::Affine i2d = SP_ITEM(_path)->i2doc_affine();
for (unsigned h = 0; h < 2; ++h) {
if ( h2attItem[h] ) {
@@ -407,7 +407,7 @@ SPConnEndPair::reroutePathFromLibavoid(void)
recreateCurve( curve, _connRef, _connCurvature );
- Geom::Matrix doc2item = SP_ITEM(_path)->i2doc_affine().inverse();
+ Geom::Affine doc2item = SP_ITEM(_path)->i2doc_affine().inverse();
curve->transform(doc2item);
return true;
diff --git a/src/sp-conn-end.cpp b/src/sp-conn-end.cpp
index 07dd852f2..3cea95cc5 100644
--- a/src/sp-conn-end.cpp
+++ b/src/sp-conn-end.cpp
@@ -43,7 +43,7 @@ get_nearest_common_ancestor(SPObject const *const obj, SPItem const *const objs[
static bool try_get_intersect_point_with_item_recursive(Geom::PathVector& conn_pv, SPItem* item,
- const Geom::Matrix& item_transform, double& intersect_pos) {
+ const Geom::Affine& item_transform, double& intersect_pos) {
double initial_pos = intersect_pos;
// if this is a group...
@@ -96,7 +96,7 @@ static bool try_get_intersect_point_with_item_recursive(Geom::PathVector& conn_p
// The transforms given should be to a common ancestor of both the path and item.
//
static bool try_get_intersect_point_with_item(SPPath* conn, SPItem* item,
- const Geom::Matrix& item_transform, const Geom::Matrix& conn_transform,
+ const Geom::Affine& item_transform, const Geom::Affine& conn_transform,
const bool at_start, double& intersect_pos) {
// Copy the curve and apply transformations up to common ancestor.
@@ -147,7 +147,7 @@ sp_conn_get_route_and_redraw(SPPath *const path,
SPItem const *const path_item = SP_ITEM(path);
SPObject const *const ancestor = get_nearest_common_ancestor(path_item, h2attItem);
- Geom::Matrix const path2anc(i2anc_affine(path_item, ancestor));
+ Geom::Affine const path2anc(i2anc_affine(path_item, ancestor));
// Set sensible values incase there the connector ends are not
// attached to any shapes.
@@ -157,7 +157,7 @@ sp_conn_get_route_and_redraw(SPPath *const path,
SPConnEnd** _connEnd = path->connEndPair.getConnEnds();
for (unsigned h = 0; h < 2; ++h) {
if (h2attItem[h] && _connEnd[h]->type == ConnPointDefault && _connEnd[h]->id == ConnPointPosCC) {
- Geom::Matrix h2i2anc = i2anc_affine(h2attItem[h], ancestor);
+ Geom::Affine h2i2anc = i2anc_affine(h2attItem[h], ancestor);
try_get_intersect_point_with_item(path, h2attItem[h], h2i2anc, path2anc,
(h == 0), endPos[h]);
}
@@ -171,7 +171,7 @@ sp_conn_get_route_and_redraw(SPPath *const path,
static void
-sp_conn_end_shape_move(Geom::Matrix const */*mp*/, SPItem */*moved_item*/,
+sp_conn_end_shape_move(Geom::Affine const */*mp*/, SPItem */*moved_item*/,
SPPath *const path)
{
if (path->connEndPair.isAutoRoutingConn()) {
diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp
index ef58e4d6e..722271fda 100644
--- a/src/sp-ellipse.cpp
+++ b/src/sp-ellipse.cpp
@@ -253,7 +253,7 @@ static void sp_genericellipse_set_shape(SPShape *shape)
curve->closepath();
}
- Geom::Matrix aff = Geom::Scale(rx, ry) * Geom::Translate(ellipse->cx.computed, ellipse->cy.computed);
+ Geom::Affine aff = Geom::Scale(rx, ry) * Geom::Translate(ellipse->cx.computed, ellipse->cy.computed);
curve->transform(aff);
/* Reset the shape'scurve to the "original_curve"
@@ -282,7 +282,7 @@ static void sp_genericellipse_snappoints(SPItem const *item, std::vector<Inkscap
SPGenericEllipse *ellipse = SP_GENERICELLIPSE(item);
sp_genericellipse_normalize(ellipse);
- Geom::Matrix const i2d = item->i2d_affine();
+ Geom::Affine const i2d = item->i2d_affine();
// figure out if we have a slice, while guarding against rounding errors
bool slice = false;
diff --git a/src/sp-flowregion.cpp b/src/sp-flowregion.cpp
index 680589b55..210f350b8 100644
--- a/src/sp-flowregion.cpp
+++ b/src/sp-flowregion.cpp
@@ -502,7 +502,7 @@ static void GetDest(SPObject* child,Shape **computed)
if ( child == NULL ) return;
SPCurve *curve=NULL;
- Geom::Matrix tr_mat;
+ Geom::Affine tr_mat;
SPObject* u_child=child;
if ( SP_IS_USE(u_child) ) {
diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp
index 3af12064f..2db1d8787 100644
--- a/src/sp-flowtext.cpp
+++ b/src/sp-flowtext.cpp
@@ -46,7 +46,7 @@ static Inkscape::XML::Node *sp_flowtext_write(SPObject *object, Inkscape::XML::D
static void sp_flowtext_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
static void sp_flowtext_set(SPObject *object, unsigned key, gchar const *value);
-static void sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+static void sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static void sp_flowtext_print(SPItem *item, SPPrintContext *ctx);
static gchar *sp_flowtext_description(SPItem *item);
static void sp_flowtext_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
@@ -328,7 +328,7 @@ static Inkscape::XML::Node *sp_flowtext_write(SPObject *object, Inkscape::XML::D
}
static void
-sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/)
+sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/)
{
SPFlowtext *group = SP_FLOWTEXT(item);
group->layout.getBoundingBox(bbox, transform);
@@ -368,7 +368,7 @@ sp_flowtext_print(SPItem *item, SPPrintContext *ctx)
dbox.y0 = 0.0;
dbox.x1 = SP_OBJECT_DOCUMENT(item)->getWidth();
dbox.y1 = SP_OBJECT_DOCUMENT(item)->getHeight();
- Geom::Matrix const ctm (item->i2d_affine());
+ Geom::Affine const ctm (item->i2d_affine());
group->layout.print(ctx, &pbox, &dbox, &bbox, ctm);
}
diff --git a/src/sp-gradient-fns.h b/src/sp-gradient-fns.h
index 5e7e1d387..be2caf5b0 100644
--- a/src/sp-gradient-fns.h
+++ b/src/sp-gradient-fns.h
@@ -23,12 +23,12 @@ void sp_gradient_render_vector_block_rgba(SPGradient *gr, guchar *px, gint w, gi
void sp_gradient_render_vector_block_rgb(SPGradient *gr, guchar *px, gint w, gint h, gint rs, gint pos, gint span, bool horizontal);
/** Transforms to/from gradient position space in given environment */
-Geom::Matrix sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Matrix const &ctm,
+Geom::Affine sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Affine const &ctm,
Geom::Rect const &bbox);
-Geom::Matrix sp_gradient_get_gs2d_matrix(SPGradient const *gr, Geom::Matrix const &ctm,
+Geom::Affine sp_gradient_get_gs2d_matrix(SPGradient const *gr, Geom::Affine const &ctm,
Geom::Rect const &bbox);
-void sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Matrix const &ctm, Geom::Rect const &bbox,
- Geom::Matrix const &gs2d);
+void sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Affine const &ctm, Geom::Rect const &bbox,
+ Geom::Affine const &gs2d);
#endif /* !SEEN_SP_GRADIENT_FNS_H */
diff --git a/src/sp-gradient-test.h b/src/sp-gradient-test.h
index 5ab08467d..696072929 100644
--- a/src/sp-gradient-test.h
+++ b/src/sp-gradient-test.h
@@ -56,13 +56,13 @@ public:
SP_OBJECT(gr)->document = _doc;
SP_OBJECT(gr)->setKeyValue( SP_ATTR_GRADIENTTRANSFORM, "translate(5, 8)");
- TS_ASSERT_EQUALS( gr->gradientTransform, Geom::Matrix(Geom::Translate(5, 8)) );
+ TS_ASSERT_EQUALS( gr->gradientTransform, Geom::Affine(Geom::Translate(5, 8)) );
SP_OBJECT(gr)->setKeyValue( SP_ATTR_GRADIENTTRANSFORM, "");
TS_ASSERT_EQUALS( gr->gradientTransform, Geom::identity() );
SP_OBJECT(gr)->setKeyValue( SP_ATTR_GRADIENTTRANSFORM, "rotate(90)");
- TS_ASSERT_EQUALS( gr->gradientTransform, Geom::Matrix(rotate_degrees(90)) );
+ TS_ASSERT_EQUALS( gr->gradientTransform, Geom::Affine(rotate_degrees(90)) );
g_object_unref(gr);
}
@@ -79,10 +79,10 @@ public:
SP_OBJECT(gr)->updateRepr(repr, SP_OBJECT_WRITE_ALL);
{
gchar const *tr = repr->attribute("gradientTransform");
- Geom::Matrix svd;
+ Geom::Affine svd;
bool const valid = sp_svg_transform_read(tr, &svd);
TS_ASSERT( valid );
- TS_ASSERT_EQUALS( svd, Geom::Matrix(rotate_degrees(90)) );
+ TS_ASSERT_EQUALS( svd, Geom::Affine(rotate_degrees(90)) );
}
g_object_unref(gr);
@@ -93,14 +93,14 @@ public:
{
SPGradient *gr = static_cast<SPGradient *>(g_object_new(SP_TYPE_GRADIENT, NULL));
SP_OBJECT(gr)->document = _doc;
- Geom::Matrix const grXform(2, 1,
+ Geom::Affine const grXform(2, 1,
1, 3,
4, 6);
gr->gradientTransform = grXform;
Geom::Rect const unit_rect(Geom::Point(0, 0), Geom::Point(1, 1));
{
- Geom::Matrix const g2d(sp_gradient_get_g2d_matrix(gr, Geom::identity(), unit_rect));
- Geom::Matrix const gs2d(sp_gradient_get_gs2d_matrix(gr, Geom::identity(), unit_rect));
+ Geom::Affine const g2d(sp_gradient_get_g2d_matrix(gr, Geom::identity(), unit_rect));
+ Geom::Affine const gs2d(sp_gradient_get_gs2d_matrix(gr, Geom::identity(), unit_rect));
TS_ASSERT_EQUALS( g2d, Geom::identity() );
TS_ASSERT( Geom::matrix_equalp(gs2d, gr->gradientTransform * g2d, 1e-12) );
@@ -109,12 +109,12 @@ public:
}
gr->gradientTransform = grXform;
- Geom::Matrix const funny(2, 3,
+ Geom::Affine const funny(2, 3,
4, 5,
6, 7);
{
- Geom::Matrix const g2d(sp_gradient_get_g2d_matrix(gr, funny, unit_rect));
- Geom::Matrix const gs2d(sp_gradient_get_gs2d_matrix(gr, funny, unit_rect));
+ Geom::Affine const g2d(sp_gradient_get_g2d_matrix(gr, funny, unit_rect));
+ Geom::Affine const gs2d(sp_gradient_get_gs2d_matrix(gr, funny, unit_rect));
TS_ASSERT_EQUALS( g2d, funny );
TS_ASSERT( Geom::matrix_equalp(gs2d, gr->gradientTransform * g2d, 1e-12) );
@@ -125,9 +125,9 @@ public:
gr->gradientTransform = grXform;
Geom::Rect const larger_rect(Geom::Point(5, 6), Geom::Point(8, 10));
{
- Geom::Matrix const g2d(sp_gradient_get_g2d_matrix(gr, funny, larger_rect));
- Geom::Matrix const gs2d(sp_gradient_get_gs2d_matrix(gr, funny, larger_rect));
- TS_ASSERT_EQUALS( g2d, Geom::Matrix(3, 0,
+ Geom::Affine const g2d(sp_gradient_get_g2d_matrix(gr, funny, larger_rect));
+ Geom::Affine const gs2d(sp_gradient_get_gs2d_matrix(gr, funny, larger_rect));
+ TS_ASSERT_EQUALS( g2d, Geom::Affine(3, 0,
0, 4,
5, 6) * funny );
TS_ASSERT( Geom::matrix_equalp(gs2d, gr->gradientTransform * g2d, 1e-12) );
@@ -136,8 +136,8 @@ public:
TS_ASSERT( Geom::matrix_equalp(gr->gradientTransform, grXform, 1e-12) );
SP_OBJECT(gr)->setKeyValue( SP_ATTR_GRADIENTUNITS, "userSpaceOnUse");
- Geom::Matrix const user_g2d(sp_gradient_get_g2d_matrix(gr, funny, larger_rect));
- Geom::Matrix const user_gs2d(sp_gradient_get_gs2d_matrix(gr, funny, larger_rect));
+ Geom::Affine const user_g2d(sp_gradient_get_g2d_matrix(gr, funny, larger_rect));
+ Geom::Affine const user_gs2d(sp_gradient_get_gs2d_matrix(gr, funny, larger_rect));
TS_ASSERT_EQUALS( user_g2d, funny );
TS_ASSERT( Geom::matrix_equalp(user_gs2d, gr->gradientTransform * user_g2d, 1e-12) );
}
diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp
index 1b8f9a111..06008c083 100644
--- a/src/sp-gradient.cpp
+++ b/src/sp-gradient.cpp
@@ -493,7 +493,7 @@ void SPGradientImpl::setGradientAttr(SPObject *object, unsigned key, gchar const
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
case SP_ATTR_GRADIENTTRANSFORM: {
- Geom::Matrix t;
+ Geom::Affine t;
if (value && sp_svg_transform_read(value, &t)) {
gr->gradientTransform = t;
gr->gradientTransform_set = TRUE;
@@ -1390,34 +1390,34 @@ sp_gradient_render_vector_block_rgb(SPGradient *gradient, guchar *buf,
}
}
-Geom::Matrix
-sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Matrix const &ctm, Geom::Rect const &bbox)
+Geom::Affine
+sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Affine const &ctm, Geom::Rect const &bbox)
{
if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
return ( Geom::Scale(bbox.dimensions())
* Geom::Translate(bbox.min())
- * Geom::Matrix(ctm) );
+ * Geom::Affine(ctm) );
} else {
return ctm;
}
}
-Geom::Matrix
-sp_gradient_get_gs2d_matrix(SPGradient const *gr, Geom::Matrix const &ctm, Geom::Rect const &bbox)
+Geom::Affine
+sp_gradient_get_gs2d_matrix(SPGradient const *gr, Geom::Affine const &ctm, Geom::Rect const &bbox)
{
if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
return ( gr->gradientTransform
* Geom::Scale(bbox.dimensions())
* Geom::Translate(bbox.min())
- * Geom::Matrix(ctm) );
+ * Geom::Affine(ctm) );
} else {
return gr->gradientTransform * ctm;
}
}
void
-sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Matrix const &ctm,
- Geom::Rect const &bbox, Geom::Matrix const &gs2d)
+sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Affine const &ctm,
+ Geom::Rect const &bbox, Geom::Affine const &gs2d)
{
gr->gradientTransform = gs2d * ctm.inverse();
if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX ) {
@@ -1444,8 +1444,8 @@ struct SPLGPainter {
NRLGradientRenderer lgr;
static SPPainter * painter_new(SPPaintServer *ps,
- Geom::Matrix const &full_transform,
- Geom::Matrix const &parent_transform,
+ Geom::Affine const &full_transform,
+ Geom::Affine const &parent_transform,
NRRect const *bbox);
};
@@ -1609,8 +1609,8 @@ sp_lineargradient_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inks
* and end < 1.
*/
SPPainter * SPLGPainter::painter_new(SPPaintServer *ps,
- Geom::Matrix const &full_transform,
- Geom::Matrix const &/*parent_transform*/,
+ Geom::Affine const &full_transform,
+ Geom::Affine const &/*parent_transform*/,
NRRect const *bbox)
{
SPLinearGradient *lg = SP_LINEARGRADIENT(ps);
@@ -1634,26 +1634,26 @@ SPPainter * SPLGPainter::painter_new(SPPaintServer *ps,
* or something similar. Originally I had 1023.9999 here - not sure
* whether we have really to cut out ceil int (Lauris).
*/
- Geom::Matrix color2norm(Geom::identity());
- Geom::Matrix color2px;
+ Geom::Affine color2norm(Geom::identity());
+ Geom::Affine color2px;
if (gr->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
- Geom::Matrix norm2pos(Geom::identity());
+ Geom::Affine norm2pos(Geom::identity());
/* BBox to user coordinate system */
- Geom::Matrix bbox2user(bbox->x1 - bbox->x0, 0, 0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
+ Geom::Affine bbox2user(bbox->x1 - bbox->x0, 0, 0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
- Geom::Matrix color2pos = color2norm * norm2pos;
- Geom::Matrix color2tpos = color2pos * gr->gradientTransform;
- Geom::Matrix color2user = color2tpos * bbox2user;
+ Geom::Affine color2pos = color2norm * norm2pos;
+ Geom::Affine color2tpos = color2pos * gr->gradientTransform;
+ Geom::Affine color2user = color2tpos * bbox2user;
color2px = color2user * full_transform;
} else {
/* Problem: What to do, if we have mixed lengths and percentages? */
/* Currently we do ignore percentages at all, but that is not good (lauris) */
- Geom::Matrix norm2pos(Geom::identity());
- Geom::Matrix color2pos = color2norm * norm2pos;
- Geom::Matrix color2tpos = color2pos * gr->gradientTransform;
+ Geom::Affine norm2pos(Geom::identity());
+ Geom::Affine color2pos = color2norm * norm2pos;
+ Geom::Affine color2tpos = color2pos * gr->gradientTransform;
color2px = color2tpos * full_transform;
}
@@ -1721,8 +1721,8 @@ struct SPRGPainter {
NRRGradientRenderer rgr;
static SPPainter *painter_new(SPPaintServer *ps,
- Geom::Matrix const &full_transform,
- Geom::Matrix const &parent_transform,
+ Geom::Affine const &full_transform,
+ Geom::Affine const &parent_transform,
NRRect const *bbox);
};
@@ -1893,8 +1893,8 @@ sp_radialgradient_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inks
* Create radial gradient context.
*/
SPPainter *SPRGPainter::painter_new(SPPaintServer *ps,
- Geom::Matrix const &full_transform,
- Geom::Matrix const &/*parent_transform*/,
+ Geom::Affine const &full_transform,
+ Geom::Affine const &/*parent_transform*/,
NRRect const *bbox)
{
SPRadialGradient *rg = SP_RADIALGRADIENT(ps);
@@ -1911,7 +1911,7 @@ SPPainter *SPRGPainter::painter_new(SPPaintServer *ps,
rgp->rg = rg;
- Geom::Matrix gs2px;
+ Geom::Affine gs2px;
if (gr->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
/** \todo
@@ -1920,9 +1920,9 @@ SPPainter *SPRGPainter::painter_new(SPPaintServer *ps,
*/
/* BBox to user coordinate system */
- Geom::Matrix bbox2user(bbox->x1 - bbox->x0, 0, 0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
+ Geom::Affine bbox2user(bbox->x1 - bbox->x0, 0, 0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
- Geom::Matrix gs2user = gr->gradientTransform * bbox2user;
+ Geom::Affine gs2user = gr->gradientTransform * bbox2user;
gs2px = gs2user * full_transform;
} else {
diff --git a/src/sp-gradient.h b/src/sp-gradient.h
index fbcc4934e..b727c38ac 100644
--- a/src/sp-gradient.h
+++ b/src/sp-gradient.h
@@ -84,7 +84,7 @@ private:
public:
/** gradientTransform attribute */
- Geom::Matrix gradientTransform;
+ Geom::Affine gradientTransform;
guint gradientTransform_set : 1;
private:
diff --git a/src/sp-image.cpp b/src/sp-image.cpp
index ad9e79de2..b23c2e161 100644
--- a/src/sp-image.cpp
+++ b/src/sp-image.cpp
@@ -84,12 +84,12 @@ static void sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags);
static void sp_image_modified (SPObject *object, unsigned int flags);
static Inkscape::XML::Node *sp_image_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
-static void sp_image_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+static void sp_image_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static void sp_image_print (SPItem * item, SPPrintContext *ctx);
static gchar * sp_image_description (SPItem * item);
static void sp_image_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
static NRArenaItem *sp_image_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
-static Geom::Matrix sp_image_set_transform (SPItem *item, Geom::Matrix const &xform);
+static Geom::Affine sp_image_set_transform (SPItem *item, Geom::Affine const &xform);
static void sp_image_set_curve(SPImage *image);
@@ -1078,7 +1078,7 @@ sp_image_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XM
}
static void
-sp_image_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/)
+sp_image_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/)
{
SPImage const &image = *SP_IMAGE(item);
@@ -1107,7 +1107,7 @@ sp_image_print (SPItem *item, SPPrintContext *ctx)
int rs = gdk_pixbuf_get_rowstride(image->pixbuf);
int pixskip = gdk_pixbuf_get_n_channels(image->pixbuf) * gdk_pixbuf_get_bits_per_sample(image->pixbuf) / 8;
- Geom::Matrix t;
+ Geom::Affine t;
if (image->aspect_align == SP_ASPECT_NONE) {
/* fixme: (Lauris) */
Geom::Translate tp(image->x.computed, image->y.computed);
@@ -1359,7 +1359,7 @@ static void sp_image_snappoints(SPItem const *item, std::vector<Inkscape::SnapCa
double const y0 = image.y.computed;
double const x1 = x0 + image.width.computed;
double const y1 = y0 + image.height.computed;
- Geom::Matrix const i2d (item->i2d_affine ());
+ Geom::Affine const i2d (item->i2d_affine ());
p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x0, y0) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER));
p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x0, y1) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER));
p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x1, y1) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER));
@@ -1372,8 +1372,8 @@ static void sp_image_snappoints(SPItem const *item, std::vector<Inkscape::SnapCa
* Transform x, y, set x, y, clear translation
*/
-static Geom::Matrix
-sp_image_set_transform(SPItem *item, Geom::Matrix const &xform)
+static Geom::Affine
+sp_image_set_transform(SPItem *item, Geom::Affine const &xform)
{
SPImage *image = SP_IMAGE(item);
@@ -1382,7 +1382,7 @@ sp_image_set_transform(SPItem *item, Geom::Matrix const &xform)
/* This function takes care of translation and scaling, we return whatever parts we can't
handle. */
- Geom::Matrix ret(Geom::Matrix(xform).without_translation());
+ Geom::Affine ret(Geom::Affine(xform).withoutTranslation());
Geom::Point const scale(hypot(ret[0], ret[1]),
hypot(ret[2], ret[3]));
if ( scale[Geom::X] > MAGIC_EPSILON ) {
diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp
index 30d085584..bdc9400cf 100644
--- a/src/sp-item-group.cpp
+++ b/src/sp-item-group.cpp
@@ -66,7 +66,7 @@ static void sp_group_modified (SPObject *object, guint flags);
static Inkscape::XML::Node *sp_group_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
static void sp_group_set(SPObject *object, unsigned key, char const *value);
-static void sp_group_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+static void sp_group_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static void sp_group_print (SPItem * item, SPPrintContext *ctx);
static gchar * sp_group_description (SPItem * item);
static NRArenaItem *sp_group_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
@@ -278,7 +278,7 @@ static Inkscape::XML::Node * sp_group_write(SPObject *object, Inkscape::XML::Doc
}
static void
-sp_group_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags)
+sp_group_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags)
{
SP_GROUP(item)->group->calculateBBox(bbox, transform, flags);
}
@@ -408,8 +408,8 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done)
Inkscape::XML::Node *nrepr = SP_OBJECT_REPR (child)->duplicate(prepr->document());
// Merging transform
- Geom::Matrix ctrans;
- Geom::Matrix const g(gitem->transform);
+ Geom::Affine ctrans;
+ Geom::Affine const g(gitem->transform);
if (SP_IS_USE(citem) && sp_use_get_original (SP_USE(citem)) &&
SP_OBJECT_PARENT (sp_use_get_original (SP_USE(citem))) == SP_OBJECT(group)) {
// make sure a clone's effective transform is the same as was under group
@@ -696,7 +696,7 @@ void CGroup::onModified(guint flags) {
}
}
-void CGroup::calculateBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned const flags) {
+void CGroup::calculateBBox(NRRect *bbox, Geom::Affine const &transform, unsigned const flags) {
Geom::OptRect dummy_bbox;
@@ -705,7 +705,7 @@ void CGroup::calculateBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned
SPObject *o = SP_OBJECT (l->data);
if (SP_IS_ITEM(o) && !SP_ITEM(o)->isHidden()) {
SPItem *child = SP_ITEM(o);
- Geom::Matrix const ct(to_2geom(child->transform) * transform);
+ Geom::Affine const ct(to_2geom(child->transform) * transform);
child->invoke_bbox_full( dummy_bbox, ct, flags, FALSE);
}
l = g_slist_remove (l, o);
diff --git a/src/sp-item-group.h b/src/sp-item-group.h
index 932241a42..e2aeb8bc5 100644
--- a/src/sp-item-group.h
+++ b/src/sp-item-group.h
@@ -69,7 +69,7 @@ public:
virtual void onChildRemoved(Inkscape::XML::Node *child);
virtual void onUpdate(SPCtx *ctx, unsigned int flags);
virtual void onModified(guint flags);
- virtual void calculateBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+ virtual void calculateBBox(NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
virtual void onPrint(SPPrintContext *ctx);
virtual void onOrderChanged(Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref);
virtual gchar *getDescription();
diff --git a/src/sp-item-transform.cpp b/src/sp-item-transform.cpp
index 81780220c..c3a95dc0f 100644
--- a/src/sp-item-transform.cpp
+++ b/src/sp-item-transform.cpp
@@ -21,10 +21,10 @@ sp_item_rotate_rel(SPItem *item, Geom::Rotate const &rotation)
{
Geom::Point center = item->getCenter();
Geom::Translate const s(item->getCenter());
- Geom::Matrix affine = Geom::Matrix(s).inverse() * Geom::Matrix(rotation) * Geom::Matrix(s);
+ Geom::Affine affine = Geom::Affine(s).inverse() * Geom::Affine(rotation) * Geom::Affine(s);
// Rotate item.
- item->set_i2d_affine(item->i2d_affine() * (Geom::Matrix)affine);
+ item->set_i2d_affine(item->i2d_affine() * (Geom::Affine)affine);
// Use each item's own transform writer, consistent with sp_selection_apply_affine()
item->doWriteTransform(SP_OBJECT_REPR(item), item->transform);
@@ -52,8 +52,8 @@ sp_item_skew_rel (SPItem *item, double skewX, double skewY)
Geom::Point center = item->getCenter();
Geom::Translate const s(item->getCenter());
- Geom::Matrix const skew(1, skewY, skewX, 1, 0, 0);
- Geom::Matrix affine = Geom::Matrix(s).inverse() * skew * Geom::Matrix(s);
+ Geom::Affine const skew(1, skewY, skewX, 1, 0, 0);
+ Geom::Affine affine = Geom::Affine(s).inverse() * skew * Geom::Affine(s);
item->set_i2d_affine(item->i2d_affine() * affine);
item->doWriteTransform(SP_OBJECT_REPR(item), item->transform);
@@ -79,16 +79,16 @@ preference value passed to it. Has to solve a quadratic equation to make sure
the goal is met exactly and the stroke scaling is obeyed.
*/
-Geom::Matrix
+Geom::Affine
get_scale_transform_with_stroke (Geom::Rect const &bbox_param, gdouble strokewidth, bool transform_stroke, gdouble x0, gdouble y0, gdouble x1, gdouble y1)
{
Geom::Rect bbox (bbox_param);
- Geom::Matrix p2o = Geom::Translate (-bbox.min());
- Geom::Matrix o2n = Geom::Translate (x0, y0);
+ Geom::Affine p2o = Geom::Translate (-bbox.min());
+ Geom::Affine o2n = Geom::Translate (x0, y0);
- Geom::Matrix scale = Geom::Scale (1, 1); // scale component
- Geom::Matrix unbudge = Geom::Translate (0, 0); // move component to compensate for the drift caused by stroke width change
+ Geom::Affine scale = Geom::Scale (1, 1); // scale component
+ Geom::Affine unbudge = Geom::Translate (0, 0); // move component to compensate for the drift caused by stroke width change
gdouble w0 = bbox[Geom::X].extent(); // will return a value >= 0, as required further down the road
gdouble h0 = bbox[Geom::Y].extent();
@@ -97,11 +97,11 @@ get_scale_transform_with_stroke (Geom::Rect const &bbox_param, gdouble strokewid
gdouble r0 = strokewidth;
if (bbox.hasZeroArea()) {
- Geom::Matrix move = Geom::Translate(x0 - bbox.min()[Geom::X], y0 - bbox.min()[Geom::Y]);
+ Geom::Affine move = Geom::Translate(x0 - bbox.min()[Geom::X], y0 - bbox.min()[Geom::Y]);
return (move); // cannot scale from empty boxes at all, so only translate
}
- Geom::Matrix direct = Geom::Scale(w1 / w0, h1 / h0);
+ Geom::Affine direct = Geom::Scale(w1 / w0, h1 / h0);
if (fabs(w0 - r0) < 1e-6 || fabs(h0 - r0) < 1e-6 || (!transform_stroke && (fabs(w1 - r0) < 1e-6 || fabs(h1 - r0) < 1e-6))) {
return (p2o * direct * o2n); // can't solve the equation: one of the dimensions is equal to stroke width, so return the straightforward scaler
@@ -120,7 +120,7 @@ get_scale_transform_with_stroke (Geom::Rect const &bbox_param, gdouble strokewid
gdouble ratio_x = (w1 - r0) / (w0 - r0);
gdouble ratio_y = (h1 - r0) / (h0 - r0);
- Geom::Matrix direct_constant_r = Geom::Scale(flip_x * ratio_x, flip_y * ratio_y);
+ Geom::Affine direct_constant_r = Geom::Scale(flip_x * ratio_x, flip_y * ratio_y);
if (transform_stroke && r0 != 0 && r0 != NR_HUGE) { // there's stroke, and we need to scale it
// These coefficients are obtained from the assumption that scaling applies to the
@@ -159,7 +159,7 @@ get_scale_transform_with_stroke (Geom::Rect const &bbox_param, gdouble strokewid
}
Geom::Rect
-get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Matrix const &abs_affine, gdouble const initial_strokewidth, bool const transform_stroke)
+get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Affine const &abs_affine, gdouble const initial_strokewidth, bool const transform_stroke)
{
g_assert(initial_geom_bbox);
diff --git a/src/sp-item-transform.h b/src/sp-item-transform.h
index 893ab5822..552b23e2f 100644
--- a/src/sp-item-transform.h
+++ b/src/sp-item-transform.h
@@ -9,8 +9,8 @@ void sp_item_scale_rel (SPItem *item, Geom::Scale const &scale);
void sp_item_skew_rel (SPItem *item, double skewX, double skewY);
void sp_item_move_rel(SPItem *item, Geom::Translate const &tr);
-Geom::Matrix get_scale_transform_with_stroke (Geom::Rect const &bbox, gdouble strokewidth, bool transform_stroke, gdouble x0, gdouble y0, gdouble x1, gdouble y1);
-Geom::Rect get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Matrix const &abs_affine, gdouble const initial_strokewidth, bool const transform_stroke);
+Geom::Affine get_scale_transform_with_stroke (Geom::Rect const &bbox, gdouble strokewidth, bool transform_stroke, gdouble x0, gdouble y0, gdouble x1, gdouble y1);
+Geom::Rect get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Affine const &abs_affine, gdouble const initial_strokewidth, bool const transform_stroke);
#endif /* !SP_ITEM_TRANSFORM_H */
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index 755ee0bf4..37bd0b19b 100644
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
@@ -70,7 +70,7 @@
#include "util/find-last-if.h"
#include "util/reverse-list.h"
#include <2geom/rect.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <2geom/transforms.h>
#include "xml/repr.h"
@@ -163,7 +163,7 @@ void SPItem::init() {
new (&constraints) std::vector<SPGuideConstraint>();
- new (&_transformed_signal) sigc::signal<void, Geom::Matrix const *, SPItem *>();
+ new (&_transformed_signal) sigc::signal<void, Geom::Affine const *, SPItem *>();
}
bool SPItem::isVisibleAndUnlocked() const {
@@ -440,7 +440,7 @@ void SPItem::sp_item_set(SPObject *object, unsigned key, gchar const *value)
switch (key) {
case SP_ATTR_TRANSFORM: {
- Geom::Matrix t;
+ Geom::Affine t;
if (value && sp_svg_transform_read(value, &t)) {
item->set_item_transform(t);
} else {
@@ -707,7 +707,7 @@ Inkscape::XML::Node *SPItem::sp_item_write(SPObject *const object, Inkscape::XML
* \return There is no guarantee that the return value will contain a rectangle.
If this item does not have a boundingbox, it might well be empty.
*/
-Geom::OptRect SPItem::getBounds(Geom::Matrix const &transform,
+Geom::OptRect SPItem::getBounds(Geom::Affine const &transform,
SPItem::BBoxType type,
unsigned int /*dkey*/) const
{
@@ -716,13 +716,13 @@ Geom::OptRect SPItem::getBounds(Geom::Matrix const &transform,
return r;
}
-void SPItem::invoke_bbox( Geom::OptRect &bbox, Geom::Matrix const &transform, unsigned const clear, SPItem::BBoxType type)
+void SPItem::invoke_bbox( Geom::OptRect &bbox, Geom::Affine const &transform, unsigned const clear, SPItem::BBoxType type)
{
invoke_bbox_full( bbox, transform, type, clear);
}
// DEPRECATED to phase out the use of NRRect in favor of Geom::OptRect
-void SPItem::invoke_bbox( NRRect *bbox, Geom::Matrix const &transform, unsigned const clear, SPItem::BBoxType type)
+void SPItem::invoke_bbox( NRRect *bbox, Geom::Affine const &transform, unsigned const clear, SPItem::BBoxType type)
{
invoke_bbox_full( bbox, transform, type, clear);
}
@@ -734,7 +734,7 @@ void SPItem::invoke_bbox( NRRect *bbox, Geom::Matrix const &transform, unsigned
* \retval bbox Note that there is no guarantee that bbox will contain a rectangle when the
* function returns. If this item does not have a boundingbox, this might well be empty.
*/
-void SPItem::invoke_bbox_full( Geom::OptRect &bbox, Geom::Matrix const &transform, unsigned const flags, unsigned const clear) const
+void SPItem::invoke_bbox_full( Geom::OptRect &bbox, Geom::Affine const &transform, unsigned const flags, unsigned const clear) const
{
if (clear) {
bbox = Geom::OptRect();
@@ -794,7 +794,7 @@ void SPItem::invoke_bbox_full( Geom::OptRect &bbox, Geom::Matrix const &transfor
}
// transform the expansions by the item's transform:
- Geom::Matrix i2d(i2d_affine ());
+ Geom::Affine i2d(i2d_affine ());
dx0 *= i2d.expansionX();
dx1 *= i2d.expansionX();
dy0 *= i2d.expansionY();
@@ -838,7 +838,7 @@ void SPItem::invoke_bbox_full( Geom::OptRect &bbox, Geom::Matrix const &transfor
* unions the resulting bbox with \a bbox. If \a clear is true, empties \a bbox first. Passes the
* transform and the flags to the actual bbox methods. Note that many of subclasses (e.g. groups,
* clones), in turn, call this function in their bbox methods. */
-void SPItem::invoke_bbox_full( NRRect *bbox, Geom::Matrix const &transform, unsigned const flags, unsigned const clear)
+void SPItem::invoke_bbox_full( NRRect *bbox, Geom::Affine const &transform, unsigned const flags, unsigned const clear)
{
g_assert(bbox != NULL);
@@ -1139,7 +1139,7 @@ void SPItem::invoke_hide(unsigned key)
// Adjusters
-void SPItem::adjust_pattern (Geom::Matrix const &postmul, bool set)
+void SPItem::adjust_pattern (Geom::Affine const &postmul, bool set)
{
if (style && (style->fill.isPaintserver())) {
SPObject *server = style->getFillPaintServer();
@@ -1158,7 +1158,7 @@ void SPItem::adjust_pattern (Geom::Matrix const &postmul, bool set)
}
}
-void SPItem::adjust_gradient( Geom::Matrix const &postmul, bool set )
+void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set )
{
if ( style && style->fill.isPaintserver() ) {
SPPaintServer *server = style->getFillPaintServer();
@@ -1208,12 +1208,12 @@ void SPItem::adjust_stroke( gdouble ex )
/**
* Find out the inverse of previous transform of an item (from its repr)
*/
-Geom::Matrix sp_item_transform_repr (SPItem *item)
+Geom::Affine sp_item_transform_repr (SPItem *item)
{
- Geom::Matrix t_old(Geom::identity());
+ Geom::Affine t_old(Geom::identity());
gchar const *t_attr = item->getRepr()->attribute("transform");
if (t_attr) {
- Geom::Matrix t;
+ Geom::Affine t;
if (sp_svg_transform_read(t_attr, &t)) {
t_old = t;
}
@@ -1244,7 +1244,7 @@ void SPItem::adjust_stroke_width_recursive(double expansion)
* Recursively adjust rx and ry of rects.
*/
void
-sp_item_adjust_rects_recursive(SPItem *item, Geom::Matrix advertized_transform)
+sp_item_adjust_rects_recursive(SPItem *item, Geom::Affine advertized_transform)
{
if (SP_IS_RECT (item)) {
sp_rect_compensate_rxry (SP_RECT(item), advertized_transform);
@@ -1259,13 +1259,13 @@ sp_item_adjust_rects_recursive(SPItem *item, Geom::Matrix advertized_transform)
/**
* Recursively compensate pattern or gradient transform.
*/
-void SPItem::adjust_paint_recursive (Geom::Matrix advertized_transform, Geom::Matrix t_ancestors, bool is_pattern)
+void SPItem::adjust_paint_recursive (Geom::Affine advertized_transform, Geom::Affine t_ancestors, bool is_pattern)
{
// _Before_ full pattern/gradient transform: t_paint * t_item * t_ancestors
// _After_ full pattern/gradient transform: t_paint_new * t_item * t_ancestors * advertised_transform
// By equating these two expressions we get t_paint_new = t_paint * paint_delta, where:
- Geom::Matrix t_item = sp_item_transform_repr (this);
- Geom::Matrix paint_delta = t_item * t_ancestors * advertized_transform * t_ancestors.inverse() * t_item.inverse();
+ Geom::Affine t_item = sp_item_transform_repr (this);
+ Geom::Affine paint_delta = t_item * t_ancestors * advertized_transform * t_ancestors.inverse() * t_item.inverse();
// Within text, we do not fork gradients, and so must not recurse to avoid double compensation;
// also we do not recurse into clones, because a clone's child is the ghost of its original -
@@ -1292,7 +1292,7 @@ void SPItem::adjust_paint_recursive (Geom::Matrix advertized_transform, Geom::Ma
}
}
-void SPItem::adjust_livepatheffect (Geom::Matrix const &postmul, bool set)
+void SPItem::adjust_livepatheffect (Geom::Affine const &postmul, bool set)
{
if ( SP_IS_LPE_ITEM(this) ) {
SPLPEItem *lpeitem = SP_LPE_ITEM (this);
@@ -1321,12 +1321,12 @@ void SPItem::adjust_livepatheffect (Geom::Matrix const &postmul, bool set)
* stored optimized. Send _transformed_signal. Invoke _write method so that
* the repr is updated with the new transform.
*/
-void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Matrix const &transform, Geom::Matrix const *adv, bool compensate)
+void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &transform, Geom::Affine const *adv, bool compensate)
{
g_return_if_fail(repr != NULL);
// calculate the relative transform, if not given by the adv attribute
- Geom::Matrix advertized_transform;
+ Geom::Affine advertized_transform;
if (adv != NULL) {
advertized_transform = *adv;
} else {
@@ -1364,7 +1364,7 @@ void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Matrix const &tra
} // endif(compensate)
gint preserve = prefs->getBool("/options/preservetransform/value", 0);
- Geom::Matrix transform_attr (transform);
+ Geom::Affine transform_attr (transform);
if ( // run the object's set_transform (i.e. embed transform) only if:
((SPItemClass *) G_OBJECT_GET_CLASS(this))->set_transform && // it does have a set_transform method
!preserve && // user did not chose to preserve all transforms
@@ -1400,7 +1400,7 @@ gint SPItem::emitEvent(SPEvent &event)
* Sets item private transform (not propagated to repr), without compensating stroke widths,
* gradients, patterns as sp_item_write_transform does.
*/
-void SPItem::set_item_transform(Geom::Matrix const &transform_matrix)
+void SPItem::set_item_transform(Geom::Affine const &transform_matrix)
{
if (!matrix_equalp(transform_matrix, transform, NR_EPSILON)) {
transform = transform_matrix;
@@ -1427,9 +1427,9 @@ void SPItem::convert_item_to_guides() {
* \pre \a ancestor really is an ancestor (\>=) of \a object, or NULL.
* ("Ancestor (\>=)" here includes as far as \a object itself.)
*/
-Geom::Matrix
+Geom::Affine
i2anc_affine(SPObject const *object, SPObject const *const ancestor) {
- Geom::Matrix ret(Geom::identity());
+ Geom::Affine ret(Geom::identity());
g_return_val_if_fail(object != NULL, ret);
/* stop at first non-renderable ancestor */
@@ -1444,14 +1444,14 @@ i2anc_affine(SPObject const *object, SPObject const *const ancestor) {
return ret;
}
-Geom::Matrix
+Geom::Affine
i2i_affine(SPObject const *src, SPObject const *dest) {
g_return_val_if_fail(src != NULL && dest != NULL, Geom::identity());
SPObject const *ancestor = src->nearestCommonAncestor(dest);
return i2anc_affine(src, ancestor) * i2anc_affine(dest, ancestor).inverse();
}
-Geom::Matrix SPItem::getRelativeTransform(SPObject const *dest) const {
+Geom::Affine SPItem::getRelativeTransform(SPObject const *dest) const {
return i2i_affine(this, dest);
}
@@ -1459,7 +1459,7 @@ Geom::Matrix SPItem::getRelativeTransform(SPObject const *dest) const {
* Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
* \pre (item != NULL) and SP_IS_ITEM(item).
*/
-Geom::Matrix SPItem::i2doc_affine() const
+Geom::Affine SPItem::i2doc_affine() const
{
return i2anc_affine(this, NULL);
}
@@ -1467,17 +1467,17 @@ Geom::Matrix SPItem::i2doc_affine() const
/**
* Returns the transformation from item to desktop coords
*/
-Geom::Matrix SPItem::i2d_affine() const
+Geom::Affine SPItem::i2d_affine() const
{
- Geom::Matrix const ret( i2doc_affine()
+ Geom::Affine const ret( i2doc_affine()
* Geom::Scale(1, -1)
* Geom::Translate(0, document->getHeight()) );
return ret;
}
-void SPItem::set_i2d_affine(Geom::Matrix const &i2dt)
+void SPItem::set_i2d_affine(Geom::Affine const &i2dt)
{
- Geom::Matrix dt2p; /* desktop to item parent transform */
+ Geom::Affine dt2p; /* desktop to item parent transform */
if (parent) {
dt2p = static_cast<SPItem *>(parent)->i2d_affine().inverse();
} else {
@@ -1485,7 +1485,7 @@ void SPItem::set_i2d_affine(Geom::Matrix const &i2dt)
* Geom::Scale(1, -1) );
}
- Geom::Matrix const i2p( i2dt * dt2p );
+ Geom::Affine const i2p( i2dt * dt2p );
set_item_transform(i2p);
}
@@ -1493,7 +1493,7 @@ void SPItem::set_i2d_affine(Geom::Matrix const &i2dt)
/**
* should rather be named "sp_item_d2i_affine" to match "sp_item_i2d_affine" (or vice versa)
*/
-Geom::Matrix SPItem::dt2i_affine() const
+Geom::Affine SPItem::dt2i_affine() const
{
/* fixme: Implement the right way (Lauris) */
return i2d_affine().inverse();
diff --git a/src/sp-item.h b/src/sp-item.h
index 4ba3dc7a4..dc440b397 100644
--- a/src/sp-item.h
+++ b/src/sp-item.h
@@ -22,7 +22,7 @@
#include "display/nr-arena-forward.h"
#include "sp-object.h"
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <libnr/nr-rect.h>
#include <2geom/forward.h>
#include <libnr/nr-convert2geom.h>
@@ -86,11 +86,11 @@ class SPItemCtx {
public:
SPCtx ctx;
/** Item to document transformation */
- Geom::Matrix i2doc;
+ Geom::Affine i2doc;
/** Viewport size */
NRRect vp;
/** Item to viewport transformation */
- Geom::Matrix i2vp;
+ Geom::Affine i2vp;
};
class SPItem;
@@ -120,7 +120,7 @@ public:
double transform_center_x;
double transform_center_y;
- Geom::Matrix transform;
+ Geom::Affine transform;
SPClipPathReference *clip_ref;
SPMaskReference *mask_ref;
@@ -132,7 +132,7 @@ public:
std::vector<SPGuideConstraint> constraints;
- sigc::signal<void, Geom::Matrix const *, SPItem *> _transformed_signal;
+ sigc::signal<void, Geom::Affine const *, SPItem *> _transformed_signal;
void init();
bool isLocked() const;
@@ -160,25 +160,25 @@ public:
bool isVisibleAndUnlocked(unsigned display_key) const;
- Geom::Matrix getRelativeTransform(SPObject const *obj) const;
+ Geom::Affine getRelativeTransform(SPObject const *obj) const;
void raiseOne();
void lowerOne();
void raiseToTop();
void lowerToBottom();
- Geom::OptRect getBounds(Geom::Matrix const &transform, BBoxType type=APPROXIMATE_BBOX, unsigned int dkey=0) const;
+ Geom::OptRect getBounds(Geom::Affine const &transform, BBoxType type=APPROXIMATE_BBOX, unsigned int dkey=0) const;
sigc::connection _clip_ref_connection;
sigc::connection _mask_ref_connection;
- sigc::connection connectTransformed(sigc::slot<void, Geom::Matrix const *, SPItem *> slot) {
+ sigc::connection connectTransformed(sigc::slot<void, Geom::Affine const *, SPItem *> slot) {
return _transformed_signal.connect(slot);
}
- void invoke_bbox( Geom::OptRect &bbox, Geom::Matrix const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX);
- void invoke_bbox( NRRect *bbox, Geom::Matrix const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) __attribute__ ((deprecated));
- void invoke_bbox_full( Geom::OptRect &bbox, Geom::Matrix const &transform, unsigned const flags, unsigned const clear) const;
- void invoke_bbox_full( NRRect *bbox, Geom::Matrix const &transform, unsigned const flags, unsigned const clear) __attribute__ ((deprecated));
+ void invoke_bbox( Geom::OptRect &bbox, Geom::Affine const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX);
+ void invoke_bbox( NRRect *bbox, Geom::Affine const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) __attribute__ ((deprecated));
+ void invoke_bbox_full( Geom::OptRect &bbox, Geom::Affine const &transform, unsigned const flags, unsigned const clear) const;
+ void invoke_bbox_full( NRRect *bbox, Geom::Affine const &transform, unsigned const flags, unsigned const clear) __attribute__ ((deprecated));
unsigned pos_in_parent();
gchar *description();
@@ -187,23 +187,23 @@ public:
NRArenaItem *invoke_show(NRArena *arena, unsigned int key, unsigned int flags);
void invoke_hide(unsigned int key);
void getSnappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs=0) const;
- void adjust_pattern(/* Geom::Matrix const &premul, */ Geom::Matrix const &postmul, bool set = false);
- void adjust_gradient(/* Geom::Matrix const &premul, */ Geom::Matrix const &postmul, bool set = false);
+ void adjust_pattern(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false);
+ void adjust_gradient(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false);
void adjust_stroke(gdouble ex);
void adjust_stroke_width_recursive(gdouble ex);
- void adjust_paint_recursive(Geom::Matrix advertized_transform, Geom::Matrix t_ancestors, bool is_pattern);
- void adjust_livepatheffect(Geom::Matrix const &postmul, bool set = false);
- void doWriteTransform(Inkscape::XML::Node *repr, Geom::Matrix const &transform, Geom::Matrix const *adv = NULL, bool compensate = true);
- void set_item_transform(Geom::Matrix const &transform_matrix);
+ void adjust_paint_recursive(Geom::Affine advertized_transform, Geom::Affine t_ancestors, bool is_pattern);
+ void adjust_livepatheffect(Geom::Affine const &postmul, bool set = false);
+ void doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &transform, Geom::Affine const *adv = NULL, bool compensate = true);
+ void set_item_transform(Geom::Affine const &transform_matrix);
void convert_item_to_guides();
gint emitEvent (SPEvent &event);
NRArenaItem *get_arenaitem(unsigned int key);
void getBboxDesktop(NRRect *bbox, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) __attribute__ ((deprecated));
Geom::OptRect getBboxDesktop(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX);
- Geom::Matrix i2doc_affine() const;
- Geom::Matrix i2d_affine() const;
- void set_i2d_affine(Geom::Matrix const &transform);
- Geom::Matrix dt2i_affine() const;
+ Geom::Affine i2doc_affine() const;
+ Geom::Affine i2d_affine() const;
+ void set_i2d_affine(Geom::Affine const &transform);
+ Geom::Affine dt2i_affine() const;
void convert_to_guides();
private:
@@ -240,7 +240,7 @@ public:
SPObjectClass parent_class;
/** BBox union in given coordinate system */
- void (* bbox) (SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+ void (* bbox) (SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
/** Printing method. Assumes ctm is set to item affine matrix */
/* \todo Think about it, and maybe implement generic export method instead (Lauris) */
@@ -258,7 +258,7 @@ public:
void (* snappoints) (SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
/** Apply the transform optimally, and return any residual transformation */
- Geom::Matrix (* set_transform)(SPItem *item, Geom::Matrix const &transform);
+ Geom::Affine (* set_transform)(SPItem *item, Geom::Affine const &transform);
/** Convert the item to guidelines */
void (* convert_to_guides)(SPItem *item);
@@ -275,8 +275,8 @@ public:
// Utility
-Geom::Matrix i2anc_affine(SPObject const *item, SPObject const *ancestor);
-Geom::Matrix i2i_affine(SPObject const *src, SPObject const *dest);
+Geom::Affine i2anc_affine(SPObject const *item, SPObject const *ancestor);
+Geom::Affine i2i_affine(SPObject const *src, SPObject const *dest);
/* fixme: - these are evil, but OK */
diff --git a/src/sp-line.cpp b/src/sp-line.cpp
index b8c5a19b7..100eefe87 100644
--- a/src/sp-line.cpp
+++ b/src/sp-line.cpp
@@ -180,7 +180,7 @@ void SPLine::convertToGuides(SPItem *item)
SPLine *line = SP_LINE(item);
Geom::Point points[2];
- Geom::Matrix const i2d(item->i2d_affine());
+ Geom::Affine const i2d(item->i2d_affine());
points[0] = Geom::Point(line->x1.computed, line->y1.computed)*i2d;
points[1] = Geom::Point(line->x2.computed, line->y2.computed)*i2d;
@@ -188,7 +188,7 @@ void SPLine::convertToGuides(SPItem *item)
SPGuide::createSPGuide(inkscape_active_desktop(), points[0], points[1]);
}
-Geom::Matrix SPLine::setTransform(SPItem *item, Geom::Matrix const &xform)
+Geom::Affine SPLine::setTransform(SPItem *item, Geom::Affine const &xform)
{
SPLine *line = SP_LINE(item);
Geom::Point points[2];
diff --git a/src/sp-line.h b/src/sp-line.h
index 8bcb81645..182f85a5c 100644
--- a/src/sp-line.h
+++ b/src/sp-line.h
@@ -44,7 +44,7 @@ private:
static Inkscape::XML::Node *write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
static gchar *getDescription(SPItem * item);
- static Geom::Matrix setTransform(SPItem *item, Geom::Matrix const &xform);
+ static Geom::Affine setTransform(SPItem *item, Geom::Affine const &xform);
static void update(SPObject *object, SPCtx *ctx, guint flags);
static void setShape(SPShape *shape);
diff --git a/src/sp-mask.cpp b/src/sp-mask.cpp
index dde91b062..372dd51da 100644
--- a/src/sp-mask.cpp
+++ b/src/sp-mask.cpp
@@ -217,7 +217,7 @@ static void sp_mask_update(SPObject *object, SPCtx *ctx, guint flags)
SPMask *mask = SP_MASK(object);
for (SPMaskView *v = mask->display; v != NULL; v = v->next) {
if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
- Geom::Matrix t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0));
+ Geom::Affine t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0));
t[4] = v->bbox.x0;
t[5] = v->bbox.y0;
nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), &t);
@@ -267,7 +267,7 @@ sp_mask_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML
// Create a mask element (using passed elements), add it to <defs>
const gchar *
-sp_mask_create (GSList *reprs, SPDocument *document, Geom::Matrix const* applyTransform)
+sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform)
{
Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document));
@@ -284,7 +284,7 @@ sp_mask_create (GSList *reprs, SPDocument *document, Geom::Matrix const* applyTr
SPItem *item = SP_ITEM(mask_object->appendChildRepr(node));
if (NULL != applyTransform) {
- Geom::Matrix transform (item->transform);
+ Geom::Affine transform (item->transform);
transform *= (*applyTransform);
item->doWriteTransform(SP_OBJECT_REPR(item), transform);
}
@@ -318,7 +318,7 @@ NRArenaItem *sp_mask_show(SPMask *mask, NRArena *arena, unsigned int key)
}
if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
- Geom::Matrix t(Geom::Scale(mask->display->bbox.x1 - mask->display->bbox.x0, mask->display->bbox.y1 - mask->display->bbox.y0));
+ Geom::Affine t(Geom::Scale(mask->display->bbox.x1 - mask->display->bbox.x0, mask->display->bbox.y1 - mask->display->bbox.y0));
t[4] = mask->display->bbox.x0;
t[5] = mask->display->bbox.y0;
nr_arena_group_set_child_transform (NR_ARENA_GROUP (ai), &t);
diff --git a/src/sp-mask.h b/src/sp-mask.h
index d8b6b33ea..5a98ac8c5 100644
--- a/src/sp-mask.h
+++ b/src/sp-mask.h
@@ -95,6 +95,6 @@ void sp_mask_hide (SPMask *mask, unsigned int key);
void sp_mask_set_bbox (SPMask *mask, unsigned int key, NRRect *bbox);
-const gchar *sp_mask_create (GSList *reprs, SPDocument *document, Geom::Matrix const* applyTransform);
+const gchar *sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform);
#endif // SEEN_SP_MASK_H
diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp
index 51bb1e1cc..6f825ab1d 100644
--- a/src/sp-offset.cpp
+++ b/src/sp-offset.cpp
@@ -90,7 +90,7 @@ static void refresh_offset_source(SPOffset* offset);
static void sp_offset_start_listening(SPOffset *offset,SPObject* to);
static void sp_offset_quit_listening(SPOffset *offset);
static void sp_offset_href_changed(SPObject *old_ref, SPObject *ref, SPOffset *offset);
-static void sp_offset_move_compensate(Geom::Matrix const *mp, SPItem *original, SPOffset *self);
+static void sp_offset_move_compensate(Geom::Affine const *mp, SPItem *original, SPOffset *self);
static void sp_offset_delete_self(SPObject *deleted, SPOffset *self);
static void sp_offset_source_modified (SPObject *iSource, guint flags, SPItem *item);
@@ -1024,20 +1024,20 @@ sp_offset_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPOffset *offse
}
static void
-sp_offset_move_compensate(Geom::Matrix const *mp, SPItem */*original*/, SPOffset *self)
+sp_offset_move_compensate(Geom::Affine const *mp, SPItem */*original*/, SPOffset *self)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
guint mode = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_PARALLEL);
if (mode == SP_CLONE_COMPENSATION_NONE) return;
- Geom::Matrix m(*mp);
+ Geom::Affine m(*mp);
if (!(m.isTranslation())) return;
// calculate the compensation matrix and the advertized movement matrix
SPItem *item = SP_ITEM(self);
- Geom::Matrix compensate;
- Geom::Matrix advertized_move;
+ Geom::Affine compensate;
+ Geom::Affine advertized_move;
if (mode == SP_CLONE_COMPENSATION_UNMOVED) {
compensate = Geom::identity();
diff --git a/src/sp-paint-server.cpp b/src/sp-paint-server.cpp
index 4b5366a46..b672e4480 100644
--- a/src/sp-paint-server.cpp
+++ b/src/sp-paint-server.cpp
@@ -82,8 +82,8 @@ static void sp_paint_server_release(SPObject *object)
}
SPPainter *sp_paint_server_painter_new(SPPaintServer *ps,
- Geom::Matrix const &full_transform,
- Geom::Matrix const &parent_transform,
+ Geom::Affine const &full_transform,
+ Geom::Affine const &parent_transform,
const NRRect *bbox)
{
g_return_val_if_fail(ps != NULL, NULL);
diff --git a/src/sp-paint-server.h b/src/sp-paint-server.h
index a663807b0..05f5b7bad 100644
--- a/src/sp-paint-server.h
+++ b/src/sp-paint-server.h
@@ -63,12 +63,12 @@ private:
struct SPPaintServerClass {
SPObjectClass sp_object_class;
/** Get SPPaint instance. */
- SPPainter * (* painter_new) (SPPaintServer *ps, Geom::Matrix const &full_transform, Geom::Matrix const &parent_transform, const NRRect *bbox);
+ SPPainter * (* painter_new) (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &parent_transform, const NRRect *bbox);
/** Free SPPaint instance. */
void (* painter_free) (SPPaintServer *ps, SPPainter *painter);
};
-SPPainter *sp_paint_server_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, Geom::Matrix const &parent_transform, const NRRect *bbox);
+SPPainter *sp_paint_server_painter_new (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &parent_transform, const NRRect *bbox);
SPPainter *sp_painter_free (SPPainter *painter);
diff --git a/src/sp-path.cpp b/src/sp-path.cpp
index 66a70e0f1..5d84b468e 100644
--- a/src/sp-path.cpp
+++ b/src/sp-path.cpp
@@ -59,7 +59,7 @@ static void sp_path_build(SPObject *object, SPDocument *document, Inkscape::XML:
static void sp_path_set(SPObject *object, unsigned key, gchar const *value);
static Inkscape::XML::Node *sp_path_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
-static Geom::Matrix sp_path_set_transform(SPItem *item, Geom::Matrix const &xform);
+static Geom::Affine sp_path_set_transform(SPItem *item, Geom::Affine const &xform);
static gchar * sp_path_description(SPItem *item);
static void sp_path_convert_to_guides(SPItem *item);
@@ -170,7 +170,7 @@ sp_path_convert_to_guides(SPItem *item)
std::list<std::pair<Geom::Point, Geom::Point> > pts;
- Geom::Matrix const i2d (SP_ITEM(path)->i2d_affine());
+ Geom::Affine const i2d (SP_ITEM(path)->i2d_affine());
Geom::PathVector const & pv = curve->get_pathvector();
for(Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit) {
@@ -372,8 +372,8 @@ sp_path_update(SPObject *object, SPCtx *ctx, guint flags)
/**
* Writes the given transform into the repr for the given item.
*/
-static Geom::Matrix
-sp_path_set_transform(SPItem *item, Geom::Matrix const &xform)
+static Geom::Affine
+sp_path_set_transform(SPItem *item, Geom::Affine const &xform)
{
SPShape *shape = (SPShape *) item;
SPPath *path = (SPPath *) item;
diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp
index fbba4cc48..b0264ad13 100644
--- a/src/sp-pattern.cpp
+++ b/src/sp-pattern.cpp
@@ -44,17 +44,17 @@ struct SPPatPainter {
SPPainter painter;
SPPattern *pat;
- Geom::Matrix ps2px;
- Geom::Matrix px2ps;
- Geom::Matrix pcs2px;
+ Geom::Affine ps2px;
+ Geom::Affine px2ps;
+ Geom::Affine pcs2px;
NRArena *arena;
unsigned int dkey;
NRArenaItem *root;
bool use_cached_tile;
- Geom::Matrix ca2pa;
- Geom::Matrix pa2ca;
+ Geom::Affine ca2pa;
+ Geom::Affine pa2ca;
NRRectL cached_bbox;
NRPixBlock cached_tile;
@@ -74,7 +74,7 @@ static void sp_pattern_modified (SPObject *object, unsigned int flags);
static void pattern_ref_changed(SPObject *old_ref, SPObject *ref, SPPattern *pat);
static void pattern_ref_modified (SPObject *ref, guint flags, SPPattern *pattern);
-static SPPainter *sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, Geom::Matrix const &parent_transform, const NRRect *bbox);
+static SPPainter *sp_pattern_painter_new (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &parent_transform, const NRRect *bbox);
static void sp_pattern_painter_free (SPPaintServer *ps, SPPainter *painter);
static SPPaintServerClass * pattern_parent_class;
@@ -228,7 +228,7 @@ sp_pattern_set (SPObject *object, unsigned int key, const gchar *value)
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
case SP_ATTR_PATTERNTRANSFORM: {
- Geom::Matrix t;
+ Geom::Affine t;
if (value && sp_svg_transform_read (value, &t)) {
pat->patternTransform = t;
pat->patternTransform_set = TRUE;
@@ -504,7 +504,7 @@ sp_pattern_clone_if_necessary (SPItem *item, SPPattern *pattern, const gchar *pr
}
void
-sp_pattern_transform_multiply (SPPattern *pattern, Geom::Matrix postmul, bool set)
+sp_pattern_transform_multiply (SPPattern *pattern, Geom::Affine postmul, bool set)
{
// this formula is for a different interpretation of pattern transforms as described in (*) in sp-pattern.cpp
// for it to work, we also need sp_object_read_attr (SP_OBJECT (item), "transform");
@@ -523,7 +523,7 @@ sp_pattern_transform_multiply (SPPattern *pattern, Geom::Matrix postmul, bool se
g_free(c);
}
-const gchar *pattern_tile(GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Matrix transform, Geom::Matrix move)
+const gchar *pattern_tile(GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move)
{
Inkscape::XML::Document *xml_doc = document->getReprDoc();
Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document));
@@ -545,7 +545,7 @@ const gchar *pattern_tile(GSList *reprs, Geom::Rect bounds, SPDocument *document
Inkscape::XML::Node *node = (Inkscape::XML::Node *)(i->data);
SPItem *copy = SP_ITEM(pat_object->appendChildRepr(node));
- Geom::Matrix dup_transform;
+ Geom::Affine dup_transform;
if (!sp_svg_transform_read (node->attribute("transform"), &dup_transform))
dup_transform = Geom::identity();
dup_transform *= move;
@@ -590,7 +590,7 @@ guint pattern_patternContentUnits (SPPattern *pat)
return pat->patternContentUnits;
}
-Geom::Matrix const &pattern_patternTransform(SPPattern const *pat)
+Geom::Affine const &pattern_patternTransform(SPPattern const *pat)
{
for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) {
if (pat_i->patternTransform_set)
@@ -679,7 +679,7 @@ Creates a painter (i.e. the thing that does actual filling at the given zoom).
See (*) below for why the parent_transform may be necessary.
*/
static SPPainter *
-sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, Geom::Matrix const &/*parent_transform*/, const NRRect *bbox)
+sp_pattern_painter_new (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &/*parent_transform*/, const NRRect *bbox)
{
SPPattern *pat = SP_PATTERN (ps);
SPPatPainter *pp = g_new (SPPatPainter, 1);
@@ -691,10 +691,10 @@ sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, G
if (pattern_patternUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
/* BBox to user coordinate system */
- Geom::Matrix bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
+ Geom::Affine bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
// the final patternTransform, taking into account bbox
- Geom::Matrix const ps2user(pattern_patternTransform(pat) * bbox2user);
+ Geom::Affine const ps2user(pattern_patternTransform(pat) * bbox2user);
// see (*) comment below
pp->ps2px = ps2user * full_transform;
@@ -725,9 +725,9 @@ sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, G
gdouble tmp_y = pattern_height (pat) / (pattern_viewBox(pat)->y1 - pattern_viewBox(pat)->y0);
// FIXME: preserveAspectRatio must be taken into account here too!
- Geom::Matrix vb2ps (tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - pattern_viewBox(pat)->x0 * tmp_x, pattern_y(pat) - pattern_viewBox(pat)->y0 * tmp_y);
+ Geom::Affine vb2ps (tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - pattern_viewBox(pat)->x0 * tmp_x, pattern_y(pat) - pattern_viewBox(pat)->y0 * tmp_y);
- Geom::Matrix vb2us = vb2ps * pattern_patternTransform(pat);
+ Geom::Affine vb2us = vb2ps * pattern_patternTransform(pat);
// see (*)
pp->pcs2px = vb2us * full_transform;
@@ -735,9 +735,9 @@ sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, G
/* No viewbox, have to parse units */
if (pattern_patternContentUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
/* BBox to user coordinate system */
- Geom::Matrix bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
+ Geom::Affine bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0);
- Geom::Matrix pcs2user = pattern_patternTransform(pat) * bbox2user;
+ Geom::Affine pcs2user = pattern_patternTransform(pat) * bbox2user;
// see (*)
pp->pcs2px = pcs2user * full_transform;
diff --git a/src/sp-pattern.h b/src/sp-pattern.h
index f50504a76..54f2c6a9b 100644
--- a/src/sp-pattern.h
+++ b/src/sp-pattern.h
@@ -64,7 +64,7 @@ struct SPPattern : public SPPaintServer {
guint patternContentUnits : 1;
guint patternContentUnits_set : 1;
/* patternTransform attribute */
- Geom::Matrix patternTransform;
+ Geom::Affine patternTransform;
guint patternTransform_set : 1;
/* Tile rectangle */
SVGLength x;
@@ -85,15 +85,15 @@ struct SPPatternClass {
guint pattern_users (SPPattern *pattern);
SPPattern *pattern_chain (SPPattern *pattern);
SPPattern *sp_pattern_clone_if_necessary (SPItem *item, SPPattern *pattern, const gchar *property);
-void sp_pattern_transform_multiply (SPPattern *pattern, Geom::Matrix postmul, bool set);
+void sp_pattern_transform_multiply (SPPattern *pattern, Geom::Affine postmul, bool set);
-const gchar *pattern_tile (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Matrix transform, Geom::Matrix move);
+const gchar *pattern_tile (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move);
SPPattern *pattern_getroot (SPPattern *pat);
guint pattern_patternUnits (SPPattern *pat);
guint pattern_patternContentUnits (SPPattern *pat);
-Geom::Matrix const &pattern_patternTransform(SPPattern const *pat);
+Geom::Affine const &pattern_patternTransform(SPPattern const *pat);
gdouble pattern_x (SPPattern *pat);
gdouble pattern_y (SPPattern *pat);
gdouble pattern_width (SPPattern *pat);
diff --git a/src/sp-rect.cpp b/src/sp-rect.cpp
index 94be7551b..fd44f64df 100644
--- a/src/sp-rect.cpp
+++ b/src/sp-rect.cpp
@@ -42,7 +42,7 @@ static void sp_rect_update(SPObject *object, SPCtx *ctx, guint flags);
static Inkscape::XML::Node *sp_rect_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
static gchar *sp_rect_description(SPItem *item);
-static Geom::Matrix sp_rect_set_transform(SPItem *item, Geom::Matrix const &xform);
+static Geom::Affine sp_rect_set_transform(SPItem *item, Geom::Affine const &xform);
static void sp_rect_convert_to_guides(SPItem *item);
static void sp_rect_set_shape(SPShape *shape);
@@ -333,8 +333,8 @@ sp_rect_set_ry(SPRect *rect, gboolean set, gdouble value)
/* fixme: Use preferred units somehow (Lauris) */
/* fixme: Alternately preserve whatever units there are (lauris) */
-static Geom::Matrix
-sp_rect_set_transform(SPItem *item, Geom::Matrix const &xform)
+static Geom::Affine
+sp_rect_set_transform(SPItem *item, Geom::Affine const &xform)
{
SPRect *rect = SP_RECT(item);
@@ -343,7 +343,7 @@ sp_rect_set_transform(SPItem *item, Geom::Matrix const &xform)
/* This function takes care of translation and scaling, we return whatever parts we can't
handle. */
- Geom::Matrix ret(Geom::Matrix(xform).without_translation());
+ Geom::Affine ret(Geom::Affine(xform).withoutTranslation());
gdouble const sw = hypot(ret[0], ret[1]);
gdouble const sh = hypot(ret[2], ret[3]);
if (sw > 1e-9) {
@@ -397,7 +397,7 @@ sp_rect_set_transform(SPItem *item, Geom::Matrix const &xform)
Returns the ratio in which the vector from p0 to p1 is stretched by transform
*/
static gdouble
-vector_stretch(Geom::Point p0, Geom::Point p1, Geom::Matrix xform)
+vector_stretch(Geom::Point p0, Geom::Point p1, Geom::Affine xform)
{
if (p0 == p1)
return 0;
@@ -467,7 +467,7 @@ sp_rect_get_rect (SPRect *rect)
}
void
-sp_rect_compensate_rxry(SPRect *rect, Geom::Matrix xform)
+sp_rect_compensate_rxry(SPRect *rect, Geom::Affine xform)
{
if (rect->rx.computed == 0 && rect->ry.computed == 0)
return; // nothing to compensate
@@ -570,7 +570,7 @@ static void sp_rect_snappoints(SPItem const *item, std::vector<Inkscape::SnapCan
SPRect *rect = SP_RECT(item);
- Geom::Matrix const i2d (item->i2d_affine ());
+ Geom::Affine const i2d (item->i2d_affine ());
Geom::Point p0 = Geom::Point(rect->x.computed, rect->y.computed) * i2d;
Geom::Point p1 = Geom::Point(rect->x.computed, rect->y.computed + rect->height.computed) * i2d;
@@ -609,7 +609,7 @@ sp_rect_convert_to_guides(SPItem *item) {
std::list<std::pair<Geom::Point, Geom::Point> > pts;
- Geom::Matrix const i2d (SP_ITEM(rect)->i2d_affine());
+ Geom::Affine const i2d (SP_ITEM(rect)->i2d_affine());
Geom::Point A1(Geom::Point(rect->x.computed, rect->y.computed) * i2d);
Geom::Point A2(Geom::Point(rect->x.computed, rect->y.computed + rect->height.computed) * i2d);
diff --git a/src/sp-rect.h b/src/sp-rect.h
index 09d96739b..7bc85dd8a 100644
--- a/src/sp-rect.h
+++ b/src/sp-rect.h
@@ -63,7 +63,7 @@ void sp_rect_set_visible_height (SPRect *rect, gdouble ry);
gdouble sp_rect_get_visible_width (SPRect *rect);
gdouble sp_rect_get_visible_height (SPRect *rect);
-void sp_rect_compensate_rxry (SPRect *rect, Geom::Matrix xform);
+void sp_rect_compensate_rxry (SPRect *rect, Geom::Affine xform);
#endif // SEEN_SP_RECT_H
diff --git a/src/sp-root.cpp b/src/sp-root.cpp
index 5f868539b..61b5fda5b 100644
--- a/src/sp-root.cpp
+++ b/src/sp-root.cpp
@@ -438,7 +438,7 @@ sp_root_update(SPObject *object, SPCtx *ctx, guint flags)
* fixme: height seems natural, as this makes the inner svg element
* fixme: self-contained. The spec is vague here.
*/
- root->c2p = Geom::Matrix(Geom::Translate(root->x.computed,
+ root->c2p = Geom::Affine(Geom::Translate(root->x.computed,
root->y.computed));
}
diff --git a/src/sp-root.h b/src/sp-root.h
index 28ed43154..ab379fb50 100644
--- a/src/sp-root.h
+++ b/src/sp-root.h
@@ -47,7 +47,7 @@ struct SPRoot : public SPGroup {
unsigned int aspect_clip : 1;
/** Child to parent additional transform. */
- Geom::Matrix c2p;
+ Geom::Affine c2p;
gchar *onload;
diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp
index 35364692b..59105a1c7 100644
--- a/src/sp-shape.cpp
+++ b/src/sp-shape.cpp
@@ -307,7 +307,7 @@ void SPShape::sp_shape_update(SPObject *object, SPCtx *ctx, unsigned int flags)
* Reference for behaviour of zero-length segments:
* http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes
*/
-Geom::Matrix sp_shape_marker_get_transform(Geom::Curve const & c1, Geom::Curve const & c2)
+Geom::Affine sp_shape_marker_get_transform(Geom::Curve const & c1, Geom::Curve const & c2)
{
Geom::Point p = c1.pointAt(1);
Geom::Curve * c1_reverse = c1.reverse();
@@ -334,10 +334,10 @@ Geom::Matrix sp_shape_marker_get_transform(Geom::Curve const & c1, Geom::Curve c
return Geom::Rotate(ret_angle) * Geom::Translate(p);
}
-Geom::Matrix sp_shape_marker_get_transform_at_start(Geom::Curve const & c)
+Geom::Affine sp_shape_marker_get_transform_at_start(Geom::Curve const & c)
{
Geom::Point p = c.pointAt(0);
- Geom::Matrix ret = Geom::Translate(p);
+ Geom::Affine ret = Geom::Translate(p);
if ( !c.isDegenerate() ) {
Geom::Point tang = c.unitTangentAt(0);
@@ -351,10 +351,10 @@ Geom::Matrix sp_shape_marker_get_transform_at_start(Geom::Curve const & c)
return ret;
}
-Geom::Matrix sp_shape_marker_get_transform_at_end(Geom::Curve const & c)
+Geom::Affine sp_shape_marker_get_transform_at_end(Geom::Curve const & c)
{
Geom::Point p = c.pointAt(1);
- Geom::Matrix ret = Geom::Translate(p);
+ Geom::Affine ret = Geom::Translate(p);
if ( !c.isDegenerate() ) {
Geom::Curve * c_reverse = c.reverse();
@@ -393,7 +393,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai)
// START marker
{
- Geom::Matrix const m (sp_shape_marker_get_transform_at_start(pathv.begin()->front()));
+ Geom::Affine const m (sp_shape_marker_get_transform_at_start(pathv.begin()->front()));
for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
if ( shape->marker[i] ) {
sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai,
@@ -411,7 +411,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai)
if ( path_it != pathv.begin()
&& ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, don't draw mid marker there
{
- Geom::Matrix const m (sp_shape_marker_get_transform_at_start(path_it->front()));
+ Geom::Affine const m (sp_shape_marker_get_transform_at_start(path_it->front()));
for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
if ( shape->marker[i] ) {
sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai,
@@ -431,7 +431,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai)
* Loop to end_default (so including closing segment), because when a path is closed,
* there should be a midpoint marker between last segment and closing straight line segment
*/
- Geom::Matrix const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2));
+ Geom::Affine const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2));
for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
if (shape->marker[i]) {
sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai,
@@ -448,7 +448,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai)
// END position
if ( path_it != (pathv.end()-1) && !path_it->empty()) {
Geom::Curve const &lastcurve = path_it->back_default();
- Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve);
+ Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve);
for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID
if (shape->marker[i]) {
sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai,
@@ -471,7 +471,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai)
index--;
}
Geom::Curve const &lastcurve = path_last[index];
- Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve);
+ Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve);
for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END
if (shape->marker[i]) {
@@ -506,7 +506,7 @@ void SPShape::sp_shape_modified(SPObject *object, unsigned int flags)
* Calculates the bounding box for item, storing it into bbox.
* This also includes the bounding boxes of any markers included in the shape.
*/
-void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags)
+void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags)
{
SPShape const *shape = SP_SHAPE (item);
if (shape->curve) {
@@ -570,7 +570,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const
SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker));
if (marker_item) {
- Geom::Matrix tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front()));
+ Geom::Affine tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front()));
if (!marker->orient_auto) {
Geom::Point transl = tr.translation();
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
@@ -602,7 +602,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const
if ( path_it != pathv.begin()
&& ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there
{
- Geom::Matrix tr(sp_shape_marker_get_transform_at_start(path_it->front()));
+ Geom::Affine tr(sp_shape_marker_get_transform_at_start(path_it->front()));
if (!marker->orient_auto) {
Geom::Point transl = tr.translation();
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
@@ -629,7 +629,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const
SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker));
if (marker_item) {
- Geom::Matrix tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2));
+ Geom::Affine tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2));
if (!marker->orient_auto) {
Geom::Point transl = tr.translation();
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
@@ -650,7 +650,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const
// END position
if ( path_it != (pathv.end()-1) && !path_it->empty()) {
Geom::Curve const &lastcurve = path_it->back_default();
- Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve);
+ Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve);
if (!marker->orient_auto) {
Geom::Point transl = tr.translation();
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
@@ -681,7 +681,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const
}
Geom::Curve const &lastcurve = path_last[index];
- Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve);
+ Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve);
if (!marker->orient_auto) {
Geom::Point transl = tr.translation();
tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl);
@@ -713,7 +713,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const
}
static void
-sp_shape_print_invoke_marker_printing(SPObject* obj, Geom::Matrix tr, SPStyle* style, SPPrintContext *ctx) {
+sp_shape_print_invoke_marker_printing(SPObject* obj, Geom::Affine tr, SPStyle* style, SPPrintContext *ctx) {
SPMarker *marker = SP_MARKER(obj);
if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
tr = Geom::Scale(style->stroke_width.computed) * tr;
@@ -722,7 +722,7 @@ sp_shape_print_invoke_marker_printing(SPObject* obj, Geom::Matrix tr, SPStyle* s
SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker));
tr = marker_item->transform * marker->c2p * tr;
- Geom::Matrix old_tr = marker_item->transform;
+ Geom::Affine old_tr = marker_item->transform;
marker_item->transform = tr;
marker_item->invoke_print (ctx);
marker_item->transform = old_tr;
@@ -761,7 +761,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx)
dbox.x1 = SP_OBJECT_DOCUMENT (item)->getWidth ();
dbox.y1 = SP_OBJECT_DOCUMENT (item)->getHeight ();
item->getBboxDesktop (&bbox);
- Geom::Matrix const i2d(item->i2d_affine());
+ Geom::Affine const i2d(item->i2d_affine());
SPStyle* style = SP_OBJECT_STYLE (item);
@@ -777,7 +777,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx)
// START marker
for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
if ( shape->marker[i] ) {
- Geom::Matrix tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front()));
+ Geom::Affine tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front()));
sp_shape_print_invoke_marker_printing(shape->marker[i], tr, style, ctx);
}
}
@@ -789,7 +789,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx)
if ( path_it != pathv.begin()
&& ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there
{
- Geom::Matrix tr(sp_shape_marker_get_transform_at_start(path_it->front()));
+ Geom::Affine tr(sp_shape_marker_get_transform_at_start(path_it->front()));
sp_shape_print_invoke_marker_printing(shape->marker[i], tr, style, ctx);
}
// MID position
@@ -801,7 +801,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx)
/* Put marker between curve_it1 and curve_it2.
* Loop to end_default (so including closing segment), because when a path is closed,
* there should be a midpoint marker between last segment and closing straight line segment */
- Geom::Matrix tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2));
+ Geom::Affine tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2));
sp_shape_print_invoke_marker_printing(shape->marker[i], tr, style, ctx);
@@ -811,7 +811,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx)
}
if ( path_it != (pathv.end()-1) && !path_it->empty()) {
Geom::Curve const &lastcurve = path_it->back_default();
- Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve);
+ Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve);
sp_shape_print_invoke_marker_printing(shape->marker[i], tr, style, ctx);
}
}
@@ -828,7 +828,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx)
}
Geom::Curve const &lastcurve = path_last[index];
- Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve);
+ Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve);
for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END
if (shape->marker[i]) {
@@ -1163,7 +1163,7 @@ void SPShape::sp_shape_snappoints(SPItem const *item, std::vector<Inkscape::Snap
if (pathv.empty())
return;
- Geom::Matrix const i2d (item->i2d_affine ());
+ Geom::Affine const i2d (item->i2d_affine ());
if (snapprefs->getSnapObjectMidpoints()) {
Geom::OptRect bbox = item->getBounds(item->i2d_affine());
diff --git a/src/sp-shape.h b/src/sp-shape.h
index 493268711..3fd356fdc 100644
--- a/src/sp-shape.h
+++ b/src/sp-shape.h
@@ -60,7 +60,7 @@ private:
static void sp_shape_modified (SPObject *object, unsigned int flags);
static Inkscape::XML::Node *sp_shape_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
- static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+ static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static NRArenaItem *sp_shape_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
static void sp_shape_hide (SPItem *item, unsigned int key);
static void sp_shape_snappoints (SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
@@ -88,9 +88,9 @@ private:
void sp_shape_set_marker (SPObject *object, unsigned int key, const gchar *value);
-Geom::Matrix sp_shape_marker_get_transform(Geom::Curve const & c1, Geom::Curve const & c2);
-Geom::Matrix sp_shape_marker_get_transform_at_start(Geom::Curve const & c);
-Geom::Matrix sp_shape_marker_get_transform_at_end(Geom::Curve const & c);
+Geom::Affine sp_shape_marker_get_transform(Geom::Curve const & c1, Geom::Curve const & c2);
+Geom::Affine sp_shape_marker_get_transform_at_start(Geom::Curve const & c);
+Geom::Affine sp_shape_marker_get_transform_at_end(Geom::Curve const & c);
#endif // SEEN_SP_SHAPE_H
diff --git a/src/sp-spiral.cpp b/src/sp-spiral.cpp
index cfe02947a..abee41473 100644
--- a/src/sp-spiral.cpp
+++ b/src/sp-spiral.cpp
@@ -532,7 +532,7 @@ static void sp_spiral_snappoints(SPItem const *item, std::vector<Inkscape::SnapC
}
if (snapprefs->getSnapObjectMidpoints()) {
- Geom::Matrix const i2d (item->i2d_affine ());
+ Geom::Affine const i2d (item->i2d_affine ());
SPSpiral *spiral = SP_SPIRAL(item);
p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(spiral->cx, spiral->cy) * i2d, Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT));
// This point is the start-point of the spiral, which is also returned when _snap_to_itemnode has been set
diff --git a/src/sp-star.cpp b/src/sp-star.cpp
index b94e2dbc4..57c72ca75 100644
--- a/src/sp-star.cpp
+++ b/src/sp-star.cpp
@@ -410,7 +410,7 @@ sp_star_get_curvepoint (SPStar *star, SPStarPoint point, gint index, bool previ)
guint32 seed = point_unique_int (o);
// randomly rotate (by step 3 from the seed) and scale (by step 4) the vector
- ret = ret * Geom::Matrix (Geom::Rotate (star->randomized * M_PI * rnd (seed, 3)));
+ ret = ret * Geom::Affine (Geom::Rotate (star->randomized * M_PI * rnd (seed, 3)));
ret *= ( 1 + star->randomized * rnd (seed, 4));
// the randomized corner point
@@ -559,7 +559,7 @@ static void sp_star_snappoints(SPItem const *item, std::vector<Inkscape::SnapCan
}
if (snapprefs->getSnapObjectMidpoints()) {
- Geom::Matrix const i2d (item->i2d_affine ());
+ Geom::Affine const i2d (item->i2d_affine ());
p.push_back(Inkscape::SnapCandidatePoint(SP_STAR(item)->center * i2d,Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT));
}
}
diff --git a/src/sp-symbol.cpp b/src/sp-symbol.cpp
index 6c8d3cd82..182a2756a 100644
--- a/src/sp-symbol.cpp
+++ b/src/sp-symbol.cpp
@@ -40,7 +40,7 @@ static Inkscape::XML::Node *sp_symbol_write (SPObject *object, Inkscape::XML::Do
static NRArenaItem *sp_symbol_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
static void sp_symbol_hide (SPItem *item, unsigned int key);
-static void sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+static void sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static void sp_symbol_print (SPItem *item, SPPrintContext *ctx);
static SPGroupClass *parent_class;
@@ -269,7 +269,7 @@ sp_symbol_update (SPObject *object, SPCtx *ctx, guint flags)
/* Calculate child to parent transformation */
/* Apply parent <use> translation (set up as vewport) */
- symbol->c2p = Geom::Matrix(Geom::Translate(rctx.vp.x0, rctx.vp.y0));
+ symbol->c2p = Geom::Affine(Geom::Translate(rctx.vp.x0, rctx.vp.y0));
if (symbol->viewBox_set) {
double x, y, width, height;
@@ -332,7 +332,7 @@ sp_symbol_update (SPObject *object, SPCtx *ctx, guint flags)
}
}
/* Compose additional transformation from scale and position */
- Geom::Matrix q;
+ Geom::Affine q;
q[0] = width / (symbol->viewBox.x1 - symbol->viewBox.x0);
q[1] = 0.0;
q[2] = 0.0;
@@ -343,7 +343,7 @@ sp_symbol_update (SPObject *object, SPCtx *ctx, guint flags)
symbol->c2p = q * symbol->c2p;
}
- rctx.i2doc = symbol->c2p * (Geom::Matrix)rctx.i2doc;
+ rctx.i2doc = symbol->c2p * (Geom::Affine)rctx.i2doc;
/* If viewBox is set initialize child viewport */
/* Otherwise <use> has set it up already */
@@ -445,7 +445,7 @@ sp_symbol_hide (SPItem *item, unsigned int key)
}
static void
-sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags)
+sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags)
{
SPSymbol const *symbol = SP_SYMBOL(item);
@@ -453,7 +453,7 @@ sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform,
/* Cloned <symbol> is actually renderable */
if (((SPItemClass *) (parent_class))->bbox) {
- Geom::Matrix const a( symbol->c2p * transform );
+ Geom::Affine const a( symbol->c2p * transform );
((SPItemClass *) (parent_class))->bbox(item, bbox, a, flags);
}
}
diff --git a/src/sp-symbol.h b/src/sp-symbol.h
index 61951cf64..6c0a36d73 100644
--- a/src/sp-symbol.h
+++ b/src/sp-symbol.h
@@ -25,7 +25,7 @@ class SPSymbol;
class SPSymbolClass;
#include <libnr/nr-matrix.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <libnr/nr-rect.h>
#include "svg/svg-length.h"
#include "enums.h"
@@ -42,7 +42,7 @@ struct SPSymbol : public SPGroup {
unsigned int aspect_clip : 1;
/* Child to parent additional transform */
- Geom::Matrix c2p;
+ Geom::Affine c2p;
};
struct SPSymbolClass {
diff --git a/src/sp-text.cpp b/src/sp-text.cpp
index 80eb786f2..3abeadaee 100644
--- a/src/sp-text.cpp
+++ b/src/sp-text.cpp
@@ -27,7 +27,7 @@
# include "config.h"
#endif
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <libnr/nr-matrix-fns.h>
#include <libnrtype/FontFactory.h>
#include <libnrtype/font-instance.h>
@@ -72,12 +72,12 @@ static void sp_text_update (SPObject *object, SPCtx *ctx, guint flags);
static void sp_text_modified (SPObject *object, guint flags);
static Inkscape::XML::Node *sp_text_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
-static void sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+static void sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static NRArenaItem *sp_text_show (SPItem *item, NRArena *arena, unsigned key, unsigned flags);
static void sp_text_hide (SPItem *item, unsigned key);
static char *sp_text_description (SPItem *item);
static void sp_text_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
-static Geom::Matrix sp_text_set_transform(SPItem *item, Geom::Matrix const &xform);
+static Geom::Affine sp_text_set_transform(SPItem *item, Geom::Affine const &xform);
static void sp_text_print (SPItem *item, SPPrintContext *gpc);
static SPItemClass *text_parent_class;
@@ -363,7 +363,7 @@ static Inkscape::XML::Node *sp_text_write(SPObject *object, Inkscape::XML::Docum
}
static void
-sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/)
+sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/)
{
SP_TEXT(item)->layout.getBoundingBox(bbox, transform);
@@ -456,8 +456,8 @@ static void sp_text_snappoints(SPItem const *item, std::vector<Inkscape::SnapCan
}
}
-static Geom::Matrix
-sp_text_set_transform (SPItem *item, Geom::Matrix const &xform)
+static Geom::Affine
+sp_text_set_transform (SPItem *item, Geom::Affine const &xform)
{
SPText *text = SP_TEXT(item);
@@ -479,7 +479,7 @@ sp_text_set_transform (SPItem *item, Geom::Matrix const &xform)
return xform;
}
- Geom::Matrix ret(Geom::Matrix(xform).without_translation());
+ Geom::Affine ret(Geom::Affine(xform).withoutTranslation());
ret[0] /= ex;
ret[1] /= ex;
ret[2] /= ex;
@@ -517,7 +517,7 @@ sp_text_print (SPItem *item, SPPrintContext *ctx)
dbox.y0 = 0.0;
dbox.x1 = SP_OBJECT_DOCUMENT (item)->getWidth ();
dbox.y1 = SP_OBJECT_DOCUMENT (item)->getHeight ();
- Geom::Matrix const ctm (item->i2d_affine());
+ Geom::Affine const ctm (item->i2d_affine());
group->layout.print(ctx,&pbox,&dbox,&bbox,ctm);
}
@@ -642,7 +642,7 @@ void SPText::_adjustFontsizeRecursive(SPItem *item, double ex, bool is_root)
}
}
-void SPText::_adjustCoordsRecursive(SPItem *item, Geom::Matrix const &m, double ex, bool is_root)
+void SPText::_adjustCoordsRecursive(SPItem *item, Geom::Affine const &m, double ex, bool is_root)
{
if (SP_IS_TSPAN(item))
SP_TSPAN(item)->attributes.transform(m, ex, ex, is_root);
@@ -903,7 +903,7 @@ void TextTagAttributes::joinSingleAttribute(std::vector<SVGLength> *dest_vector,
}
}
-void TextTagAttributes::transform(Geom::Matrix const &matrix, double scale_x, double scale_y, bool extend_zero_length)
+void TextTagAttributes::transform(Geom::Affine const &matrix, double scale_x, double scale_y, bool extend_zero_length)
{
SVGLength zero_length;
zero_length = 0.0;
diff --git a/src/sp-text.h b/src/sp-text.h
index e7c264b07..116d8d869 100644
--- a/src/sp-text.h
+++ b/src/sp-text.h
@@ -53,7 +53,7 @@ struct SPText : public SPItem {
extend zero-length position vectors to length 1 in order to record the
new position. This is necessary to convert from objects whose position is
completely specified by transformations. */
- static void _adjustCoordsRecursive(SPItem *item, Geom::Matrix const &m, double ex, bool is_root = true);
+ static void _adjustCoordsRecursive(SPItem *item, Geom::Affine const &m, double ex, bool is_root = true);
static void _adjustFontsizeRecursive(SPItem *item, double ex, bool is_root = true);
/** discards the NRArena objects representing this text. */
diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp
index eddcd270c..a882ee0b0 100644
--- a/src/sp-tref.cpp
+++ b/src/sp-tref.cpp
@@ -65,7 +65,7 @@ static void sp_tref_update(SPObject *object, SPCtx *ctx, guint flags);
static void sp_tref_modified(SPObject *object, guint flags);
static Inkscape::XML::Node *sp_tref_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
-static void sp_tref_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+static void sp_tref_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static gchar *sp_tref_description(SPItem *item);
static void sp_tref_href_changed(SPObject *old_ref, SPObject *ref, SPTRef *tref);
@@ -320,7 +320,7 @@ sp_tref_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML:
* The code for this function is swiped from the tspan bbox code, since tref should work pretty much the same way
*/
static void
-sp_tref_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/)
+sp_tref_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/)
{
// find out the ancestor text which holds our layout
SPObject *parent_text = SP_OBJECT(item);
diff --git a/src/sp-tspan.cpp b/src/sp-tspan.cpp
index 2afd75e75..57c23929d 100644
--- a/src/sp-tspan.cpp
+++ b/src/sp-tspan.cpp
@@ -57,7 +57,7 @@ static void sp_tspan_release(SPObject *object);
static void sp_tspan_set(SPObject *object, unsigned key, gchar const *value);
static void sp_tspan_update(SPObject *object, SPCtx *ctx, guint flags);
static void sp_tspan_modified(SPObject *object, unsigned flags);
-static void sp_tspan_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+static void sp_tspan_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static Inkscape::XML::Node *sp_tspan_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
static char *sp_tspan_description (SPItem *item);
@@ -204,7 +204,7 @@ static void sp_tspan_modified(SPObject *object, unsigned flags)
}
}
-static void sp_tspan_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/)
+static void sp_tspan_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/)
{
// find out the ancestor text which holds our layout
SPObject *parent_text = SP_OBJECT(item);
diff --git a/src/sp-use-reference.cpp b/src/sp-use-reference.cpp
index a05dc0e93..0784f2dd1 100644
--- a/src/sp-use-reference.cpp
+++ b/src/sp-use-reference.cpp
@@ -41,7 +41,7 @@ bool SPUseReference::_acceptObject(SPObject * const obj) const
static void sp_usepath_href_changed(SPObject *old_ref, SPObject *ref, SPUsePath *offset);
-static void sp_usepath_move_compensate(Geom::Matrix const *mp, SPItem *original, SPUsePath *self);
+static void sp_usepath_move_compensate(Geom::Affine const *mp, SPItem *original, SPUsePath *self);
static void sp_usepath_delete_self(SPObject *deleted, SPUsePath *offset);
static void sp_usepath_source_modified(SPObject *iSource, guint flags, SPUsePath *offset);
@@ -139,7 +139,7 @@ sp_usepath_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPUsePath *off
}
static void
-sp_usepath_move_compensate(Geom::Matrix const *mp, SPItem *original, SPUsePath *self)
+sp_usepath_move_compensate(Geom::Affine const *mp, SPItem *original, SPUsePath *self)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
guint mode = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_PARALLEL);
@@ -150,15 +150,15 @@ sp_usepath_move_compensate(Geom::Matrix const *mp, SPItem *original, SPUsePath *
// TODO kill naughty naughty #if 0
#if 0
- Geom::Matrix m(*mp);
+ Geom::Affine m(*mp);
if (!(m.is_translation())) {
return;
}
- Geom::Matrix const t(item->transform);
- Geom::Matrix clone_move = t.inverse() * m * t;
+ Geom::Affine const t(item->transform);
+ Geom::Affine clone_move = t.inverse() * m * t;
// Calculate the compensation matrix and the advertized movement matrix.
- Geom::Matrix advertized_move;
+ Geom::Affine advertized_move;
if (mode == SP_CLONE_COMPENSATION_PARALLEL) {
//clone_move = clone_move.inverse();
advertized_move.set_identity();
diff --git a/src/sp-use.cpp b/src/sp-use.cpp
index 505c64fd2..dd5a6c5f9 100644
--- a/src/sp-use.cpp
+++ b/src/sp-use.cpp
@@ -51,7 +51,7 @@ static Inkscape::XML::Node *sp_use_write(SPObject *object, Inkscape::XML::Docume
static void sp_use_update(SPObject *object, SPCtx *ctx, guint flags);
static void sp_use_modified(SPObject *object, guint flags);
-static void sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
+static void sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags);
static void sp_use_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
static void sp_use_print(SPItem *item, SPPrintContext *ctx);
static gchar *sp_use_description(SPItem *item);
@@ -64,7 +64,7 @@ static void sp_use_delete_self(SPObject *deleted, SPUse *self);
static SPItemClass *parent_class;
-//void m_print(gchar *say, Geom::Matrix m)
+//void m_print(gchar *say, Geom::Affine m)
//{ g_print("%s %g %g %g %g %g %g\n", say, m[0], m[1], m[2], m[3], m[4], m[5]); }
GType
@@ -278,13 +278,13 @@ sp_use_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::
}
static void
-sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags)
+sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags)
{
SPUse const *use = SP_USE(item);
if (use->child && SP_IS_ITEM(use->child)) {
SPItem *child = SP_ITEM(use->child);
- Geom::Matrix const ct( child->transform
+ Geom::Affine const ct( child->transform
* Geom::Translate(use->x.computed,
use->y.computed)
* transform );
@@ -306,7 +306,7 @@ sp_use_print(SPItem *item, SPPrintContext *ctx)
SPUse *use = SP_USE(item);
if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) {
- Geom::Matrix tp(Geom::Translate(use->x.computed, use->y.computed));
+ Geom::Affine tp(Geom::Translate(use->x.computed, use->y.computed));
sp_print_bind(ctx, tp, 1.0);
translated = true;
}
@@ -363,7 +363,7 @@ sp_use_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags)
}
Geom::Translate t(use->x.computed,
use->y.computed);
- nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), Geom::Matrix(t));
+ nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), Geom::Affine(t));
}
return ai;
@@ -407,7 +407,7 @@ sp_use_root(SPUse *use)
* Returns the effective transform that goes from the ultimate original to given SPUse, both ends
* included.
*/
-Geom::Matrix
+Geom::Affine
sp_use_get_root_transform(SPUse *use)
{
//track the ultimate source of a chain of uses
@@ -422,7 +422,7 @@ sp_use_get_root_transform(SPUse *use)
//calculate the accummulated transform, starting from the original
- Geom::Matrix t(Geom::identity());
+ Geom::Affine t(Geom::identity());
for (GSList *i = chain; i != NULL; i = i->next) {
SPItem *i_tem = SP_ITEM(i->data);
@@ -447,10 +447,10 @@ sp_use_get_root_transform(SPUse *use)
* Returns the transform that leads to the use from its immediate original.
* Does not inlcude the original's transform if any.
*/
-Geom::Matrix
+Geom::Affine
sp_use_get_parent_transform(SPUse *use)
{
- Geom::Matrix t(Geom::identity());
+ Geom::Affine t(Geom::identity());
if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) {
t *= Geom::Translate(use->x._set ? use->x.computed : 0,
use->y._set ? use->y.computed : 0);
@@ -466,7 +466,7 @@ sp_use_get_parent_transform(SPUse *use)
* clone's transform.
*/
static void
-sp_use_move_compensate(Geom::Matrix const *mp, SPItem */*original*/, SPUse *self)
+sp_use_move_compensate(Geom::Affine const *mp, SPItem */*original*/, SPUse *self)
{
// the clone is orphaned; or this is not a real use, but a clone of another use;
// we skip it, otherwise duplicate compensation will occur
@@ -485,7 +485,7 @@ sp_use_move_compensate(Geom::Matrix const *mp, SPItem */*original*/, SPUse *self
if (mode == SP_CLONE_COMPENSATION_NONE)
return;
- Geom::Matrix m(*mp);
+ Geom::Affine m(*mp);
// this is not a simple move, do not try to compensate
if (!(m.isTranslation()))
@@ -494,11 +494,11 @@ sp_use_move_compensate(Geom::Matrix const *mp, SPItem */*original*/, SPUse *self
// restore item->transform field from the repr, in case it was changed by seltrans
SP_OBJECT (self)->readAttr ("transform");
- Geom::Matrix t = sp_use_get_parent_transform(self);
- Geom::Matrix clone_move = t.inverse() * m * t;
+ Geom::Affine t = sp_use_get_parent_transform(self);
+ Geom::Affine clone_move = t.inverse() * m * t;
// calculate the compensation matrix and the advertized movement matrix
- Geom::Matrix advertized_move;
+ Geom::Affine advertized_move;
if (mode == SP_CLONE_COMPENSATION_PARALLEL) {
clone_move = clone_move.inverse() * m;
advertized_move = m;
@@ -633,7 +633,7 @@ sp_use_update(SPObject *object, SPCtx *ctx, unsigned flags)
/* As last step set additional transform of arena group */
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- Geom::Matrix t(Geom::Translate(use->x.computed, use->y.computed));
+ Geom::Affine t(Geom::Translate(use->x.computed, use->y.computed));
nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), t);
}
}
@@ -686,7 +686,7 @@ SPItem *sp_use_unlink(SPUse *use)
}
// Calculate the accumulated transform, starting from the original.
- Geom::Matrix t = sp_use_get_root_transform(use);
+ Geom::Affine t = sp_use_get_root_transform(use);
Inkscape::XML::Node *copy = NULL;
if (SP_IS_SYMBOL(orig)) { // make a group, copy children
@@ -739,7 +739,7 @@ SPItem *sp_use_unlink(SPUse *use)
SPItem *item = SP_ITEM(unlinked);
// Set the accummulated transform.
{
- Geom::Matrix nomove(Geom::identity());
+ Geom::Affine nomove(Geom::identity());
// Advertise ourselves as not moving.
item->doWriteTransform(SP_OBJECT_REPR(item), t, &nomove);
}
diff --git a/src/sp-use.h b/src/sp-use.h
index c5c07158f..ff0e1c604 100644
--- a/src/sp-use.h
+++ b/src/sp-use.h
@@ -59,8 +59,8 @@ GType sp_use_get_type (void);
SPItem *sp_use_unlink (SPUse *use);
SPItem *sp_use_get_original (SPUse *use);
-Geom::Matrix sp_use_get_parent_transform (SPUse *use);
-Geom::Matrix sp_use_get_root_transform(SPUse *use);
+Geom::Affine sp_use_get_parent_transform (SPUse *use);
+Geom::Affine sp_use_get_root_transform(SPUse *use);
SPItem *sp_use_root(SPUse *use);
#endif
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index 5f32e591e..bcb9b1bb6 100644
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
@@ -452,7 +452,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
// adjust style properties that depend on a possible transform in the source object in order
// to get a correct style attribute for the new path
SPItem* item_source = SP_ITEM(source);
- Geom::Matrix i2doc(item_source->i2doc_affine());
+ Geom::Affine i2doc(item_source->i2doc_affine());
item_source->adjust_stroke(i2doc.descrim());
item_source->adjust_pattern(i2doc);
item_source->adjust_gradient(i2doc);
@@ -485,7 +485,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
// premultiply by the inverse of parent's repr
SPItem *parent_item = SP_ITEM(sp_desktop_document(desktop)->getObjectByRepr(parent));
- Geom::Matrix local (parent_item->i2doc_affine());
+ Geom::Affine local (parent_item->i2doc_affine());
gchar *transform = sp_svg_transform_write(local.inverse());
// now that we have the result, add it on the canvas
@@ -601,14 +601,14 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb
}
static
-void sp_selected_path_outline_add_marker( SPObject *marker_object, Geom::Matrix marker_transform,
- Geom::Scale stroke_scale, Geom::Matrix transform,
+void sp_selected_path_outline_add_marker( SPObject *marker_object, Geom::Affine marker_transform,
+ Geom::Scale stroke_scale, Geom::Affine transform,
Inkscape::XML::Node *g_repr, Inkscape::XML::Document *xml_doc, SPDocument * doc )
{
SPMarker* marker = SP_MARKER (marker_object);
SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker_object));
- Geom::Matrix tr(marker_transform);
+ Geom::Affine tr(marker_transform);
if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
tr = stroke_scale * tr;
@@ -626,13 +626,13 @@ void sp_selected_path_outline_add_marker( SPObject *marker_object, Geom::Matrix
}
static
-void item_outline_add_marker( SPObject const *marker_object, Geom::Matrix marker_transform,
+void item_outline_add_marker( SPObject const *marker_object, Geom::Affine marker_transform,
Geom::Scale stroke_scale, Geom::PathVector* pathv_in )
{
SPMarker* marker = SP_MARKER (marker_object);
SPItem* marker_item = sp_item_first_item_child(SP_OBJECT(marker_object));
- Geom::Matrix tr(marker_transform);
+ Geom::Affine tr(marker_transform);
if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
tr = stroke_scale * tr;
}
@@ -682,7 +682,7 @@ Geom::PathVector* item_outline(SPItem const *item)
// remember old stroke style, to be set on fill
SPStyle *i_style = SP_OBJECT_STYLE(item);
- Geom::Matrix const transform(item->transform);
+ Geom::Affine const transform(item->transform);
float const scale = transform.descrim();
float o_width, o_miter;
@@ -794,7 +794,7 @@ Geom::PathVector* item_outline(SPItem const *item)
// START marker
for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
if ( SPObject *marker_obj = shape->marker[i] ) {
- Geom::Matrix const m (sp_shape_marker_get_transform_at_start(pathv.front().front()));
+ Geom::Affine const m (sp_shape_marker_get_transform_at_start(pathv.front().front()));
item_outline_add_marker( marker_obj, m,
Geom::Scale(i_style->stroke_width.computed),
ret_pathv );
@@ -809,7 +809,7 @@ Geom::PathVector* item_outline(SPItem const *item)
if ( path_it != pathv.begin()
&& ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there
{
- Geom::Matrix const m (sp_shape_marker_get_transform_at_start(path_it->front()));
+ Geom::Affine const m (sp_shape_marker_get_transform_at_start(path_it->front()));
item_outline_add_marker( midmarker_obj, m,
Geom::Scale(i_style->stroke_width.computed),
ret_pathv );
@@ -824,7 +824,7 @@ Geom::PathVector* item_outline(SPItem const *item)
* Loop to end_default (so including closing segment), because when a path is closed,
* there should be a midpoint marker between last segment and closing straight line segment
*/
- Geom::Matrix const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2));
+ Geom::Affine const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2));
item_outline_add_marker( midmarker_obj, m,
Geom::Scale(i_style->stroke_width.computed),
ret_pathv);
@@ -836,7 +836,7 @@ Geom::PathVector* item_outline(SPItem const *item)
// END position
if ( path_it != (pathv.end()-1) && !path_it->empty()) {
Geom::Curve const &lastcurve = path_it->back_default();
- Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve);
+ Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve);
item_outline_add_marker( midmarker_obj, m,
Geom::Scale(i_style->stroke_width.computed),
ret_pathv );
@@ -855,7 +855,7 @@ Geom::PathVector* item_outline(SPItem const *item)
}
Geom::Curve const &lastcurve = path_last[index];
- Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve);
+ Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve);
item_outline_add_marker( marker_obj, m,
Geom::Scale(i_style->stroke_width.computed),
ret_pathv );
@@ -936,7 +936,7 @@ sp_selected_path_outline(SPDesktop *desktop)
sp_repr_css_unset_property(ncss, "marker-end");
}
- Geom::Matrix const transform(item->transform);
+ Geom::Affine const transform(item->transform);
float const scale = transform.descrim();
gchar const *mask = SP_OBJECT_REPR(item)->attribute("mask");
gchar const *clip_path = SP_OBJECT_REPR(item)->attribute("clip-path");
@@ -1112,7 +1112,7 @@ sp_selected_path_outline(SPDesktop *desktop)
// START marker
for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START
if ( SPObject *marker_obj = shape->marker[i] ) {
- Geom::Matrix const m (sp_shape_marker_get_transform_at_start(pathv.front().front()));
+ Geom::Affine const m (sp_shape_marker_get_transform_at_start(pathv.front().front()));
sp_selected_path_outline_add_marker( marker_obj, m,
Geom::Scale(i_style->stroke_width.computed), transform,
g_repr, xml_doc, doc );
@@ -1127,7 +1127,7 @@ sp_selected_path_outline(SPDesktop *desktop)
if ( path_it != pathv.begin()
&& ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there
{
- Geom::Matrix const m (sp_shape_marker_get_transform_at_start(path_it->front()));
+ Geom::Affine const m (sp_shape_marker_get_transform_at_start(path_it->front()));
sp_selected_path_outline_add_marker( midmarker_obj, m,
Geom::Scale(i_style->stroke_width.computed), transform,
g_repr, xml_doc, doc );
@@ -1142,7 +1142,7 @@ sp_selected_path_outline(SPDesktop *desktop)
* Loop to end_default (so including closing segment), because when a path is closed,
* there should be a midpoint marker between last segment and closing straight line segment
*/
- Geom::Matrix const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2));
+ Geom::Affine const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2));
sp_selected_path_outline_add_marker(midmarker_obj, m,
Geom::Scale(i_style->stroke_width.computed), transform,
g_repr, xml_doc, doc);
@@ -1154,7 +1154,7 @@ sp_selected_path_outline(SPDesktop *desktop)
// END position
if ( path_it != (pathv.end()-1) && !path_it->empty()) {
Geom::Curve const &lastcurve = path_it->back_default();
- Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve);
+ Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve);
sp_selected_path_outline_add_marker( midmarker_obj, m,
Geom::Scale(i_style->stroke_width.computed), transform,
g_repr, xml_doc, doc );
@@ -1173,7 +1173,7 @@ sp_selected_path_outline(SPDesktop *desktop)
}
Geom::Curve const &lastcurve = path_last[index];
- Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve);
+ Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve);
sp_selected_path_outline_add_marker( marker_obj, m,
Geom::Scale(i_style->stroke_width.computed), transform,
g_repr, xml_doc, doc );
@@ -1327,7 +1327,7 @@ sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool updat
return;
}
- Geom::Matrix const transform(item->transform);
+ Geom::Affine const transform(item->transform);
item->doWriteTransform(SP_OBJECT_REPR(item), Geom::identity());
@@ -1555,7 +1555,7 @@ sp_selected_path_do_offset(SPDesktop *desktop, bool expand, double prefOffset)
continue;
}
- Geom::Matrix const transform(item->transform);
+ Geom::Affine const transform(item->transform);
item->doWriteTransform(SP_OBJECT_REPR(item), Geom::identity());
@@ -1802,7 +1802,7 @@ sp_selected_path_simplify_item(SPDesktop *desktop,
size /= item->i2doc_affine().descrim();
// save the transform, to re-apply it after simplification
- Geom::Matrix const transform(item->transform);
+ Geom::Affine const transform(item->transform);
/*
reset the transform, effectively transforming the item by transform.inverse();
@@ -2089,7 +2089,7 @@ Path_for_item(SPItem *item, bool doTransformation, bool transformFull)
* TODO: see if calling this method can be optimized. All the pathvector copying might be slow.
*/
Geom::PathVector*
-pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull, Geom::Matrix extraPreAffine, Geom::Matrix extraPostAffine)
+pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull, Geom::Affine extraPreAffine, Geom::Affine extraPostAffine)
{
if (curve == NULL)
return NULL;
@@ -2101,7 +2101,7 @@ pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool t
if (transformFull) {
*dest *= extraPreAffine * item->i2doc_affine() * extraPostAffine;
} else {
- *dest *= extraPreAffine * (Geom::Matrix)item->transform * extraPostAffine;
+ *dest *= extraPreAffine * (Geom::Affine)item->transform * extraPostAffine;
}
} else {
*dest *= extraPreAffine * extraPostAffine;
diff --git a/src/splivarot.h b/src/splivarot.h
index d85ae030a..ea8183b67 100644
--- a/src/splivarot.h
+++ b/src/splivarot.h
@@ -49,7 +49,7 @@ Geom::PathVector* item_outline(SPItem const *item);
void sp_selected_path_simplify (SPDesktop *desktop);
Path *Path_for_item(SPItem *item, bool doTransformation, bool transformFull = true);
-Geom::PathVector* pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull, Geom::Matrix extraPreAffine, Geom::Matrix extraPostAffine);
+Geom::PathVector* pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull, Geom::Affine extraPreAffine, Geom::Affine extraPostAffine);
SPCurve *curve_for_item(SPItem *item);
boost::optional<Path::cut_position> get_nearest_position_on_Path(Path *path, Geom::Point p, unsigned seg = 0);
Geom::Point get_point_on_Path(Path *path, int piece, double t);
diff --git a/src/spray-context.cpp b/src/spray-context.cpp
index 6d19cbce4..244c52fad 100644
--- a/src/spray-context.cpp
+++ b/src/spray-context.cpp
@@ -151,9 +151,9 @@ void sp_spray_rotate_rel(Geom::Point c,SPDesktop */*desktop*/,SPItem *item, Geom
{
Geom::Point center = c;
Geom::Translate const s(c);
- Geom::Matrix affine = Geom::Matrix(s).inverse() * Geom::Matrix(rotation) * Geom::Matrix(s);
+ Geom::Affine affine = Geom::Affine(s).inverse() * Geom::Affine(rotation) * Geom::Affine(s);
// Rotate item.
- item->set_i2d_affine(item->i2d_affine() * (Geom::Matrix)affine);
+ item->set_i2d_affine(item->i2d_affine() * (Geom::Affine)affine);
// Use each item's own transform writer, consistent with sp_selection_apply_affine()
item->doWriteTransform(SP_OBJECT_REPR(item), item->transform);
// Restore the center position (it's changed because the bbox center changed)
@@ -679,7 +679,7 @@ bool sp_spray_dilate(SPSprayContext *tc, Geom::Point /*event_p*/, Geom::Point p,
void sp_spray_update_area(SPSprayContext *tc)
{
double radius = get_dilate_radius(tc);
- Geom::Matrix const sm ( Geom::Scale(radius/(1-tc->ratio), radius/(1+tc->ratio)) );
+ Geom::Affine const sm ( Geom::Scale(radius/(1-tc->ratio), radius/(1+tc->ratio)) );
sp_canvas_item_affine_absolute(tc->dilate_area, (sm* Geom::Rotate(tc->tilt))* Geom::Translate(SP_EVENT_CONTEXT(tc)->desktop->point()));
sp_canvas_item_show(tc->dilate_area);
}
@@ -763,7 +763,7 @@ gint sp_spray_context_root_handler(SPEventContext *event_context,
// draw the dilating cursor
double radius = get_dilate_radius(tc);
- Geom::Matrix const sm (Geom::Scale(radius/(1-tc->ratio), radius/(1+tc->ratio)) );
+ Geom::Affine const sm (Geom::Scale(radius/(1-tc->ratio), radius/(1+tc->ratio)) );
sp_canvas_item_affine_absolute(tc->dilate_area, (sm*Geom::Rotate(tc->tilt))*Geom::Translate(desktop->w2d(motion_w)));
sp_canvas_item_show(tc->dilate_area);
diff --git a/src/svg/svg-affine-test.h b/src/svg/svg-affine-test.h
index be5a941bb..11b9012a8 100644
--- a/src/svg/svg-affine-test.h
+++ b/src/svg/svg-affine-test.h
@@ -2,7 +2,7 @@
#include "svg/svg.h"
#include "streq.h"
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <algorithm>
#include <glib.h>
#include <iostream>
@@ -14,10 +14,10 @@ class SvgAffineTest : public CxxTest::TestSuite
private:
struct test_t {
char const * str;
- Geom::Matrix matrix;
+ Geom::Affine matrix;
};
struct approx_equal_pred {
- bool operator()(Geom::Matrix const &ref, Geom::Matrix const &cm) const
+ bool operator()(Geom::Affine const &ref, Geom::Affine const &cm) const
{
double maxabsdiff = 0;
for(size_t i=0; i<6; i++) {
@@ -59,7 +59,7 @@ public:
"skewY(0)"};
size_t n = G_N_ELEMENTS(strs);
for(size_t i=0; i<n; i++) {
- Geom::Matrix cm;
+ Geom::Affine cm;
TSM_ASSERT(strs[i] , sp_svg_transform_read(strs[i], &cm));
TSM_ASSERT_EQUALS(strs[i] , Geom::identity() , cm);
}
@@ -73,7 +73,7 @@ public:
void testReadMatrix()
{
for(size_t i=0; i<G_N_ELEMENTS(read_matrix_tests); i++) {
- Geom::Matrix cm;
+ Geom::Affine cm;
TSM_ASSERT(read_matrix_tests[i].str , sp_svg_transform_read(read_matrix_tests[i].str, &cm));
TSM_ASSERT_RELATION(read_matrix_tests[i].str , approx_equal_pred , read_matrix_tests[i].matrix , cm);
}
@@ -82,7 +82,7 @@ public:
void testReadTranslate()
{
for(size_t i=0; i<G_N_ELEMENTS(read_translate_tests); i++) {
- Geom::Matrix cm;
+ Geom::Affine cm;
TSM_ASSERT(read_translate_tests[i].str , sp_svg_transform_read(read_translate_tests[i].str, &cm));
TSM_ASSERT_RELATION(read_translate_tests[i].str , approx_equal_pred , read_translate_tests[i].matrix , cm);
}
@@ -91,7 +91,7 @@ public:
void testReadScale()
{
for(size_t i=0; i<G_N_ELEMENTS(read_scale_tests); i++) {
- Geom::Matrix cm;
+ Geom::Affine cm;
TSM_ASSERT(read_scale_tests[i].str , sp_svg_transform_read(read_scale_tests[i].str, &cm));
TSM_ASSERT_RELATION(read_scale_tests[i].str , approx_equal_pred , read_scale_tests[i].matrix , cm);
}
@@ -100,7 +100,7 @@ public:
void testReadRotate()
{
for(size_t i=0; i<G_N_ELEMENTS(read_rotate_tests); i++) {
- Geom::Matrix cm;
+ Geom::Affine cm;
TSM_ASSERT(read_rotate_tests[i].str , sp_svg_transform_read(read_rotate_tests[i].str, &cm));
TSM_ASSERT_RELATION(read_rotate_tests[i].str , approx_equal_pred , read_rotate_tests[i].matrix , cm);
}
@@ -109,7 +109,7 @@ public:
void testReadSkew()
{
for(size_t i=0; i<G_N_ELEMENTS(read_skew_tests); i++) {
- Geom::Matrix cm;
+ Geom::Affine cm;
TSM_ASSERT(read_skew_tests[i].str , sp_svg_transform_read(read_skew_tests[i].str, &cm));
TSM_ASSERT_RELATION(read_skew_tests[i].str , approx_equal_pred , read_skew_tests[i].matrix , cm);
}
@@ -166,8 +166,8 @@ public:
// there should be 1 or more comma-wsp sequences between transforms... This doesn't make sense and it seems
// likely that instead of a + they meant a ? (zero or one comma-wsp sequences).
char const * str = "skewY(17)skewX(9)translate(7,13)scale(2)rotate(13)translate(3,5)";
- Geom::Matrix ref(2.0199976232558053, 1.0674773585906016, -0.14125199392774669, 1.9055550612095459, 14.412730624347654, 28.499820929377454); // Precomputed using Mathematica
- Geom::Matrix cm;
+ Geom::Affine ref(2.0199976232558053, 1.0674773585906016, -0.14125199392774669, 1.9055550612095459, 14.412730624347654, 28.499820929377454); // Precomputed using Mathematica
+ Geom::Affine cm;
TS_ASSERT(sp_svg_transform_read(str, &cm));
TS_ASSERT_RELATION(approx_equal_pred , ref , cm);
}
@@ -175,7 +175,7 @@ public:
void testReadFailures()
{
for(size_t i=0; i<G_N_ELEMENTS(read_fail_tests); i++) {
- Geom::Matrix cm;
+ Geom::Affine cm;
TSM_ASSERT(read_fail_tests[i] , !sp_svg_transform_read(read_fail_tests[i], &cm));
}
}
@@ -184,26 +184,26 @@ public:
static double const DEGREE = M_PI/180.;
SvgAffineTest::test_t const SvgAffineTest::read_matrix_tests[3] = {
- {"matrix(0,0,0,0,0,0)",Geom::Matrix(0,0,0,0,0,0)},
- {" matrix(1,2,3,4,5,6)",Geom::Matrix(1,2,3,4,5,6)},
- {"matrix (1 2 -3,-4,5e6,-6e-7)",Geom::Matrix(1,2,-3,-4,5e6,-6e-7)}};
+ {"matrix(0,0,0,0,0,0)",Geom::Affine(0,0,0,0,0,0)},
+ {" matrix(1,2,3,4,5,6)",Geom::Affine(1,2,3,4,5,6)},
+ {"matrix (1 2 -3,-4,5e6,-6e-7)",Geom::Affine(1,2,-3,-4,5e6,-6e-7)}};
SvgAffineTest::test_t const SvgAffineTest::read_translate_tests[3] = {
- {"translate(1)",Geom::Matrix(1,0,0,1,1,0)},
- {"translate(1,1)",Geom::Matrix(1,0,0,1,1,1)},
- {"translate(-1e3 .123e2)",Geom::Matrix(1,0,0,1,-1e3,.123e2)}};
+ {"translate(1)",Geom::Affine(1,0,0,1,1,0)},
+ {"translate(1,1)",Geom::Affine(1,0,0,1,1,1)},
+ {"translate(-1e3 .123e2)",Geom::Affine(1,0,0,1,-1e3,.123e2)}};
SvgAffineTest::test_t const SvgAffineTest::read_scale_tests[3] = {
- {"scale(2)",Geom::Matrix(2,0,0,2,0,0)},
- {"scale(2,3)",Geom::Matrix(2,0,0,3,0,0)},
- {"scale(0.1e-2 -.475e0)",Geom::Matrix(0.1e-2,0,0,-.475e0,0,0)}};
+ {"scale(2)",Geom::Affine(2,0,0,2,0,0)},
+ {"scale(2,3)",Geom::Affine(2,0,0,3,0,0)},
+ {"scale(0.1e-2 -.475e0)",Geom::Affine(0.1e-2,0,0,-.475e0,0,0)}};
SvgAffineTest::test_t const SvgAffineTest::read_rotate_tests[4] = {
- {"rotate(13 )",Geom::Matrix(cos(13.*DEGREE),sin(13.*DEGREE),-sin(13.*DEGREE),cos(13.*DEGREE),0,0)},
- {"rotate(-13)",Geom::Matrix(cos(-13.*DEGREE),sin(-13.*DEGREE),-sin(-13.*DEGREE),cos(-13.*DEGREE),0,0)},
- {"rotate(373)",Geom::Matrix(cos(13.*DEGREE),sin(13.*DEGREE),-sin(13.*DEGREE),cos(13.*DEGREE),0,0)},
- {"rotate(13,7,11)",Geom::Matrix(cos(13.*DEGREE),sin(13.*DEGREE),-sin(13.*DEGREE),cos(13.*DEGREE),(1-cos(13.*DEGREE))*7+sin(13.*DEGREE)*11,(1-cos(13.*DEGREE))*11-sin(13.*DEGREE)*7)}};
+ {"rotate(13 )",Geom::Affine(cos(13.*DEGREE),sin(13.*DEGREE),-sin(13.*DEGREE),cos(13.*DEGREE),0,0)},
+ {"rotate(-13)",Geom::Affine(cos(-13.*DEGREE),sin(-13.*DEGREE),-sin(-13.*DEGREE),cos(-13.*DEGREE),0,0)},
+ {"rotate(373)",Geom::Affine(cos(13.*DEGREE),sin(13.*DEGREE),-sin(13.*DEGREE),cos(13.*DEGREE),0,0)},
+ {"rotate(13,7,11)",Geom::Affine(cos(13.*DEGREE),sin(13.*DEGREE),-sin(13.*DEGREE),cos(13.*DEGREE),(1-cos(13.*DEGREE))*7+sin(13.*DEGREE)*11,(1-cos(13.*DEGREE))*11-sin(13.*DEGREE)*7)}};
SvgAffineTest::test_t const SvgAffineTest::read_skew_tests[3] = {
- {"skewX( 30)",Geom::Matrix(1,0,tan(30.*DEGREE),1,0,0)},
- {"skewX(-30)",Geom::Matrix(1,0,tan(-30.*DEGREE),1,0,0)},
- {"skewY(390)",Geom::Matrix(1,tan(30.*DEGREE),0,1,0,0)}};
+ {"skewX( 30)",Geom::Affine(1,0,tan(30.*DEGREE),1,0,0)},
+ {"skewX(-30)",Geom::Affine(1,0,tan(-30.*DEGREE),1,0,0)},
+ {"skewY(390)",Geom::Affine(1,tan(30.*DEGREE),0,1,0,0)}};
char const * const SvgAffineTest::read_fail_tests[25] = {
"matrix((1,2,3,4,5,6)",
"matrix((1,2,3,4,5,6))",
@@ -232,22 +232,22 @@ char const * const SvgAffineTest::read_fail_tests[25] = {
"skewY(1,2)"};
SvgAffineTest::test_t const SvgAffineTest::write_matrix_tests[2] = {
- {"matrix(1,2,3,4,5,6)",Geom::Matrix(1,2,3,4,5,6)},
- {"matrix(-1,2123,3,0.4,1e-8,1e20)",Geom::Matrix(-1,2.123e3,3+1e-14,0.4,1e-8,1e20)}};
+ {"matrix(1,2,3,4,5,6)",Geom::Affine(1,2,3,4,5,6)},
+ {"matrix(-1,2123,3,0.4,1e-8,1e20)",Geom::Affine(-1,2.123e3,3+1e-14,0.4,1e-8,1e20)}};
SvgAffineTest::test_t const SvgAffineTest::write_translate_tests[3] = {
- {"translate(1,1)",Geom::Matrix(1,0,0,1,1,1)},
- {"translate(1)",Geom::Matrix(1,0,0,1,1,0)},
- {"translate(-1345,0.123)",Geom::Matrix(1,0,0,1,-1.345e3,.123)}};
+ {"translate(1,1)",Geom::Affine(1,0,0,1,1,1)},
+ {"translate(1)",Geom::Affine(1,0,0,1,1,0)},
+ {"translate(-1345,0.123)",Geom::Affine(1,0,0,1,-1.345e3,.123)}};
SvgAffineTest::test_t const SvgAffineTest::write_scale_tests[2] = {
- {"scale(0)",Geom::Matrix(0,0,0,0,0,0)},
- {"scale(2,3)",Geom::Matrix(2,0,0,3,0,0)}};
+ {"scale(0)",Geom::Affine(0,0,0,0,0,0)},
+ {"scale(2,3)",Geom::Affine(2,0,0,3,0,0)}};
SvgAffineTest::test_t const SvgAffineTest::write_rotate_tests[2] = {
- {"rotate(13)",Geom::Matrix(cos(13.*DEGREE),sin(13.*DEGREE),-sin(13.*DEGREE),cos(13.*DEGREE),0,0)},
- {"rotate(-13,7,11)",Geom::Matrix(cos(-13.*DEGREE),sin(-13.*DEGREE),-sin(-13.*DEGREE),cos(-13.*DEGREE),(1-cos(-13.*DEGREE))*7+sin(-13.*DEGREE)*11,(1-cos(-13.*DEGREE))*11-sin(-13.*DEGREE)*7)}};
+ {"rotate(13)",Geom::Affine(cos(13.*DEGREE),sin(13.*DEGREE),-sin(13.*DEGREE),cos(13.*DEGREE),0,0)},
+ {"rotate(-13,7,11)",Geom::Affine(cos(-13.*DEGREE),sin(-13.*DEGREE),-sin(-13.*DEGREE),cos(-13.*DEGREE),(1-cos(-13.*DEGREE))*7+sin(-13.*DEGREE)*11,(1-cos(-13.*DEGREE))*11-sin(-13.*DEGREE)*7)}};
SvgAffineTest::test_t const SvgAffineTest::write_skew_tests[3] = {
- {"skewX(30)",Geom::Matrix(1,0,tan(30.*DEGREE),1,0,0)},
- {"skewX(-30)",Geom::Matrix(1,0,tan(-30.*DEGREE),1,0,0)},
- {"skewY(390)",Geom::Matrix(1,tan(30.*DEGREE),0,1,0,0)}};
+ {"skewX(30)",Geom::Affine(1,0,tan(30.*DEGREE),1,0,0)},
+ {"skewX(-30)",Geom::Affine(1,0,tan(-30.*DEGREE),1,0,0)},
+ {"skewY(390)",Geom::Affine(1,tan(30.*DEGREE),0,1,0,0)}};
/*
Local Variables:
diff --git a/src/svg/svg-affine.cpp b/src/svg/svg-affine.cpp
index aa817d2f9..69685e04c 100644
--- a/src/svg/svg-affine.cpp
+++ b/src/svg/svg-affine.cpp
@@ -33,7 +33,7 @@
#endif
bool
-sp_svg_transform_read(gchar const *str, Geom::Matrix *transform)
+sp_svg_transform_read(gchar const *str, Geom::Affine *transform)
{
int idx;
char keyword[32];
@@ -43,7 +43,7 @@ sp_svg_transform_read(gchar const *str, Geom::Matrix *transform)
if (str == NULL) return false;
- Geom::Matrix a(Geom::identity());
+ Geom::Affine a(Geom::identity());
idx = 0;
while (str[idx]) {
@@ -103,7 +103,7 @@ sp_svg_transform_read(gchar const *str, Geom::Matrix *transform)
/* ok, have parsed keyword and args, now modify the transform */
if (!strcmp (keyword, "matrix")) {
if (n_args != 6) return false;
- a = (*((Geom::Matrix *) &(args)[0])) * a;
+ a = (*((Geom::Affine *) &(args)[0])) * a;
} else if (!strcmp (keyword, "translate")) {
if (n_args == 1) {
args[1] = 0;
@@ -127,19 +127,19 @@ sp_svg_transform_read(gchar const *str, Geom::Matrix *transform)
a = ( Geom::Translate(-args[1], -args[2])
* rot
* Geom::Translate(args[1], args[2])
- * Geom::Matrix(a) );
+ * Geom::Affine(a) );
} else {
a = rot * a;
}
} else if (!strcmp (keyword, "skewX")) {
if (n_args != 1) return false;
- a = ( Geom::Matrix(1, 0,
+ a = ( Geom::Affine(1, 0,
tan(args[0] * M_PI / 180.0), 1,
0, 0)
* a );
} else if (!strcmp (keyword, "skewY")) {
if (n_args != 1) return false;
- a = ( Geom::Matrix(1, tan(args[0] * M_PI / 180.0),
+ a = ( Geom::Affine(1, tan(args[0] * M_PI / 180.0),
0, 1,
0, 0)
* a );
@@ -157,7 +157,7 @@ sp_svg_transform_read(gchar const *str, Geom::Matrix *transform)
#define EQ(a,b) (fabs ((a) - (b)) < 1e-9)
gchar *
-sp_svg_transform_write(Geom::Matrix const &transform)
+sp_svg_transform_write(Geom::Affine const &transform)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -246,7 +246,7 @@ sp_svg_transform_write(Geom::Matrix const &transform)
gchar *
-sp_svg_transform_write(Geom::Matrix const *transform)
+sp_svg_transform_write(Geom::Affine const *transform)
{
return sp_svg_transform_write(*transform);
}
diff --git a/src/svg/svg-path.cpp b/src/svg/svg-path.cpp
index 22af18acb..8781d75e6 100644
--- a/src/svg/svg-path.cpp
+++ b/src/svg/svg-path.cpp
@@ -93,9 +93,9 @@ static void sp_svg_write_curve(Inkscape::SVG::PathString & str, Geom::Curve cons
(*cubic_bezier)[3][0], (*cubic_bezier)[3][1] );
}
else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::SVGEllipticalArc const *>(c)) {
- str.arcTo( svg_elliptical_arc->ray(0), svg_elliptical_arc->ray(1),
- Geom::rad_to_deg(svg_elliptical_arc->rotation_angle()),
- svg_elliptical_arc->large_arc_flag(), svg_elliptical_arc->sweep_flag(),
+ str.arcTo( svg_elliptical_arc->ray(Geom::X), svg_elliptical_arc->ray(Geom::Y),
+ Geom::rad_to_deg(svg_elliptical_arc->rotationAngle()),
+ svg_elliptical_arc->largeArc(), svg_elliptical_arc->sweep(),
svg_elliptical_arc->finalPoint() );
}
else if(Geom::HLineSegment const *hline_segment = dynamic_cast<Geom::HLineSegment const *>(c)) {
diff --git a/src/svg/svg.h b/src/svg/svg.h
index 237a5d348..d5335e1b4 100644
--- a/src/svg/svg.h
+++ b/src/svg/svg.h
@@ -54,10 +54,10 @@ unsigned int sp_svg_length_read_ldd( const gchar *str, SVGLength::Unit *unit, do
std::string sp_svg_length_write_with_units(SVGLength const &length);
-bool sp_svg_transform_read(gchar const *str, Geom::Matrix *transform);
+bool sp_svg_transform_read(gchar const *str, Geom::Affine *transform);
-gchar *sp_svg_transform_write(Geom::Matrix const &transform);
-gchar *sp_svg_transform_write(Geom::Matrix const *transform);
+gchar *sp_svg_transform_write(Geom::Affine const &transform);
+gchar *sp_svg_transform_write(Geom::Affine const *transform);
double sp_svg_read_percentage( const char * str, double def );
diff --git a/src/text-editing.cpp b/src/text-editing.cpp
index 2e6e2f9fa..fb9e2e6a3 100644
--- a/src/text-editing.cpp
+++ b/src/text-editing.cpp
@@ -87,7 +87,7 @@ bool sp_te_input_is_empty(SPObject const *item)
Inkscape::Text::Layout::iterator
sp_te_get_position_by_coords (SPItem const *item, Geom::Point const &i_p)
{
- Geom::Matrix im (item->i2d_affine ());
+ Geom::Affine im (item->i2d_affine ());
im = im.inverse();
Geom::Point p = i_p * im;
@@ -95,7 +95,7 @@ sp_te_get_position_by_coords (SPItem const *item, Geom::Point const &i_p)
return layout->getNearestCursorPositionTo(p);
}
-std::vector<Geom::Point> sp_te_create_selection_quads(SPItem const *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, Geom::Matrix const &transform)
+std::vector<Geom::Point> sp_te_create_selection_quads(SPItem const *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, Geom::Affine const &transform)
{
if (start == end)
return std::vector<Geom::Point>();
@@ -979,7 +979,7 @@ sp_te_adjust_kerning_screen (SPItem *item, Inkscape::Text::Layout::iterator cons
// divide increment by zoom
// divide increment by matrix expansion
gdouble factor = 1 / desktop->current_zoom();
- Geom::Matrix t (item->i2doc_affine());
+ Geom::Affine t (item->i2doc_affine());
factor = factor / t.descrim();
by = factor * by;
@@ -1037,7 +1037,7 @@ sp_te_adjust_rotation_screen(SPItem *text, Inkscape::Text::Layout::iterator cons
// divide increment by zoom
// divide increment by matrix expansion
gdouble factor = 1 / desktop->current_zoom();
- Geom::Matrix t (text->i2doc_affine());
+ Geom::Affine t (text->i2doc_affine());
factor = factor / t.descrim();
Inkscape::Text::Layout const *layout = te_get_layout(text);
if (layout == NULL) return;
@@ -1215,7 +1215,7 @@ sp_te_adjust_linespacing_screen (SPItem *text, Inkscape::Text::Layout::iterator
gdouble zby = by / (desktop->current_zoom() * (line_count == 0 ? 1 : line_count));
// divide increment by matrix expansion
- Geom::Matrix t (SP_ITEM(text)->i2doc_affine ());
+ Geom::Affine t (SP_ITEM(text)->i2doc_affine ());
zby = zby / t.descrim();
switch (style->line_height.unit) {
@@ -1908,7 +1908,7 @@ void sp_te_apply_style(SPItem *text, Inkscape::Text::Layout::iterator const &sta
SPCSSAttr *css_set = sp_repr_css_attr_new();
sp_repr_css_merge(css_set, (SPCSSAttr*) css);
{
- Geom::Matrix const local(SP_ITEM(common_ancestor)->i2doc_affine());
+ Geom::Affine const local(SP_ITEM(common_ancestor)->i2doc_affine());
double const ex(local.descrim());
if ( ( ex != 0. )
&& ( ex != 1. ) ) {
diff --git a/src/text-editing.h b/src/text-editing.h
index 3d5efbbec..529b25ff5 100644
--- a/src/text-editing.h
+++ b/src/text-editing.h
@@ -43,7 +43,7 @@ unsigned sp_text_get_length(SPObject const *item);
\a item, before and not including \a upto. Also adds 1 for each line break encountered. */
unsigned sp_text_get_length_upto(SPObject const *item, SPObject const *upto);
-std::vector<Geom::Point> sp_te_create_selection_quads(SPItem const *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, Geom::Matrix const &transform);
+std::vector<Geom::Point> sp_te_create_selection_quads(SPItem const *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, Geom::Affine const &transform);
Inkscape::Text::Layout::iterator sp_te_get_position_by_coords (SPItem const *item, Geom::Point const &i_p);
void sp_te_get_cursor_coords (SPItem const *item, Inkscape::Text::Layout::iterator const &position, Geom::Point &p0, Geom::Point &p1);
diff --git a/src/text-tag-attributes.h b/src/text-tag-attributes.h
index 11b751a2c..fdcfa8ce0 100644
--- a/src/text-tag-attributes.h
+++ b/src/text-tag-attributes.h
@@ -88,7 +88,7 @@ public:
If \a extend_zero_length is true, then if the x or y vectors are empty
they will be made length 1 in order to store the newly calculated
position. */
- void transform(Geom::Matrix const &matrix, double scale_x, double scale_y, bool extend_zero_length = false);
+ void transform(Geom::Affine const &matrix, double scale_x, double scale_y, bool extend_zero_length = false);
/** Gets current value of dx vector at \a index. */
double getDx(unsigned index);
diff --git a/src/trace/trace.cpp b/src/trace/trace.cpp
index 48d25d0c4..1ee32e6bf 100644
--- a/src/trace/trace.cpp
+++ b/src/trace/trace.cpp
@@ -515,7 +515,7 @@ void Tracer::traceThread()
Geom::Scale scal(iwscale, ihscale);
//# Convolve scale, translation, and the original transform
- Geom::Matrix tf(scal * trans);
+ Geom::Affine tf(scal * trans);
tf *= img->transform;
diff --git a/src/transf_mat_3x4.cpp b/src/transf_mat_3x4.cpp
index 533972e29..20eee658c 100644
--- a/src/transf_mat_3x4.cpp
+++ b/src/transf_mat_3x4.cpp
@@ -13,7 +13,7 @@
#include "transf_mat_3x4.h"
#include <gtk/gtk.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include "svg/stringstream.h"
#include "syseq.h"
#include "document.h"
@@ -133,7 +133,7 @@ TransfMat3x4::operator==(const TransfMat3x4 &rhs) const
/* Multiply a projective matrix by an affine matrix (by only multiplying the 'affine part' of the
* projective matrix) */
TransfMat3x4
-TransfMat3x4::operator*(Geom::Matrix const &A) const {
+TransfMat3x4::operator*(Geom::Affine const &A) const {
TransfMat3x4 ret;
for (int j = 0; j < 4; ++j) {
@@ -148,7 +148,7 @@ TransfMat3x4::operator*(Geom::Matrix const &A) const {
// FIXME: Shouldn't rather operator* call operator*= for efficiency? (Because in operator*=
// there is in principle no need to create a temporary object, which happens in the assignment)
TransfMat3x4 &
-TransfMat3x4::operator*=(Geom::Matrix const &A) {
+TransfMat3x4::operator*=(Geom::Affine const &A) {
*this = *this * A;
return *this;
}
diff --git a/src/transf_mat_3x4.h b/src/transf_mat_3x4.h
index 6229f61aa..69174d9df 100644
--- a/src/transf_mat_3x4.h
+++ b/src/transf_mat_3x4.h
@@ -47,8 +47,8 @@ public:
gchar * pt_to_str (Proj::Axis axis);
bool operator==(const TransfMat3x4 &rhs) const;
- TransfMat3x4 operator*(Geom::Matrix const &A) const;
- TransfMat3x4 &operator*=(Geom::Matrix const &A);
+ TransfMat3x4 operator*(Geom::Affine const &A) const;
+ TransfMat3x4 &operator*=(Geom::Affine const &A);
void print() const;
diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp
index 3b93c659b..999ee877f 100644
--- a/src/tweak-context.cpp
+++ b/src/tweak-context.cpp
@@ -582,7 +582,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P
Shape *theShape = new Shape;
Shape *theRes = new Shape;
- Geom::Matrix i2doc(item->i2doc_affine());
+ Geom::Affine i2doc(item->i2doc_affine());
orig->ConvertWithBackData((0.08 - (0.07 * fidelity)) / i2doc.descrim()); // default 0.059
orig->Fill(theShape, 0);
@@ -803,7 +803,7 @@ tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke,
if (!gradient || !SP_IS_GRADIENT(gradient))
return;
- Geom::Matrix i2d (item->i2doc_affine ());
+ Geom::Affine i2d (item->i2doc_affine ());
Geom::Point p = p_w * i2d.inverse();
p *= (gradient->gradientTransform).inverse();
// now p is in gradient's original coordinates
@@ -820,7 +820,7 @@ tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke,
// This is the matrix which moves and rotates the gradient line
// so it's oriented along the X axis:
- Geom::Matrix norm = Geom::Matrix(Geom::Translate(-p1)) * Geom::Matrix(Geom::Rotate(-atan2(pdiff[Geom::Y], pdiff[Geom::X])));
+ Geom::Affine norm = Geom::Affine(Geom::Translate(-p1)) * Geom::Affine(Geom::Rotate(-atan2(pdiff[Geom::Y], pdiff[Geom::X])));
// Transform the mouse point by it to find out its projection onto the gradient line:
Geom::Point pnorm = p * norm;
@@ -979,7 +979,7 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point,
}
double blur_now = 0;
- Geom::Matrix i2d = item->i2d_affine ();
+ Geom::Affine i2d = item->i2d_affine ();
if (style->filter.set && style->getFilter()) {
//cycle through filter primitives
SPObject *primitive_obj = style->getFilter()->children;
@@ -1140,7 +1140,7 @@ void
sp_tweak_update_area (SPTweakContext *tc)
{
double radius = get_dilate_radius(tc);
- Geom::Matrix const sm (Geom::Scale(radius, radius) * Geom::Translate(SP_EVENT_CONTEXT(tc)->desktop->point()));
+ Geom::Affine const sm (Geom::Scale(radius, radius) * Geom::Translate(SP_EVENT_CONTEXT(tc)->desktop->point()));
sp_canvas_item_affine_absolute(tc->dilate_area, sm);
sp_canvas_item_show(tc->dilate_area);
}
@@ -1216,7 +1216,7 @@ sp_tweak_context_root_handler(SPEventContext *event_context,
// draw the dilating cursor
double radius = get_dilate_radius(tc);
- Geom::Matrix const sm (Geom::Scale(radius, radius) * Geom::Translate(desktop->w2d(motion_w)));
+ Geom::Affine const sm (Geom::Scale(radius, radius) * Geom::Translate(desktop->w2d(motion_w)));
sp_canvas_item_affine_absolute(tc->dilate_area, sm);
sp_canvas_item_show(tc->dilate_area);
diff --git a/src/ui/cache/svg_preview_cache.cpp b/src/ui/cache/svg_preview_cache.cpp
index 6e05f6c03..a7ad1701d 100644
--- a/src/ui/cache/svg_preview_cache.cpp
+++ b/src/ui/cache/svg_preview_cache.cpp
@@ -34,7 +34,7 @@
GdkPixbuf* render_pixbuf(NRArenaItem* root, double scale_factor, const Geom::Rect& dbox, unsigned psize) {
NRGC gc(NULL);
- Geom::Matrix t(Geom::Scale(scale_factor, scale_factor));
+ Geom::Affine t(Geom::Scale(scale_factor, scale_factor));
nr_arena_item_set_transform(root, t);
gc.transform.setIdentity();
diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index d405afb8f..1b98d7474 100644
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
@@ -844,7 +844,7 @@ void ClipboardManagerImpl::_pasteDocument(SPDesktop *desktop, SPDocument *clipdo
selection->setReprList(pasted_objects);
// invers apply parent transform
- Geom::Matrix doc2parent = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
+ Geom::Affine doc2parent = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
sp_selection_apply_affine(selection, desktop->dt2doc() * doc2parent * desktop->doc2dt(), true, false);
// Update (among other things) all curves in paths, for bounds() to work
diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp
index ca3a99561..e5175be4c 100644
--- a/src/ui/dialog/filedialogimpl-win32.cpp
+++ b/src/ui/dialog/filedialogimpl-win32.cpp
@@ -949,7 +949,7 @@ bool FileOpenDialogImplWin32::set_svg_preview()
arena, key, SP_ITEM_SHOW_DISPLAY);
NRGC gc(NULL);
- gc.transform = Geom::Matrix(Geom::Scale(scaleFactor, scaleFactor));
+ gc.transform = Geom::Affine(Geom::Scale(scaleFactor, scaleFactor));
nr_arena_item_invoke_update (root, NULL, &gc,
NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
diff --git a/src/ui/dialog/svg-fonts-dialog.cpp b/src/ui/dialog/svg-fonts-dialog.cpp
index 042acb6e1..a7f914327 100644
--- a/src/ui/dialog/svg-fonts-dialog.cpp
+++ b/src/ui/dialog/svg-fonts-dialog.cpp
@@ -498,7 +498,7 @@ void SvgFontsDialog::set_glyph_description_from_selected_path(){
Geom::PathVector pathv = sp_svg_read_pathv(node->attribute("d"));
//This matrix flips the glyph vertically
- Geom::Matrix m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0));
+ Geom::Affine m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0));
pathv*=m;
//then we offset it
pathv+=Geom::Point(Geom::Coord(0),Geom::Coord(get_selected_spfont()->horiz_adv_x));
@@ -543,7 +543,7 @@ void SvgFontsDialog::missing_glyph_description_from_selected_path(){
Geom::PathVector pathv = sp_svg_read_pathv(node->attribute("d"));
//This matrix flips the glyph vertically
- Geom::Matrix m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0));
+ Geom::Affine m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0));
pathv*=m;
//then we offset it
// pathv+=Geom::Point(Geom::Coord(0),Geom::Coord(get_selected_spfont()->horiz_adv_x));
diff --git a/src/ui/dialog/tile.cpp b/src/ui/dialog/tile.cpp
index 4b994335e..8ae81d528 100644
--- a/src/ui/dialog/tile.cpp
+++ b/src/ui/dialog/tile.cpp
@@ -336,7 +336,7 @@ g_print("\n row = %f col = %f selection x= %f selection y = %f", total_row_h
// signs are inverted between x and y due to y inversion
Geom::Point move = Geom::Point(new_x - min[Geom::X], min[Geom::Y] - new_y);
- Geom::Matrix const affine = Geom::Matrix(Geom::Translate(move));
+ Geom::Affine const affine = Geom::Affine(Geom::Translate(move));
item->set_i2d_affine(item->i2d_affine() * affine);
item->doWriteTransform(repr, item->transform, NULL);
SP_OBJECT (current_row->data)->updateRepr();
diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp
index 8da9914bc..38664fd3a 100644
--- a/src/ui/dialog/transformation.cpp
+++ b/src/ui/dialog/transformation.cpp
@@ -539,9 +539,9 @@ Transformation::updatePageTransform(Inkscape::Selection *selection)
{
if (selection && !selection->isEmpty()) {
if (_check_replace_matrix.get_active()) {
- Geom::Matrix current (SP_ITEM(selection->itemList()->data)->transform); // take from the first item in selection
+ Geom::Affine current (SP_ITEM(selection->itemList()->data)->transform); // take from the first item in selection
- Geom::Matrix new_displayed = current;
+ Geom::Affine new_displayed = current;
_scalar_transform_a.setValue(new_displayed[0]);
_scalar_transform_b.setValue(new_displayed[1]);
@@ -841,7 +841,7 @@ Transformation::applyPageTransform(Inkscape::Selection *selection)
double e = _scalar_transform_e.getValue();
double f = _scalar_transform_f.getValue();
- Geom::Matrix displayed(a, b, c, d, e, f);
+ Geom::Affine displayed(a, b, c, d, e, f);
if (_check_replace_matrix.get_active()) {
for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
@@ -989,10 +989,10 @@ Transformation::onReplaceMatrixToggled()
double e = _scalar_transform_e.getValue();
double f = _scalar_transform_f.getValue();
- Geom::Matrix displayed (a, b, c, d, e, f);
- Geom::Matrix current = SP_ITEM(selection->itemList()->data)->transform; // take from the first item in selection
+ Geom::Affine displayed (a, b, c, d, e, f);
+ Geom::Affine current = SP_ITEM(selection->itemList()->data)->transform; // take from the first item in selection
- Geom::Matrix new_displayed;
+ Geom::Affine new_displayed;
if (_check_replace_matrix.get_active()) {
new_displayed = current;
} else {
diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp
index 517e90da2..1fb98d78f 100644
--- a/src/ui/tool/control-point-selection.cpp
+++ b/src/ui/tool/control-point-selection.cpp
@@ -166,7 +166,7 @@ void ControlPointSelection::spatialGrow(SelectableControlPoint *origin, int dir)
}
/** Transform all selected control points by the given affine transformation. */
-void ControlPointSelection::transform(Geom::Matrix const &m)
+void ControlPointSelection::transform(Geom::Affine const &m)
{
for (iterator i = _points.begin(); i != _points.end(); ++i) {
SelectableControlPoint *cur = *i;
@@ -273,7 +273,7 @@ void ControlPointSelection::_pointGrabbed(SelectableControlPoint *point)
_grabbed_point = point;
_farthest_point = point;
double maxdist = 0;
- Geom::Matrix m;
+ Geom::Affine m;
m.setIdentity();
for (iterator i = _points.begin(); i != _points.end(); ++i) {
_original_positions.insert(std::make_pair(*i, (*i)->position()));
@@ -294,7 +294,7 @@ void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion *
// Sculpting
for (iterator i = _points.begin(); i != _points.end(); ++i) {
SelectableControlPoint *cur = (*i);
- Geom::Matrix trans;
+ Geom::Affine trans;
trans.setIdentity();
double dist = Geom::distance(_original_positions[cur], _original_positions[_grabbed_point]);
double deltafrac = 0.5 + 0.5 * cos(M_PI * dist/fdist);
@@ -323,7 +323,7 @@ void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion *
Geom::Point newdx = (newpx - newp) / Geom::EPSILON;
Geom::Point newdy = (newpy - newp) / Geom::EPSILON;
- Geom::Matrix itrans(newdx[Geom::X], newdx[Geom::Y], newdy[Geom::X], newdy[Geom::Y], 0, 0);
+ Geom::Affine itrans(newdx[Geom::X], newdx[Geom::Y], newdy[Geom::X], newdy[Geom::Y], 0, 0);
if (itrans.isSingular())
itrans.setIdentity();
@@ -502,7 +502,7 @@ bool ControlPointSelection::_keyboardRotate(GdkEventKey const &event, int dir)
}
// translate to origin, rotate, translate back to original position
- Geom::Matrix m = Geom::Translate(-rc)
+ Geom::Affine m = Geom::Translate(-rc)
* Geom::Rotate(angle) * Geom::Translate(rc);
transform(m);
signal_commit.emit(COMMIT_KEYBOARD_ROTATE);
@@ -538,7 +538,7 @@ bool ControlPointSelection::_keyboardScale(GdkEventKey const &event, int dir)
}
double scale = (maxext + length_change) / maxext;
- Geom::Matrix m = Geom::Translate(-center) * Geom::Scale(scale) * Geom::Translate(center);
+ Geom::Affine m = Geom::Translate(-center) * Geom::Scale(scale) * Geom::Translate(center);
transform(m);
signal_commit.emit(COMMIT_KEYBOARD_SCALE_UNIFORM);
return true;
@@ -559,7 +559,7 @@ bool ControlPointSelection::_keyboardFlip(Geom::Dim2 d)
dynamic_cast<SelectableControlPoint*>(ControlPoint::mouseovered_point);
Geom::Point center = scp ? scp->position() : _handles->rotationCenter().position();
- Geom::Matrix m = Geom::Translate(-center) * scale_transform * Geom::Translate(center);
+ Geom::Affine m = Geom::Translate(-center) * scale_transform * Geom::Translate(center);
transform(m);
signal_commit.emit(d == Geom::X ? COMMIT_FLIP_X : COMMIT_FLIP_Y);
return true;
diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h
index 0e5acf6c5..a9c929cb1 100644
--- a/src/ui/tool/control-point-selection.h
+++ b/src/ui/tool/control-point-selection.h
@@ -91,7 +91,7 @@ public:
virtual bool event(GdkEvent *);
- void transform(Geom::Matrix const &m);
+ void transform(Geom::Affine const &m);
void align(Geom::Dim2 d);
void distribute(Geom::Dim2 d);
@@ -130,14 +130,14 @@ private:
bool _keyboardRotate(GdkEventKey const &, int);
bool _keyboardScale(GdkEventKey const &, int);
bool _keyboardFlip(Geom::Dim2);
- void _keyboardTransform(Geom::Matrix const &);
+ void _keyboardTransform(Geom::Affine const &);
void _commitHandlesTransform(CommitEvent ce);
double _rotationRadius(Geom::Point const &);
set_type _points;
set_type _all_points;
INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Point> _original_positions;
- INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Matrix> _last_trans;
+ INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Affine> _last_trans;
boost::optional<double> _rot_radius;
boost::optional<double> _mouseover_rot_radius;
Geom::OptRect _bounds;
diff --git a/src/ui/tool/control-point.cpp b/src/ui/tool/control-point.cpp
index 38b421553..bece1324b 100644
--- a/src/ui/tool/control-point.cpp
+++ b/src/ui/tool/control-point.cpp
@@ -214,7 +214,7 @@ void ControlPoint::move(Geom::Point const &pos)
/** Apply an arbitrary affine transformation to a control point. This is used
* by ControlPointSelection, and is important for things like nodes with handles.
* The default implementation simply moves the point according to the transform. */
-void ControlPoint::transform(Geom::Matrix const &m) {
+void ControlPoint::transform(Geom::Affine const &m) {
move(position() * m);
}
diff --git a/src/ui/tool/control-point.h b/src/ui/tool/control-point.h
index 3f5fe668d..0b88786e5 100644
--- a/src/ui/tool/control-point.h
+++ b/src/ui/tool/control-point.h
@@ -56,7 +56,7 @@ public:
operator Geom::Point const &() { return _position; }
virtual void move(Geom::Point const &pos);
virtual void setPosition(Geom::Point const &pos);
- virtual void transform(Geom::Matrix const &m);
+ virtual void transform(Geom::Affine const &m);
/// @}
/// @name Toggle the point's visibility
diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp
index fea02d399..8e3da266b 100644
--- a/src/ui/tool/node.cpp
+++ b/src/ui/tool/node.cpp
@@ -514,7 +514,7 @@ void Node::move(Geom::Point const &new_pos)
_fixNeighbors(old_pos, new_pos);
}
-void Node::transform(Geom::Matrix const &m)
+void Node::transform(Geom::Affine const &m)
{
Geom::Point old_pos = position();
setPosition(position() * m);
@@ -829,26 +829,6 @@ bool Node::_eventHandler(GdkEvent *event)
return ControlPoint::_eventHandler(event);
}
-// TODO Move this to 2Geom!
-static double bezier_length (Geom::Point a0, Geom::Point a1, Geom::Point a2, Geom::Point a3)
-{
- double lower = Geom::distance(a0, a3);
- double upper = Geom::distance(a0, a1) + Geom::distance(a1, a2) + Geom::distance(a2, a3);
-
- if (upper - lower < Geom::EPSILON) return (lower + upper)/2;
-
- Geom::Point // Casteljau subdivision
- b0 = a0,
- c0 = a3,
- b1 = 0.5*(a0 + a1),
- t0 = 0.5*(a1 + a2),
- c1 = 0.5*(a2 + a3),
- b2 = 0.5*(b1 + t0),
- c2 = 0.5*(t0 + c1),
- b3 = 0.5*(b2 + c2); // == c3
- return bezier_length(b0, b1, b2, b3) + bezier_length(b3, c2, c1, c0);
-}
-
/** Select or deselect a node in this node's subpath based on its path distance from this node.
* @param dir If negative, shrink selection by one node; if positive, grow by one node */
void Node::_linearGrow(int dir)
@@ -875,7 +855,7 @@ void Node::_linearGrow(int dir)
// find first unselected nodes on both sides
while (fwd && fwd->selected()) {
NodeList::iterator n = fwd.next();
- distance_front += bezier_length(*fwd, fwd->_front, n->_back, *n);
+ distance_front += Geom::bezier_length(*fwd, fwd->_front, n->_back, *n);
fwd = n;
if (fwd == this_iter)
// there is no unselected node in this cyclic subpath
@@ -886,7 +866,7 @@ void Node::_linearGrow(int dir)
// so we are guaranteed to stop.
while (rev && rev->selected()) {
NodeList::iterator p = rev.prev();
- distance_back += bezier_length(*rev, rev->_back, p->_front, *p);
+ distance_back += Geom::bezier_length(*rev, rev->_back, p->_front, *p);
rev = p;
}
@@ -917,7 +897,7 @@ void Node::_linearGrow(int dir)
last_distance_front = distance_front;
}
NodeList::iterator n = fwd.next();
- if (n) distance_front += bezier_length(*fwd, fwd->_front, n->_back, *n);
+ if (n) distance_front += Geom::bezier_length(*fwd, fwd->_front, n->_back, *n);
fwd = n;
} else if (rev && (!fwd || distance_front > distance_back)) {
if (rev->selected()) {
@@ -925,7 +905,7 @@ void Node::_linearGrow(int dir)
last_distance_back = distance_back;
}
NodeList::iterator p = rev.prev();
- if (p) distance_back += bezier_length(*rev, rev->_back, p->_front, *p);
+ if (p) distance_back += Geom::bezier_length(*rev, rev->_back, p->_front, *p);
rev = p;
}
// Check whether we walked the entire cyclic subpath.
@@ -935,8 +915,8 @@ void Node::_linearGrow(int dir)
if (fwd && fwd == rev) {
if (!fwd->selected()) break;
NodeList::iterator fwdp = fwd.prev(), revn = rev.next();
- double df = distance_front + bezier_length(*fwdp, fwdp->_front, fwd->_back, *fwd);
- double db = distance_back + bezier_length(*revn, revn->_back, rev->_front, *rev);
+ double df = distance_front + Geom::bezier_length(*fwdp, fwdp->_front, fwd->_back, *fwd);
+ double db = distance_back + Geom::bezier_length(*revn, revn->_back, rev->_front, *rev);
if (df > db) {
last_fwd = fwd;
last_distance_front = df;
diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h
index b5d4d88f2..451915dbe 100644
--- a/src/ui/tool/node.h
+++ b/src/ui/tool/node.h
@@ -128,7 +128,7 @@ class Node : ListNode, public SelectableControlPoint {
public:
Node(NodeSharedData const &data, Geom::Point const &pos);
virtual void move(Geom::Point const &p);
- virtual void transform(Geom::Matrix const &m);
+ virtual void transform(Geom::Affine const &m);
virtual Geom::Rect bounds();
NodeType type() { return _type; }
diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp
index ea7f3412d..47e28a788 100644
--- a/src/ui/tool/path-manipulator.cpp
+++ b/src/ui/tool/path-manipulator.cpp
@@ -102,7 +102,7 @@ private:
void build_segment(Geom::PathBuilder &, Node *, Node *);
PathManipulator::PathManipulator(MultiPathManipulator &mpm, SPPath *path,
- Geom::Matrix const &et, guint32 outline_color, Glib::ustring lpe_key)
+ Geom::Affine const &et, guint32 outline_color, Glib::ustring lpe_key)
: PointManipulator(mpm._path_data.node_data.desktop, *mpm._path_data.node_data.selection)
, _subpaths(*this)
, _multi_path_manipulator(mpm)
@@ -847,9 +847,9 @@ void PathManipulator::setLiveObjects(bool set)
_live_objects = set;
}
-void PathManipulator::setControlsTransform(Geom::Matrix const &tnew)
+void PathManipulator::setControlsTransform(Geom::Affine const &tnew)
{
- Geom::Matrix delta = _i2d_transform.inverse() * _edit_transform.inverse() * tnew * _i2d_transform;
+ Geom::Affine delta = _i2d_transform.inverse() * _edit_transform.inverse() * tnew * _i2d_transform;
_edit_transform = tnew;
for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) {
for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j) {
@@ -894,7 +894,7 @@ NodeList::iterator PathManipulator::subdivideSegment(NodeList::iterator first, d
// build bezier curve and subdivide
Geom::CubicBezier temp(first->position(), first->front()->position(),
second->back()->position(), second->position());
- std::pair<Geom::CubicBezier, Geom::CubicBezier> div = temp.subdivide(t);
+ std::pair<Geom::BezierCurve, Geom::BezierCurve> div = temp.subdivide(t);
std::vector<Geom::Point> seg1 = div.first.points(), seg2 = div.second.points();
// set new handle positions
@@ -975,7 +975,7 @@ void PathManipulator::_externalChange(unsigned type)
_updateOutline();
} break;
case PATH_CHANGE_TRANSFORM: {
- Geom::Matrix i2d_change = _d2i_transform;
+ Geom::Affine i2d_change = _d2i_transform;
_i2d_transform = SP_ITEM(_path)->i2d_affine();
_d2i_transform = _i2d_transform.inverse();
i2d_change *= _i2d_transform;
@@ -1388,7 +1388,7 @@ void PathManipulator::_commit(Glib::ustring const &annotation, gchar const *key)
* point of the path. */
void PathManipulator::_updateDragPoint(Geom::Point const &evp)
{
- Geom::Matrix to_desktop = _edit_transform * _i2d_transform;
+ Geom::Affine to_desktop = _edit_transform * _i2d_transform;
Geom::PathVector pv = _spcurve->get_pathvector();
boost::optional<Geom::PathVectorPosition> pvp
= Geom::nearestPoint(pv, _desktop->w2d(evp) * to_desktop.inverse());
diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h
index 58907ea96..27a83f06b 100644
--- a/src/ui/tool/path-manipulator.h
+++ b/src/ui/tool/path-manipulator.h
@@ -14,7 +14,7 @@
#include <string>
#include <memory>
#include <2geom/pathvector.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include "forward.h"
@@ -53,7 +53,7 @@ class PathManipulator : public PointManipulator {
public:
typedef SPPath *ItemType;
- PathManipulator(MultiPathManipulator &mpm, SPPath *path, Geom::Matrix const &edit_trans,
+ PathManipulator(MultiPathManipulator &mpm, SPPath *path, Geom::Affine const &edit_trans,
guint32 outline_color, Glib::ustring lpe_key);
~PathManipulator();
virtual bool event(GdkEvent *);
@@ -85,7 +85,7 @@ public:
void showPathDirection(bool show);
void setLiveOutline(bool set);
void setLiveObjects(bool set);
- void setControlsTransform(Geom::Matrix const &);
+ void setControlsTransform(Geom::Affine const &);
void hideDragPoint();
MultiPathManipulator &mpm() { return _multi_path_manipulator; }
@@ -134,9 +134,9 @@ private:
SPCanvasItem *_outline;
CurveDragPoint *_dragpoint; // an invisible control point hoverng over curve
PathManipulatorObserver *_observer;
- Geom::Matrix _d2i_transform; ///< desktop-to-item transform
- Geom::Matrix _i2d_transform; ///< item-to-desktop transform, inverse of _d2i_transform
- Geom::Matrix _edit_transform; ///< additional transform to apply to editing controls
+ Geom::Affine _d2i_transform; ///< desktop-to-item transform
+ Geom::Affine _i2d_transform; ///< item-to-desktop transform, inverse of _d2i_transform
+ Geom::Affine _edit_transform; ///< additional transform to apply to editing controls
unsigned _num_selected; ///< number of selected nodes
bool _show_handles;
bool _show_outline;
diff --git a/src/ui/tool/shape-record.h b/src/ui/tool/shape-record.h
index 893231404..646e6f4f6 100644
--- a/src/ui/tool/shape-record.h
+++ b/src/ui/tool/shape-record.h
@@ -14,7 +14,7 @@
#include <glibmm/ustring.h>
#include <boost/operators.hpp>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
class SPItem;
namespace Inkscape {
@@ -32,7 +32,7 @@ struct ShapeRecord :
public boost::totally_ordered<ShapeRecord>
{
SPItem *item; // SP node for the edited shape
- Geom::Matrix edit_transform; // how to transform controls - used for clipping paths and masks
+ Geom::Affine edit_transform; // how to transform controls - used for clipping paths and masks
ShapeRole role;
Glib::ustring lpe_key; // name of LPE shape param being edited
diff --git a/src/ui/tool/transform-handle-set.cpp b/src/ui/tool/transform-handle-set.cpp
index 5c3b494ce..26263c26b 100644
--- a/src/ui/tool/transform-handle-set.cpp
+++ b/src/ui/tool/transform-handle-set.cpp
@@ -94,10 +94,10 @@ public:
protected:
virtual void startTransform() {}
virtual void endTransform() {}
- virtual Geom::Matrix computeTransform(Geom::Point const &pos, GdkEventMotion *event) = 0;
+ virtual Geom::Affine computeTransform(Geom::Point const &pos, GdkEventMotion *event) = 0;
virtual CommitEvent getCommitEvent() = 0;
- Geom::Matrix _last_transform;
+ Geom::Affine _last_transform;
Geom::Point _origin;
TransformHandleSet &_th;
std::vector<Inkscape::SnapCandidatePoint> _snap_points;
@@ -129,10 +129,10 @@ private:
}
virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event)
{
- Geom::Matrix t = computeTransform(new_pos, event);
+ Geom::Affine t = computeTransform(new_pos, event);
// protect against degeneracies
if (t.isSingular()) return;
- Geom::Matrix incr = _last_transform.inverse() * t;
+ Geom::Affine incr = _last_transform.inverse() * t;
if (incr.isSingular()) return;
_th.signal_transform.emit(incr);
_last_transform = t;
@@ -202,7 +202,7 @@ protected:
ControlPointSelection *selection = nt->_selected_nodes.get();
selection->setOriginalPoints();
}
- virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) {
+ virtual Geom::Affine computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) {
Geom::Point scc = held_shift(*event) ? _sc_center : _sc_opposite;
Geom::Point vold = _origin - scc, vnew = new_pos - scc;
@@ -257,7 +257,7 @@ protected:
_last_scale_x = scale[0];
_last_scale_y = scale[1];
- Geom::Matrix t = Geom::Translate(-scc)
+ Geom::Affine t = Geom::Translate(-scc)
* Geom::Scale(scale[0], scale[1])
* Geom::Translate(scc);
return t;
@@ -294,7 +294,7 @@ protected:
_sc_opposite = Geom::middle_point(b.corner(_side + 2), b.corner(_side + 3));
_last_scale_x = _last_scale_y = 1.0;
}
- virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) {
+ virtual Geom::Affine computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) {
Geom::Point scc = held_shift(*event) ? _sc_center : _sc_opposite;
Geom::Point vs;
Geom::Dim2 d1 = static_cast<Geom::Dim2>((_side + 1) % 2);
@@ -313,7 +313,7 @@ protected:
_last_scale_x = vs[Geom::X];
_last_scale_y = vs[Geom::Y];
- Geom::Matrix t = Geom::Translate(-scc)
+ Geom::Affine t = Geom::Translate(-scc)
* Geom::Scale(vs)
* Geom::Translate(scc);
return t;
@@ -351,7 +351,7 @@ protected:
_last_angle = 0;
}
- virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event)
+ virtual Geom::Affine computeTransform(Geom::Point const &new_pos, GdkEventMotion *event)
{
Geom::Point rotc = held_shift(*event) ? _rot_opposite : _rot_center;
double angle = Geom::angle_between(_origin - rotc, new_pos - rotc);
@@ -359,7 +359,7 @@ protected:
angle = snap_angle(angle);
}
_last_angle = angle;
- Geom::Matrix t = Geom::Translate(-rotc)
+ Geom::Affine t = Geom::Translate(-rotc)
* Geom::Rotate(angle)
* Geom::Translate(rotc);
return t;
@@ -425,7 +425,7 @@ protected:
_last_horizontal = _side % 2;
}
- virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event)
+ virtual Geom::Affine computeTransform(Geom::Point const &new_pos, GdkEventMotion *event)
{
Geom::Point scc = held_shift(*event) ? _skew_center : _skew_opposite;
// d1 and d2 are reversed with respect to ScaleSideHandle
@@ -458,12 +458,12 @@ protected:
// skew matrix has the from [[1, k],[0, 1]] for horizontal skew
// and [[1,0],[k,1]] for vertical skew.
- Geom::Matrix skew = Geom::identity();
+ Geom::Affine skew = Geom::identity();
// correct the sign of the tangent
skew[d2 + 1] = (d1 == Geom::X ? -1.0 : 1.0) * tan(angle);
_last_angle = angle;
- Geom::Matrix t = Geom::Translate(-scc)
+ Geom::Affine t = Geom::Translate(-scc)
* Geom::Scale(scale) * skew
* Geom::Translate(scc);
return t;
@@ -645,7 +645,7 @@ bool TransformHandleSet::event(GdkEvent*)
return false;
}
-void TransformHandleSet::_emitTransform(Geom::Matrix const &t)
+void TransformHandleSet::_emitTransform(Geom::Affine const &t)
{
signal_transform.emit(t);
_center->transform(t);
diff --git a/src/ui/tool/transform-handle-set.h b/src/ui/tool/transform-handle-set.h
index b18c598ee..0557b1278 100644
--- a/src/ui/tool/transform-handle-set.h
+++ b/src/ui/tool/transform-handle-set.h
@@ -50,10 +50,10 @@ public:
bool transforming() { return _in_transform; }
ControlPoint &rotationCenter();
- sigc::signal<void, Geom::Matrix const &> signal_transform;
+ sigc::signal<void, Geom::Affine const &> signal_transform;
sigc::signal<void, CommitEvent> signal_commit;
private:
- void _emitTransform(Geom::Matrix const &);
+ void _emitTransform(Geom::Affine const &);
void _setActiveHandle(ControlPoint *h);
void _clearActiveHandle();
void _updateVisibility(bool v);
diff --git a/src/ui/widget/registered-widget.cpp b/src/ui/widget/registered-widget.cpp
index 04bd27285..c68e8348b 100644
--- a/src/ui/widget/registered-widget.cpp
+++ b/src/ui/widget/registered-widget.cpp
@@ -553,7 +553,7 @@ RegisteredTransformedPoint::setValue(Geom::Point const & p)
}
void
-RegisteredTransformedPoint::setTransform(Geom::Matrix const & canvas_to_svg)
+RegisteredTransformedPoint::setTransform(Geom::Affine const & canvas_to_svg)
{
// check if matrix is singular / has inverse
if ( ! canvas_to_svg.isSingular() ) {
diff --git a/src/ui/widget/registered-widget.h b/src/ui/widget/registered-widget.h
index efb5eb70e..9c3ecb5e6 100644
--- a/src/ui/widget/registered-widget.h
+++ b/src/ui/widget/registered-widget.h
@@ -18,7 +18,7 @@
#include <gtkmm/adjustment.h>
#include <gtkmm/tooltips.h>
#include <gtkmm/togglebutton.h>
-#include <2geom/matrix.h>
+#include <2geom/affine.h>
#include "xml/node.h"
#include "registry.h"
@@ -326,14 +326,14 @@ public:
// redefine setValue, because transform must be applied
void setValue(Geom::Point const & p);
- void setTransform(Geom::Matrix const & canvas_to_svg);
+ void setTransform(Geom::Affine const & canvas_to_svg);
protected:
sigc::connection _value_x_changed_connection;
sigc::connection _value_y_changed_connection;
void on_value_changed();
- Geom::Matrix to_svg;
+ Geom::Affine to_svg;
};
diff --git a/src/unclump.cpp b/src/unclump.cpp
index 1039351a3..951719900 100644
--- a/src/unclump.cpp
+++ b/src/unclump.cpp
@@ -287,7 +287,7 @@ unclump_push (SPItem *from, SPItem *what, double dist)
Geom::Point p = unclump_center (from);
Geom::Point by = dist * Geom::unit_vector (- (p - it));
- Geom::Matrix move = Geom::Translate (by);
+ Geom::Affine move = Geom::Translate (by);
std::map<const gchar *, Geom::Point>::iterator i = c_cache.find(what->getId());
if ( i != c_cache.end() ) {
@@ -310,7 +310,7 @@ unclump_pull (SPItem *to, SPItem *what, double dist)
Geom::Point p = unclump_center (to);
Geom::Point by = dist * Geom::unit_vector (p - it);
- Geom::Matrix move = Geom::Translate (by);
+ Geom::Affine move = Geom::Translate (by);
std::map<const gchar *, Geom::Point>::iterator i = c_cache.find(what->getId());
if ( i != c_cache.end() ) {
diff --git a/src/widgets/font-selector.cpp b/src/widgets/font-selector.cpp
index 1972ea046..71e9563cd 100644
--- a/src/widgets/font-selector.cpp
+++ b/src/widgets/font-selector.cpp
@@ -805,7 +805,7 @@ void sp_font_preview_set_font(SPFontPreview *fprev, font_instance *font, SPFontS
if (fprev->font)
{
- Geom::Matrix flip(Geom::Scale(fsel->fontsize, -fsel->fontsize));
+ Geom::Affine flip(Geom::Scale(fsel->fontsize, -fsel->fontsize));
fprev->rfont = fprev->font->RasterFont(flip, 0);
}
diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp
index e7207d944..25be59942 100644
--- a/src/widgets/icon.cpp
+++ b/src/widgets/icon.cpp
@@ -1082,7 +1082,7 @@ extern "C" guchar *sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
SPObject *object = doc->getObjectById(name);
if (object && SP_IS_ITEM(object)) {
/* Find bbox in document */
- Geom::Matrix const i2doc(SP_ITEM(object)->i2doc_affine());
+ Geom::Affine const i2doc(SP_ITEM(object)->i2doc_affine());
Geom::OptRect dbox = SP_ITEM(object)->getBounds(i2doc);
if ( SP_OBJECT_PARENT(object) == NULL )
@@ -1096,7 +1096,7 @@ extern "C" guchar *sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
NRGC gc(NULL);
/* Update to renderable state */
double sf = 1.0;
- nr_arena_item_set_transform(root, (Geom::Matrix)Geom::Scale(sf, sf));
+ nr_arena_item_set_transform(root, (Geom::Affine)Geom::Scale(sf, sf));
gc.transform.setIdentity();
nr_arena_item_invoke_update( root, NULL, &gc,
NR_ARENA_ITEM_STATE_ALL,
@@ -1128,7 +1128,7 @@ extern "C" guchar *sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
}
sf = (double)psize / (double)block;
- nr_arena_item_set_transform(root, (Geom::Matrix)Geom::Scale(sf, sf));
+ nr_arena_item_set_transform(root, (Geom::Affine)Geom::Scale(sf, sf));
gc.transform.setIdentity();
nr_arena_item_invoke_update( root, NULL, &gc,
NR_ARENA_ITEM_STATE_ALL,
diff --git a/src/widgets/select-toolbar.cpp b/src/widgets/select-toolbar.cpp
index a0ec248ca..89253983b 100644
--- a/src/widgets/select-toolbar.cpp
+++ b/src/widgets/select-toolbar.cpp
@@ -242,7 +242,7 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw)
gdouble strokewidth = stroke_average_width (selection->itemList());
int transform_stroke = prefs->getBool("/options/transform/stroke", true) ? 1 : 0;
- Geom::Matrix scaler = get_scale_transform_with_stroke (*bbox, strokewidth, transform_stroke, x0, y0, x1, y1);
+ Geom::Affine scaler = get_scale_transform_with_stroke (*bbox, strokewidth, transform_stroke, x0, y0, x1, y1);
sp_selection_apply_affine(selection, scaler);
DocumentUndo::maybeDone(document, actionkey, SP_VERB_CONTEXT_SELECT,
diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp
index 885a58536..9b79ed09e 100644
--- a/src/widgets/stroke-style.cpp
+++ b/src/widgets/stroke-style.cpp
@@ -186,7 +186,7 @@ sp_marker_prev_new(unsigned psize, gchar const *mname,
return NULL; // sandbox broken?
// Find object's bbox in document
- Geom::Matrix const i2doc(SP_ITEM(object)->i2doc_affine());
+ Geom::Affine const i2doc(SP_ITEM(object)->i2doc_affine());
Geom::OptRect dbox = SP_ITEM(object)->getBounds(i2doc);
if (!dbox) {
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index f72b0d907..d9e72fe50 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -8038,7 +8038,7 @@ static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl)
GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop);
for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) {
SPItem *item = reinterpret_cast<SPItem *>(iter->data);
- Geom::Matrix m = Geom::identity();
+ Geom::Affine m = Geom::identity();
avoid_item_move(&m, item);
modmade = true;
}