1 // Copyright (C) 2012-2019 The VPaint Developers.
2 // See the COPYRIGHT file at the top-level directory of this distribution
3 // and at https://github.com/dalboris/vpaint/blob/master/COPYRIGHT
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #ifndef VAC_INSTANT_EDGE_H
18 #define VAC_INSTANT_EDGE_H
19 
20 #include "EdgeCell.h"
21 #include "KeyCell.h"
22 #include "Eigen.h"
23 #include "Triangles.h"
24 
25 namespace VectorAnimationComplex
26 {
27 class EdgeGeometry;
28 class EdgeInter;
29 class IntersectionList;
30 
31 class KeyEdge: public KeyCell, public EdgeCell
32 {
33 public:
34 
35     // Constructor. Geometry must be a valid non-null pointer.
36     // KeyEdge takes ownership of geometry. The rationale is to let the
37     // caller specify the actual derived class used for geometry, for instance:
38     // new InstanceEdge(this, time, left, right, new LinearSpline(...));
39     // non loop
40     KeyEdge(VAC * vac, Time time,
41          KeyVertex * startVertex,
42          KeyVertex * endVertex,
43          EdgeGeometry * geometry);
44     // loop
45     KeyEdge(VAC * vac, Time time,
46          EdgeGeometry * geometry);
47 
48     // Drawing
49     virtual void drawPickTopology(Time time, ViewSettings & viewSettings);
50     void draw3DSmall();
51     void drawRaw3D(View3DSettings & viewSettings);
52 
53     // Topology
startVertex()54     KeyVertex * startVertex() const { return startVertex_; }
endVertex()55     KeyVertex * endVertex() const { return endVertex_; }
isSplittedLoop()56     bool isSplittedLoop() const
57         { return (!isClosed()) && (startVertex_ == endVertex_); }
isClosed()58     bool isClosed() const { return !startVertex_; }
59 
60     // reimplements
61     VertexCellSet startVertices() const;
62     VertexCellSet endVertices() const;
63 
64 
65     // Geometry
geometry()66     EdgeGeometry * geometry() const { return geometry_; }
67     void correctGeometry();
68     void setWidth(double newWidth);
69     QList<EdgeSample> getSampling(Time time) const;
70 
71 
72     // Sculpting
73     // prepare edge for potential sculpting:
74     //    - (x,y) is mouse position
75     //    - radius is the radius of influence of the sculpt tool
76     //    - must return the distance from (x,y) to the point where it would be sculpted.
77     //    - may store all relevant info to provide sculptVertex() later.
78     double updateSculpt(double x, double y, double radius);
79     // Deform
80     void beginSculptDeform(double x, double y);
81     void continueSculptDeform(double x, double y);
82     void endSculptDeform();
83     // Change edge width
84     void beginSculptEdgeWidth(double x, double y);
85     void continueSculptEdgeWidth(double x, double y);
86     void endSculptEdgeWidth();
87     // Change edge width
88     void beginSculptSmooth(double x, double y);
89     void continueSculptSmooth(double x, double y);
90     void endSculptSmooth();
91     // Affine transform
92     void prepareAffineTransform();
93     void performAffineTransform(const Eigen::Affine2d & xf);
94 
95 private:
96     friend class VAC;
97 
98     ~KeyEdge();
99     KeyVertex * startVertex_;
100     KeyVertex * endVertex_;
101     EdgeGeometry * geometry_;
102 
103     // Trusting operators
104     friend class Operator;
105     bool check_() const;
106 
107     // Update Boundary
108     void updateBoundary_impl(KeyVertex * oldVertex, KeyVertex * newVertex);
109 
110     // Note:  topFace  or  bottom  can be  either  instant  or
111     // animated, at  the contrary of InbetweenEdge  where it is
112     // necessarily animated, and  hence have a specific member
113     // to  store  it,  in   addition  to  the  one  stored  in
114     // EdgeObject base class
115 
116     // for sculpting
117     void prepareSculptPreserveTangents_();
118     void continueSculptPreserveTangents_();
119     KeyEdgeSet sculpt_keepRightAsLeft_;
120     KeyEdgeSet sculpt_keepLeftAsLeft_;
121     KeyEdgeSet sculpt_keepLeftAsRight_;
122     KeyEdgeSet sculpt_keepRightAsRight_;
123     Eigen::Vector2d sculpt_beginLeftDer_;
124     Eigen::Vector2d sculpt_beginRightDer_;
125     bool sculpt_keepMyselfTangent_;
126     double sculptRadius_;
127     double remainingRadiusLeft_;
128     double remainingRadiusRight_;
129 
130     // Implementation of triangulate
131     void triangulate_(Time time, Triangles & out) const;
132     void triangulate_(double width, Time time, Triangles & out) const;
133 
134     EIGEN_MAKE_ALIGNED_OPERATOR_NEW
135 
136 
137 // --------- Cloning, Assigning, Copying, Serializing ----------
138 
139 protected:
140     // Cloning
141     KeyEdge(KeyEdge * other);
142     virtual KeyEdge * clone();
143     virtual void remapPointers(VAC * newVAC);
144 
145     // Serializing
146     virtual void save_(QTextStream & out);
stringType()147     QString stringType() const {return "Edge";}
148     virtual QString xmlType_() const;
149     virtual void write_(XmlStreamWriter & xml) const;
150 
151 
152     // Unserializing
153     KeyEdge(VAC * vac, XmlStreamReader & xml);
154     KeyEdge(VAC * vac, QTextStream & in);
155       public: class Read1stPass {
156     friend Cell * Cell::read1stPass(VAC * vac, QTextStream & in);
create(VAC * g,QTextStream & in)157     static KeyEdge * create(VAC * g, QTextStream & in)
158             {return new KeyEdge(g, in);}  };
159       protected: virtual void read2ndPass();
160 private:
161     struct TempRead { int left, right; };
162     TempRead * tmp_;
163 };
164 
165 }
166 
167 #endif
168