1 // spline.cpp: NURBS object
3 // Part of the Architektonas Project
4 // (C) 2014 Underground Software
5 // See the README and GPLv3 files for licensing and warranty information
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- ------------------------------------------------------------
11 // JLH 03/20/2014 Created this file
20 #warning "!!! This class is NOT CORRECT !!! FIX !!!"
21 Spline::Spline(Vector p1, double r, Object * p/*= NULL*/): Object(p1, p), radius(r),
22 draggingEdge(false), draggingCenter(false), hitCenter(false), hitSpline(false)
33 /*virtual*/ void Spline::Draw(Painter * painter)
35 if (state == OSSelected || hitSpline || hitCenter)
36 painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine));
38 painter->SetPen(QPen(Qt::black, 1.0, Qt::SolidLine));
41 // QBrush brush(Qt::DiagCrossPattern);
42 // brush.setColor(QColor(255, 255, 0));
43 // painter->SetBrush(brush);
44 painter->SetBrush(QBrush(Qt::NoBrush));
47 painter->DrawEllipse(position, radius, radius);
49 // & draw handles (if needed)
50 if (state == OSSelected || hitCenter)
51 painter->DrawHandle(position);
53 if (state == OSSelected && draggingEdge && objectWasDragged)
54 painter->DrawHandle(dragPoint);
56 // If resizing the circle, draw an information panel showing the new radius.
59 QString text = QObject::tr("Radius: %1\nScale: %2%");
60 text = text.arg(radius, 0, 'd', 4).arg(radius / oldRadius * 100.0, 0, 'd', 0);
62 QPen pen = QPen(QColor(0x00, 0xFF, 0x00), 1.0, Qt::SolidLine);
64 painter->SetBrush(QBrush(QColor(0x40, 0xFF, 0x40, 0x9F)));
65 QRectF textRect(10.0, 10.0, 270.0, 70.0); // x, y, w, h
66 painter->DrawRoundedRect(textRect, 7.0, 7.0);
68 textRect.setLeft(textRect.left() + 14);
69 painter->SetFont(*Object::font);
70 pen = QPen(QColor(0x00, 0x5F, 0xDF));
72 painter->DrawText(textRect, Qt::AlignVCenter, text);
74 painter->DrawInformativeText(text);
80 /*virtual*/ Vector Spline::Center(void)
86 /*virtual*/ bool Spline::Collided(Vector point)
88 // Someone told us to fuck off, so we'll fuck off. :-)
92 // We can assume this, since this is a mouse down event here.
93 objectWasDragged = false;
96 // Now that we've done our hit testing on the non-snapped point, snap it if
99 point = SnapPointToGrid(point);
101 draggingCenter = hitCenter;
102 draggingEdge = hitSpline;
104 if (hitCenter || hitSpline)
113 // We didn't hit anything, so deselect this object and report failure to hit
119 /*virtual*/ bool Spline::PointerMoved(Vector point)
121 if (selectionInProgress)
123 // Check for whether or not the rect contains this circle
124 // if (selection.normalized().contains(Extents()))
125 if (selection.contains(Extents()))
133 // Hit test tells us what we hit (if anything) through boolean variables. It
134 // also tells us whether or not the state changed.
136 bool hovered = HitTest(point);
137 needUpdate = HitStateChanged();
138 objectWasDragged = (draggingEdge | draggingCenter);
140 if (objectWasDragged)
144 radius = Vector::Magnitude(point, position);
145 else if (draggingCenter)
148 // Save this point so the rendering code knows where to draw the handle...
154 /*virtual*/ void Spline::PointerReleased(void)
156 // Mouse went up, so our dragging is done (if any *was* done, that is)
157 draggingEdge = draggingCenter = false;
158 hitCenter = hitSpline = false;
160 // If the object was dragged, then revert to the old state.
161 // Otherwise, we were probably just clicked, and want to stay in the selected state.
162 if (objectWasDragged)
167 /*virtual*/ bool Spline::HitTest(Point point)
170 hitCenter = hitSpline = false;
171 double length = Vector::Magnitude(position, point);
172 //printf("Spline::length = %lf, radius = %lf\n", length, radius);
173 //How to translate this into pixels from Document space???
174 //Maybe we need to pass a scaling factor in here from the caller? That would make sense, as
175 //the caller knows about the zoom factor and all that good kinda crap
177 Document passes in the correct Cartesian coordinates being pointed to by the mouse.
178 So all we have to be concerned with is properly scaling our hot zones/handle sizes,
179 since we generally *don't* want those to scale with the zoom level. ;-)
181 What is going on here?
182 If we're zoomed out to, say, 50%, & our radius is 10.0 (absolute), then on screen
183 the radius will be 5.0. By multiplying the length by the zoom factor, we align our
184 pointed at length with our on screen length.
186 if ((length * Painter::zoom) < 8.0)
188 //wrong: else if ((length < (radius + 2.0)) && (length > (radius - 2.0)))
189 /*NB: The following should be identical to what we have down below, but it doesn't work out that way... :-P */
190 //close, but no else if (((length * Painter::zoom) < ((radius * Painter::zoom) + 2.0)) && ((length * Painter::zoom) > ((radius * Painter::zoom) - 2.0)))
191 //really wrong! else if (((length * Painter::zoom) < (radius + 2.0)) && ((length * Painter::zoom) > (radius - 2.0)))
192 // close again, but sill no else if (((length * Painter::zoom) < ((radius + 2.0) * Painter::zoom)) && ((length * Painter::zoom) > ((radius - 2.0) * Painter::zoom)))
193 else if ((fabs(length - radius) * Painter::zoom) < 2.0)
196 // return HitStateChanged();
197 return (hitCenter || hitSpline ? true : false);
201 /*virtual*/ QRectF Spline::Extents(void)
203 return QRectF(QPointF(position.x - radius, position.y - radius), QPointF(position.x + radius, position.y + radius));
207 void Spline::SaveHitState(void)
209 oldHitCenter = hitCenter;
210 oldHitSpline = hitSpline;
214 bool Spline::HitStateChanged(void)
216 if ((hitCenter != oldHitCenter) || (hitSpline != oldHitSpline))
223 /*virtual*/ void Spline::Enumerate(FILE * file)
225 fprintf(file, "SPLINE %i (%lf,%lf) %lf\n", layer, position.x, position.y, radius);
229 /*virtual*/ Object * Spline::Copy(void)
231 #warning "!!! This doesn't take care of attached Dimensions !!!"
233 This is a real problem. While having a pointer in the Dimension to this line's points
234 is fast & easy, it creates a huge problem when trying to replicate an object like this.
236 Maybe a way to fix that then, is to have reference numbers instead of pointers. That
237 way, if you copy them, ... you might still have problems. Because you can't be sure if
238 a copy will be persistant or not, you then *definitely* do not want them to have the
239 same reference number.
241 return new Spline(position, radius, parent);
245 /*virtual*/ void Spline::Rotate(Point point, double angle)
247 Point c1 = Geometry::RotatePointAroundPoint(position, point, angle);
252 /*virtual*/ void Spline::Mirror(Point p1, Point p2)
254 Point c1 = Geometry::MirrorPointAroundLine(position, p1, p2);
259 /*virtual*/ void Spline::Save(void)
266 /*virtual*/ void Spline::Restore(void)