]> Shamusworld >> Repos - architektonas/blob - src/base/vectorsolutions.cpp
Start of bringing back missing forms/dialogs
[architektonas] / src / base / vectorsolutions.cpp
1 // vectorsolutions.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // (C) 2010 Underground Software
7 //
8 // JLH = James L. Hammons <jlhamm@acm.org>
9 //
10 // Who  When        What
11 // ---  ----------  -----------------------------------------------------------
12 // JLH  05/21/2010  Added this text. :-)
13 //
14
15 #include "vectorsolutions.h"
16
17 #include "rs_math.h"
18
19 /**
20  * Constructor for no solution.
21  */
22 VectorSolutions::VectorSolutions(): vector(NULL)
23 {
24         clean();
25 }
26
27 /**
28  * Copy constructor
29  */
30 VectorSolutions::VectorSolutions(const VectorSolutions & s): vector(NULL)
31 {
32         alloc(s.getNumber());
33         setTangent(s.isTangent());
34
35         for(int i=0; i<s.getNumber(); ++i)
36                 set(i, s.get(i));
37 }
38
39 /**
40  * Constructor for num solutions.
41  */
42 VectorSolutions::VectorSolutions(int num): vector(NULL)
43 {
44         alloc(num);
45 }
46
47 /**
48  * Constructor for one solution.
49  */
50 VectorSolutions::VectorSolutions(const Vector & v1)
51 {
52         num = 1;
53         vector = new Vector[num];
54         vector[0] = v1;
55         tangent = false;
56 }
57
58 /**
59  * Constructor for two solutions.
60  */
61 VectorSolutions::VectorSolutions(const Vector & v1, const Vector & v2)
62 {
63         num = 2;
64         vector = new Vector[num];
65         vector[0] = v1;
66         vector[1] = v2;
67         tangent = false;
68 }
69
70 /**
71  * Constructor for three solutions.
72  */
73 VectorSolutions::VectorSolutions(const Vector & v1, const Vector & v2, const Vector & v3)
74 {
75         num = 3;
76         vector = new Vector[num];
77         vector[0] = v1;
78         vector[1] = v2;
79         vector[2] = v3;
80         tangent = false;
81 }
82
83 /**
84  * Constructor for four solutions.
85  */
86 VectorSolutions::VectorSolutions(const Vector & v1, const Vector & v2, const Vector & v3,
87         const Vector & v4)
88 {
89         num = 4;
90         vector = new Vector[num];
91         vector[0] = v1;
92         vector[1] = v2;
93         vector[2] = v3;
94         vector[3] = v4;
95         tangent = false;
96 }
97
98 /**
99  * Constructor for four solutions.
100  */
101 VectorSolutions::VectorSolutions(const Vector & v1, const Vector & v2, const Vector & v3,
102         const Vector & v4, const Vector & v5)
103 {
104         num = 5;
105         vector = new Vector[num];
106         vector[0] = v1;
107         vector[1] = v2;
108         vector[2] = v3;
109         vector[3] = v4;
110         vector[4] = v5;
111         tangent = false;
112 }
113
114 /**
115  * Destructor.
116  */
117 VectorSolutions::~VectorSolutions()
118 {
119         clean();
120 }
121
122 /**
123  * Allocates 'num' vectors.
124  */
125 void VectorSolutions::alloc(int num)
126 {
127         clean();
128         this->num = num;
129         vector = new Vector[num];
130
131         for(int i=0; i<num; ++i)
132                 vector[i] = Vector(false);
133
134         tangent = false;
135 }
136
137 /**
138  * Deletes vector array and resets everything.
139  */
140 void VectorSolutions::clean()
141 {
142         if (vector != NULL)
143                 delete[] vector;
144
145         vector = NULL;
146         num = 0;
147         tangent = false;
148 }
149
150 /**
151  * @return vector solution number i or an invalid vector if there
152  * are less solutions.
153  */
154 Vector VectorSolutions::get(int i) const
155 {
156         if (i < num)
157                 return vector[i];
158         else
159                 return Vector(false);
160 }
161
162 /**
163  * @return Number of solutions available.
164  */
165 int VectorSolutions::getNumber() const
166 {
167         return num;
168 }
169
170 /**
171  * @retval true There's at least one valid solution.
172  * @retval false There's no valid solution.
173  */
174 bool VectorSolutions::hasValid() const
175 {
176         for(int i=0; i<num; i++)
177                 if (vector[i].valid)
178                         return true;
179
180         return false;
181 }
182
183 /**
184  * Sets the solution i to the given vector.
185  * If i is greater than the current number of solutions available,
186  * nothing happens.
187  */
188 void VectorSolutions::set(int i, const Vector & v)
189 {
190         if (i < num)
191                 vector[i] = v;
192 }
193
194 /**
195  * Sets the tangent flag.
196  */
197 void VectorSolutions::setTangent(bool t)
198 {
199         tangent = t;
200 }
201
202 /**
203  * @return true if at least one of the solutions is a double solution
204  * (tangent).
205  */
206 bool VectorSolutions::isTangent() const
207 {
208         return tangent;
209 }
210
211 /**
212  * Rotates all vectors around the given center by the given angle.
213  */
214 void VectorSolutions::rotate(Vector center, double ang)
215 {
216         for(int i=0; i<num; i++)
217                 if (vector[i].valid)
218                         vector[i].rotate(center, ang);
219 }
220
221 /**
222  * Scales all vectors by the given factors with the given center.
223  */
224 void VectorSolutions::scale(Vector center, Vector factor)
225 {
226         for(int i=0; i<num; i++)
227                 if (vector[i].valid)
228                         vector[i].scale(center, factor);
229 }
230
231 /**
232  * @return vector solution which is the closest to the given coordinate.
233  * dist will contain the distance if it doesn't point to NULL (default).
234  */
235 Vector VectorSolutions::getClosest(const Vector & coord, double * dist, int * index) const
236 {
237         double curDist;
238         double minDist = RS_MAXDOUBLE;
239         Vector closestPoint(false);
240
241         for(int i=0; i<num; i++)
242         {
243                 if (vector[i].valid)
244                 {
245                         curDist = coord.distanceTo(vector[i]);
246
247                         if (curDist < minDist)
248                         {
249                                 closestPoint = vector[i];
250                                 minDist = curDist;
251
252                                 if (dist != NULL)
253                                         *dist = curDist;
254
255                                 if (index != NULL)
256                                         *index = i;
257                         }
258                 }
259         }
260
261         return closestPoint;
262 }
263
264 VectorSolutions VectorSolutions::operator=(const VectorSolutions & s)
265 {
266         alloc(s.getNumber());
267         setTangent(s.isTangent());
268
269         for (int i=0; i<s.getNumber(); ++i)
270                 set(i, s.get(i));
271
272         return *this;
273 }
274
275 std::ostream& operator << (std::ostream& os, const VectorSolutions& s)
276 {
277         for(int i=0; i<s.num; ++i)
278                 os << "(" << s.get(i) << ")\n";
279
280         os << " tangent: " << (int)s.isTangent() << "\n";
281         return os;
282 }