summaryrefslogtreecommitdiffstats
path: root/src/pure-transform.h
blob: b6393d3b3dc546cd2ebbe3bc81fb84131bbe229e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Class for pure transformations, such as translating, scaling, stretching, skewing, and rotating. Pure means that they
 * cannot be combined. This is what makes them different from affine transformations. Pure transformations are being
 * used in the selector tool and node tool
 *
 * Authors:
 *   Diederik van Lierop <mail@diedenrezi.nl>
 *
 * Copyright (C) 2015 Diederik van Lierop
 *
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#ifndef SEEN_PURE_TRANSFORM_H
#define SEEN_PURE_TRANSFORM_H

#include <glib.h> // for g_warning
#include "snapper.h" // for SnapConstraint

class SnapManager;

namespace Inkscape {

class PureTransform {

protected:
    virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const = 0;
    virtual Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const = 0;
    virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) = 0;

public:
    //PureTransform();
    virtual ~PureTransform() = default;;
//    virtual PureTransform * clone () const = 0;  // https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Virtual_Constructor

    // Snap a group of points
    SnappedPoint best_snapped_point;
    void snap(::SnapManager *sm, std::vector<Inkscape::SnapCandidatePoint> const &points, Geom::Point const &pointer);
};

// **************************************************************************************************************

class PureTranslate: public PureTransform {

protected:
    Geom::Point _vector;
    Geom::Point _vector_snapped;

    SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const override;
    Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const override;
    void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) override;

public:
//    PureTranslate();                        // Default constructor
//    PureTranslate(PureTranslate const &);   // Copy constructor
    ~PureTranslate() override = default;;
    PureTranslate(Geom::Point vector = Geom::Point()) : _vector(vector), _vector_snapped(vector) {}

    Geom::Point getTranslationSnapped() {return _vector_snapped;}
//    PureTranslate * clone () const {return new PureTranslate(*this);}
};


class PureTranslateConstrained: public PureTranslate {

protected:
    Geom::Dim2 _direction;
    SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const override;

public:
    ~PureTranslateConstrained() override = default;
    PureTranslateConstrained(Geom::Coord displacement, Geom::Dim2 direction):
        PureTranslate(),
        _direction(direction)
        {
            _vector[direction] = displacement;
            _vector[1-direction] = 0.0;
        }
    // PureTranslateConstrained * clone () const {return new PureTranslateConstrained(*this);}
};

// **************************************************************************************************************

class PureScale: public PureTransform {

protected:
    Geom::Scale _scale;
    Geom::Scale _scale_snapped;
    Geom::Point _origin;
    bool        _uniform;

    SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const override;
    Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const override;
    void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) override;

public:
//    PureScale();                    // Default constructor
//    PureScale(PureScale const &);   // Copy constructor
    ~PureScale() override = default;

    PureScale(Geom::Scale scale, Geom::Point origin, bool uniform) : 
        _scale (scale),
        _scale_snapped (scale),
        _origin (origin),
        _uniform (uniform)
    {}

    Geom::Scale getScaleSnapped() {return _scale_snapped;}
//    PureScale * clone () const {return new PureScale (*this);}
};

class PureScaleConstrained: public PureScale {
//Magnitude of the scale components will be the same, but the sign could still be different ()
protected:
    SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const override;

public:
    ~PureScaleConstrained() override = default;
    PureScaleConstrained(Geom::Scale scale, Geom::Point origin):
        PureScale(scale, origin, true) {}; // Non-uniform constrained scaling is not supported

//    PureScaleConstrained * clone () const {return new PureScaleConstrained(*this);}
};

// **************************************************************************************************************

class PureStretchConstrained: public PureTransform {
// A stretch is always implicitly constrained

protected:
    Geom::Coord _magnitude;
    Geom::Scale _stretch_snapped;
    Geom::Point _origin;
    Geom::Dim2  _direction;
    bool        _uniform;

    SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const override;
    Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const override;
    void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) override;

public:
    ~PureStretchConstrained() override = default;;
    PureStretchConstrained(Geom::Coord magnitude, Geom::Point origin, Geom::Dim2 direction, bool uniform) :
        _magnitude (magnitude),
        _stretch_snapped (Geom::Scale(magnitude, magnitude)),
        _origin (origin),
        _direction (direction),
        _uniform (uniform)
    {
        if (not uniform) {
            _stretch_snapped[1-direction] = 1.0;
        }
    }

    Geom::Scale getStretchSnapped() {return _stretch_snapped;}
    Geom::Coord getMagnitude() {return _magnitude;}
    Geom::Coord getMagnitudeSnapped() {return _stretch_snapped[_direction];}

//    PureStretchConstrained * clone () const {return new PureStretchConstrained(*this);}
};

// **************************************************************************************************************

class PureSkewConstrained: public PureTransform {
// A skew is always implicitly constrained

protected:
    Geom::Coord _skew;
    Geom::Coord _skew_snapped;
    Geom::Coord _scale;
    Geom::Point _origin;
    Geom::Dim2  _direction;

    SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const override;
    Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const override;
    void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) override;

public:
    ~PureSkewConstrained() override = default;;
    PureSkewConstrained(Geom::Coord skew, Geom::Coord scale, Geom::Point origin, Geom::Dim2 direction) :
        _skew (skew),
        _skew_snapped (skew),
        _scale (scale),
        _origin (origin),
        _direction (direction)
    {};

    Geom::Coord getSkewSnapped() {return _skew_snapped;}

//    PureSkewConstrained * clone () const {return new PureSkewConstrained(*this);}
};

// **************************************************************************************************************

class PureRotateConstrained: public PureTransform {
// A rotation is always implicitly constrained, so we will hide the constructor by making it protected; devs should use PureRotateConstrained instead
// It's _constraint member variable though will be empty

protected:
    double      _angle; // in radians
    double      _angle_snapped;
    Geom::Point _origin;
    bool        _uniform;

    SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const override;
    Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const override;
    void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) override;

public:
//    PureRotate();                        // Default constructor
//    PureRotate(PureRotate const &);   // Copy constructor
    ~PureRotateConstrained() override = default;;

    PureRotateConstrained(double angle, Geom::Point origin) :
        _angle (angle), // in radians!
        _angle_snapped (angle),
        _origin (origin),
        _uniform (true) // We do not yet allow for simultaneous rotation and scaling
    {}

    double getAngleSnapped() {return _angle_snapped;}

//    PureRotate * clone () const {return new PureRotate(*this);}
};

}

#endif // !SEEN_PURE_TRANSFORM_H