#include "painter.h"
#include "penwidget.h"
#include "structs.h"
+#include "units.h"
#include "utils.h"
#define BACKGROUND_MAX_SIZE 512
gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE),
scale(1.0), offsetX(-10), offsetY(-10), supressSelected(false),
document(true),
- gridPixels(0), collided(false), scrollDrag(false), hoverPointValid(false),
- hoveringIntersection(false), dragged(NULL), draggingObject(false),
+ gridPixels(0), collided(false), scrollDrag(false),
+ hoverPointValid(false), hoveringIntersection(false),
+ dragged(NULL), draggingObject(false),
angleSnap(false), dirty(false)
{
//wtf? doesn't work except in c++11??? document = { 0 };
painter->SetBrush(0xF0F0F0);
painter->SetPen(0xF0F0F0, 1, 1);
- painter->DrawRect(QRectF(QPointF(ul.x, ul.y), QPointF(br.x, br.y)));
+ painter->DrawRect(Rect(ul, br));
double spacing = Global::gridSpacing;
//
void DrawingView::DeleteCurrentLayer(int layer)
{
-//printf("DrawingView::DeleteCurrentLayer(): currentLayer = %i\n", layer);
VPVectorIter i = document.objects.begin();
while (i != document.objects.end())
//
void DrawingView::HandleLayerSwap(int layer1, int layer2)
{
-//printf("DrawingView: Swapping layers %i and %i.\n", layer1, layer2);
HandleLayerSwap(layer1, layer2, document.objects);
}
}
}
-void DrawingView::HandlePenWidth(float width)
-{
- for(VPVectorIter i=select.begin(); i!=select.end(); i++)
- {
- Object * obj = (Object *)(*i);
- obj->thickness = width;
- }
-
- supressSelected = true;
- update();
-}
-
-void DrawingView::HandlePenStyle(int style)
-{
- for(VPVectorIter i=select.begin(); i!=select.end(); i++)
- {
- Object * obj = (Object *)(*i);
- obj->style = style;
- }
-
- supressSelected = true;
- update();
-}
-
-void DrawingView::HandlePenColor(uint32_t color)
-{
- for(VPVectorIter i=select.begin(); i!=select.end(); i++)
- {
- Object * obj = (Object *)(*i);
- obj->color = color;
- }
-
- supressSelected = true;
- update();
-}
-
void DrawingView::HandlePenStamp(QAction * action)
{
PenWidget * pw = (PenWidget *)action->parentWidget();
void DrawingView::focusOutEvent(QFocusEvent * /*event*/)
{
-// printf("DrawingView::focusOutEvent()...\n");
// Make sure all modkeys being held are marked as released when the app
// loses focus (N.B.: This only works because the app sets the focus policy
// of this object to something other than Qt::NoFocus)
setCursor(curMarker);
else if (Global::penDropper)
setCursor(curDropper);
-//FocusOut already set this...
-// else
-// setCursor(Qt::ArrowCursor);
}
void DrawingView::paintEvent(QPaintEvent * /*event*/)
// Do selection rectangle rendering, if any
if (Global::selectionInProgress)
{
- painter.SetPen(QPen(QColor(255, 127, 0, 255)));
- painter.SetBrush(QBrush(QColor(255, 127, 0, 100)));
+ painter.SetPen(QPen(QColor(0xFF, 0x7F, 0x00, 0xFF)));
+ painter.SetBrush(QBrush(QColor(0xFF, 0x7F, 0x00, 0x64)));
painter.DrawRect(Global::selection);
}
break;
+ case OTPolyline:
+ {
+ painter->SetBrush(QBrush(Qt::NoBrush));
+ Polyline * pl = (Polyline *)obj;
+ Point lastp;
+ double lastbump;
+
+ for(VPVectorIter i=pl->points.begin(); i!=pl->points.end(); i++)
+ {
+ if (i != pl->points.begin())
+ {
+ Point p = ((Object *)(*i))->p[0];
+ double bump = ((Object *)(*i))->length;
+
+ if (lastbump == 0)
+ painter->DrawLine(lastp, p);
+ else
+ {
+ Arc a = Geometry::Unpack(lastp, p, lastbump);
+ painter->DrawArc(a.p[0], a.radius[0], a.angle[0], a.angle[1]);
+ }
+
+ lastp = p;
+ lastbump = bump;
+ }
+ else
+ {
+ lastp = ((Object *)(*i))->p[0];
+ lastbump = ((Object *)(*i))->length;
+ }
+ }
+
+ break;
+ }
+
case OTDimension:
{
Dimension * d = (Dimension *)obj;
painter->SetFont(QFont("Arial", 8.0 * Global::zoom * scaledThickness));
Point ctr = p2 + (Vector(p2, p1) / 2.0);
- QString dimText;
-
- if (length < 12.0)
- dimText = QString("%1\"").arg(length);
- else
- {
- double feet = (double)((int)length / 12);
- double inches = length - (feet * 12.0);
-
- if (inches == 0)
- dimText = QString("%1'").arg(feet);
- else
- dimText = QString("%1' %2\"").arg(feet).arg(inches);
- }
+ QString dimText = GetDimensionText(&document, length);
/*
Where is the text offset? It looks like it's drawing in the center, but obviously it isn't. It isn't here, it's in Painter::DrawAngledText().
break;
}
+#if 0
case OTPolygon:
{
break;
}
-
- case OTPolyline:
- {
- break;
- }
+#endif
case OTContainer:
{
}
//
-// This toggles the selection being hovered (typically, only 1 object)
+// This toggles the selection being hovered (typically, only 1 object). We
+// toggle because the CTRL key might be held, in which case, we want to
+// deselect a selected object.
//
-void DrawingView::AddHoveredToSelection(void)
+void DrawingView::HandleSelectionClick(VPVector & v)
{
- for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++)
+ if (ctrlDown)
+ {
+ for(VPVectorIter i=v.begin(); i!=v.end(); i++)
+ {
+ Object * obj = (Object *)(*i);
+
+ if (obj->hovered)
+ obj->selected = !obj->selected;
+ }
+
+ return;
+ }
+
+ for(VPVectorIter i=v.begin(); i!=v.end(); i++)
+ ((Object *)(*i))->selected = false;
+
+ // Check if the hover changed, and if so, reset the selection stack
+ if (oldHover.size() != v.size())
{
- if (((Object *)(*i))->hovered)
-// ((Object *)(*i))->selected = true;
- ((Object *)(*i))->selected = !((Object *)(*i))->selected;
+ oldHover = v;
+ currentSelect = 0;
}
+ else
+ {
+ // Select next object in the stack under the cursor
+ currentSelect++;
+
+ if (currentSelect >= v.size())
+ currentSelect = 0;
+ }
+
+ dragged = (Object *)v[currentSelect];
+ dragged->selected = true;
}
VPVector DrawingView::GetSelection(void)
void DrawingView::ToolDraw(Painter * painter)
{
- if (Global::tool == TTLine)
+ switch (Global::tool)
{
+ case TTLine:
if (Global::toolState == TSNone)
{
painter->DrawHandle(toolPoint[0]);
QString text = tr("Length: %1 in.\n") + QChar(0x2221) + tr(": %2");
informativeText = text.arg(absLength).arg(absAngle);
}
- }
- else if (Global::tool == TTCircle)
- {
+
+ break;
+
+ case TTCircle:
if (Global::toolState == TSNone)
{
painter->DrawHandle(toolPoint[0]);
QString text = tr("Radius: %1 in.");
informativeText = text.arg(length);
}
- }
- else if (Global::tool == TTArc)
- {
+
+ break;
+
+ case TTArc:
if (Global::toolState == TSNone)
{
painter->DrawHandle(toolPoint[0]);
QString text = tr("Arc span: %1") + QChar(0x00B0);
informativeText = text.arg(RADIANS_TO_DEGREES * span);
}
- }
- else if (Global::tool == TTRotate)
- {
+
+ break;
+
+ case TTRotate:
if ((Global::toolState == TSNone) || (Global::toolState == TSPoint1))
painter->DrawHandle(toolPoint[0]);
else if ((Global::toolState == TSPoint2) && shiftDown)
if (ctrlDown)
informativeText += " (Copy)";
}
- }
- else if (Global::tool == TTMirror)
- {
+
+ break;
+
+ case TTMirror:
if ((Global::toolState == TSNone) || (Global::toolState == TSPoint1))
painter->DrawHandle(toolPoint[0]);
else if ((Global::toolState == TSPoint2) && shiftDown)
if (ctrlDown)
informativeText += " (Copy)";
}
- }
- else if (Global::tool == TTDimension)
- {
+
+ break;
+
+ case TTDimension:
if (Global::toolState == TSNone)
{
painter->DrawHandle(toolPoint[0]);
QString text = tr("Length: %1 in.\n") + QChar(0x2221) + tr(": %2");
informativeText = text.arg(absLength).arg(absAngle);
}
- }
- else if (Global::tool == TTTrim)
- {
+
+ break;
+
+ case TTTrim:
if (toolObj[0] != NULL)
{
// We're assuming ATM it's just a line...
// QString text = tr("Arc span: %1") + QChar(0x00B0);
// informativeText = text.arg(RADIANS_TO_DEGREES * span);
}
- }
- else if (Global::tool == TTParallel)
- {
+
+ break;
+
+ case TTParallel:
+ if (Global::toolState == TSPoint1)
+ {
+ painter->SetPen(0xFF00FF, 2.0, LSSolid);
+ painter->SetBrush(QBrush(Qt::NoBrush));
+
+ double length = Vector::Magnitude(toolObj[0]->p[0], toolPoint[0]);
+ bool inside = (length >= toolObj[0]->radius[0] ? false : true);
+
+ for(int i=1; i<=Global::parallelNum; i++)
+ {
+ if (toolObj[0]->type == OTLine)
+ {
+ painter->DrawLine(toolObj[0]->p[0] + (toolPoint[0] * Global::parallelDist * (double)i), toolObj[0]->p[1] + (toolPoint[0] * Global::parallelDist * (double)i));
+ }
+ else if ((toolObj[0]->type == OTCircle) || (toolObj[0]->type == OTArc))
+ {
+ double radius = toolObj[0]->radius[0] + ((double)i * Global::parallelDist * (inside ? -1.0 : 1.0));
+
+ if (radius > 0)
+ {
+ if (toolObj[0]->type == OTCircle)
+ painter->DrawEllipse(toolObj[0]->p[0], radius, radius);
+ else
+ painter->DrawArc(toolObj[0]->p[0], radius, toolObj[0]->angle[0], toolObj[0]->angle[1]);
+ }
+ }
+ }
+ }
+
+ break;
+
+ default:
+ break;
}
}
}
}
-void DrawingView::ParallelHandler(int mode, Point /*p*/)
+void DrawingView::ParallelHandler(int mode, Point p)
{
switch (mode)
{
case ToolMouseDown:
+ if (numHovered == 1)
+ {
+ // New selection made...
+ VPVector hover = GetHovered();
+ toolObj[0] = (Object *)hover[0];
+ Global::toolState = TSNone;
+ }
+ else if ((numHovered == 0) && (toolObj[0] != NULL))
+ {
+ double length = Vector::Magnitude(toolObj[0]->p[0], toolPoint[0]);
+ bool inside = (length >= toolObj[0]->radius[0] ? false : true);
+
+ // Stamp out new parallel object(s)...
+ for(int i=1; i<=Global::parallelNum; i++)
+ {
+ if (toolObj[0]->type == OTLine)
+ {
+ Line * l = new Line(toolObj[0]->p[0] + (toolPoint[0] * Global::parallelDist * (double)i), toolObj[0]->p[1] + (toolPoint[0] * Global::parallelDist * (double)i), Global::penWidth, Global::penColor, Global::penStyle);
+ // Should probably have a user selection for this whether it goes into the selected objects layer or the global layer...
+ l->layer = toolObj[0]->layer;
+ document.objects.push_back(l);
+ }
+ else if (toolObj[0]->type == OTCircle)
+ {
+ double radius = toolObj[0]->radius[0] + ((double)i * Global::parallelDist * (inside ? -1.0 : 1.0));
+
+ if (radius > 0)
+ {
+ Circle * c = new Circle(toolObj[0]->p[0], radius, Global::penWidth, Global::penColor, Global::penStyle);
+ c->layer = toolObj[0]->layer;
+ document.objects.push_back(c);
+ }
+ }
+ else if (toolObj[0]->type == OTArc)
+ {
+ double radius = toolObj[0]->radius[0] + ((double)i * Global::parallelDist * (inside ? -1.0 : 1.0));
+
+ if (radius > 0)
+ {
+ Arc * a = new Arc(toolObj[0]->p[0], radius, toolObj[0]->angle[0], toolObj[0]->angle[1], Global::penWidth, Global::penColor, Global::penStyle);
+ a->layer = toolObj[0]->layer;
+ document.objects.push_back(a);
+ }
+ }
+ }
+
+ // Then reset the state
+ toolObj[0]->selected = false;
+ toolObj[0] = NULL;
+ Global::toolState = TSNone;
+ }
+
break;
case ToolMouseMove:
+ if ((numHovered == 0) && toolObj[0] != NULL)
+ Global::toolState = TSPoint1;
+ else
+ Global::toolState = TSNone;
+
+ if (Global::toolState == TSPoint1)
+ {
+ // Figure out which side of the object we're on, and draw the preview on that side...
+ if (toolObj[0]->type == OTLine)
+ {
+ Vector normal = Geometry::GetNormalOfPointAndLine(p, (Line *)toolObj[0]);
+ toolPoint[0] = normal;
+ }
+ else if ((toolObj[0]->type == OTCircle) || (toolObj[0]->type == OTArc))
+ {
+ toolPoint[0] = p;
+ }
+ }
+
break;
case ToolMouseUp:
{
if (event->button() == Qt::LeftButton)
{
-//printf("mousePressEvent::Qt::LeftButton numHovered=%li\n", numHovered);
Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
// Handle tool processing, if any
if (!ctrlDown)
ClearSelected(document.objects);
- // If any objects are being hovered on click, add them to the selection
- // & return
+ // If any objects are being hovered on click, deal with 'em
if (numHovered > 0)
{
- AddHoveredToSelection();
- update(); // needed??
-// GetHovered(hover); // prolly needed
VPVector hover2 = GetHovered();
dragged = (Object *)hover2[0];
- draggingObject = true;
-//printf("mousePressEvent::numHovered > 0 (hover2[0]=$%llx, type=%s)\n", dragged, objName[dragged->type]);
// Alert the pen widget
if (Global::penDropper)
Global::penWidth = dragged->thickness;
Global::penStyle = dragged->style;
emit ObjectSelected(dragged);
- ClearSelected(document.objects);
return;
}
-
- if (Global::penStamp)
+ else if (Global::penStamp)
{
dragged->color = Global::penColor;
dragged->thickness = Global::penWidth;
dragged->style = Global::penStyle;
return;
}
-
- // See if anything is using just a straight click on a handle
- if (HandleObjectClicked())
+ // See if anything is using just a straight click on a custom
+ // object handle (like Dimension objects)
+ else if (HandleObjectClicked())
{
- draggingObject = false;
update();
return;
}
+ draggingObject = true;
+ HandleSelectionClick(hover2);
+ update(); // needed??
+
// Needed for grab & moving objects
// We do it *after*... why? (doesn't seem to confer any advantage...)
if (hoveringIntersection)
if (Global::fixedLength)
{
if (dragged->type == OTLine)
- {
- dragged->length = Vector::Magnitude(dragged->p[0], dragged->p[1]);
- }
+ dragged->length = ((Line *)dragged)->Length();
+ }
+
+ // Needed for fixed angle handling
+ if (Global::fixedAngle)
+ {
+ if (dragged->type == OTLine)
+ dragged->p[2] = ((Line *)dragged)->Unit();
}
if (dragged->type == OTCircle)
// Didn't hit any object and not using a tool, so do a selection
// rectangle
Global::selectionInProgress = true;
- Global::selection.setTopLeft(QPointF(point.x, point.y));
- Global::selection.setBottomRight(QPointF(point.x, point.y));
+ Global::selection.l = Global::selection.r = point.x;
+ Global::selection.t = Global::selection.b = point.y;
select = GetSelection();
}
else if (event->button() == Qt::MiddleButton)
}
Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
- Global::selection.setBottomRight(QPointF(point.x, point.y));
+ Global::selection.r = point.x;
+ Global::selection.b = point.y;
// Only needs to be done here, as mouse down is always preceded by movement
Global::snapPointIsValid = false;
hoveringIntersection = false;
double start = a->angle[0];
double end = start + a->angle[1];
+
+ // Swap 'em if the span is negative...
+ if (a->angle[1] < 0)
+ {
+ end = a->angle[0];
+ start = end + a->angle[1];
+ }
+
rect = Rect(Point(cos(start), sin(start)), Point(cos(end), sin(end)));
// If the end of the arc is before the beginning, add 360 degrees to it
if (end < start)
end += TAU;
+/*
+Find which quadrant the start angle is in (consider the beginning of the 90° angle to be in the quadrant, the end to be in the next quadrant). Then, divide the span into 90° segments. The integer portion is the definite axis crossings; the remainder needs more scrutiny. There will be an additional axis crossing if the the sum of the start angle and the remainder is > 90°.
+*/
+#if 1
+ int quadStart = (int)(a->angle[0] / QTR_TAU);
+ double qsRemain = a->angle[0] - ((double)quadStart * QTR_TAU);
+ int numAxes = (int)((a->angle[1] + qsRemain) / QTR_TAU);
+
+ double axis[4] = { 0, 0, 0, 0 };
+ axis[0] = rect.t, axis[1] = rect.l, axis[2] = rect.b, axis[3] = rect.r;
+ double box[4] = { 1.0, -1.0, -1.0, 1.0 };
+
+ for(int i=0; i<numAxes; i++)
+ axis[(quadStart + i) % 4] = box[(quadStart + i) % 4];
+
+ // The rect is constructed the same way we traverse the axes: TLBR
+ Rect r2(axis[0], axis[1], axis[2], axis[3]);
+
+ rect |= r2;
+#else
// Adjust the bounds depending on which axes are crossed
if ((start < QTR_TAU) && (end > QTR_TAU))
rect.t = 1.0;
if ((start < (TAU + THREE_QTR_TAU)) && (end > (TAU + THREE_QTR_TAU)))
rect.b = -1.0;
+#endif
rect *= a->radius[0];
rect.Translate(a->p[0]);
{
Object * obj = (Object *)(*i);
obj->selected = false;
+ Rect selection = Global::selection;
+ selection.Normalize();
switch (obj->type)
{
{
Line * l = (Line *)obj;
- if (Global::selection.contains(l->p[0].x, l->p[0].y) && Global::selection.contains(l->p[1].x, l->p[1].y))
+ if (selection.Contains(l->p[0]) && selection.Contains(l->p[1]))
l->selected = true;
break;
case OTCircle:
{
Circle * c = (Circle *)obj;
+ Vector radVec(c->radius[0], c->radius[0]);
- if (Global::selection.contains(c->p[0].x - c->radius[0], c->p[0].y - c->radius[0]) && Global::selection.contains(c->p[0].x + c->radius[0], c->p[0].y + c->radius[0]))
+ if (selection.Contains(c->p[0] - radVec) && selection.Contains(c->p[0] + radVec))
c->selected = true;
break;
double start = a->angle[0];
double end = start + a->angle[1];
- QPointF p1(cos(start), sin(start));
- QPointF p2(cos(end), sin(end));
- QRectF bounds(p1, p2);
-
-#if 1
- // Swap X/Y coordinates if they're backwards...
- if (bounds.left() > bounds.right())
- {
- double temp = bounds.left();
- bounds.setLeft(bounds.right());
- bounds.setRight(temp);
- }
- if (bounds.bottom() > bounds.top())
+ // Swap 'em if the span is negative...
+ if (a->angle[1] < 0)
{
- double temp = bounds.bottom();
- bounds.setBottom(bounds.top());
- bounds.setTop(temp);
+ end = a->angle[0];
+ start = end + a->angle[1];
}
-#else
- // Doesn't work as advertised! For shame!
- bounds = bounds.normalized();
-#endif
// If the end of the arc is before the beginning, add 360 degrees
// to it
if (end < start)
end += TAU;
+#if 1
+ int quadStart = (int)(a->angle[0] / QTR_TAU);
+ double qsRemain = a->angle[0] - ((double)quadStart * QTR_TAU);
+ int numAxes = (int)((a->angle[1] + qsRemain) / QTR_TAU);
+
+ Rect bounds(sin(start), cos(start), sin(end), cos(end));
+ const double box[4] = { 1.0, -1.0, -1.0, 1.0 };
+
+ for(int i=0; i<numAxes; i++)
+ bounds[(quadStart + i) % 4] = box[(quadStart + i) % 4];
+#else
// Adjust the bounds depending on which axes are crossed
if ((start < QTR_TAU) && (end > QTR_TAU))
- bounds.setTop(1.0);
+ bounds.t = 1.0;
if ((start < HALF_TAU) && (end > HALF_TAU))
- bounds.setLeft(-1.0);
+ bounds.l = -1.0;
if ((start < THREE_QTR_TAU) && (end > THREE_QTR_TAU))
- bounds.setBottom(-1.0);
+ bounds.b = -1.0;
if ((start < TAU) && (end > TAU))
- bounds.setRight(1.0);
+ bounds.r = 1.0;
if ((start < (TAU + QTR_TAU)) && (end > (TAU + QTR_TAU)))
- bounds.setTop(1.0);
+ bounds.t = 1.0;
if ((start < (TAU + HALF_TAU)) && (end > (TAU + HALF_TAU)))
- bounds.setLeft(-1.0);
+ bounds.l = -1.0;
if ((start < (TAU + THREE_QTR_TAU)) && (end > (TAU + THREE_QTR_TAU)))
- bounds.setBottom(-1.0);
+ bounds.b = -1.0;
+#endif
- bounds.setTopLeft(QPointF(bounds.left() * a->radius[0], bounds.top() * a->radius[0]));
- bounds.setBottomRight(QPointF(bounds.right() * a->radius[0], bounds.bottom() * a->radius[0]));
- bounds.translate(a->p[0].x, a->p[0].y);
+ bounds *= a->radius[0];
+ bounds.Translate(a->p[0]);
- if (Global::selection.contains(bounds))
+ if (selection.Contains(bounds))
a->selected = true;
break;
}
+ case OTPolyline:
+ {
+ Polyline * pl = (Polyline *)obj;
+ Rect r(((Object *)(pl->points[0]))->p[0]);
+
+ for(int i=0; i<(pl->points.size()-1); i++)
+ {
+ r += ((Object *)(pl->points[i]))->p[0];
+ r += ((Object *)(pl->points[i + 1]))->p[0];
+ }
+
+ if (selection.Contains(r))
+ pl->selected = true;
+
+ break;
+ }
+
case OTText:
{
Text * t = (Text *)obj;
Rect r(obj->p[0], Point(t->p[0].x + t->extents.Width(), t->p[0].y - t->extents.Height()));
- if (Global::selection.contains(r.l, r.t) && Global::selection.contains(r.r, r.b))
+ if (selection.Contains(r))
t->selected = true;
break;
{
Container * c = (Container *)obj;
- if (Global::selection.contains(c->p[0].x, c->p[0].y) && Global::selection.contains(c->p[1].x, c->p[1].y))
+ if (selection.Contains(c->p[0]) && selection.Contains(c->p[1]))
c->selected = true;
break;
{
bool needUpdate = false;
+ // Make sure we don't hit test stuff on an invisible layer...
+ if (Global::layerHidden[obj->layer] == true)
+ return false;
+
switch (obj->type)
{
case OTLine:
case OTLine:
if (obj->hitPoint[0])
{
+/*
+N.B.: Mixing fixed length with fixed angle (and in this order) is probably *not* going to work out in any meaningful way, and we should probably make the GUI force these to be mutually exclusive. Besides, this combined effect already works by dragging the line segment by clicking on it. :-P
+*/
if (Global::fixedLength)
{
- Vector line = point - obj->p[1];
- Vector unit = line.Unit();
+ Vector unit = Vector::Unit(obj->p[1], point);
point = obj->p[1] + (unit * obj->length);
}
+ if (Global::fixedAngle)
+ {
+ // Calculate the component of the current vector along the
+ // fixed angle: A_compB = (A • Bu) * Bu (p[2] has the unit
+ // vector "Bu".)
+ double magnitudeAlongB = Vector::Dot(Vector(point - obj->p[1]), obj->p[2]);
+ point = obj->p[1] + (obj->p[2] * magnitudeAlongB);
+ }
+
obj->p[0] = point;
}
else if (obj->hitPoint[1])
{
if (Global::fixedLength)
{
- Vector line = point - obj->p[0];
- Vector unit = line.Unit();
+ Vector unit = Vector::Unit(obj->p[0], point);
point = obj->p[0] + (unit * obj->length);
}
+ if (Global::fixedAngle)
+ {
+ double magnitudeAlongB = Vector::Dot(Vector(point - obj->p[0]), obj->p[2]);
+ point = obj->p[0] + (obj->p[2] * magnitudeAlongB);
+ }
+
obj->p[1] = point;
}
else if (obj->hitObject)
obj->radius[0] = Vector::Magnitude(obj->p[0], point);
QString text = QObject::tr("Radius: %1\nScale: %2%");
- informativeText = text.arg(obj->radius[0], 0, 'd', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'd', 0);
+ informativeText = text.arg(obj->radius[0], 0, 'f', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'f', 0);
}
break;
obj->angle[1] += TAU;
QString text = QObject::tr("Span: %1") + QChar(0x00B0) + QObject::tr("\n%2") + QChar(0x00B0) + QObject::tr(" - %3") + QChar(0x00B0);
- informativeText = text.arg(obj->angle[1] * RADIANS_TO_DEGREES, 0, 'd', 4).arg(obj->angle[0] * RADIANS_TO_DEGREES, 0, 'd', 2).arg((obj->angle[0] + obj->angle[1]) * RADIANS_TO_DEGREES, 0, 'd', 2);
+ informativeText = text.arg(obj->angle[1] * RADIANS_TO_DEGREES, 0, 'f', 4).arg(obj->angle[0] * RADIANS_TO_DEGREES, 0, 'f', 2).arg((obj->angle[0] + obj->angle[1]) * RADIANS_TO_DEGREES, 0, 'f', 2);
return;
}
double angle = Vector::Angle(obj->p[0], point);
obj->angle[0] = angle;
QString text = QObject::tr("Start angle: %1") + QChar(0x00B0);
- informativeText = text.arg(obj->angle[0] * RADIANS_TO_DEGREES, 0, 'd', 4);
+ informativeText = text.arg(obj->angle[0] * RADIANS_TO_DEGREES, 0, 'f', 4);
}
else if (obj->hitPoint[2])
{
obj->angle[1] += TAU;
QString text = QObject::tr("Span: %1") + QChar(0x00B0) + QObject::tr("\n%2") + QChar(0x00B0) + QObject::tr(" - %3") + QChar(0x00B0);
- informativeText = text.arg(obj->angle[1] * RADIANS_TO_DEGREES, 0, 'd', 4).arg(obj->angle[0] * RADIANS_TO_DEGREES, 0, 'd', 2).arg((obj->angle[0] + obj->angle[1]) * RADIANS_TO_DEGREES, 0, 'd', 2);
+ informativeText = text.arg(obj->angle[1] * RADIANS_TO_DEGREES, 0, 'f', 4).arg(obj->angle[0] * RADIANS_TO_DEGREES, 0, 'f', 2).arg((obj->angle[0] + obj->angle[1]) * RADIANS_TO_DEGREES, 0, 'f', 2);
return;
}
if (obj->angle[0] < 0)
obj->angle[0] += TAU;
+ double endAngle = obj->angle[0] + obj->angle[1];
+
+ if (endAngle > TAU)
+ endAngle -= TAU;
+
QString text = QObject::tr("End angle: %1") + QChar(0x00B0);
- informativeText = text.arg((obj->angle[0] + obj->angle[1]) * RADIANS_TO_DEGREES, 0, 'd', 4);
+ informativeText = text.arg(endAngle * RADIANS_TO_DEGREES, 0, 'f', 4);
}
else if (obj->hitObject)
{
obj->radius[0] = Vector::Magnitude(obj->p[0], point);
QString text = QObject::tr("Radius: %1");
- informativeText = text.arg(obj->radius[0], 0, 'd', 4);
+ informativeText = text.arg(obj->radius[0], 0, 'f', 4);
}
break;