src/mathconstants.h \
src/object.h \
src/painter.h \
+ src/rotateaction.h \
src/settingsdialog.h \
src/text.h \
src/vector.h
src/mirroraction.cpp \
src/object.cpp \
src/painter.cpp \
+ src/rotateaction.cpp \
src/settingsdialog.cpp \
src/text.cpp \
src/vector.cpp
#include "layerwidget.h"
#include "mirroraction.h"
#include "painter.h"
+#include "rotateaction.h"
#include "settingsdialog.h"
{
Object::SetDeleteActive(deleteAct->isChecked());
Object::SetDimensionActive(addDimensionAct->isChecked());
- drawing->SetRotateToolActive(rotateAct->isChecked());
// We can be sure that if we've come here, then either an active tool is
// being deactivated, or a new tool is being created. In either case, the
Object::ignoreClicks = false;
}
-#if 0
- drawing->SetAddLineToolActive(addLineAct->isChecked());
- drawing->SetAddCircleToolActive(addCircleAct->isChecked());
- drawing->SetAddArcToolActive(addArcAct->isChecked());
- drawing->SetAddDimensionToolActive(addDimensionAct->isChecked());
-#else
drawing->SetToolActive(addLineAct->isChecked() ? new DrawLineAction() : NULL);
drawing->SetToolActive(addCircleAct->isChecked() ? new DrawCircleAction() : NULL);
drawing->SetToolActive(addArcAct->isChecked() ? new DrawArcAction() : NULL);
drawing->SetToolActive(addDimensionAct->isChecked() ? new DrawDimensionAction() : NULL);
drawing->SetToolActive(mirrorAct->isChecked() ? new MirrorAction() : NULL);
-#endif
+ drawing->SetToolActive(rotateAct->isChecked() ? new RotateAction() : NULL);
if (drawing->toolAction)
Object::ignoreClicks = true;
- update();
+ drawing->update();
}
}
+/*virtual*/ void Arc::Rotate(Point point, double angle)
+{
+ Point c1 = Geometry::RotatePointAroundPoint(position, point, angle);
+ Point ap1(cos(startAngle), sin(startAngle));
+ Point angleStartPoint = (ap1 * radius) + position;
+ Point c2 = Geometry::RotatePointAroundPoint(angleStartPoint, point, angle);
+
+ position = c1;
+ startAngle = Vector(c2, c1).Angle();
+}
+
+
/*virtual*/ void Arc::Mirror(Point p1, Point p2)
{
Point c1 = Geometry::MirrorPointAroundLine(position, p1, p2);
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);
}
+/*virtual*/ void Circle::Rotate(Point point, double angle)
+{
+ Point c1 = Geometry::RotatePointAroundPoint(position, point, angle);
+ position = c1;
+}
+
+
/*virtual*/ void Circle::Mirror(Point p1, Point p2)
{
Point c1 = Geometry::MirrorPointAroundLine(position, p1, p2);
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);
//
// STILL TO BE DONE:
//
+// - Lots of stuff
//
// Uncomment this for debugging...
gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE),
scale(1.0), offsetX(-10), offsetY(-10),
document(Vector(0, 0)),
- /*gridSpacing(12.0),*/ gridPixels(0), collided(false), rotateTool(false),
- rx(150.0), ry(150.0),
+ /*gridSpacing(12.0),*/ gridPixels(0), collided(false), //rotateTool(false),
+// rx(150.0), ry(150.0),
// scrollDrag(false), addLineTool(false), addCircleTool(false),
// addDimensionTool(false),
toolAction(NULL)
}
-void DrawingView::SetRotateToolActive(bool state/*= true*/)
-{
- rotateTool = state;
- update();
-}
-
-
void DrawingView::SetToolActive(Action * action)
{
if (action != NULL)
}
-#if 0
-//
-// This looks strange, but it's really quite simple: We want a point that's
-// more than half-way to the next grid point to snap there while conversely we
-// want a point that's less than half-way to to the next grid point then snap
-// to the one before it. So we add half of the grid spacing to the point, then
-// divide by it so that we can remove the fractional part, then multiply it
-// back to get back to the correct answer.
-//
-Vector DrawingView::SnapPointToGrid(Vector point)
-{
- point += gridSpacing / 2.0; // *This* adds to Z!!!
- point /= gridSpacing;
- point.x = floor(point.x);//need to fix this for negative numbers...
- point.y = floor(point.y);
- point.z = 0; // Make *sure* Z doesn't go anywhere!!!
- point *= gridSpacing;
- return point;
-}
-#endif
-
-
void DrawingView::paintEvent(QPaintEvent * /*event*/)
{
QPainter qtPainter(this);
if (useAntialiasing)
qtPainter.setRenderHint(QPainter::Antialiasing);
-// Painter::screenSize = Vector(size().width(), size().height());
Object::SetViewportHeight(size().height());
// Draw coordinate axes
-
painter.SetPen(QPen(Qt::blue, 1.0, Qt::DotLine));
painter.DrawLine(0, -16384, 0, 16384);
painter.DrawLine(-16384, 0, 16384, 0);
- // Draw supplemental (tool related) points
-// NOTE that this can be done as an action!
-// In that case, we would need access to the document...
-// [We can do that by making the document a class object...]
- if (rotateTool)
- {
- painter.SetPen(QPen(QColor(0, 200, 0), 2.0, Qt::SolidLine));
- painter.DrawLine(rx - 10, ry, rx + 10, ry);
- painter.DrawLine(rx, ry - 10, rx, ry + 10);
- }
-
-// Maybe we can make the grid into a background brush instead, and let Qt deal
-// with it??? YES!!
-
// The top level document takes care of rendering for us...
document.Draw(&painter);
if (toolAction)
{
-// painter.SetPen(QPen(Qt::green, 1.0, Qt::DashLine));
painter.SetPen(QPen(QColor(200, 100, 0, 255), 1.0, Qt::DashLine));
painter.DrawCrosshair(oldPoint);
toolAction->Draw(&painter);
if (Object::selectionInProgress)
{
-// painter.SetPen(QPen(Qt::green, 1.0, Qt::SolidLine));
painter.SetPen(QPen(QColor(255, 127, 0, 255)));
-// painter.SetBrush(QBrush(Qt::NoBrush));
painter.SetBrush(QBrush(QColor(255, 127, 0, 100)));
painter.DrawRect(Object::selection);
}
DrawingView(QWidget * parent = NULL);
public:
- void SetRotateToolActive(bool state = true);
+// void SetRotateToolActive(bool state = true);
void SetToolActive(Action * action);
void SetGridSize(uint32_t);
void UpdateGridBackground(void);
bool collided;
//Should this go into Object's class variables???
//maybe, maybe not... :-P
- bool rotateTool;
- double rx, ry;
+// bool rotateTool;
+// double rx, ry;
bool scrollDrag;
Vector oldPoint;
// bool addLineTool;
//
#include "geometry.h"
-
+#include <math.h>
Point Geometry::IntersectionOfLineAndLine(Point p1, Point p2, Point p3, Point p4)
{
return mirroredPoint;
}
+
+Point Geometry::RotatePointAroundPoint(Point point, Point rotationPoint, double angle)
+{
+ Vector v = Vector(point, rotationPoint);
+ double px = (v.x * cos(angle)) - (v.y * sin(angle));
+ double py = (v.x * sin(angle)) + (v.y * cos(angle));
+
+ return Vector(rotationPoint.x + px, rotationPoint.y + py, 0);
+}
+
static Point IntersectionOfLineAndLine(Point, Point, Point, Point);
static double ParameterOfLineAndPoint(Point, Point, Point);
static Point MirrorPointAroundLine(Point, Point, Point);
+ static Point RotatePointAroundPoint(Point, Point, double);
};
#endif // __GEOMETRY_H__
/*virtual*/ bool Line::Collided(Vector point)
{
+/*
+what we can do here is set ignoreClicks to true to keep other objects that are
+selected from deselecting themselves. Will that fuck up something else? Not sure
+yet... :-/
+*/
// Someone told us to fuck off, so we'll fuck off. :-)
if (ignoreClicks)
return false;
}
-/*virtual*/ void Line::Rotate(Vector point, double angle)
+/*virtual*/ void Line::Rotate(Point point, double angle)
{
+ Point l1 = Geometry::RotatePointAroundPoint(position, point, angle);
+ Point l2 = Geometry::RotatePointAroundPoint(endpoint, point, angle);
+ position = l1;
+ endpoint = l2;
}
-/*virtual*/ void Line::Scale(Vector point, double amount)
+/*virtual*/ void Line::Scale(Point point, double amount)
{
}
virtual Vector GetPointAtParameter(double parameter);
virtual QRectF Extents(void);
virtual void Translate(Vector);
- virtual void Rotate(Vector, double);
+ virtual void Rotate(Point, double);
virtual void Scale(Vector, double);
virtual void Mirror(Point, Point);
virtual void Save(void);
}
-/*virtual*/ void Object::Rotate(Vector, double)
+/*virtual*/ void Object::Rotate(Point, double)
{
}
-/*virtual*/ void Object::Scale(Vector, double)
+/*virtual*/ void Object::Scale(Point, double)
{
}
virtual QRectF Extents(void);
// virtual ObjectType Type(void);// = 0; // Pure virtual, must be implemented
virtual void Translate(Vector);
- virtual void Rotate(Vector, double);
- virtual void Scale(Vector, double);
+ virtual void Rotate(Point, double);
+ virtual void Scale(Point, double);
virtual void Mirror(Point, Point);
virtual void Save(void);
virtual void Restore(void);
--- /dev/null
+// rotateaction.cpp: Action class for rotating selected objects
+//
+// Part of the Architektonas Project
+// (C) 2011 Underground Software
+// See the README and GPLv3 files for licensing and warranty information
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// WHO WHEN WHAT
+// --- ---------- ------------------------------------------------------------
+// JLH 09/03/2011 Created this file
+//
+
+#include "rotateaction.h"
+#include "applicationwindow.h"
+#include "container.h"
+#include "drawingview.h"
+#include "line.h"
+#include "mathconstants.h"
+#include "painter.h"
+//#include "vector.h"
+
+
+//#define FIRST_POINT 0
+//#define NEXT_POINT 1
+enum { FIRST_POINT, NEXT_POINT };
+
+
+RotateAction::RotateAction(): state(FIRST_POINT), line(NULL),
+ shiftWasPressedOnNextPoint(false), spin(new Container(Vector()))
+{
+// ApplicationWindow::drawing->document.CopySelectedContentsTo(selected);
+ ApplicationWindow::drawing->document.CopySelectedContentsTo(spin);
+
+// for(std::vector<Object *>::iterator i=spin->objects.begin(); i!=spin->objects.end(); i++)
+// (*i)->Save();
+ spin->Save();
+}
+
+
+RotateAction::~RotateAction()
+{
+}
+
+
+/*virtual*/ void RotateAction::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
+ {
+// Vector reflectedP2 = -(p2 - p1);
+// Point newP2 = p1 + reflectedP2;
+ painter->DrawLine(p1, p2);
+ painter->DrawHandle(p1);
+
+ double absAngle = (Vector(p2 - p1).Angle()) * RADIANS_TO_DEGREES;
+
+ // Keep the angle between 0 and 180 degrees
+// if (absAngle > 180.0)
+// absAngle -= 180.0;
+
+ QString text = QChar(0x2221) + QObject::tr(": %1");
+ text = text.arg(absAngle);
+// QString text = tr("Length: %1 in.");
+// text = text.arg(Vector::Magnitude(p1, p2));
+ painter->DrawInformativeText(text);
+
+ // Draw the rotated objects only if there's been a line to spin around
+ if (p1 != p2)
+ spin->Draw(painter);
+ }
+}
+
+
+/*virtual*/ void RotateAction::MouseDown(Vector point)
+{
+ // Clear our override...
+ shiftWasPressedOnNextPoint = false;
+
+ if (state == FIRST_POINT)
+ p1 = point;
+ else
+ p2 = point;
+}
+
+
+/*virtual*/ void RotateAction::MouseMoved(Vector point)
+{
+ if (state == FIRST_POINT)
+ p1 = point;
+ else
+ {
+ p2 = point;
+ double angle = Vector(p2, p1).Angle();
+
+ for(std::vector<Object *>::iterator i=spin->objects.begin(); i!=spin->objects.end(); i++)
+ {
+ (*i)->Restore();
+ (*i)->Rotate(p1, angle);
+ }
+ }
+}
+
+
+/*virtual*/ void RotateAction::MouseReleased(void)
+{
+ if (state == FIRST_POINT)
+ {
+ p2 = p1;
+ state = NEXT_POINT;
+ }
+ else if (state == NEXT_POINT)
+ {
+ state = FIRST_POINT;
+
+ std::vector<Object *> & objs = ApplicationWindow::drawing->document.objects;
+ double angle = Vector(p2, p1).Angle();
+
+ for(std::vector<Object *>::iterator i=objs.begin(); i!=objs.end(); i++)
+ {
+ if ((*i)->state == OSSelected)
+ (*i)->Rotate(p1, angle);
+ }
+
+ spin->Clear();
+ ApplicationWindow::drawing->document.CopySelectedContentsTo(spin);
+ spin->Save();
+ }
+}
+
+
+/*virtual*/ bool RotateAction::KeyDown(int key)
+{
+ if ((key == Qt::Key_Shift) && (state == NEXT_POINT))
+ {
+ shiftWasPressedOnNextPoint = true;
+ p1Save = p1;
+ p1 = p2;
+ state = FIRST_POINT;
+ return true;
+ }
+
+ return false;
+}
+
+
+/*virtual*/ bool RotateAction::KeyReleased(int key)
+{
+ if ((key == Qt::Key_Shift) && shiftWasPressedOnNextPoint)
+ {
+ shiftWasPressedOnNextPoint = false;
+ p2 = p1;
+ p1 = p1Save;
+ state = NEXT_POINT;
+ return true;
+ }
+
+ return false;
+}
+
--- /dev/null
+#ifndef __ROTATEACTION_H__
+#define __ROTATEACTION_H__
+
+#include "action.h"
+
+class Container;
+class Line;
+
+class RotateAction: public Action
+{
+ public:
+ RotateAction();
+ ~RotateAction();
+
+ virtual void Draw(Painter *);
+ virtual void MouseDown(Vector);
+ virtual void MouseMoved(Vector);
+ virtual void MouseReleased(void);
+ virtual bool KeyDown(int);
+ virtual bool KeyReleased(int);
+
+ private:
+ int state;
+ Line * line;
+ Point p1, p2, p1Save;
+ bool shiftWasPressedOnNextPoint;
+// Container * selected;
+ Container * spin;
+};
+
+#endif // __ROTATEACTION_H__
+