From c85958d34fac175452fe420ff24ea82f26d6f1f3 Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Thu, 20 Mar 2014 21:18:56 -0500 Subject: [PATCH] Added new Spline object and Add Spline tool to GUI. --- TODO | 11 +- architektonas.pro | 4 + res/add-spline-tool.png | Bin 0 -> 1743 bytes res/architektonas.qrc | 1 + src/applicationwindow.cpp | 17 +++ src/applicationwindow.h | 2 + src/drawsplineaction.cpp | 135 +++++++++++++++++++ src/drawsplineaction.h | 29 ++++ src/object.h | 2 +- src/spline.cpp | 271 ++++++++++++++++++++++++++++++++++++++ src/spline.h | 47 +++++++ 11 files changed, 513 insertions(+), 6 deletions(-) create mode 100644 res/add-spline-tool.png create mode 100644 src/drawsplineaction.cpp create mode 100644 src/drawsplineaction.h create mode 100644 src/spline.cpp create mode 100644 src/spline.h diff --git a/TODO b/TODO index 9251e2b..608c081 100644 --- a/TODO +++ b/TODO @@ -5,11 +5,11 @@ Stuff To Be Implemented/Fixed - Add Ellipse - Add Spline - Add Text - - Manipulate Dimension - Object connections (two types: flexible and rigid) - - Group selection (kind done, needs more work though) - - Take movement code out of Objects and put it into top level Container (actually - I think this should be more of the state code handling. Have to see.) + - Group selection (kinda done, needs more work though) + - Take movement code out of Objects and put it into top level Container + (actually I think this should be more of the state code handling. Have to + see.) - Add OSD to Object creation - Add layers - Add blocks @@ -18,7 +18,7 @@ Stuff To Be Implemented/Fixed - Add fill/hatch to Objects - Fix zooming to be more intuitive - Add other Dimension types, like radial, diametric, leader - - Restrict movement horizontal/vertical tool + - Restrict movement horizontal/vertical tool (keyboard shortcut?) - Fix Arc manipulator. Idea: split edge handles so that the inner half controls arc sizing, outer half controls rotation. That way you can grab either handle and know what it's supposed to do. @@ -33,6 +33,7 @@ Stuff To Be Implemented/Fixed Stuff That's Done ----------------- + - Manipulate Dimension [Shamus 2014-03-20] - Fix snap to grid to honor both states (right now, it's a weird mix of states) [Shamus 2013-08-11] - Add Arc [Shamus 2013-08-14] diff --git a/architektonas.pro b/architektonas.pro index eea6798..ce6ce57 100644 --- a/architektonas.pro +++ b/architektonas.pro @@ -62,6 +62,7 @@ HEADERS = \ src/drawcircleaction.h \ src/drawdimensionaction.h \ src/drawlineaction.h \ + src/drawsplineaction.h \ src/drawtextaction.h \ src/ellipse.h \ src/fileio.h \ @@ -77,6 +78,7 @@ HEADERS = \ src/painter.h \ src/rotateaction.h \ src/settingsdialog.h \ + src/spline.h \ src/text.h \ src/trimaction.h \ src/vector.h @@ -98,6 +100,7 @@ SOURCES = \ src/drawcircleaction.cpp \ src/drawdimensionaction.cpp \ src/drawlineaction.cpp \ + src/drawsplineaction.cpp \ src/drawtextaction.cpp \ src/ellipse.cpp \ src/fileio.cpp \ @@ -112,6 +115,7 @@ SOURCES = \ src/painter.cpp \ src/rotateaction.cpp \ src/settingsdialog.cpp \ + src/spline.cpp \ src/text.cpp \ src/trimaction.cpp \ src/vector.cpp diff --git a/res/add-spline-tool.png b/res/add-spline-tool.png new file mode 100644 index 0000000000000000000000000000000000000000..23e6b24856c56ea45502044cf1e6f825c380605a GIT binary patch literal 1743 zcmV;=1~B=FP)art70cKVQTmW1SOa*$) zY!`6IId`UJ6<}r!z!ks};AY@bU>tB1_)xo}<`iINV}UuqQs6$|N}x%x$pJmUeqgJa z9ZJF-(gQ{NLNbECip>sYmI5vW?gCZ-Hv-L(pqvFx0e=GBNyUP61*~2VEC7}R_W+jw zb-q4e;e>DFe7619$ETL zU=z^goa-;bfUc?$pmeqz_!8*$p9h=(-T;0n{$;hamt!bAmXFyEWc3CT2$ADG9#_;eZq^|(T#9ax-3Hy{fx%LS3{{>zGnxp<&s2da;Co1IvlLY-% z5Bfd8YT#ApTz4r2OxOcdH6>7V84u z0(Mv9!DB;!tbaGK&Oky-~6r{_vz5$m3*Lv2^ z0>1;F7t_@h;sQQf?7c7JeKuPO1S}AV=|}4h;7GaNr87Ip*&^a}9xxx6sl)Hp`wp7f zPW{|hsPfBIKuW&f=>0Au9xq!Ws_GO>=L1&(6GfZN049q|Y>FV@v|8;0z%M|DnY96J zLuH^i5YQ5_{wZKvvG5l)J{NdEL3NIrs+4x%AtQQ*Chf^WWJZ+wIx|}Z>~hZaB%y$i z$MaVwu*b}-klrpg=pV!O99?5%8&*y$$^Aoa>Dn0b#EnDkKx> z0|skq#sfD2j{&y=(||E~Qgg^B^m($I-q#>$go=woGln*O zI%g+OVema1sUs?WMJ52U3Eci@0Pc_i{ED?b+ND-h0SR7#n+@E+*_$U$W%Q0jSmA0~ z;u97t9f$Dm1-@0C;c8j|s{fa$91g9282C(XP`e1wwY#O_C<8C}eGhy$P?cG02$%yr z5n-u1flme~i)%{(qSTfGS9|?PFS&b18wcw#g7f&m(c)?IbFn@{@IUq^vs`Jk9!Q-z2Kl=H)yKTB>j zwx$s4mlFf58eB&KcN?%%W$tcZrIb+ELC*JooHVm$as!ch0XK literal 0 HcmV?d00001 diff --git a/res/architektonas.qrc b/res/architektonas.qrc index 602ddae..c8e8f90 100644 --- a/res/architektonas.qrc +++ b/res/architektonas.qrc @@ -5,6 +5,7 @@ add-circle-tool.png add-line-tool.png add-polygon-tool.png + add-spline-tool.png atns-icon.png delete-tool.png dimension-tool.png diff --git a/src/applicationwindow.cpp b/src/applicationwindow.cpp index 4f1be35..23c8654 100644 --- a/src/applicationwindow.cpp +++ b/src/applicationwindow.cpp @@ -36,6 +36,7 @@ #include "drawcircleaction.h" #include "drawdimensionaction.h" #include "drawlineaction.h" +#include "drawsplineaction.h" #include "fileio.h" #include "generaltab.h" #include "geometry.h" @@ -303,6 +304,13 @@ void ApplicationWindow::AddPolygonTool(void) } +void ApplicationWindow::AddSplineTool(void) +{ + ClearUIToolStatesExcept(addSplineAct); + SetInternalToolStates(); +} + + void ApplicationWindow::ZoomInTool(void) { double zoomFactor = 2.0; @@ -397,6 +405,9 @@ void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception) if (exception != addPolygonAct) addPolygonAct->setChecked(false); + if (exception != addSplineAct) + addSplineAct->setChecked(false); + if (exception != deleteAct) deleteAct->setChecked(false); @@ -430,6 +441,7 @@ void ApplicationWindow::SetInternalToolStates(void) drawing->SetToolActive(addCircleAct->isChecked() ? new DrawCircleAction() : NULL); drawing->SetToolActive(addArcAct->isChecked() ? new DrawArcAction() : NULL); drawing->SetToolActive(addDimensionAct->isChecked() ? new DrawDimensionAction() : NULL); + drawing->SetToolActive(addSplineAct->isChecked() ? new DrawSplineAction() : NULL); drawing->SetToolActive(mirrorAct->isChecked() ? new MirrorAction() : NULL); drawing->SetToolActive(rotateAct->isChecked() ? new RotateAction() : NULL); drawing->SetToolActive(trimAct->isChecked() ? new TrimAction() : NULL); @@ -671,6 +683,9 @@ void ApplicationWindow::CreateActions(void) addPolygonAct = CreateAction(tr("Add &Polygon"), tr("Add Polygon"), tr("Add polygons to the drawing."), QIcon(":/res/add-polygon-tool.png"), QKeySequence("A,P"), true); connect(addPolygonAct, SIGNAL(triggered()), this, SLOT(AddPolygonTool())); + addSplineAct = CreateAction(tr("Add &Spline"), tr("Add Spline"), tr("Add a NURB spline to the drawing."), QIcon(":/res/add-spline-tool.png"), QKeySequence("A,S"), true); + connect(addSplineAct, SIGNAL(triggered()), this, SLOT(AddSplineTool())); + aboutAct = CreateAction(tr("About &Architektonas"), tr("About Architektonas"), tr("Gives information about this program."), QIcon(":/res/generic-tool.png"), QKeySequence()); connect(aboutAct, SIGNAL(triggered()), this, SLOT(HelpAbout())); @@ -795,6 +810,7 @@ void ApplicationWindow::CreateMenus(void) menu->addAction(addCircleAct); menu->addAction(addArcAct); menu->addAction(addPolygonAct); + menu->addAction(addSplineAct); menu->addAction(addDimensionAct); menu->addSeparator(); menu->addAction(settingsAct); @@ -843,6 +859,7 @@ void ApplicationWindow::CreateToolbars(void) toolbar->addAction(addCircleAct); toolbar->addAction(addArcAct); toolbar->addAction(addPolygonAct); + toolbar->addAction(addSplineAct); toolbar->addAction(addDimensionAct); spinbox->setRange(4, 256); diff --git a/src/applicationwindow.h b/src/applicationwindow.h index 089ab8f..b695c1e 100644 --- a/src/applicationwindow.h +++ b/src/applicationwindow.h @@ -39,6 +39,7 @@ class ApplicationWindow: public QMainWindow void AddCircleTool(void); void AddArcTool(void); void AddPolygonTool(void); + void AddSplineTool(void); void ZoomInTool(void); void ZoomOutTool(void); void HelpAbout(void); @@ -86,6 +87,7 @@ class ApplicationWindow: public QMainWindow QAction * addCircleAct; QAction * addArcAct; QAction * addPolygonAct; + QAction * addSplineAct; QAction * aboutAct; QAction * rotateAct; QAction * zoomInAct; diff --git a/src/drawsplineaction.cpp b/src/drawsplineaction.cpp new file mode 100644 index 0000000..644cd50 --- /dev/null +++ b/src/drawsplineaction.cpp @@ -0,0 +1,135 @@ +// drawsplineaction.cpp: Action class for drawing NURBS +// +// Part of the Architektonas Project +// (C) 2014 Underground Software +// See the README and GPLv3 files for licensing and warranty information +// +// JLH = James Hammons +// +// WHO WHEN WHAT +// --- ---------- ------------------------------------------------------------ +// JLH 03/20/2014 Created this file +// + +#include "drawsplineaction.h" +#include "spline.h" +#include "mathconstants.h" +#include "painter.h" + + +enum { FIRST_POINT, NEXT_POINT }; + + +DrawSplineAction::DrawSplineAction(): state(FIRST_POINT), spline(NULL), + shiftWasPressedOnNextPoint(false) +{ +} + + +DrawSplineAction::~DrawSplineAction() +{ +} + + +/*virtual*/ void DrawSplineAction::Draw(Painter * painter) +{ + painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine)); + + // I think stuff like crosshairs should be done in the DrawingView, tho + // (and it's done there now...) + if (state == FIRST_POINT) + { + painter->DrawHandle(p1); + } + else + { + painter->DrawLine(p1, p2); + painter->DrawHandle(p2); + + Vector v(p1, p2); + double absAngle = v.Angle() * RADIANS_TO_DEGREES; + double absLength = v.Magnitude(); + QString text = tr("Length: %1 in.\n") + QChar(0x2221) + tr(": %2"); + text = text.arg(absLength).arg(absAngle); + painter->DrawInformativeText(text); + } +} + + +/*virtual*/ void DrawSplineAction::MouseDown(Vector point) +{ + // Clear our override... + shiftWasPressedOnNextPoint = false; + + if (state == FIRST_POINT) + p1 = point; + else + p2 = point; +} + + +/*virtual*/ void DrawSplineAction::MouseMoved(Vector point) +{ + if (state == FIRST_POINT) + p1 = point; + else + p2 = point; +} + + +/*virtual*/ void DrawSplineAction::MouseReleased(void) +{ + if (state == FIRST_POINT) + { + p2 = p1; + state = NEXT_POINT; + spline = NULL; + } + else if (state == NEXT_POINT) + { + Spline * oldSpline = spline; + // We create the new object here, and then pass it off to the + // DrawingView which stuffs it into the document. + spline = new Spline(p1, p2.Angle()); + + // Connect Lines by default + if (oldSpline) + { + oldSpline->Connect(spline, 0); + spline->Connect(oldSpline, 1.0); + } + + // We don't need no stinkin' sentinels, when we have signals & slots! + emit ObjectReady(spline); + + p1 = p2; + state = NEXT_POINT; + } +} + + +/*virtual*/ void DrawSplineAction::KeyDown(int key) +{ + if ((key == Qt::Key_Shift) && (state == NEXT_POINT)) + { + shiftWasPressedOnNextPoint = true; + p1Save = p1; + p1 = p2; + state = FIRST_POINT; + emit NeedRefresh(); + } +} + + +/*virtual*/ void DrawSplineAction::KeyReleased(int key) +{ + if ((key == Qt::Key_Shift) && shiftWasPressedOnNextPoint) + { + shiftWasPressedOnNextPoint = false; + p2 = p1; + p1 = p1Save; + state = NEXT_POINT; + emit(NeedRefresh()); + } +} + diff --git a/src/drawsplineaction.h b/src/drawsplineaction.h new file mode 100644 index 0000000..a5c7483 --- /dev/null +++ b/src/drawsplineaction.h @@ -0,0 +1,29 @@ +#ifndef __DRAWSPLINEACTION_H__ +#define __DRAWSPLINEACTION_H__ + +#include "action.h" + +class Spline; + +class DrawSplineAction: public Action +{ + public: + DrawSplineAction(); + ~DrawSplineAction(); + + virtual void Draw(Painter *); + virtual void MouseDown(Vector); + virtual void MouseMoved(Vector); + virtual void MouseReleased(void); + virtual void KeyDown(int); + virtual void KeyReleased(int); + + private: + int state; + Spline * spline; + Vector p1, p2, p1Save; + bool shiftWasPressedOnNextPoint; +}; + +#endif // __DRAWSPLINEACTION_H__ + diff --git a/src/object.h b/src/object.h index f7d5d7c..b83adaf 100644 --- a/src/object.h +++ b/src/object.h @@ -13,7 +13,7 @@ class Dimension; //class FILE; enum ObjectState { OSInactive, OSSelected }; -enum ObjectType { OTNone, OTObject, OTLine, OTCircle, OTArc, OTDimension, OTEllipse, OTContainer }; +enum ObjectType { OTNone, OTObject, OTLine, OTCircle, OTArc, OTDimension, OTEllipse, OTContainer, OTSpline }; class Object { diff --git a/src/spline.cpp b/src/spline.cpp new file mode 100644 index 0000000..dd3edc6 --- /dev/null +++ b/src/spline.cpp @@ -0,0 +1,271 @@ +// spline.cpp: NURBS object +// +// Part of the Architektonas Project +// (C) 2014 Underground Software +// See the README and GPLv3 files for licensing and warranty information +// +// JLH = James Hammons +// +// WHO WHEN WHAT +// --- ---------- ------------------------------------------------------------ +// JLH 03/20/2014 Created this file +// + +#include "spline.h" + +#include +#include "geometry.h" +#include "painter.h" + +#warning "!!! This class is NOT CORRECT !!! FIX !!!" +Spline::Spline(Vector p1, double r, Object * p/*= NULL*/): Object(p1, p), radius(r), + draggingEdge(false), draggingCenter(false), hitCenter(false), hitSpline(false) +{ + type = OTSpline; +} + + +Spline::~Spline() +{ +} + + +/*virtual*/ void Spline::Draw(Painter * painter) +{ + if (state == OSSelected || hitSpline || hitCenter) + painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine)); + else + painter->SetPen(QPen(Qt::black, 1.0, Qt::SolidLine)); + + // Hatch/Fill... +// QBrush brush(Qt::DiagCrossPattern); +// brush.setColor(QColor(255, 255, 0)); +// painter->SetBrush(brush); + painter->SetBrush(QBrush(Qt::NoBrush)); + + // Draw the object... + painter->DrawEllipse(position, radius, radius); + + // & draw handles (if needed) + if (state == OSSelected || hitCenter) + painter->DrawHandle(position); + + if (state == OSSelected && draggingEdge && objectWasDragged) + painter->DrawHandle(dragPoint); + + // If resizing the circle, draw an information panel showing the new radius. + if (draggingEdge) + { + QString text = QObject::tr("Radius: %1\nScale: %2%"); + text = text.arg(radius, 0, 'd', 4).arg(radius / oldRadius * 100.0, 0, 'd', 0); +#if 0 + QPen pen = QPen(QColor(0x00, 0xFF, 0x00), 1.0, Qt::SolidLine); + painter->SetPen(pen); + painter->SetBrush(QBrush(QColor(0x40, 0xFF, 0x40, 0x9F))); + QRectF textRect(10.0, 10.0, 270.0, 70.0); // x, y, w, h + painter->DrawRoundedRect(textRect, 7.0, 7.0); + + textRect.setLeft(textRect.left() + 14); + painter->SetFont(*Object::font); + pen = QPen(QColor(0x00, 0x5F, 0xDF)); + painter->SetPen(pen); + painter->DrawText(textRect, Qt::AlignVCenter, text); +#else + painter->DrawInformativeText(text); +#endif + } +} + + +/*virtual*/ Vector Spline::Center(void) +{ + return position; +} + + +/*virtual*/ bool Spline::Collided(Vector point) +{ + // Someone told us to fuck off, so we'll fuck off. :-) + if (ignoreClicks) + return false; + + // We can assume this, since this is a mouse down event here. + objectWasDragged = false; + HitTest(point); + + // Now that we've done our hit testing on the non-snapped point, snap it if + // necessary... + if (snapToGrid) + point = SnapPointToGrid(point); + + draggingCenter = hitCenter; + draggingEdge = hitSpline; + + if (hitCenter || hitSpline) + { + dragPoint = point; + oldState = state; + state = OSSelected; + oldRadius = radius; + return true; + } + + // We didn't hit anything, so deselect this object and report failure to hit + state = OSInactive; + return false; +} + + +/*virtual*/ bool Spline::PointerMoved(Vector point) +{ + if (selectionInProgress) + { + // Check for whether or not the rect contains this circle +// if (selection.normalized().contains(Extents())) + if (selection.contains(Extents())) + state = OSSelected; + else + state = OSInactive; + + return false; + } + + // Hit test tells us what we hit (if anything) through boolean variables. It + // also tells us whether or not the state changed. + SaveHitState(); + bool hovered = HitTest(point); + needUpdate = HitStateChanged(); + objectWasDragged = (draggingEdge | draggingCenter); + + if (objectWasDragged) + needUpdate = true; + + if (draggingEdge) + radius = Vector::Magnitude(point, position); + else if (draggingCenter) + position = point; + + // Save this point so the rendering code knows where to draw the handle... + dragPoint = point; + return hovered; +} + + +/*virtual*/ void Spline::PointerReleased(void) +{ + // Mouse went up, so our dragging is done (if any *was* done, that is) + draggingEdge = draggingCenter = false; + hitCenter = hitSpline = false; + + // If the object was dragged, then revert to the old state. + // Otherwise, we were probably just clicked, and want to stay in the selected state. + if (objectWasDragged) + state = oldState; +} + + +/*virtual*/ bool Spline::HitTest(Point point) +{ +// SaveHitState(); + hitCenter = hitSpline = false; + double length = Vector::Magnitude(position, point); +//printf("Spline::length = %lf, radius = %lf\n", length, radius); +//How to translate this into pixels from Document space??? +//Maybe we need to pass a scaling factor in here from the caller? That would make sense, as +//the caller knows about the zoom factor and all that good kinda crap +/* +Document passes in the correct Cartesian coordinates being pointed to by the mouse. +So all we have to be concerned with is properly scaling our hot zones/handle sizes, +since we generally *don't* want those to scale with the zoom level. ;-) + +What is going on here? +If we're zoomed out to, say, 50%, & our radius is 10.0 (absolute), then on screen +the radius will be 5.0. By multiplying the length by the zoom factor, we align our +pointed at length with our on screen length. +*/ + if ((length * Painter::zoom) < 8.0) + hitCenter = true; +//wrong: else if ((length < (radius + 2.0)) && (length > (radius - 2.0))) +/*NB: The following should be identical to what we have down below, but it doesn't work out that way... :-P */ +//close, but no else if (((length * Painter::zoom) < ((radius * Painter::zoom) + 2.0)) && ((length * Painter::zoom) > ((radius * Painter::zoom) - 2.0))) +//really wrong! else if (((length * Painter::zoom) < (radius + 2.0)) && ((length * Painter::zoom) > (radius - 2.0))) +// close again, but sill no else if (((length * Painter::zoom) < ((radius + 2.0) * Painter::zoom)) && ((length * Painter::zoom) > ((radius - 2.0) * Painter::zoom))) + else if ((fabs(length - radius) * Painter::zoom) < 2.0) + hitSpline = true; + +// return HitStateChanged(); + return (hitCenter || hitSpline ? true : false); +} + + +/*virtual*/ QRectF Spline::Extents(void) +{ + return QRectF(QPointF(position.x - radius, position.y - radius), QPointF(position.x + radius, position.y + radius)); +} + + +void Spline::SaveHitState(void) +{ + oldHitCenter = hitCenter; + oldHitSpline = hitSpline; +} + + +bool Spline::HitStateChanged(void) +{ + if ((hitCenter != oldHitCenter) || (hitSpline != oldHitSpline)) + return true; + + return false; +} + + +/*virtual*/ void Spline::Enumerate(FILE * file) +{ + fprintf(file, "SPLINE %i (%lf,%lf) %lf\n", layer, position.x, position.y, radius); +} + + +/*virtual*/ Object * Spline::Copy(void) +{ +#warning "!!! This doesn't take care of attached Dimensions !!!" +/* +This is a real problem. While having a pointer in the Dimension to this line's points +is fast & easy, it creates a huge problem when trying to replicate an object like this. + +Maybe a way to fix that then, is to have reference numbers instead of pointers. That +way, if you copy them, ... you might still have problems. Because you can't be sure if +a copy will be persistant or not, you then *definitely* do not want them to have the +same reference number. +*/ + return new Spline(position, radius, parent); +} + + +/*virtual*/ void Spline::Rotate(Point point, double angle) +{ + Point c1 = Geometry::RotatePointAroundPoint(position, point, angle); + position = c1; +} + + +/*virtual*/ void Spline::Mirror(Point p1, Point p2) +{ + Point c1 = Geometry::MirrorPointAroundLine(position, p1, p2); + position = c1; +} + + +/*virtual*/ void Spline::Save(void) +{ + Object::Save(); + oldRadius2 = radius; +} + + +/*virtual*/ void Spline::Restore(void) +{ + Object::Restore(); + radius = oldRadius2; +} + diff --git a/src/spline.h b/src/spline.h new file mode 100644 index 0000000..7bfa8e2 --- /dev/null +++ b/src/spline.h @@ -0,0 +1,47 @@ +#ifndef __SPLINE_H__ +#define __SPLINE_H__ + +#include "object.h" + +class Spline: public Object +{ + friend class Geometry; + + public: + Spline(Vector, double, Object * p = 0); + ~Spline(); + + virtual void Draw(Painter *); + virtual Vector Center(void); + virtual bool Collided(Vector); + virtual bool PointerMoved(Vector); + virtual void PointerReleased(void); + virtual bool HitTest(Point); + virtual void Enumerate(FILE *); + virtual Object * Copy(void); + virtual QRectF Extents(void); + virtual void Rotate(Point, double); + virtual void Mirror(Point, Point); + virtual void Save(void); + virtual void Restore(void); + + protected: + void SaveHitState(void); + bool HitStateChanged(void); + + protected: + double radius; // Center is Object::position + Vector dragPoint; // Used for rendering edge dragging + double oldRadius2; + + private: + bool draggingEdge; + bool draggingCenter; + bool objectWasDragged; + bool hitCenter, hitSpline; + bool oldHitCenter, oldHitSpline; + double oldRadius; +}; + +#endif // __SPLINE_H__ + -- 2.37.2