This commit is contained in:
Chenwenxuan
2024-03-06 14:54:30 +08:00
commit edac2715f0
1525 changed files with 809982 additions and 0 deletions

View File

@@ -0,0 +1,256 @@
/****************************************************************************
*
This file is part of the LibreCAD project, a 2D CAD program
Copyright (C) 2014-2015 Dongxu Li (dongxuli2011 at gmail.com)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include<cmath>
#include <QAction>
#include <QMouseEvent>
#include "lc_actiondrawcircle2pr.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_circle.h"
#include "rs_point.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
struct LC_ActionDrawCircle2PR::Points
{
RS_Vector point1;
RS_Vector point2;
};
LC_ActionDrawCircle2PR::LC_ActionDrawCircle2PR(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_ActionDrawCircleCR(container, graphicView)
,pPoints(new Points{})
{
actionType=RS2::ActionDrawCircle2PR;
reset();
}
LC_ActionDrawCircle2PR::~LC_ActionDrawCircle2PR() = default;
void LC_ActionDrawCircle2PR::reset() {
deletePreview();
*data = {};
pPoints->point1 = {};
pPoints->point2 = {};
}
void LC_ActionDrawCircle2PR::init(int status) {
RS_PreviewActionInterface::init(status);
reset();
}
void LC_ActionDrawCircle2PR::trigger() {
RS_PreviewActionInterface::trigger();
RS_Circle* circle = new RS_Circle(container,
*data);
circle->setLayerToActive();
circle->setPenToActive();
container->addEntity(circle);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(circle);
document->endUndoCycle();
}
RS_Vector rz = graphicView->getRelativeZero();
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(rz);
drawSnapper();
setStatus(SetPoint1);
reset();
}
bool LC_ActionDrawCircle2PR::preparePreview(const RS_Vector& mouse) {
const RS_Vector vp=(pPoints->point1 + pPoints->point2)*0.5;
double const angle=pPoints->point1.angleTo(pPoints->point2) + 0.5*M_PI;
double const& r0=data->radius;
double const r=sqrt(r0*r0-0.25*pPoints->point1.squaredTo(pPoints->point2));
const RS_Vector dvp=RS_Vector(angle)*r;
const RS_Vector& center1= vp + dvp;
const RS_Vector& center2= vp - dvp;
if( center1.squaredTo(center2) < RS_TOLERANCE ) {
//no need to select center, as only one solution possible
data->center=vp;
return false;
}
const double ds=mouse.squaredTo(center1) - mouse.squaredTo(center2);
if (ds < 0. ){
data->center=center1;
return true;
}
if (ds > 0. ){
data->center=center2;
return true;
}
data->center.valid=false;
return false;
}
void LC_ActionDrawCircle2PR::mouseMoveEvent(QMouseEvent* e) {
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
case SetPoint1:
pPoints->point1 = mouse;
break;
case SetPoint2:
if(mouse.distanceTo(pPoints->point1) <= 2.*data->radius) pPoints->point2 = mouse;
break;
case SelectCenter: {
if(preparePreview(mouse)){
bool existing=false;
for(auto p: *preview){
if(p->rtti() == RS2::EntityCircle){
if( static_cast<RS_Circle*>(p)->getData() == *data)
existing=true;
}
}
if(!existing){
deletePreview();
preview->addEntity(new RS_Point(preview.get(), RS_PointData(data->center)));
RS_Circle* circle = new RS_Circle(preview.get(), *data);
preview->addEntity(circle);
drawPreview();
}
}else{
if(data->isValid()) trigger();
}
}
}
}
void LC_ActionDrawCircle2PR::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void LC_ActionDrawCircle2PR::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) return;
RS_Vector mouse = e->getCoordinate();
switch (getStatus()) {
case SetPoint1:
pPoints->point1 = mouse;
graphicView->moveRelativeZero(mouse);
setStatus(SetPoint2);
break;
case SetPoint2:
if(mouse.distanceTo(pPoints->point1) <= 2.*data->radius){
pPoints->point2 = mouse;
graphicView->moveRelativeZero(mouse);
setStatus(SelectCenter);
}else{
RS_DIALOGFACTORY->commandMessage(tr("radius=%1 is too small for points selected\ndistance between points=%2 is larger than diameter=%3").
arg(data->radius).arg(pPoints->point1.distanceTo(pPoints->point2)).arg(2.*data->radius));
}
break;
case SelectCenter: {
bool showPreview=preparePreview(mouse);
if(showPreview || data->isValid())
trigger();
else
RS_DIALOGFACTORY->commandMessage(tr("Select from two possible circle centers"));
}
break;
default:
break;
}
}
void LC_ActionDrawCircle2PR::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
}
QStringList LC_ActionDrawCircle2PR::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void LC_ActionDrawCircle2PR::updateMouseButtonHints() {
switch (getStatus()) {
case SetPoint1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify first point"),
tr("Cancel"));
break;
case SetPoint2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify second point"),
tr("Back"));
break;
case SelectCenter:
RS_DIALOGFACTORY->updateMouseWidget(tr("Select circle center"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void LC_ActionDrawCircle2PR::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,72 @@
/****************************************************************************
**
* Draw circle, given its radius and two points on circle
Copyright (C) 2014-2015 Dongxu Li (dongxuli2011 at gmail.com)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef LC_ACTIONDRAWCIRCLE2PR_H
#define LC_ACTIONDRAWCIRCLE2PR_H
#include "rs_previewactioninterface.h"
#include "rs_actiondrawcirclecr.h"
/**
* This action class can handle user events to draw a
* circle with radius and two points on the circle
*
* @author Dongxu Li
*/
class LC_ActionDrawCircle2PR : public RS_ActionDrawCircleCR {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetPoint1, /**< Setting the 1st point. */
SetPoint2, /**< Setting the 2nd point. */
SelectCenter /**< select center out of two possibilities. */
};
public:
LC_ActionDrawCircle2PR(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~LC_ActionDrawCircle2PR() override;
void reset();
void init(int status=0) override;
void trigger() override;
bool preparePreview(const RS_Vector& mouse);
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,234 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2017 A. Stebich (librecad@mail.lordofbikes.de)
** Copyright (C) 2017 taoxumuye (tfy.hi@163.com)
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include "lc_actiondrawlinepolygon3.h"
#include <QAction>
#include <QMouseEvent>
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_creation.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct LC_ActionDrawLinePolygonCenTan::Points {
/** Center of polygon */
RS_Vector center;
/** Edge */
RS_Vector corner;
};
LC_ActionDrawLinePolygonCenTan::LC_ActionDrawLinePolygonCenTan(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw Polygons (Center,Corner)", container, graphicView)
, pPoints(new Points{})
,number(3)
,lastStatus(SetCenter)
{
actionType=RS2::ActionDrawLinePolygonCenCor;
}
LC_ActionDrawLinePolygonCenTan::~LC_ActionDrawLinePolygonCenTan() = default;
void LC_ActionDrawLinePolygonCenTan::trigger() {
RS_PreviewActionInterface::trigger();
deletePreview();
RS_Creation creation(container, graphicView);
bool ok = creation.createPolygon3(pPoints->center, pPoints->corner, number);
if (!ok) {
RS_DEBUG->print("RS_ActionDrawLinePolygon::trigger:"
" No polygon added\n");
}
}
void LC_ActionDrawLinePolygonCenTan::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawLinePolygon::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
case SetCenter:
break;
case SetTangent:
if (pPoints->center.valid) {
pPoints->corner = mouse;
deletePreview();
RS_Creation creation(preview.get(), nullptr, false);
creation.createPolygon3(pPoints->center, pPoints->corner, number);
drawPreview();
}
break;
default:
break;
}
}
void LC_ActionDrawLinePolygonCenTan::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void LC_ActionDrawLinePolygonCenTan::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) return;
RS_Vector mouse = e->getCoordinate();
switch (getStatus()) {
case SetCenter:
pPoints->center = mouse;
setStatus(SetTangent);
graphicView->moveRelativeZero(mouse);
break;
case SetTangent:
pPoints->corner = mouse;
trigger();
break;
default:
break;
}
}
void LC_ActionDrawLinePolygonCenTan::updateMouseButtonHints() {
switch (getStatus()) {
case SetCenter:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify center"),
"");
break;
case SetTangent:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify a tangent"), "");
break;
case SetNumber:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter number:"), "");
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void LC_ActionDrawLinePolygonCenTan::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
}
void LC_ActionDrawLinePolygonCenTan::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void LC_ActionDrawLinePolygonCenTan::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetCenter:
case SetTangent:
if (checkCommand("number", c)) {
deletePreview();
lastStatus = (Status)getStatus();
setStatus(SetNumber);
}
break;
case SetNumber: {
bool ok;
int n = c.toInt(&ok);
if (ok) {
e->accept();
if (n>0 && n<10000) {
number = n;
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid number. "
"Try 1..9999"));
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
default:
break;
}
}
QStringList LC_ActionDrawLinePolygonCenTan::getAvailableCommands() {
QStringList cmd;
switch (getStatus()) {
case SetCenter:
case SetTangent:
cmd += command("number");
break;
default:
break;
}
return cmd;
}
void LC_ActionDrawLinePolygonCenTan::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2017 A. Stebich (librecad@mail.lordofbikes.de)
** Copyright (C) 2017 taoxumuye (tfy.hi@163.com)
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef LC_ACTIONDRAWLINEPOLYGON3_H
#define LC_ACTIONDRAWLINEPOLYGON3_H
#include "rs_previewactioninterface.h"
/**
* This action class can handle user events to draw polygons.
*
*/
class LC_ActionDrawLinePolygonCenTan : public RS_PreviewActionInterface {
Q_OBJECT
enum Status {
SetCenter, /**< Setting center. */
SetTangent, /**< Setting tangent. */
SetNumber /**< Setting number in the command line. */
};
public:
LC_ActionDrawLinePolygonCenTan(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~LC_ActionDrawLinePolygonCenTan() override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void updateMouseButtonHints() override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseCursor() override;
int getNumber() const{
return number;
}
void setNumber(int n) {
number = n;
}
private:
struct Points;
std::unique_ptr<Points> pPoints;
/** Number of edges. */
int number;
/** Last status before entering text. */
Status lastStatus;
};
#endif // LC_ACTIONDRAWLINEPOLYGON3_H

View File

@@ -0,0 +1,400 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2014 Dongxu Li (dongxuli2011@gmail.com)
** Copyright (C) 2014 Pavel Krejcir (pavel@pamsoft.cz)
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "lc_actiondrawsplinepoints.h"
#include "lc_splinepoints.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commands.h"
#include "rs_commandevent.h"
#include "rs_point.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct LC_ActionDrawSplinePoints::Points {
/**
* Spline data defined so far.
*/
LC_SplinePointsData data;
/**
* Spline used.
*/
std::unique_ptr<LC_SplinePoints> spline;
/**
* Point history (for undo)
*/
std::vector<RS_Vector> undoBuffer;
};
LC_ActionDrawSplinePoints::LC_ActionDrawSplinePoints(RS_EntityContainer& container,
RS_GraphicView& graphicView):
RS_ActionDrawSpline( container, graphicView)
, pPoints(new Points{})
{
actionType=RS2::ActionDrawSplinePoints;
setName("DrawSplinePoints");
}
LC_ActionDrawSplinePoints::~LC_ActionDrawSplinePoints() = default;
void LC_ActionDrawSplinePoints::reset() {
pPoints->spline.reset();
pPoints->undoBuffer.clear();
}
void LC_ActionDrawSplinePoints::init(int status)
{
RS_PreviewActionInterface::init(status);
reset();
}
void LC_ActionDrawSplinePoints::trigger()
{
if(!pPoints->spline.get()) return;
pPoints->spline->setLayerToActive();
pPoints->spline->setPenToActive();
pPoints->spline->update();
RS_Entity* s=pPoints->spline->clone();
container->addEntity(s);
// upd. undo list:
if (document)
{
document->startUndoCycle();
document->addUndoable(s);
document->endUndoCycle();
}
// upd view
RS_Vector r = graphicView->getRelativeZero();
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(r);
RS_DEBUG->print("RS_ActionDrawSplinePoints::trigger(): spline added: %d",
s->getId());
reset();
}
void LC_ActionDrawSplinePoints::mouseMoveEvent(QMouseEvent* e)
{
RS_DEBUG->print("RS_ActionDrawSplinePoints::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
if(getStatus() == SetNextPoint)
{
LC_SplinePoints* sp = static_cast<LC_SplinePoints*>(pPoints->spline->clone());
sp->addPoint(mouse);
deletePreview();
preview->addEntity(sp);
for(auto const& v: sp->getPoints())
{
preview->addEntity(new RS_Point(preview.get(), RS_PointData(v)));
}
drawPreview();
}
RS_DEBUG->print("RS_ActionDrawSplinePoints::mouseMoveEvent end");
}
void LC_ActionDrawSplinePoints::mouseReleaseEvent(QMouseEvent* e)
{
if(e->button() == Qt::LeftButton)
{
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
}
else if(e->button() == Qt::RightButton)
{
if(getStatus() == SetNextPoint && pPoints->spline.get())
{
trigger();
}
init(getStatus() - 1);
}
}
void LC_ActionDrawSplinePoints::coordinateEvent(RS_CoordinateEvent* e)
{
if(e == nullptr) return;
RS_Vector mouse = e->getCoordinate();
switch (getStatus())
{
case SetStartPoint:
pPoints->undoBuffer.clear();
if(!pPoints->spline.get())
{
pPoints->spline.reset(new LC_SplinePoints(container, pPoints->data));
pPoints->spline->addPoint(mouse);
preview->addEntity(new RS_Point(preview.get(), RS_PointData(mouse)));
}
setStatus(SetNextPoint);
graphicView->moveRelativeZero(mouse);
updateMouseButtonHints();
break;
case SetNextPoint:
graphicView->moveRelativeZero(mouse);
if(pPoints->spline.get())
{
pPoints->spline->addPoint(mouse);
drawPreview();
drawSnapper();
}
updateMouseButtonHints();
break;
default:
break;
}
}
void LC_ActionDrawSplinePoints::commandEvent(RS_CommandEvent* e)
{
QString c = e->getCommand().toLower();
switch (getStatus())
{
case SetStartPoint:
if(checkCommand("help", c))
{
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
break;
case SetNextPoint:
if (checkCommand("undo", c))
{
undo();
updateMouseButtonHints();
return;
}
if (checkCommand("redo", c))
{
redo();
updateMouseButtonHints();
return;
}
break;
default:
break;
}
}
QStringList LC_ActionDrawSplinePoints::getAvailableCommands()
{
QStringList cmd;
switch (getStatus())
{
case SetStartPoint:
break;
case SetNextPoint:
if(pPoints->data.splinePoints.size() > 0)
{
cmd += command("undo");
}
if(pPoints->undoBuffer.size() > 0)
{
cmd += command("redo");
}
if(pPoints->data.splinePoints.size() > 2)
{
cmd += command("close");
}
break;
default:
break;
}
return cmd;
}
void LC_ActionDrawSplinePoints::updateMouseButtonHints()
{
switch (getStatus())
{
case SetStartPoint:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify first control point"),
tr("Cancel"));
break;
case SetNextPoint:
{
QString msg = "";
if(pPoints->data.splinePoints.size() > 2)
{
msg += RS_COMMANDS->command("close");
msg += "/";
}
if(pPoints->data.splinePoints.size() > 0)
{
msg += RS_COMMANDS->command("undo");
}
if(pPoints->undoBuffer.size() > 0)
{
msg += RS_COMMANDS->command("redo");
}
if(pPoints->data.splinePoints.size() > 0)
{
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify next control point or [%1]").arg(msg),
tr("Back"));
}
else
{
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify next control point"),
tr("Back"));
}
}
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void LC_ActionDrawSplinePoints::showOptions()
{
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
}
void LC_ActionDrawSplinePoints::hideOptions()
{
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void LC_ActionDrawSplinePoints::updateMouseCursor()
{
graphicView->setMouseCursor(RS2::CadCursor);
}
/*
void RS_ActionDrawSplinePoints::close() {
if (history.size()>2 && start.valid) {
//data.endpoint = start;
//trigger();
if (spline) {
RS_CoordinateEvent e(spline->getStartpoint());
coordinateEvent(&e);
}
trigger();
setStatus(SetStartpoint);
graphicView->moveRelativeZero(start);
} else {
RS_DIALOGFACTORY->commandMessage(
tr("Cannot close sequence of lines: "
"Not enough entities defined yet."));
}
}
*/
void LC_ActionDrawSplinePoints::undo()
{
if(!pPoints->spline.get())
{
RS_DIALOGFACTORY->commandMessage(
tr("Cannot undo: Not enough entities defined yet."));
return;
}
auto& splinePts = pPoints->spline->getData().splinePoints;
size_t nPoints = splinePts.size();
if(nPoints > 1)
{
RS_Vector v = splinePts.back();
pPoints->undoBuffer.push_back(v);
pPoints->spline->removeLastPoint();
if(!splinePts.size()) setStatus(SetStartPoint);
else
{
v = splinePts.back();
graphicView->moveRelativeZero(v);
}
graphicView->redraw(RS2::RedrawDrawing);
drawPreview();
}
else
{
RS_DIALOGFACTORY->commandMessage(
tr("Cannot undo: Not enough entities defined yet."));
}
}
void LC_ActionDrawSplinePoints::redo()
{
int iBufLen = pPoints->undoBuffer.size();
if(iBufLen > 1)
{
RS_Vector v = pPoints->undoBuffer.back();
pPoints->spline->addPoint(v);
pPoints->undoBuffer.pop_back();
setStatus(SetNextPoint);
v = pPoints->data.splinePoints.back();
graphicView->moveRelativeZero(v);
graphicView->redraw(RS2::RedrawDrawing);
}
else
{
RS_DIALOGFACTORY->commandMessage(
tr("Cannot undo: Nothing could be redone."));
}
}
void LC_ActionDrawSplinePoints::setClosed(bool c)
{
pPoints->data.closed = c;
if(pPoints->spline.get())
{
pPoints->spline->setClosed(c);
}
}
bool LC_ActionDrawSplinePoints::isClosed()
{
return pPoints->data.closed;
return false;
}
// EOF

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2014 Dongxu Li (dongxuli2011@gmail.com)
** Copyright (C) 2014 Pavel Krejcir (pavel@pamsoft.cz)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef LC_ACTIONDRAWSPLINEPOINTS_H
#define LC_ACTIONDRAWSPLINEPOINTS_H
#include "rs_previewactioninterface.h"
#include "rs_actiondrawspline.h"
/**
* This action class can handle user events to draw splines through points.
*
* @author Pavel Krejcir
*/
class LC_ActionDrawSplinePoints : public RS_ActionDrawSpline
{
Q_OBJECT
public:
/**
* Action States.
*/
enum Status
{
SetStartPoint, /**< Setting the startpoint. */
SetNextPoint /**< Setting the next point. */
};
LC_ActionDrawSplinePoints(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~LC_ActionDrawSplinePoints() override;
void reset();
void init(int status = 0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void showOptions() override;
void hideOptions() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
void setClosed(bool c) override;
bool isClosed() override;
void undo() override;
//using degree=2 only
void setDegree(int /*deg*/) override{}
private:
void redo();
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,92 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2014 Christian Luginbühl (dinkel@pimprecords.com)
** Copyright (C) 2018 Andrey Yaromenok (ayaromenok@gmail.com)
**
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License along
** with this program; if not, write to the Free Software Foundation, Inc.,
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
**
**********************************************************************/
#include "lc_actionfileexportmakercam.h"
#include <fstream>
#include <QAction>
#include "rs_dialogfactory.h"
#include "rs_graphic.h"
#include "lc_makercamsvg.h"
#include "rs_settings.h"
#include "lc_xmlwriterqxmlstreamwriter.h"
#include "rs_debug.h"
LC_ActionFileExportMakerCam::LC_ActionFileExportMakerCam(RS_EntityContainer& container,
RS_GraphicView& graphicView)
: RS_ActionInterface("Export as CAM/plain SVG...", container, graphicView) {}
void LC_ActionFileExportMakerCam::init(int status) {
RS_ActionInterface::init(status);
trigger();
}
void LC_ActionFileExportMakerCam::trigger() {
RS_DEBUG->print("LC_ActionFileExportMakerCam::trigger()");
if (graphic != NULL) {
bool accepted = RS_DIALOGFACTORY->requestOptionsMakerCamDialog();
if (accepted) {
QString filename = RS_DIALOGFACTORY->requestFileSaveAsDialog(tr("Export as"),
"",
"Scalable Vector Graphics (*.svg)");
if (!filename.isEmpty()) {
RS_SETTINGS->beginGroup("/ExportMakerCam");
std::unique_ptr<LC_MakerCamSVG> generator(new LC_MakerCamSVG(new LC_XMLWriterQXmlStreamWriter(),
(bool)RS_SETTINGS->readNumEntry("/ExportInvisibleLayers"),
(bool)RS_SETTINGS->readNumEntry("/ExportConstructionLayers"),
(bool)RS_SETTINGS->readNumEntry("/WriteBlocksInline"),
(bool)RS_SETTINGS->readNumEntry("/ConvertEllipsesToBeziers"),
(bool)RS_SETTINGS->readNumEntry("/ExportImages"),
(bool)RS_SETTINGS->readNumEntry("/BakeDashDotLines"),
(double)RS_SETTINGS->readEntry("/DefaultElementWidth").toDouble(),
(double)RS_SETTINGS->readEntry("/DefaultDashLinePatternLength").toDouble())
);
RS_SETTINGS->endGroup();
if (generator->generate(graphic)) {
std::ofstream file;
file.open(filename.toStdString());
file << generator->resultAsString();
file.close();
}
}
}
}
finish(false);
}

View File

@@ -0,0 +1,39 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2014 Christian Luginbühl (dinkel@pimprecords.com)
**
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License along
** with this program; if not, write to the Free Software Foundation, Inc.,
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
**
**********************************************************************/
#ifndef LC_ACTIONFILEEXPORTMAKERCAM_H
#define LC_ACTIONFILEEXPORTMAKERCAM_H
#include "rs_actioninterface.h"
class LC_ActionFileExportMakerCam : public RS_ActionInterface {
Q_OBJECT
public:
LC_ActionFileExportMakerCam(RS_EntityContainer& container, RS_GraphicView& graphicView);
void init(int status=0) override;
void trigger() override;
};
#endif

View File

@@ -0,0 +1,101 @@
/****************************************************************************
**
* Toggle whether a layer is a construction layer
* Construction layer doesn't appear on printout
* and have straight lines of infinite length
Copyright (C) 2015 A. Stebich (librecad@mail.lordofbikes.de)
Copyright (C) 2011 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include "lc_actionlayerstoggleconstruction.h"
#include <QAction>
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_graphic.h"
#include "rs_layer.h"
#include "rs_debug.h"
/**
* whether a layer is a construction layer or not
* construction layers doesn't appear on printout,
* and have straight lines of infinite length
*
* @author Armin Stebich
*/
LC_ActionLayersToggleConstruction::LC_ActionLayersToggleConstruction(
RS_EntityContainer& container,
RS_GraphicView& graphicView,
RS_Layer* layer)
: RS_ActionInterface("Toggle Construction Layer", container, graphicView)
, a_layer(layer)
{}
void LC_ActionLayersToggleConstruction::trigger() {
RS_DEBUG->print("toggle layer construction");
if (graphic) {
RS_LayerList* ll = graphic->getLayerList();
unsigned cnt = 0;
// toggle selected layers
for (auto layer: *ll) {
if (!layer) continue;
if (!layer->isVisibleInLayerList()) continue;
if (!layer->isSelectedInLayerList()) continue;
graphic->toggleLayerConstruction(layer);
deselectEntities(layer);
cnt++;
}
// if there wasn't selected layers, toggle active layer
if (!cnt) {
graphic->toggleLayerConstruction(a_layer);
deselectEntities(a_layer);
}
}
finish(false);
}
void LC_ActionLayersToggleConstruction::init(int status) {
RS_ActionInterface::init(status);
trigger();
}
void LC_ActionLayersToggleConstruction::deselectEntities(RS_Layer* layer)
{
if (!layer) return;
for(auto e: *container){
if (e && e->isVisible() && e->getLayer() == layer) {
if (graphicView) {
graphicView->deleteEntity(e);
}
if (graphicView) {
graphicView->drawEntity(e);
}
}
}
}
// EOF

View File

@@ -0,0 +1,58 @@
/****************************************************************************
**
* Toggle whether a layer is a construction layer
* Construction layer doesn't appear on printout
* and have straight lines of infinite length
Copyright (C) 2015 A. Stebich (librecad@mail.lordofbikes.de)
Copyright (C) 2011 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef LC_ACTIONLAYERSTOGGLECONSTRUCTION_H
#define LC_ACTIONLAYERSTOGGLECONSTRUCTION_H
#include "rs_actioninterface.h"
class RS_Layer;
/**
* whether a layer is a construction layer or not
* construction layers doesn't appear on printout,
* and have straight lines of infinite length
*
* @author Armin Stebich
*/
class LC_ActionLayersToggleConstruction : public RS_ActionInterface {
Q_OBJECT
public:
LC_ActionLayersToggleConstruction(RS_EntityContainer& container,
RS_GraphicView& graphicView,
RS_Layer* layer);
void init(int status=0) override;
void trigger() override;
protected:
RS_Layer* a_layer;
private:
void deselectEntities(RS_Layer* layer);
};
#endif

View File

@@ -0,0 +1,70 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include "rs_actionblocksadd.h"
#include <QAction>
#include "rs_graphic.h"
#include "rs_dialogfactory.h"
#include "rs_debug.h"
RS_ActionBlocksAdd::RS_ActionBlocksAdd(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_ActionInterface("Add Block", container, graphicView) {
actionType = RS2::ActionBlocksAdd;
}
void RS_ActionBlocksAdd::trigger() {
RS_DEBUG->print("adding block");
if (graphic) {
RS_BlockList* blockList = graphic->getBlockList();
if (blockList) {
RS_BlockData d =
RS_DIALOGFACTORY->requestNewBlockDialog(blockList);
if (d.isValid()) {
// Block cannot contain blocks.
if (container->rtti() == RS2::EntityBlock) {
graphic->addBlock(new RS_Block(container->getParent(), d));
} else {
graphic->addBlock(new RS_Block(container, d));
}
}
}
}
finish(false);
}
void RS_ActionBlocksAdd::init(int status) {
RS_ActionInterface::init(status);
trigger();
}
// EOF

View File

@@ -0,0 +1,48 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONBLOCKSADD_H
#define RS_ACTIONBLOCKSADD_H
#include "rs_actioninterface.h"
/**
* This action class can handle user events to edit blocks.
*
* @author Andrew Mustun
*/
class RS_ActionBlocksAdd : public RS_ActionInterface {
Q_OBJECT
public:
RS_ActionBlocksAdd(RS_EntityContainer& container,
RS_GraphicView& graphicView);
void init(int status=0) override;
void trigger() override;
};
#endif

View File

@@ -0,0 +1,92 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include "rs_actionblocksattributes.h"
#include <QAction>
#include "qc_applicationwindow.h"
#include "qc_mdiwindow.h"
#include "rs_graphic.h"
#include "rs_dialogfactory.h"
#include "rs_debug.h"
RS_ActionBlocksAttributes::RS_ActionBlocksAttributes(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_ActionInterface("Edit Block Attributes", container, graphicView) {}
void RS_ActionBlocksAttributes::trigger() {
RS_DEBUG->print("editing block attributes");
if (graphic) {
RS_Block* block = graphic->getActiveBlock();
RS_BlockList* blockList = graphic->getBlockList();
if (blockList && block) {
QString oldName = block->getName();
RS_BlockData d;
d = RS_DIALOGFACTORY->requestBlockAttributesDialog(
blockList);
if (d.isValid()) {
QString newName = d.name;
// update window title of opened block
QC_ApplicationWindow* appWindow = QC_ApplicationWindow::getAppWindow();
QC_MDIWindow* blockWindow = appWindow->getWindowWithDoc(block);
if (blockWindow) {
QString title = blockWindow->windowTitle();
title = title.replace(
"'" + oldName + "'",
"'" + newName + "'");
blockWindow->setWindowTitle(title);
}
blockList->rename(block, newName);
// update the name of all inserts:
graphic->renameInserts(oldName, newName);
graphic->addBlockNotification();
}
}
}
finish(false);
}
void RS_ActionBlocksAttributes::init(int status) {
RS_ActionInterface::init(status);
trigger();
}
// EOF

View File

@@ -0,0 +1,48 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONBLOCKSATTRIBUTES_H
#define RS_ACTIONBLOCKSATTRIBUTES_H
#include "rs_actioninterface.h"
/**
* This action class can handle user events to edit block attributes.
*
* @author Andrew Mustun
*/
class RS_ActionBlocksAttributes : public RS_ActionInterface {
Q_OBJECT
public:
RS_ActionBlocksAttributes(RS_EntityContainer& container,
RS_GraphicView& graphicView);
void init(int status=0) override;
void trigger() override;
};
#endif

View File

@@ -0,0 +1,163 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actionblockscreate.h"
#include "rs_creation.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_graphic.h"
#include "rs_insert.h"
#include "rs_modification.h"
#include "rs_coordinateevent.h"
/**
* Constructor.
*/
RS_ActionBlocksCreate::RS_ActionBlocksCreate(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Blocks Create",
container, graphicView)
,referencePoint(new RS_Vector{})
{
actionType=RS2::ActionBlocksCreate;
}
RS_ActionBlocksCreate::~RS_ActionBlocksCreate() = default;
void RS_ActionBlocksCreate::init(int status) {
RS_PreviewActionInterface::init(status);
}
void RS_ActionBlocksCreate::trigger() {
if (graphic) {
RS_BlockList* blockList = graphic->getBlockList();
if (blockList) {
RS_BlockData d =
RS_DIALOGFACTORY->requestNewBlockDialog(blockList);
if (!d.name.isEmpty()) {
RS_Creation creation(container, graphicView);
creation.createBlock(&d, *referencePoint, true);
RS_InsertData id(
d.name,
*referencePoint,
RS_Vector(1.0,1.0),
0.0,
1, 1, RS_Vector(0.0,0.0)
);
creation.createInsert(&id);
}
}
}
graphicView->redraw(RS2::RedrawDrawing);
setStatus(getStatus()+1); // clear mouse button hints
updateMouseButtonHints();
graphicView->killSelectActions();
finish(false);
}
void RS_ActionBlocksCreate::mouseMoveEvent(QMouseEvent* e) {
snapPoint(e);
switch (getStatus()) {
case SetReferencePoint:
//data.insertionPoint = snapPoint(e);
/*if (block) {
deletePreview();
//preview->addAllFrom(*block);
//preview->move(data.insertionPoint);
RS_Creation creation(preview, nullptr, false);
creation.createInsert(data);
drawPreview();
}*/
break;
default:
break;
}
}
void RS_ActionBlocksCreate::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
init(getStatus()-1);
}
}
void RS_ActionBlocksCreate::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) {
return;
}
switch (getStatus()) {
case SetReferencePoint:
*referencePoint = e->getCoordinate();
trigger();
break;
default:
break;
}
}
void RS_ActionBlocksCreate::updateMouseButtonHints() {
switch (getStatus()) {
case SetReferencePoint:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify reference point"),
tr("Cancel"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionBlocksCreate::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONBLOCKSCREATE_H
#define RS_ACTIONBLOCKSCREATE_H
#include "rs_previewactioninterface.h"
/**
* This action class can handle user events for creating blocks from
* existing entities.
*
* @author Andrew Mustun
*/
class RS_ActionBlocksCreate : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetReferencePoint, /**< Setting the reference point. */
ShowDialog /**< Showing dialog for name. */
};
public:
RS_ActionBlocksCreate(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionBlocksCreate() override;
void init(int status=0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
//void commandEvent(RS_CommandEvent* e) override;
//QStringList getAvailableCommands() override;
//void showOptions() override;
//void hideOptions() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
std::unique_ptr<RS_Vector> referencePoint;
};
#endif

View File

@@ -0,0 +1,69 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include "rs_actionblocksedit.h"
#include <QAction>
#include "rs_graphic.h"
#include "rs_dialogfactory.h"
#include "rs_debug.h"
RS_ActionBlocksEdit::RS_ActionBlocksEdit(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_ActionInterface("Edit Block", container, graphicView) {}
void RS_ActionBlocksEdit::trigger() {
RS_DEBUG->print(RS_Debug::D_DEBUGGING, "RS_ActionBlocksEdit::trigger(): edit block");
if (!graphic) {
RS_DEBUG->print(RS_Debug::D_ERROR, "RS_ActionBlocksEdit::trigger(): nullptr graphic");
return;
}
RS_BlockList *bl = graphic->getBlockList();
if (!bl) {
RS_DEBUG->print(RS_Debug::D_ERROR, "RS_ActionBlocksEdit::trigger(): nullptr block list in graphic");
return;
}
// std::cout<<__func__<<" : "<<__LINE__<<" : graphic->getBlockList()->count()="<<graphic->getBlockList()->count()<<std::endl;
RS_DIALOGFACTORY->requestEditBlockWindow(bl);
finish(false);
RS_DEBUG->print(RS_Debug::D_DEBUGGING, "RS_ActionBlocksEdit::trigger(): OK");
}
void RS_ActionBlocksEdit::init(int status) {
RS_ActionInterface::init(status);
trigger();
}

View File

@@ -0,0 +1,48 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONBLOCKSEDIT_H
#define RS_ACTIONBLOCKSEDIT_H
#include "rs_actioninterface.h"
/**
* This action class can handle user events to edit blocks.
*
* @author Andrew Mustun
*/
class RS_ActionBlocksEdit : public RS_ActionInterface {
Q_OBJECT
public:
RS_ActionBlocksEdit(RS_EntityContainer& container,
RS_GraphicView& graphicView);
void init(int status=0) override;
void trigger() override;
};
#endif

View File

@@ -0,0 +1,57 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include "rs_actionblocksexplode.h"
#include <QAction>
#include "rs_modification.h"
/**
* Constructor.
*/
RS_ActionBlocksExplode::RS_ActionBlocksExplode(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Blocks Explode",
container, graphicView) {
actionType=RS2::ActionBlocksExplode;
}
void RS_ActionBlocksExplode::init(int status) {
RS_PreviewActionInterface::init(status);
trigger();
finish(false);
}
void RS_ActionBlocksExplode::trigger() {
RS_Modification m(*container, graphicView);
m.explode();
}
// EOF

View File

@@ -0,0 +1,49 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONBLOCKSEXPLODE_H
#define RS_ACTIONBLOCKSEXPLODE_H
#include "rs_previewactioninterface.h"
/**
* This action class can handle user events for exploding blocks and
* other entity containers into single entities.
*
* @author Andrew Mustun
*/
class RS_ActionBlocksExplode : public RS_PreviewActionInterface {
Q_OBJECT
public:
RS_ActionBlocksExplode(RS_EntityContainer& container,
RS_GraphicView& graphicView);
void init(int status=0) override;
void trigger() override;
};
#endif

View File

@@ -0,0 +1,63 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include "rs_actionblocksfreezeall.h"
#include <QAction>
#include "rs_graphicview.h"
#include "rs_graphic.h"
#include "rs_debug.h"
RS_ActionBlocksFreezeAll::RS_ActionBlocksFreezeAll(bool freeze,
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_ActionInterface("Freeze all Blocks",
container, graphicView) {
this->freeze = freeze;
}
void RS_ActionBlocksFreezeAll::trigger() {
RS_DEBUG->print("RS_ActionBlocksFreezeAll::trigger");
if (graphic) {
graphic->freezeAllBlocks(freeze);
}
graphicView->redraw(RS2::RedrawDrawing);
finish(false);
}
void RS_ActionBlocksFreezeAll::init(int status) {
RS_ActionInterface::init(status);
trigger();
}
// EOF

View File

@@ -0,0 +1,52 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONBLOCKSFREEZEALL_H
#define RS_ACTIONBLOCKSFREEZEALL_H
#include "rs_actioninterface.h"
/**
* This action class can handle user events to edit layers.
*
* @author Andrew Mustun
*/
class RS_ActionBlocksFreezeAll : public RS_ActionInterface {
Q_OBJECT
public:
RS_ActionBlocksFreezeAll(bool freeze,
RS_EntityContainer& container,
RS_GraphicView& graphicView);
void init(int status=0) override;
void trigger() override;
private:
bool freeze;
};
#endif

View File

@@ -0,0 +1,420 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actionblocksinsert.h"
#include "rs_insert.h"
#include "rs_block.h"
#include "rs_graphic.h"
#include "rs_graphicview.h"
#include "rs_dialogfactory.h"
#include "rs_commandevent.h"
#include "rs_coordinateevent.h"
#include "rs_creation.h"
#include "rs_math.h"
#include "rs_preview.h"
/**
* Constructor.
*/
RS_ActionBlocksInsert::RS_ActionBlocksInsert(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Blocks Insert",
container, graphicView)
,block(nullptr)
,lastStatus(SetUndefined)
{
actionType = RS2::ActionBlocksInsert;
reset(); // init data Member
}
RS_ActionBlocksInsert::~RS_ActionBlocksInsert() = default;
void RS_ActionBlocksInsert::init(int status) {
RS_PreviewActionInterface::init(status);
reset();
if (graphic) {
block = graphic->getActiveBlock();
if (block) {
QString blockName = block->getName();
data->name = blockName;
if (document->rtti() == RS2::EntityBlock) {
QString parentBlockName = ((RS_Block*)(document))->getName();
if (parentBlockName == blockName) {
RS_DIALOGFACTORY->commandMessage(tr("Block cannot contain an insert of itself."));
finish(false);
} else {
QStringList bnChain = block->findNestedInsert(parentBlockName);
if (!bnChain.empty()) {
RS_DIALOGFACTORY->commandMessage(blockName
+ tr(" has nested insert of current block in:\n")
+ bnChain.join("->")
+ tr("\nThis block cannot be inserted."));
finish(false);
}
}
}
} else {
finish(false);
}
}
}
void RS_ActionBlocksInsert::reset() {
data.reset(new RS_InsertData("",
RS_Vector(0.0,0.0),
RS_Vector(1.0,1.0),
0.0,
1, 1,
RS_Vector(1.0,1.0),
NULL,
RS2::Update));
}
void RS_ActionBlocksInsert::trigger() {
deletePreview();
//RS_Modification m(*container, graphicView);
//m.paste(img->insertionPoint);
//std::cout << *RS_Clipboard::instance();
if (block) {
RS_Creation creation(container, graphicView);
data->updateMode = RS2::Update;
creation.createInsert(data.get());
}
graphicView->redraw(RS2::RedrawDrawing);
//finish();
}
void RS_ActionBlocksInsert::mouseMoveEvent(QMouseEvent* e) {
switch (getStatus()) {
case SetTargetPoint:
data->insertionPoint = snapPoint(e);
if (block) {
deletePreview();
//preview->addAllFrom(*block);
//preview->move(data->insertionPoint);
RS_Creation creation(preview.get(), nullptr, false);
// Create insert as preview only
data->updateMode = RS2::PreviewUpdate;
creation.createInsert(data.get());
drawPreview();
}
break;
default:
break;
}
}
void RS_ActionBlocksInsert::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
init(getStatus()-1);
}
}
void RS_ActionBlocksInsert::coordinateEvent(RS_CoordinateEvent* e) {
if (e==NULL) {
return;
}
data->insertionPoint = e->getCoordinate();
trigger();
}
void RS_ActionBlocksInsert::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetTargetPoint:
if (checkCommand("angle", c)) {
deletePreview();
lastStatus = (Status)getStatus();
setStatus(SetAngle);
} else if (checkCommand("factor", c)) {
deletePreview();
lastStatus = (Status)getStatus();
setStatus(SetFactor);
} else if (checkCommand("columns", c)) {
deletePreview();
lastStatus = (Status)getStatus();
setStatus(SetColumns);
} else if (checkCommand("rows", c)) {
deletePreview();
lastStatus = (Status)getStatus();
setStatus(SetRows);
} else if (checkCommand("columnspacing", c)) {
deletePreview();
lastStatus = (Status)getStatus();
setStatus(SetColumnSpacing);
} else if (checkCommand("rowspacing", c)) {
deletePreview();
lastStatus = (Status)getStatus();
setStatus(SetRowSpacing);
}
break;
case SetAngle: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
data->angle = RS_Math::deg2rad(a);
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
case SetFactor: {
bool ok;
double f = RS_Math::eval(c, &ok);
if (ok) {
setFactor(f);
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
case SetColumns: {
bool ok;
int cols = (int)RS_Math::eval(c, &ok);
if (ok) {
data->cols = cols;
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
case SetRows: {
bool ok;
int rows = (int)RS_Math::eval(c, &ok);
if (ok) {
data->rows = rows;
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
case SetColumnSpacing: {
bool ok;
double cs = (int)RS_Math::eval(c, &ok);
if (ok) {
data->spacing.x = cs;
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
case SetRowSpacing: {
bool ok;
int rs = (int)RS_Math::eval(c, &ok);
if (ok) {
data->spacing.y = rs;
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
default:
break;
}
}
double RS_ActionBlocksInsert::getAngle() const {
return data->angle;
}
void RS_ActionBlocksInsert::setAngle(double a) {
data->angle = a;
}
double RS_ActionBlocksInsert::getFactor() const {
return data->scaleFactor.x;
}
void RS_ActionBlocksInsert::setFactor(double f) {
data->scaleFactor = RS_Vector(f, f);
}
int RS_ActionBlocksInsert::getColumns() const {
return data->cols;
}
void RS_ActionBlocksInsert::setColumns(int c) {
data->cols = c;
}
int RS_ActionBlocksInsert::getRows() const {
return data->rows;
}
void RS_ActionBlocksInsert::setRows(int r) {
data->rows = r;
}
double RS_ActionBlocksInsert::getColumnSpacing() const {
return data->spacing.x;
}
void RS_ActionBlocksInsert::setColumnSpacing(double cs) {
data->spacing.x = cs;
}
double RS_ActionBlocksInsert::getRowSpacing() const {
return data->spacing.y;
}
void RS_ActionBlocksInsert::setRowSpacing(double rs) {
data->spacing.y = rs;
}
QStringList RS_ActionBlocksInsert::getAvailableCommands() {
QStringList cmd;
switch (getStatus()) {
case SetTargetPoint:
cmd += command("angle");
cmd += command("factor");
;
cmd += command("columns");
cmd += command("rows");
cmd += command("columnspacing");
cmd += command("rowspacing");
break;
default:
break;
}
return cmd;
}
void RS_ActionBlocksInsert::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
}
void RS_ActionBlocksInsert::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void RS_ActionBlocksInsert::updateMouseButtonHints() {
switch (getStatus()) {
case SetTargetPoint:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify reference point"),
tr("Cancel"));
break;
case SetAngle:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter angle:"),
"");
break;
case SetFactor:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter factor:"),
"");
break;
case SetColumns:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter columns:"),
"");
break;
case SetRows:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter rows:"),
"");
break;
case SetColumnSpacing:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter column spacing:"),
"");
break;
case SetRowSpacing:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter row spacing:"),
"");
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionBlocksInsert::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,115 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONBLOCKSINSERT_H
#define RS_ACTIONBLOCKSINSERT_H
#include "rs_previewactioninterface.h"
#include "rs_insert.h"
class RS_Block;
struct RS_InsertData;
/**
* This action class can handle user events for inserting blocks into the
* current drawing.
*
* @author Andrew Mustun
*/
class RS_ActionBlocksInsert : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetUndefined = -1, /**< Setting undefined for initialisation. */
SetTargetPoint = 0,/**< Setting the reference point. */
SetAngle, /**< Setting angle in the command line. */
SetFactor, /**< Setting factor in the command line. */
SetColumns, /**< Setting columns in the command line. */
SetRows, /**< Setting rows in the command line. */
SetColumnSpacing, /**< Setting column spacing in the command line. */
SetRowSpacing /**< Setting row spacing in the command line. */
};
public:
RS_ActionBlocksInsert(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionBlocksInsert() override;
void init(int status=0) override;
void reset();
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void showOptions() override;
void hideOptions() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
double getAngle() const;
void setAngle(double a);
double getFactor() const;
void setFactor(double f);
int getColumns() const;
void setColumns(int c);
int getRows() const;
void setRows(int r);
double getColumnSpacing() const;
void setColumnSpacing(double cs);
double getRowSpacing() const;
void setRowSpacing(double rs);
protected:
RS_Block* block;
std::unique_ptr<RS_InsertData> data;
/** Last status before entering option. */
Status lastStatus;
};
#endif

View File

@@ -0,0 +1,122 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include "rs_actionblocksremove.h"
#include <QAction>
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_graphic.h"
#include "rs_insert.h"
#include "rs_debug.h"
RS_ActionBlocksRemove::RS_ActionBlocksRemove(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_ActionInterface("Remove Block", container, graphicView) {}
void RS_ActionBlocksRemove::trigger() {
RS_DEBUG->print("RS_ActionBlocksRemove::trigger");
if (!(graphic && document)) {
finish(false);
return;
}
RS_BlockList* bl = graphic->getBlockList();
QList<RS_Block*> blocks =
RS_DIALOGFACTORY->requestSelectedBlocksRemovalDialog(bl);
if (blocks.isEmpty()) {
finish(false);
return;
}
// list of containers that might refer to the block via inserts:
std::vector<RS_EntityContainer*> containerList;
containerList.push_back(graphic);
for (int bi = 0; bi < bl->count(); bi++) {
containerList.push_back(bl->at(bi));
}
document->startUndoCycle();
for (auto block: blocks) {
if (nullptr == block) {
continue;
}
for(auto cont: containerList){
// remove all inserts from the graphic:
bool done;
do {
done = true;
for(auto e: *cont){
if (e->rtti()==RS2::EntityInsert) {
RS_Insert* ins = (RS_Insert*)e;
if (ins->getName()==block->getName() && !ins->isUndone()) {
document->addUndoable(ins);
ins->setUndoState(true);
done = false;
break;
}
}
}
} while (!done);
}
// clear selection and active state
block->selectedInBlockList(false);
if (block == bl->getActive()) {
bl->activate(nullptr);
}
// close all windows that are editing this block:
RS_DIALOGFACTORY->closeEditBlockWindow(block);
// Now remove block from the block list, but do not delete:
block->setUndoState(true);
document->addUndoable(block);
}
document->endUndoCycle();
graphic->addBlockNotification();
graphic->updateInserts();
graphicView->redraw(RS2::RedrawDrawing);
bl->activate(nullptr);
finish(false);
RS_DIALOGFACTORY->updateSelectionWidget(container->countSelected(),container->totalSelectedLength());
}
void RS_ActionBlocksRemove::init(int status) {
RS_ActionInterface::init(status);
trigger();
}
// EOF

View File

@@ -0,0 +1,48 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONBLOCKSREMOVE_H
#define RS_ACTIONBLOCKSREMOVE_H
#include "rs_actioninterface.h"
/**
* This action class can handle user events to remove blocks.
*
* @author Andrew Mustun
*/
class RS_ActionBlocksRemove : public RS_ActionInterface {
Q_OBJECT
public:
RS_ActionBlocksRemove(RS_EntityContainer& container,
RS_GraphicView& graphicView);
void init(int status=0) override;
void trigger() override;
};
#endif

View File

@@ -0,0 +1,109 @@
/****************************************************************************
This file is part of the LibreCAD project, a 2D CAD program
** Copyright (C) 2012 Dongxu Li (dongxuli2011@gmail.com)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include "rs_actionblockssave.h"
#include <QAction>
#include <QApplication>
#include "qg_blockwidget.h"
#include "qg_filedialog.h"
#include "qc_applicationwindow.h"
#include "rs_graphic.h"
#include "rs_dialogfactory.h"
#include "rs_insert.h"
#include "rs_coordinateevent.h"
#include "qc_mdiwindow.h"
#include "rs_debug.h"
RS_ActionBlocksSave::RS_ActionBlocksSave(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_ActionInterface("Edit Block", container, graphicView) {}
/*recursive add blocks in graphic*/
void RS_ActionBlocksSave::addBlock(RS_Insert* in, RS_Graphic* g) {
for(auto e: *in){
if (e->rtti() == RS2::EntityInsert) {
RS_Insert * in=static_cast<RS_Insert *>(e);
addBlock(in,g);
g->addBlock(in->getBlockForInsert());
}
}
}
void RS_ActionBlocksSave::trigger() {
RS_DEBUG->print("save block to file");
QC_ApplicationWindow* appWindow = QC_ApplicationWindow::getAppWindow();
if(!appWindow) {
finish(false);
return;
}
RS_BlockList* bList = appWindow->getBlockWidget() -> getBlockList();
if (bList) {
auto b=bList->getActive();
if(b) {
RS_Graphic g(nullptr);
g.setOwner(false);
g.getBlockList()->setOwner(false);
g.clearLayers();
// g.addLayer(b->getLayer());
for (RS_Entity* e=b->firstEntity(RS2::ResolveNone);
e;
e = b->nextEntity(RS2::ResolveNone)) {
g.addEntity(e);
if (e->rtti() == RS2::EntityInsert) {
RS_Insert *in = static_cast<RS_Insert *>(e);
g.addBlock(in->getBlockForInsert());
addBlock(in,&g);
}
// std::cout<<__FILE__<<" : "<<__func__<<" : line: "<<__LINE__<<" : "<<e->rtti()<<std::endl;
// g.addLayer(e->getLayer());
// std::cout<<__FILE__<<" : "<<__func__<<" : line: "<<__LINE__<<" : "<<e->rtti()<<std::endl;
}
// std::cout<<__FILE__<<" : "<<__func__<<" : line: "<<__LINE__<<std::endl;
// std::cout<<"add layer name="<<qPrintable(b->getLayer()->getName())<<std::endl;
RS2::FormatType t = RS2::FormatDXFRW;
QG_FileDialog dlg(appWindow->getMDIWindow(),0, QG_FileDialog::BlockFile);
QString const& fn = dlg.getSaveFile(&t);
QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
// g.setModified(true);
g.saveAs(fn, t);
QApplication::restoreOverrideCursor();
} else
RS_DIALOGFACTORY->commandMessage(tr("No block activated to save"));
} else {
RS_DEBUG->print(RS_Debug::D_WARNING,
"RS_ActionBlocksSave::trigger(): blockList is NULL");
}
finish(false);
}
void RS_ActionBlocksSave::init(int status) {
RS_ActionInterface::init(status);
trigger();
}

View File

@@ -0,0 +1,46 @@
/****************************************************************************
This file is part of the LibreCAD project, a 2D CAD program
** Copyright (C) 2012 Dongxu Li (dongxuli2011@gmail.com)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef RS_ACTIONBLOCKSSAVE_H
#define RS_ACTIONBLOCKSSAVE_H
#include "rs_actioninterface.h"
class RS_Insert;
/**
* This action class can handle user events to save the active block to a file.
*
* @author Dongxu Li
*/
class RS_ActionBlocksSave : public RS_ActionInterface {
Q_OBJECT
public:
RS_ActionBlocksSave(RS_EntityContainer& container,
RS_GraphicView& graphicView);
void init(int status=0) override;
void trigger() override;
private:
void addBlock(RS_Insert* in, RS_Graphic* g);
};
#endif

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include "rs_actionblockstoggleview.h"
#include <QAction>
#include "rs_graphicview.h"
#include "rs_graphic.h"
#include "rs_block.h"
#include "rs_debug.h"
RS_ActionBlocksToggleView::RS_ActionBlocksToggleView(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_ActionInterface("Toggle Block Visibility",
container, graphicView) {}
void RS_ActionBlocksToggleView::trigger() {
RS_DEBUG->print("toggle block");
if (graphic) {
RS_BlockList* bl = graphic->getBlockList();
unsigned cnt = 0;
// toggle selected blocks
for (auto block: *bl) {
if (!block) continue;
if (!block->isVisibleInBlockList()) continue;
if (!block->isSelectedInBlockList()) continue;
graphic->toggleBlock(block);
cnt++;
}
// if there wasn't selected blocks, toggle active block
if (!cnt) {
graphic->toggleBlock(graphic->getActiveBlock());
}
}
graphicView->redraw(RS2::RedrawDrawing);
finish(false);
}
void RS_ActionBlocksToggleView::init(int status) {
RS_ActionInterface::init(status);
trigger();
}
// EOF

View File

@@ -0,0 +1,49 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONBLOCKSTOGGLEVIEW_H
#define RS_ACTIONBLOCKSTOGGLEVIEW_H
#include "rs_actioninterface.h"
/**
* This action class can handle user events to edit layers.
*
* @author Andrew Mustun
*/
class RS_ActionBlocksToggleView : public RS_ActionInterface {
Q_OBJECT
public:
RS_ActionBlocksToggleView(RS_EntityContainer& container,
RS_GraphicView& graphicView);
void init(int status=0) override;
void trigger() override;
};
#endif

View File

@@ -0,0 +1,424 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<QMouseEvent>
#include "rs_actiondefault.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_line.h"
#include "rs_coordinateevent.h"
#include "rs_commandevent.h"
#include "rs_modification.h"
#include "rs_selection.h"
#include "rs_overlaybox.h"
#include "rs_preview.h"
#include "rs_debug.h"
#include <cmath>
struct RS_ActionDefault::Points {
RS_Vector v1;
RS_Vector v2;
};
/**
* Constructor.
*/
RS_ActionDefault::RS_ActionDefault(RS_EntityContainer& container,
RS_GraphicView& graphicView)
: RS_PreviewActionInterface("Default",
container, graphicView)
, pPoints(new Points{})
, restrBak(RS2::RestrictNothing)
{
RS_DEBUG->print("RS_ActionDefault::RS_ActionDefault");
actionType=RS2::ActionDefault;
RS_DEBUG->print("RS_ActionDefault::RS_ActionDefault: OK");
}
RS_ActionDefault::~RS_ActionDefault() = default;
void RS_ActionDefault::init(int status) {
RS_DEBUG->print("RS_ActionDefault::init");
if(status==Neutral){
deletePreview();
deleteSnapper();
}
RS_PreviewActionInterface::init(status);
pPoints->v1 = pPoints->v2 = {};
// snapMode.clear();
// snapMode.restriction = RS2::RestrictNothing;
// restrBak = RS2::RestrictNothing;
// RS_DIALOGFACTORY->requestToolBar(RS2::ToolBarMain);
RS_DEBUG->print("RS_ActionDefault::init: OK");
}
void RS_ActionDefault::keyPressEvent(QKeyEvent* e) {
// std::cout<<"RS_ActionDefault::keyPressEvent(): begin"<<std::endl;
switch(e->key()){
case Qt::Key_Shift:
restrBak = snapMode.restriction;
setSnapRestriction(RS2::RestrictOrthogonal);
e->accept();
break; //avoid clearing command line at shift key
//cleanup default action, issue#285
case Qt::Key_Escape:
// std::cout<<"RS_ActionDefault::keyPressEvent(): Qt::Key_Escape"<<std::endl;
deletePreview();
deleteSnapper();
setStatus(Neutral);
e->accept();
break;
default:
e->ignore();
}
}
void RS_ActionDefault::keyReleaseEvent(QKeyEvent* e) {
if (e->key()==Qt::Key_Shift) {
setSnapRestriction(restrBak);
e->accept();
}
}
void RS_ActionDefault::mouseMoveEvent(QMouseEvent* e) {
RS_Vector mouse = graphicView->toGraph(e->x(), e->y());
RS_Vector relMouse = mouse - graphicView->getRelativeZero();
RS_DIALOGFACTORY->updateCoordinateWidget(mouse, relMouse);
switch (getStatus()) {
case Neutral:
deleteSnapper();
break;
case Dragging:
//v2 = graphicView->toGraph(e->x(), e->y());
pPoints->v2 = mouse;
if (graphicView->toGuiDX(pPoints->v1.distanceTo(pPoints->v2))>10) {
// look for reference points to drag:
double dist;
RS_Vector ref = container->getNearestSelectedRef(pPoints->v1, &dist);
if (ref.valid==true && graphicView->toGuiDX(dist)<8) {
RS_DEBUG->print("RS_ActionDefault::mouseMoveEvent: "
"moving reference point");
setStatus(MovingRef);
pPoints->v1 = ref;
graphicView->moveRelativeZero(pPoints->v1);
}
else {
// test for an entity to drag:
RS_Entity* en = catchEntity(pPoints->v1);
if (en && en->isSelected()) {
RS_DEBUG->print("RS_ActionDefault::mouseMoveEvent: "
"moving entity");
setStatus(Moving);
RS_Vector vp= en->getNearestRef(pPoints->v1);
if(vp.valid) pPoints->v1=vp;
//graphicView->moveRelativeZero(v1);
}
// no entity found. start area selection:
else {
setStatus(SetCorner2);
}
}
}
break;
case MovingRef:
pPoints->v2 = snapPoint(e);
RS_DIALOGFACTORY->updateCoordinateWidget(pPoints->v2, pPoints->v2 - graphicView->getRelativeZero());
if (e->modifiers() & Qt::ShiftModifier) {
mouse = snapToAngle(mouse, pPoints->v1, 15.);
pPoints->v2 = mouse;
}
deletePreview();
preview->addSelectionFrom(*container);
preview->moveRef(pPoints->v1, pPoints->v2 - pPoints->v1);
if (e->modifiers() & Qt::ShiftModifier) {
RS_Line *line = new RS_Line(pPoints->v1, mouse);
preview->addEntity(line);
line->setSelected(true);
}
drawPreview();
break;
case Moving:
pPoints->v2 = snapPoint(e);
RS_DIALOGFACTORY->updateCoordinateWidget(pPoints->v2, pPoints->v2 - graphicView->getRelativeZero());
if (e->modifiers() & Qt::ShiftModifier) {
mouse = snapToAngle(mouse, pPoints->v1, 15.);
pPoints->v2 = mouse;
}
deletePreview();
preview->addSelectionFrom(*container);
preview->move(pPoints->v2 - pPoints->v1);
if (e->modifiers() & Qt::ShiftModifier) {
RS_Line *line = new RS_Line(pPoints->v1, mouse);
preview->addEntity(line);
line->setSelected(true);
}
drawPreview();
break;
case SetCorner2:
if (pPoints->v1.valid) {
pPoints->v2 = mouse;
deletePreview();
RS_OverlayBox* ob=new RS_OverlayBox(preview.get(),
RS_OverlayBoxData(pPoints->v1, pPoints->v2));
preview->addEntity(ob);
drawPreview();
}
break;
case Panning:
{
RS_Vector const vTarget(e->x(), e->y());
RS_Vector const v01=vTarget - pPoints->v1;
if(v01.squared()>=64.){
graphicView->zoomPan((int) v01.x, (int) v01.y);
pPoints->v1=vTarget;
}
}
break;
default:
break;
}
}
void RS_ActionDefault::mousePressEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
switch (getStatus()) {
case Neutral:
{
auto const m=e->modifiers();
if(m & (Qt::ControlModifier|Qt::MetaModifier)){
pPoints->v1 = RS_Vector(e->x(), e->y());
setStatus(Panning);
} else {
pPoints->v1 = graphicView->toGraph(e->x(), e->y());
setStatus(Dragging);
}
}
break;
case Moving: {
pPoints->v2 = snapPoint(e);
if (e->modifiers() & Qt::ShiftModifier) {
pPoints->v2 = snapToAngle(pPoints->v2, pPoints->v1, 15.);
}
deletePreview();
RS_Modification m(*container, graphicView);
RS_MoveData data;
data.number = 0;
data.useCurrentLayer = false;
data.useCurrentAttributes = false;
data.offset = pPoints->v2 - pPoints->v1;
m.move(data);
setStatus(Neutral);
RS_DIALOGFACTORY->updateSelectionWidget(
container->countSelected(),container->totalSelectedLength());
deleteSnapper();
}
break;
case MovingRef: {
pPoints->v2 = snapPoint(e);
if (e->modifiers() & Qt::ShiftModifier) {
pPoints->v2 = snapToAngle(pPoints->v2, pPoints->v1, 15.);
}
deletePreview();
RS_Modification m(*container, graphicView);
RS_MoveRefData data;
data.ref = pPoints->v1;
data.offset = pPoints->v2 - pPoints->v1;
m.moveRef(data);
//container->moveSelectedRef(v1, v2-v2);
setStatus(Neutral);
RS_DIALOGFACTORY->updateSelectionWidget(
container->countSelected(),container->totalSelectedLength());
}
break;
default:
break;
}
} else if (e->button()==Qt::RightButton) {
//cleanup
setStatus(Neutral);
e->accept();
}
}
void RS_ActionDefault::mouseReleaseEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDefault::mouseReleaseEvent()");
if (e->button()==Qt::LeftButton) {
pPoints->v2 = graphicView->toGraph(e->x(), e->y());
switch (getStatus()) {
case Dragging: {
// select single entity:
RS_Entity* en = catchEntity(e);
if (en) {
deletePreview();
RS_Selection s(*container, graphicView);
s.selectSingle(en);
RS_DIALOGFACTORY->updateSelectionWidget(
container->countSelected(),container->totalSelectedLength());
e->accept();
setStatus(Neutral);
} else {
setStatus(SetCorner2);
}
}
break;
case SetCorner2: {
//v2 = snapPoint(e);
pPoints->v2 = graphicView->toGraph(e->x(), e->y());
// select window:
//if (graphicView->toGuiDX(v1.distanceTo(v2))>20) {
deletePreview();
bool cross = (pPoints->v1.x > pPoints->v2.x);
RS_Selection s(*container, graphicView);
bool select = (e->modifiers() & Qt::ShiftModifier) ? false : true;
s.selectWindow(pPoints->v1, pPoints->v2, select, cross);
RS_DIALOGFACTORY->updateSelectionWidget(
container->countSelected(),container->totalSelectedLength());
setStatus(Neutral);
e->accept();
//}
}
break;
case Panning:
setStatus(Neutral);
break;
default:
break;
}
} else if (e->button()==Qt::RightButton) {
//cleanup
setStatus(Neutral);
e->accept();
}
}
void RS_ActionDefault::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
// if the current action can't deal with the command,
// it might be intended to launch a new command
//if (!e.isAccepted()) {
// command for new action:
//RS2::ActionType type = RS_COMMANDS->cmdToAction(c);
//if (type!=RS2::ActionNone) {
//graphicView->setCurrentAction(type);
//return true;
//}
//}
}
QStringList RS_ActionDefault::getAvailableCommands() {
QStringList cmd;
//cmd += "line";
//cmd += "rectangle";
return cmd;
}
void RS_ActionDefault::updateMouseButtonHints() {
switch (getStatus()) {
case Neutral:
RS_DIALOGFACTORY->updateMouseWidget();
break;
case SetCorner2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Choose second edge"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDefault::updateMouseCursor() {
switch (getStatus()) {
case Neutral:
graphicView->setMouseCursor(RS2::ArrowCursor);
break;
case Moving:
case MovingRef:
graphicView->setMouseCursor(RS2::SelectCursor);
break;
case Panning:
graphicView->setMouseCursor(RS2::ClosedHandCursor);
break;
default:
break;
}
}
// EOF

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONSELECTWINDOW_H
#define RS_ACTIONSELECTWINDOW_H
#include "rs_previewactioninterface.h"
/**
* This action class can handle user events to select all entities.
*
* @author Andrew Mustun
*/
class RS_ActionDefault : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
Neutral, /**< we don't know what we do yet. */
Dragging, /**< dragging (either an entity or the
first part of a selection window) */
SetCorner2, /**< Setting the 2nd corner of a selection window. */
Moving, /**< Moving entities (drag'n'drop) */
MovingRef, /**< Moving a reference point of one or more selected
entities */
Panning /**< view panning triggered by Ctl- mouse dragging */
};
public:
RS_ActionDefault(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDefault() override;
void finish(bool /*updateTB*/ = true ) override{}
void init(int status=0) override;
void keyPressEvent(QKeyEvent* e) override;
void keyReleaseEvent(QKeyEvent* e) override;
void mouseMoveEvent(QMouseEvent* e) override;
void mousePressEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
// void resume() override;
protected:
struct Points;
std::unique_ptr<Points> pPoints;
RS2::SnapRestriction restrBak;
};
#endif

View File

@@ -0,0 +1,290 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<cmath>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondimaligned.h"
#include "rs_dimaligned.h"
#include "rs_dialogfactory.h"
#include "rs_line.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_constructionline.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
#include "rs_debug.h"
RS_ActionDimAligned::RS_ActionDimAligned(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_ActionDimension("Draw aligned dimensions",
container, graphicView) {
actionType=RS2::ActionDimAligned;
reset();
}
RS_ActionDimAligned::~RS_ActionDimAligned() = default;
void RS_ActionDimAligned::reset() {
RS_ActionDimension::reset();
edata.reset(new RS_DimAlignedData(RS_Vector(false),
RS_Vector(false))
);
lastStatus = SetExtPoint1;
RS_DIALOGFACTORY->requestOptions(this, true, true);
}
void RS_ActionDimAligned::trigger() {
RS_ActionDimension::trigger();
preparePreview();
graphicView->moveRelativeZero(data->definitionPoint);
//data->text = getText();
RS_DimAligned* dim =
new RS_DimAligned(container, *data, *edata);
dim->setLayerToActive();
dim->setPenToActive();
dim->update();
container->addEntity(dim);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(dim);
document->endUndoCycle();
}
RS_Vector rz = graphicView->getRelativeZero();
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(rz);
RS_DEBUG->print("RS_ActionDimAligned::trigger():"
" dim added: %d", dim->getId());
}
void RS_ActionDimAligned::preparePreview() {
RS_Vector dirV = RS_Vector::polar(100.,
edata->extensionPoint1.angleTo(
edata->extensionPoint2)
+M_PI_2);
RS_ConstructionLine cl(nullptr,
RS_ConstructionLineData(
edata->extensionPoint2,
edata->extensionPoint2+dirV));
data->definitionPoint =
cl.getNearestPointOnEntity(data->definitionPoint);
}
void RS_ActionDimAligned::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDimAligned::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
case SetExtPoint1:
break;
case SetExtPoint2:
if (edata->extensionPoint1.valid) {
deletePreview();
preview->addEntity(
new RS_Line{preview.get(),edata->extensionPoint1, mouse}
);
drawPreview();
}
break;
case SetDefPoint:
if (edata->extensionPoint1.valid && edata->extensionPoint2.valid) {
deletePreview();
data->definitionPoint = mouse;
preparePreview();
//data->text = getText();
RS_DimAligned* dim = new RS_DimAligned(preview.get(), *data, *edata);
preview->addEntity(dim);
dim->update();
drawPreview();
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDimAligned::mouseMoveEvent end");
}
void RS_ActionDimAligned::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDimAligned::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) return;
RS_Vector pos = e->getCoordinate();
switch (getStatus()) {
case SetExtPoint1:
edata->extensionPoint1 = pos;
graphicView->moveRelativeZero(pos);
setStatus(SetExtPoint2);
break;
case SetExtPoint2:
edata->extensionPoint2 = pos;
graphicView->moveRelativeZero(pos);
setStatus(SetDefPoint);
break;
case SetDefPoint:
data->definitionPoint = pos;
trigger();
reset();
setStatus(SetExtPoint1);
break;
default:
break;
}
}
void RS_ActionDimAligned::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetText: {
setText(c);
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
graphicView->enableCoordinateInput();
}
break;
default:
if (checkCommand("text", c)) {
lastStatus = (Status)getStatus();
graphicView->disableCoordinateInput();
setStatus(SetText);
}
break;
}
}
QStringList RS_ActionDimAligned::getAvailableCommands() {
QStringList cmd;
switch (getStatus()) {
case SetExtPoint1:
case SetExtPoint2:
case SetDefPoint:
cmd += command("text");
break;
default:
break;
}
return cmd;
}
void RS_ActionDimAligned::updateMouseButtonHints() {
switch (getStatus()) {
case SetExtPoint1:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify first extension line origin"),
tr("Cancel"));
break;
case SetExtPoint2:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify second extension line origin"),
tr("Back"));
break;
case SetDefPoint:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify dimension line location"),
tr("Back"));
break;
case SetText:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter dimension text:"), "");
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDimAligned::hideOptions() {
RS_DIALOGFACTORY->requestOptions(this, false);
RS_ActionDimension::hideOptions();
}
void RS_ActionDimAligned::showOptions() {
RS_ActionDimension::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
}
// EOF

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDIMALIGNED_H
#define RS_ACTIONDIMALIGNED_H
#include "rs_actiondimension.h"
struct RS_DimAlignedData;
/**
* This action class can handle user events to draw
* aligned dimensions.
*
* @author Andrew Mustun
*/
class RS_ActionDimAligned : public RS_ActionDimension {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetExtPoint1, /**< Setting the 1st ext point. */
SetExtPoint2, /**< Setting the 2nd ext point. */
SetDefPoint, /**< Setting the common def point */
SetText /**< Setting the text label in command line */
};
public:
RS_ActionDimAligned(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDimAligned() override;
void reset() override;
void trigger() override;
void preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseButtonHints() override;
protected:
/**
* Aligned dimension data.
*/
std::unique_ptr<RS_DimAlignedData> edata;
/** Last status before entering text. */
Status lastStatus;
}
;
#endif

View File

@@ -0,0 +1,431 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2018 A. Stebich (librecad@mail.lordofbikes.de)
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <cmath>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondimangular.h"
#include "rs_dimangular.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_information.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
#include "rs_debug.h"
#include "rs_math.h"
RS_ActionDimAngular::RS_ActionDimAngular(RS_EntityContainer& container,
RS_GraphicView& graphicView) :
RS_ActionDimension( "Draw Angular Dimensions", container, graphicView)
{
reset();
}
RS_ActionDimAngular::~RS_ActionDimAngular() = default;
void RS_ActionDimAngular::reset()
{
RS_ActionDimension::reset();
actionType = RS2::ActionDimAngular;
edata.reset( new RS_DimAngularData( RS_Vector( false),
RS_Vector( false),
RS_Vector( false),
RS_Vector( false)) );
RS_DIALOGFACTORY->requestOptions( this, true, true);
}
void RS_ActionDimAngular::trigger()
{
RS_PreviewActionInterface::trigger();
if (line1.getStartpoint().valid && line2.getStartpoint().valid) {
RS_DimAngular* newEntity {new RS_DimAngular( container,
*data,
*edata)};
newEntity->setLayerToActive();
newEntity->setPenToActive();
newEntity->update();
container->addEntity(newEntity);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(newEntity);
document->endUndoCycle();
}
RS_Vector rz {graphicView->getRelativeZero()};
setStatus( SetLine1);
graphicView->redraw( RS2::RedrawDrawing);
graphicView->moveRelativeZero( rz);
RS_Snapper::finish();
}
else {
RS_DEBUG->print( "RS_ActionDimAngular::trigger: Entity is nullptr\n");
}
}
void RS_ActionDimAngular::mouseMoveEvent(QMouseEvent* e)
{
RS_DEBUG->print( "RS_ActionDimAngular::mouseMoveEvent begin");
switch (getStatus()) {
case SetPos:
if( setData( snapPoint(e))) {
RS_DimAngular *d {new RS_DimAngular( preview.get(), *data, *edata)};
deletePreview();
preview->addEntity(d);
d->update();
drawPreview();
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDimAngular::mouseMoveEvent end");
}
void RS_ActionDimAngular::mouseReleaseEvent(QMouseEvent* e)
{
if (Qt::LeftButton == e->button()) {
switch (getStatus()) {
case SetLine1: {
RS_Entity *en {catchEntity( e, RS2::ResolveAll)};
if (en && RS2::EntityLine == en->rtti()) {
line1 = *dynamic_cast<RS_Line*>(en);
click1 = line1.getNearestPointOnEntity( graphicView->toGraph( e->x(), e->y()));
setStatus(SetLine2);
}
break; }
case SetLine2: {
RS_Entity *en{catchEntity(e, RS2::ResolveAll)};
if (en && en->rtti()==RS2::EntityLine) {
line2 = *dynamic_cast<RS_Line*>(en);
click2 = line2.getNearestPointOnEntity( graphicView->toGraph( e->x(), e->y()));
if( setData( click2, true)) {
graphicView->moveRelativeZero( center);
setStatus(SetPos);
}
}
break; }
case SetPos: {
RS_CoordinateEvent ce( snapPoint( e));
coordinateEvent( &ce);
break; }
}
}
else if (Qt::RightButton == e->button()) {
deletePreview();
init( getStatus() - 1);
}
}
void RS_ActionDimAngular::coordinateEvent(RS_CoordinateEvent* e)
{
if ( ! e) {
return;
}
switch (getStatus()) {
case SetPos:
if( setData( e->getCoordinate())) {
trigger();
reset();
setStatus( SetLine1);
}
break;
default:
break;
}
}
void RS_ActionDimAngular::commandEvent(RS_CommandEvent* e)
{
QString c( e->getCommand().toLower());
if (checkCommand( QStringLiteral( "help"), c)) {
RS_DIALOGFACTORY->commandMessage( msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
// setting new text label:
if (SetText == getStatus()) {
setText( c);
RS_DIALOGFACTORY->requestOptions( this, true, true);
graphicView->enableCoordinateInput();
setStatus( lastStatus);
return;
}
// command: text
if (checkCommand( QStringLiteral( "text"), c)) {
lastStatus = static_cast<Status>(getStatus());
graphicView->disableCoordinateInput();
setStatus( SetText);
}
}
QStringList RS_ActionDimAngular::getAvailableCommands()
{
QStringList cmd;
switch (getStatus()) {
case SetLine1:
case SetLine2:
case SetPos:
cmd += command( QStringLiteral( "text"));
break;
default:
break;
}
return cmd;
}
void RS_ActionDimAngular::showOptions()
{
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions( this, true);
}
void RS_ActionDimAngular::hideOptions()
{
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions( this, false);
}
void RS_ActionDimAngular::updateMouseButtonHints()
{
switch (getStatus()) {
case SetLine1:
RS_DIALOGFACTORY->updateMouseWidget( tr("Select first line"),
tr("Cancel"));
break;
case SetLine2:
RS_DIALOGFACTORY->updateMouseWidget( tr("Select second line"),
tr("Cancel"));
break;
case SetPos:
RS_DIALOGFACTORY->updateMouseWidget( tr("Specify dimension arc line location"),
tr("Cancel"));
break;
case SetText:
RS_DIALOGFACTORY->updateMouseWidget( tr("Enter dimension text:"), "");
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
/**
* Justify one of the angle lines to ensure that the starting point
* of the line has the same angle from the intersection point as the
* selection click point and it is further away than the line end point
*
* @param line A selected line for the dimension
* @param click The click pos which selected the line
* @param center The intersection of the 2 lines to dimension
*/
void RS_ActionDimAngular::justify(RS_Line &line, const RS_Vector &click)
{
RS_Vector vStartPoint( line.getStartpoint());
if( ! RS_Math::equal( vStartPoint.angleTo(center), click.angleTo( center))
|| vStartPoint.distanceTo( center) < click.distanceTo( center)) {
line.reverse();
}
}
/**
* Create a sorted array with angles from the lines intersection point
* to the starting points and their revers angles.
* Ensure, that line1 and line2 are in CCW order.
* Compute an offset for quadrant() method.
*
* @param line A selected line for the dimension
* @param click The click pos which selected the line
* @param center The intersection of the 2 lines to dimension
*/
void RS_ActionDimAngular::lineOrder(const RS_Vector &dimPos)
{
if( ! center.valid) {
return;
}
// starting point angles and selection point angle from intersection point
double a0 {(dimPos - center).angle()};
double a1 {(line1.getStartpoint() - center).angle()};
double a2 {(line2.getStartpoint() - center).angle()};
// swap lines if necessary to ensure CCW order
if( RS_Math::correctAngle2( a1 - a0) > RS_Math::correctAngle2( a2 - a0)) {
RS_Line swapLines( line1);
line1 = line2;
line2 = swapLines;
double swapAngle {a1};
a1 = a2;
a2 = swapAngle;
}
// sorted array with starting point and reverse angles
angles.clear();
angles.push_back( a1);
angles.push_back( RS_Math::correctAngle( a1 + M_PI));
angles.push_back( a2);
angles.push_back( RS_Math::correctAngle( a2 + M_PI));
std::sort( angles.begin(), angles.end());
// find starting quadrant and compute the offset for quadrant() method
int startQuadrant = 0;
for( auto angle : angles) {
if( RS_Math::equal( a1, angle)) {
break;
}
++startQuadrant;
}
quadrantOffset = 0x03 & (4 - startQuadrant);
}
/**
* Find the quadrant of \p angle relative to 1st quadrant.
* When the angle lines are selected, the starting quadrant
* is shifted to become 0 by \p quadrantOffset.
* This is the criterion how the angles dimension is drawn.
*
* @param angle The angle, e.g. mouse or coordinate position
* @return The quadrant of \p angle, relative to the 1st selection quadrant
*/
int RS_ActionDimAngular::quadrant(const double angle)
{
if( 1 > angles.size()) {
return 0;
}
double a1 {RS_Math::correctAngle2( angles.at(0) - angle)};
double a2 {RS_Math::correctAngle2( angles.at(1) - angle)};
int angleQuadrant {0};
if( 0.0 < a1 && 0.0 < a2) {
angleQuadrant = 3;
}
else if( 0.0 >= a1 && 0.0 >= a2) {
angleQuadrant = 1;
}
else if( 0.0 < a1 && 0.0 >= a2) {
angleQuadrant = 2;
}
return (0x03 & (angleQuadrant + quadrantOffset));
}
/**
* On \p mouseMoveEvent, \p mouseReleaseEvent and \p coordinateEvent
* this method sets the dimension data appropriate to the mouse
* cursor/coordinate in \p dimPos.
* When \p calcCenter is true, the intersection point and other static
* values are computed. This is only necessary, when line selection changes,
* e.g. on \p mouseReleaseEvent. For \p mouseMoveEvent calcCenter is false.
*
* @param dimPos The mouse/coordinate position
* @param calcCenter If true, the center and corresponding values are calculated
* @return true If the dimension data were set, false is a parameter is invalid
*/
bool RS_ActionDimAngular::setData(const RS_Vector &dimPos, const bool calcCenter /*= false*/)
{
if( ! line1.getStartpoint().valid || ! line2.getStartpoint().valid) {
return false;
}
if ( ! center.valid || calcCenter) {
RS_VectorSolutions sol = RS_Information::getIntersectionLineLine( &line1, &line2);
center = sol.get(0);
}
if ( ! center.valid) {
return false;
}
if( calcCenter) {
justify( line1, click1);
justify( line2, click2);
lineOrder( dimPos);
}
edata->definitionPoint4 = dimPos;
switch( quadrant( (dimPos - center).angle())) {
default:
case 0:
edata->definitionPoint1 = line1.getEndpoint();
edata->definitionPoint2 = line1.getStartpoint();
edata->definitionPoint3 = line2.getEndpoint();
data->definitionPoint = line2.getStartpoint();
break;
case 1:
edata->definitionPoint1 = line2.getEndpoint();
edata->definitionPoint2 = line2.getStartpoint();
edata->definitionPoint3 = line1.getStartpoint();
data->definitionPoint = line1.getEndpoint();
break;
case 2:
edata->definitionPoint1 = line2.getEndpoint();
edata->definitionPoint2 = line2.getStartpoint();
edata->definitionPoint3 = line1.getEndpoint();
data->definitionPoint = line1.getStartpoint();
break;
case 3:
edata->definitionPoint1 = line2.getStartpoint();
edata->definitionPoint2 = line2.getEndpoint();
edata->definitionPoint3 = line1.getEndpoint();
data->definitionPoint = line1.getStartpoint();
break;
}
return true;
}
// EOF

View File

@@ -0,0 +1,91 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2018 A. Stebich (librecad@mail.lordofbikes.de)
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDIMANGULAR_H
#define RS_ACTIONDIMANGULAR_H
#include "rs_actiondimension.h"
#include "rs_line.h"
struct RS_DimAngularData;
/**
* This action class can handle user events to draw angular dimensions.
*
* @author Andrew Mustun
*/
class RS_ActionDimAngular : public RS_ActionDimension
{
Q_OBJECT
private:
enum Status {
SetLine1, ///< Choose 1st line
SetLine2, ///< Choose 2nd line
SetPos, ///< Choose position
SetText ///< Setting text label in consle
};
public:
RS_ActionDimAngular(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDimAngular() override;
void reset() override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseButtonHints() override;
private:
RS_Line line1; ///< 1st chosen line
RS_Line line2; ///< 2nd chosen line
RS_Vector click1; ///< 1st click pos
RS_Vector click2; ///< 2nd click pos
RS_Vector center; ///< Center of arc
std::unique_ptr<RS_DimAngularData> edata; ///< Data of new dimension
Status lastStatus; ///< Last status before entering text
std::vector<double> angles; ///< Array to sort line angles
int quadrantOffset {0}; ///< Offset on starting quadrant
void justify( RS_Line &line, const RS_Vector &click);
void lineOrder(const RS_Vector &dimPos);
int quadrant(const double angle);
bool setData(const RS_Vector& dimPos, const bool calcCenter = false);
};
#endif

View File

@@ -0,0 +1,321 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<cmath>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondimdiametric.h"
#include "rs_dimdiametric.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_arc.h"
#include "rs_circle.h"
#include "rs_line.h"
#include "rs_coordinateevent.h"
#include "rs_math.h"
#include "rs_preview.h"
#include "rs_debug.h"
RS_ActionDimDiametric::RS_ActionDimDiametric(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_ActionDimension("Draw Diametric Dimensions",
container, graphicView)
, pos(new RS_Vector{})
{
actionType=RS2::ActionDimDiametric;
reset();
}
RS_ActionDimDiametric::~RS_ActionDimDiametric() = default;
void RS_ActionDimDiametric::reset() {
RS_ActionDimension::reset();
edata.reset(new RS_DimDiametricData(RS_Vector{false},
0.0)
);
entity = nullptr;
*pos = {};
RS_DIALOGFACTORY->requestOptions(this, true, true);
}
void RS_ActionDimDiametric::trigger() {
RS_PreviewActionInterface::trigger();
preparePreview();
if (entity) {
RS_DimDiametric* newEntity = nullptr;
newEntity = new RS_DimDiametric(container,
*data,
*edata);
newEntity->setLayerToActive();
newEntity->setPenToActive();
newEntity->update();
container->addEntity(newEntity);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(newEntity);
document->endUndoCycle();
}
RS_Vector rz = graphicView->getRelativeZero();
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(rz);
RS_Snapper::finish();
} else {
RS_DEBUG->print("RS_ActionDimDiametric::trigger:"
" Entity is nullptr\n");
}
}
void RS_ActionDimDiametric::preparePreview() {
if (entity) {
double radius{0.};
RS_Vector center{false};
if (entity->rtti()==RS2::EntityArc) {
RS_Arc* p = static_cast<RS_Arc*>(entity);
radius = p->getRadius();
center = p->getCenter();
} else if (entity->rtti()==RS2::EntityCircle) {
RS_Circle* p = static_cast<RS_Circle*>(entity);
radius = p->getRadius();
center = p->getCenter();
}
double angle = center.angleTo(*pos);
data->definitionPoint.setPolar(radius, angle + M_PI);
data->definitionPoint += center;
edata->definitionPoint.setPolar(radius, angle);
edata->definitionPoint += center;
}
}
void RS_ActionDimDiametric::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDimDiametric::mouseMoveEvent begin");
switch (getStatus()) {
case SetPos:
if (entity) {
*pos = snapPoint(e);
preparePreview();
RS_DimDiametric* d = new RS_DimDiametric(preview.get(), *data, *edata);
deletePreview();
preview->addEntity(d);
d->update();
drawPreview();
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDimDiametric::mouseMoveEvent end");
}
void RS_ActionDimDiametric::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
switch (getStatus()) {
case SetEntity: {
RS_Entity* en = catchEntity(e, RS2::ResolveAll);
if (en) {
if (en->rtti()==RS2::EntityArc ||
en->rtti()==RS2::EntityCircle) {
entity = en;
RS_Vector center;
if (entity->rtti()==RS2::EntityArc) {
center =
static_cast<RS_Arc*>(entity)->getCenter();
} else {
center =
static_cast<RS_Circle*>(entity)->getCenter();
}
graphicView->moveRelativeZero(center);
setStatus(SetPos);
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a circle "
"or arc entity"));
}
}
break;
case SetPos: {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
}
break;
default:
break;
}
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDimDiametric::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) return;
switch (getStatus()) {
case SetPos:
*pos = e->getCoordinate();
trigger();
reset();
setStatus(SetEntity);
break;
default:
break;
}
}
void RS_ActionDimDiametric::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
// setting new text label:
if (getStatus()==SetText) {
setText(c);
RS_DIALOGFACTORY->requestOptions(this, true, true);
graphicView->enableCoordinateInput();
setStatus(lastStatus);
return;
}
// command: text
if (checkCommand("text", c)) {
lastStatus = (Status)getStatus();
graphicView->disableCoordinateInput();
setStatus(SetText);
}
// setting angle
if (getStatus()==SetPos) {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
pos->setPolar(1.0, RS_Math::deg2rad(a));
*pos += data->definitionPoint;
trigger();
reset();
setStatus(SetEntity);
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
return;
}
}
QStringList RS_ActionDimDiametric::getAvailableCommands() {
QStringList cmd;
switch (getStatus()) {
case SetEntity:
case SetPos:
cmd += command("text");
break;
default:
break;
}
return cmd;
}
void RS_ActionDimDiametric::updateMouseButtonHints() {
switch (getStatus()) {
case SetEntity:
RS_DIALOGFACTORY->updateMouseWidget(tr("Select arc or circle entity"),
tr("Cancel"));
break;
case SetPos:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify dimension line location"), tr("Cancel"));
break;
case SetText:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter dimension text:"), "");
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDimDiametric::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
}
void RS_ActionDimDiametric::hideOptions() {
RS_ActionInterface::hideOptions();
//RS_DIALOGFACTORY->requestDimDiametricOptions(edata, false);
RS_DIALOGFACTORY->requestOptions(this, false);
}
// EOF

View File

@@ -0,0 +1,81 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDIMDIAMETRIC_H
#define RS_ACTIONDIMDIAMETRIC_H
#include "rs_actiondimension.h"
struct RS_DimDiametricData;
/**
* This action class can handle user events to draw diametric dimensions.
*
* @author Andrew Mustun
*/
class RS_ActionDimDiametric : public RS_ActionDimension {
Q_OBJECT
private:
enum Status {
SetEntity, /**< Choose entity. */
SetPos, /**< Choose point. */
SetText /**< Setting text label in the command line. */
};
public:
RS_ActionDimDiametric(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDimDiametric() override;
void reset() override;
void trigger() override;
void preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseButtonHints() override;
private:
/** Chosen entity (arc / circle) */
RS_Entity* entity;
/** Chosen position */
std::unique_ptr<RS_Vector> pos;
/** Data of new dimension */
std::unique_ptr<RS_DimDiametricData> edata;
/** Last status before entering text. */
Status lastStatus;
};
#endif

View File

@@ -0,0 +1,163 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include "rs_actiondimaligned.h"
#include "rs_dimension.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
RS_ActionDimension::RS_ActionDimension(const char* name,
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface(name,
container, graphicView) {
reset();
}
RS_ActionDimension::~RS_ActionDimension() = default;
void RS_ActionDimension::reset() {
data.reset(new RS_DimensionData(RS_Vector(false),
RS_Vector(false),
RS_MTextData::VAMiddle,
RS_MTextData::HACenter,
RS_MTextData::Exact,
1.0,
"",
"Standard",
0.0)
);
diameter = false;
}
void RS_ActionDimension::init(int status) {
RS_PreviewActionInterface::init(status);
//reset();
}
void RS_ActionDimension::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void RS_ActionDimension::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true, true);
}
void RS_ActionDimension::updateMouseCursor() {
graphicView->setMouseCursor(RS2::SelectCursor);
}
bool RS_ActionDimension::isDimensionAction(RS2::ActionType type) {
switch(type){
case RS2::ActionDimAligned:
case RS2::ActionDimLinear:
case RS2::ActionDimLinearVer:
case RS2::ActionDimLinearHor:
case RS2::ActionDimAngular:
case RS2::ActionDimDiametric:
case RS2::ActionDimRadial:
return true;
default:
return false;
}
}
QString RS_ActionDimension::getText() const {
if (!data->text.isEmpty()) {
return data->text;
}
QString l = label;
if (l.isEmpty() &&
(diameter==true || !tol1.isEmpty() || !tol2.isEmpty())) {
l = "<>";
}
if (diameter==true) {
l = QChar(0x2205) + l;
}
if (!tol1.isEmpty() || !tol2.isEmpty()) {
l += QString("\\S%1\\%2;").arg(tol1).arg(tol2);
}
return l;
}
void RS_ActionDimension::setText(const QString& t) {
data->text = t;
}
const QString& RS_ActionDimension::getLabel() const{
return label;
}
void RS_ActionDimension::setLabel(const QString& t) {
//data->text = t;
label = t;
}
const QString& RS_ActionDimension::getTol1() const{
return tol1;
}
void RS_ActionDimension::setTol1(const QString& t) {
tol1 = t;
}
const QString& RS_ActionDimension::getTol2() const{
return tol2;
}
void RS_ActionDimension::setTol2(const QString& t) {
tol2 = t;
}
bool RS_ActionDimension::getDiameter() const {
return diameter;
}
void RS_ActionDimension::setDiameter(bool d) {
diameter = d;
}
// EOF

View File

@@ -0,0 +1,92 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDIMENSION_H
#define RS_ACTIONDIMENSION_H
#include "rs_previewactioninterface.h"
struct RS_DimensionData;
/**
* Base class for dimension actions.
*
* @author Andrew Mustun
*/
class RS_ActionDimension : public RS_PreviewActionInterface {
Q_OBJECT
public:
RS_ActionDimension(const char* name,
RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDimension() override;
virtual void reset();
void init(int status=0) override;
void hideOptions() override;
void showOptions() override;
void updateMouseCursor() override;
// void updateToolBar() override;
QString getText() const;
void setText(const QString& t);
const QString& getLabel() const;
void setLabel(const QString& t);
const QString& getTol1() const;
void setTol1(const QString& t);
const QString& getTol2() const;
void setTol2(const QString& t);
bool getDiameter() const;
void setDiameter(bool d);
static bool isDimensionAction(RS2::ActionType type);
protected:
/**
* Generic dimension data.
*/
std::unique_ptr<RS_DimensionData> data;
QString label;
QString tol1;
QString tol2;
bool diameter;
/**
* Commands.
*/
/*
QString cmdText;
QString cmdText2;
*/
};
#endif

View File

@@ -0,0 +1,241 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<vector>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondimleader.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_leader.h"
#include "rs_line.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDimLeader::Points {
std::vector<RS_Vector> points;
};
RS_ActionDimLeader::RS_ActionDimLeader(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw leaders",
container, graphicView)
, pPoints(new Points{})
{
actionType=RS2::ActionDimLeader;
reset();
}
RS_ActionDimLeader::~RS_ActionDimLeader() = default;
void RS_ActionDimLeader::reset() {
//data = RS_LineData(RS_Vector(false), RS_Vector(false));
//start = RS_Vector(false);
//history.clear();
pPoints->points.clear();
}
void RS_ActionDimLeader::init(int status) {
RS_PreviewActionInterface::init(status);
reset();
}
void RS_ActionDimLeader::trigger() {
RS_PreviewActionInterface::trigger();
if (pPoints->points.size()){
RS_Leader* leader = new RS_Leader(container, RS_LeaderData(true));
leader->setLayerToActive();
leader->setPenToActive();
for(const auto& vp: pPoints->points){
leader->addVertex(vp);
}
container->addEntity(leader);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(leader);
document->endUndoCycle();
}
deletePreview();
RS_Vector rz = graphicView->getRelativeZero();
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(rz);
//drawSnapper();
RS_DEBUG->print("RS_ActionDimLeader::trigger(): leader added: %d",
leader->getId());
}
}
void RS_ActionDimLeader::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDimLeader::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
if (getStatus()==SetEndpoint && pPoints->points.size()) {
deletePreview();
// fill in lines that were already set:
RS_Vector last(false);
for(const auto& v: pPoints->points){
if (last.valid) {
preview->addEntity(new RS_Line{preview.get(), last, v});
}
last = v;
}
if (pPoints->points.size() ) {
RS_Vector const& p = pPoints->points.back();
preview->addEntity(new RS_Line{preview.get(), p, mouse});
}
drawPreview();
}
RS_DEBUG->print("RS_ActionDimLeader::mouseMoveEvent end");
}
void RS_ActionDimLeader::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
if (getStatus()==SetEndpoint) {
trigger();
reset();
setStatus(SetStartpoint);
} else {
deletePreview();
init(getStatus()-1);
}
}
}
void RS_ActionDimLeader::keyPressEvent(QKeyEvent* e) {
if (getStatus()==SetEndpoint && e->key()==Qt::Key_Enter) {
trigger();
reset();
setStatus(SetStartpoint);
}
}
void RS_ActionDimLeader::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) {
return;
}
RS_Vector mouse = e->getCoordinate();
switch (getStatus()) {
case SetStartpoint:
//data.startpoint = mouse;
pPoints->points.clear();
pPoints->points.push_back(mouse);
//start = data.startpoint;
setStatus(SetEndpoint);
graphicView->moveRelativeZero(mouse);
break;
case SetEndpoint:
//data.endpoint = mouse;
pPoints->points.push_back(mouse);
//trigger();
//data.startpoint = data.endpoint;
graphicView->moveRelativeZero(mouse);
break;
default:
break;
}
}
void RS_ActionDimLeader::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
// enter to finish
if (c=="") {
trigger();
reset();
setStatus(SetStartpoint);
//finish();
}
}
QStringList RS_ActionDimLeader::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void RS_ActionDimLeader::updateMouseButtonHints() {
switch (getStatus()) {
case SetStartpoint:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify target point"),
tr("Cancel"));
break;
case SetEndpoint:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify next point"),
tr("Finish"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDimLeader::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDIMLEADER_H
#define RS_ACTIONDIMLEADER_H
#include<memory>
#include "rs_previewactioninterface.h"
class RS_Leader;
/**
* This action class can handle user events to draw
* leaders (arrows).
*
* @author Andrew Mustun
*/
class RS_ActionDimLeader : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetStartpoint, /**< Setting the startpoint. */
SetEndpoint /**< Setting the endpoint. */
};
public:
RS_ActionDimLeader(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDimLeader() override;
void reset();
void init(int status=0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void keyPressEvent(QKeyEvent*) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
/**
* Leader entity.
*/
RS_Leader* leader;
/**
* Points set so far.
*/
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,332 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<cmath>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondimlinear.h"
#include "rs_dimlinear.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_constructionline.h"
#include "rs_line.h"
#include "rs_coordinateevent.h"
#include "rs_math.h"
#include "rs_preview.h"
#include "rs_debug.h"
/**
* Constructor.
*
* @param angle Initial angle in rad.
* @param fixedAngle true: The user can't change the angle.
* false: The user can change the angle in a option widget.
*/
RS_ActionDimLinear::RS_ActionDimLinear(RS_EntityContainer& container,
RS_GraphicView& graphicView,
double angle,
bool _fixedAngle, RS2::ActionType /*type*/)
:RS_ActionDimension("Draw linear dimensions",
container, graphicView)
,edata(new RS_DimLinearData(RS_Vector(0., 0.), RS_Vector(0., 0.), angle, 0.))
,fixedAngle(_fixedAngle)
,lastStatus(SetExtPoint1)
{
//TODO: fix dim linear type logic: whether it's for linear only, or should cover horizontal/vertical dim types
actionType=RS2::ActionDimLinear;
reset();
}
RS_ActionDimLinear::~RS_ActionDimLinear() = default;
void RS_ActionDimLinear::reset() {
RS_ActionDimension::reset();
edata.reset(new RS_DimLinearData(RS_Vector(false),
RS_Vector(false),
(fixedAngle ? edata->angle : 0.0), 0.0)
);
RS_DIALOGFACTORY->requestOptions(this, true, true);
}
void RS_ActionDimLinear::trigger() {
RS_ActionDimension::trigger();
preparePreview();
RS_DimLinear* dim = new RS_DimLinear(container, *data, *edata);
dim->setLayerToActive();
dim->setPenToActive();
dim->update();
container->addEntity(dim);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(dim);
document->endUndoCycle();
}
RS_Vector rz = graphicView->getRelativeZero();
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(rz);
RS_DEBUG->print("RS_ActionDimLinear::trigger():"
" dim added: %d", dim->getId());
}
void RS_ActionDimLinear::preparePreview() {
RS_Vector dirV = RS_Vector::polar(100., edata->angle+M_PI_2);
RS_ConstructionLine cl(
NULL,
RS_ConstructionLineData(
edata->extensionPoint2,
edata->extensionPoint2+dirV));
data->definitionPoint =
cl.getNearestPointOnEntity(data->definitionPoint);
}
void RS_ActionDimLinear::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDimLinear::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
case SetExtPoint1:
break;
case SetExtPoint2:
if (edata->extensionPoint1.valid) {
deletePreview();
preview->addEntity(new RS_Line{preview.get(),
edata->extensionPoint1, mouse});
drawPreview();
}
break;
case SetDefPoint:
if (edata->extensionPoint1.valid && edata->extensionPoint2.valid) {
deletePreview();
data->definitionPoint = mouse;
preparePreview();
RS_DimLinear* dim = new RS_DimLinear(preview.get(), *data, *edata);
preview->addEntity(dim);
dim->update();
drawPreview();
}
break;
}
RS_DEBUG->print("RS_ActionDimLinear::mouseMoveEvent end");
}
void RS_ActionDimLinear::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDimLinear::coordinateEvent(RS_CoordinateEvent* e) {
if (e==NULL) {
return;
}
RS_Vector pos = e->getCoordinate();
switch (getStatus()) {
case SetExtPoint1:
edata->extensionPoint1 = pos;
graphicView->moveRelativeZero(pos);
setStatus(SetExtPoint2);
break;
case SetExtPoint2:
edata->extensionPoint2 = pos;
graphicView->moveRelativeZero(pos);
setStatus(SetDefPoint);
break;
case SetDefPoint:
data->definitionPoint = pos;
trigger();
reset();
setStatus(SetExtPoint1);
break;
default:
break;
}
}
double RS_ActionDimLinear::getAngle() const{
return edata->angle;
}
void RS_ActionDimLinear::setAngle(double a) {
edata->angle = a;
}
bool RS_ActionDimLinear::hasFixedAngle() const{
return fixedAngle;
}
void RS_ActionDimLinear::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetText:
setText(c);
RS_DIALOGFACTORY->requestOptions(this, true, true);
graphicView->enableCoordinateInput();
setStatus(lastStatus);
break;
case SetAngle: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
setAngle(RS_Math::deg2rad(a));
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
default:
lastStatus = (Status)getStatus();
deletePreview();
if (checkCommand("text", c)) {
graphicView->disableCoordinateInput();
setStatus(SetText);
return;
} else if (!fixedAngle && (checkCommand("angle", c))) {
setStatus(SetAngle);
}
break;
}
}
QStringList RS_ActionDimLinear::getAvailableCommands() {
QStringList cmd;
switch (getStatus()) {
case SetExtPoint1:
case SetExtPoint2:
case SetDefPoint:
cmd += command("text");
if (!fixedAngle) {
cmd += command("angle");
}
break;
default:
break;
}
return cmd;
}
void RS_ActionDimLinear::updateMouseButtonHints() {
switch (getStatus()) {
case SetExtPoint1:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify first extension line origin"),
tr("Cancel"));
break;
case SetExtPoint2:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify second extension line origin"),
tr("Back"));
break;
case SetDefPoint:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify dimension line location"),
tr("Back"));
break;
case SetText:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter dimension text:"), "");
break;
case SetAngle:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Enter dimension line angle:"), "");
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDimLinear::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true, true);
}
void RS_ActionDimLinear::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
// EOF

View File

@@ -0,0 +1,107 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDIMLINEAR_H
#define RS_ACTIONDIMLINEAR_H
#include "rs_actiondimension.h"
struct RS_DimLinearData;
/**
* This action class can handle user events to draw
* aligned dimensions.
*
* @author Andrew Mustun
*/
class RS_ActionDimLinear : public RS_ActionDimension {
Q_OBJECT
public:
/**
* Varitions of this action.
*/
enum Variation {
AnyAngle,
Horizontal,
Vertical
};
/**
* Action States.
*/
enum Status {
SetExtPoint1, /**< Setting the 1st ext point. */
SetExtPoint2, /**< Setting the 2nd ext point. */
SetDefPoint, /**< Setting the common def point. */
SetText, /**< Setting the text label in the command line. */
SetAngle /**< Setting the angle in the command line. */
};
public:
RS_ActionDimLinear(RS_EntityContainer& container,
RS_GraphicView& graphicView,
double angle=0.0, bool fixedAngle=false,
RS2::ActionType type = RS2::ActionDimLinear);
~RS_ActionDimLinear() override;
void reset() override;
void trigger() override;
void preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseButtonHints() override;
double getAngle() const;
void setAngle(double a);
bool hasFixedAngle() const;
protected:
/**
* Aligned dimension data.
*/
std::unique_ptr<RS_DimLinearData> edata;
/**
* Is the angle fixed?
*/
bool fixedAngle;
/** Last status before entering text or angle. */
Status lastStatus;
};
#endif

View File

@@ -0,0 +1,317 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondimradial.h"
#include "rs_dimradial.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_arc.h"
#include "rs_circle.h"
#include "rs_coordinateevent.h"
#include "rs_math.h"
#include "rs_preview.h"
#include "rs_debug.h"
RS_ActionDimRadial::RS_ActionDimRadial(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_ActionDimension("Draw Radial Dimensions",
container, graphicView)
,entity(nullptr)
,pos(new RS_Vector{})
,lastStatus(SetEntity)
{
actionType=RS2::ActionDimRadial;
reset();
}
RS_ActionDimRadial::~RS_ActionDimRadial() = default;
void RS_ActionDimRadial::reset() {
RS_ActionDimension::reset();
edata.reset(new RS_DimRadialData{{}, 0.0});
entity = nullptr;
*pos = {};
lastStatus = SetEntity;
RS_DIALOGFACTORY->requestOptions(this, true, true);
}
void RS_ActionDimRadial::trigger() {
RS_ActionDimension::trigger();
preparePreview();
if (entity) {
RS_DimRadial* newEntity = nullptr;
newEntity = new RS_DimRadial(container,
*data,
*edata);
newEntity->setLayerToActive();
newEntity->setPenToActive();
newEntity->update();
container->addEntity(newEntity);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(newEntity);
document->endUndoCycle();
}
RS_Vector rz = graphicView->getRelativeZero();
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(rz);
RS_Snapper::finish();
}
else {
RS_DEBUG->print("RS_ActionDimRadial::trigger:"
" Entity is nullptr\n");
}
}
void RS_ActionDimRadial::preparePreview() {
if (entity) {
double angle = data->definitionPoint.angleTo(*pos);
double radius=0.0;
if (entity->rtti()==RS2::EntityArc) {
radius = ((RS_Arc*)entity)->getRadius();
} else if (entity->rtti()==RS2::EntityCircle) {
radius = ((RS_Circle*)entity)->getRadius();
}
edata->definitionPoint.setPolar(radius, angle);
edata->definitionPoint += data->definitionPoint;
}
}
void RS_ActionDimRadial::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDimRadial::mouseMoveEvent begin");
//RS_Vector mouse(graphicView->toGraphX(e->x()),
// graphicView->toGraphY(e->y()));
switch (getStatus()) {
case SetPos:
if (entity) {
*pos = snapPoint(e);
preparePreview();
RS_DimRadial* d = new RS_DimRadial(preview.get(), *data, *edata);
deletePreview();
preview->addEntity(d);
d->update();
drawPreview();
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDimRadial::mouseMoveEvent end");
}
void RS_ActionDimRadial::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
switch (getStatus()) {
case SetEntity: {
RS_Entity* en = catchEntity(e, RS2::ResolveAll);
if (en) {
if (en->rtti()==RS2::EntityArc ||
en->rtti()==RS2::EntityCircle) {
entity = en;
if (entity->rtti()==RS2::EntityArc) {
data->definitionPoint =
static_cast<RS_Arc*>(entity)->getCenter();
} else if (entity->rtti()==RS2::EntityCircle) {
data->definitionPoint =
static_cast<RS_Circle*>(entity)->getCenter();
}
graphicView->moveRelativeZero(data->definitionPoint);
setStatus(SetPos);
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a circle "
"or arc entity"));
}
}
}
break;
case SetPos: {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
}
break;
default:
break;
}
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDimRadial::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) return;
switch (getStatus()) {
case SetPos:
*pos = e->getCoordinate();
trigger();
reset();
setStatus(SetEntity);
break;
default:
break;
}
}
void RS_ActionDimRadial::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
// setting new text label:
if (getStatus()==SetText) {
setText(c);
RS_DIALOGFACTORY->requestOptions(this, true, true);
graphicView->enableCoordinateInput();
setStatus(lastStatus);
return;
}
// command: text
if (checkCommand("text", c)) {
lastStatus = (Status)getStatus();
graphicView->disableCoordinateInput();
setStatus(SetText);
}
// setting angle
if (getStatus()==SetPos) {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
pos->setPolar(1.0, RS_Math::deg2rad(a));
*pos += data->definitionPoint;
trigger();
reset();
setStatus(SetEntity);
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
return;
}
}
QStringList RS_ActionDimRadial::getAvailableCommands() {
QStringList cmd;
switch (getStatus()) {
case SetEntity:
case SetPos:
cmd += command("text");
break;
default:
break;
}
return cmd;
}
void RS_ActionDimRadial::updateMouseButtonHints() {
switch (getStatus()) {
case SetEntity:
RS_DIALOGFACTORY->updateMouseWidget(tr("Select arc or circle entity"),
tr("Cancel"));
break;
case SetPos:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify dimension line position or enter angle:"),
tr("Cancel"));
break;
case SetText:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter dimension text:"), "");
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDimRadial::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
//RS_DIALOGFACTORY->requestDimRadialOptions(edata, true);
}
void RS_ActionDimRadial::hideOptions() {
RS_ActionInterface::hideOptions();
//RS_DIALOGFACTORY->requestDimRadialOptions(edata, false);
RS_DIALOGFACTORY->requestOptions(this, false);
}
// EOF

View File

@@ -0,0 +1,83 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDIMRADIAL_H
#define RS_ACTIONDIMRADIAL_H
#include "rs_actiondimension.h"
struct RS_DimRadialData;
/**
* This action class can handle user events to draw radial dimensions.
*
* @author Andrew Mustun
*/
class RS_ActionDimRadial : public RS_ActionDimension {
Q_OBJECT
private:
enum Status {
SetEntity, /**< Choose entity. */
SetPos, /**< Choose point. */
SetText /**< Setting text label in the command line. */
};
public:
RS_ActionDimRadial(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDimRadial() override;
void reset() override;
void trigger() override;
void preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseButtonHints() override;
private:
/** Chosen entity (arc / circle) */
RS_Entity* entity;
/** Chosen position */
std::unique_ptr<RS_Vector> pos;
/** Data of new dimension */
std::unique_ptr<RS_DimRadialData> edata;
/** Last status before entering text. */
Status lastStatus;
};
#endif

View File

@@ -0,0 +1,405 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<cmath>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawarc.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commands.h"
#include "rs_commandevent.h"
#include "rs_arc.h"
#include "rs_circle.h"
#include "rs_coordinateevent.h"
#include "rs_math.h"
#include "rs_preview.h"
#include "rs_debug.h"
RS_ActionDrawArc::RS_ActionDrawArc(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw arcs",
container, graphicView)
,data(new RS_ArcData())
{
actionType= RS2::ActionDrawArc;
reset();
}
RS_ActionDrawArc::~RS_ActionDrawArc() = default;
void RS_ActionDrawArc::reset() {
if (data->reversed) {
data.reset(new RS_ArcData(RS_Vector(false),
0.0,
2.*M_PI, 0.0,
true));
} else {
data.reset(new RS_ArcData(RS_Vector(false),
0.0,
0.0, 2.*M_PI,
false));
}
}
void RS_ActionDrawArc::init(int status) {
RS_PreviewActionInterface::init(status);
reset();
}
void RS_ActionDrawArc::trigger() {
RS_PreviewActionInterface::trigger();
RS_Arc* arc = new RS_Arc(container,
*data);
arc->setLayerToActive();
arc->setPenToActive();
container->addEntity(arc);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(arc);
document->endUndoCycle();
}
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(arc->getCenter());
setStatus(SetCenter);
reset();
RS_DEBUG->print("RS_ActionDrawArc::trigger(): arc added: %d",
arc->getId());
}
void RS_ActionDrawArc::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawArc::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
case SetCenter:
data->center = mouse;
break;
case SetRadius:
if (data->center.valid) {
data->radius = data->center.distanceTo(mouse);
deletePreview();
preview->addEntity(new RS_Circle(preview.get(),
{data->center, data->radius}));
drawPreview();
}
break;
case SetAngle1:
data->angle1 = data->center.angleTo(mouse);
if (data->reversed) {
data->angle2 = RS_Math::correctAngle(data->angle1-M_PI/3);
} else {
data->angle2 = RS_Math::correctAngle(data->angle1+M_PI/3);
}
deletePreview();
preview->addEntity(new RS_Arc(preview.get(),
*data));
drawPreview();
break;
case SetAngle2:
data->angle2 = data->center.angleTo(mouse);
deletePreview();
preview->addEntity(new RS_Arc(preview.get(),
*data));
drawPreview();
break;
case SetIncAngle:
data->angle2 = data->angle1 + data->center.angleTo(mouse);
deletePreview();
preview->addEntity(new RS_Arc(preview.get(),
*data));
drawPreview();
break;
case SetChordLength: {
double x = data->center.distanceTo(mouse);
if (fabs(x/(2*data->radius))<=1.0) {
data->angle2 = data->angle1 + asin(x/(2*data->radius)) * 2;
deletePreview();
preview->addEntity(new RS_Arc(preview.get(),
*data));
drawPreview();
}
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDrawArc::mouseMoveEvent end");
}
void RS_ActionDrawArc::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawArc::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) return;
RS_Vector mouse = e->getCoordinate();
switch (getStatus()) {
case SetCenter:
data->center = mouse;
graphicView->moveRelativeZero(mouse);
setStatus(SetRadius);
break;
case SetRadius:
if (data->center.valid) {
data->radius = data->center.distanceTo(mouse);
}
setStatus(SetAngle1);
break;
case SetAngle1:
data->angle1 = data->center.angleTo(mouse);
setStatus(SetAngle2);
break;
case SetAngle2:
data->angle2 = data->center.angleTo(mouse);
trigger();
break;
case SetIncAngle:
data->angle2 = data->angle1 + data->center.angleTo(mouse);
trigger();
break;
case SetChordLength: {
double x = data->center.distanceTo(mouse);
if (fabs(x/(2*data->radius))<=1.0) {
data->angle2 = data->angle1 + asin(x/(2*data->radius)) * 2;
trigger();
}
}
break;
default:
break;
}
}
void RS_ActionDrawArc::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (RS_COMMANDS->checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
if (RS_COMMANDS->checkCommand("reversed", c)) {
e->accept();
setReversed(!isReversed());
RS_DIALOGFACTORY->requestOptions(this, true, true);
return;
}
switch (getStatus()) {
case SetRadius: {
bool ok;
double r = RS_Math::eval(c, &ok);
if (ok) {
data->radius = r;
setStatus(SetAngle1);
e->accept();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle1: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
data->angle1 = RS_Math::deg2rad(a);
e->accept();
setStatus(SetAngle2);
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle2: {
if (RS_COMMANDS->checkCommand("angle", c)) {
setStatus(SetIncAngle);
} else if (RS_COMMANDS->checkCommand("chord length", c)) {
setStatus(SetChordLength);
} else {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
data->angle2 = RS_Math::deg2rad(a);
e->accept();
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
}
break;
case SetIncAngle: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
data->angle2 = data->angle1 + RS_Math::deg2rad(a);
e->accept();
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetChordLength: {
bool ok;
double l = RS_Math::eval(c, &ok);
if (ok) {
if (fabs(l/(2*data->radius))<=1.0) {
data->angle2 = data->angle1 + asin(l/(2*data->radius)) * 2;
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid chord length"));
e->accept();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
default:
break;
}
}
QStringList RS_ActionDrawArc::getAvailableCommands() {
QStringList cmd;
cmd += RS_COMMANDS->command("reversed");
return cmd;
}
void RS_ActionDrawArc::updateMouseButtonHints() {
switch (getStatus()) {
case SetCenter:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify center"), tr("Cancel"));
break;
case SetRadius:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify radius"), tr("Back"));
break;
case SetAngle1:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify start angle:"), tr("Back"));
break;
case SetAngle2:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify end angle or [angle/chord length]"),
tr("Back"));
break;
case SetIncAngle:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify included angle:"),
tr("Back"));
break;
case SetChordLength:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify chord length:"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawArc::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
}
void RS_ActionDrawArc::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void RS_ActionDrawArc::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
bool RS_ActionDrawArc::isReversed() const{
return data->reversed;
}
void RS_ActionDrawArc::setReversed(bool r) const{
data->reversed = r;
}
// EOF

View File

@@ -0,0 +1,96 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWARC_H
#define RS_ACTIONDRAWARC_H
#include "rs_previewactioninterface.h"
struct RS_ArcData;
/**
* This action class can handle user events to draw
* simple arcs with the center, radius, start- and endangle given.
*
* @author Andrew Mustun
*/
class RS_ActionDrawArc : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetCenter, /**< Setting the center point. */
SetRadius, /**< Setting the radius. */
SetAngle1, /**< Setting the startpoint. */
SetAngle2, /**< Setting the endpoint. */
SetIncAngle, /**< Setting the included angle. */
SetChordLength /**< Setting carc chord length. */
};
public:
RS_ActionDrawArc(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawArc() override;
void reset();
void init(int status=0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
bool isReversed() const;
void setReversed(bool r) const;
protected:
/**
* Arc data defined so far.
*/
std::unique_ptr<RS_ArcData> data;
/**
* Commands
*/
/*QString cmdReversed;
QString cmdReversed2;
QString cmdReversed3;
*/
};
#endif

View File

@@ -0,0 +1,262 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawarc3p.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_actiondrawarc.h"
#include "rs_commands.h"
#include "rs_commandevent.h"
#include "rs_arc.h"
#include "rs_line.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
struct RS_ActionDrawArc3P::Points {
RS_ArcData data;
/**
* 1st point.
*/
RS_Vector point1;
/**
* 2nd point.
*/
RS_Vector point2;
/**
* 3rd point.
*/
RS_Vector point3;
};
RS_ActionDrawArc3P::RS_ActionDrawArc3P(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw arcs 3P",
container, graphicView)
, pPoints(new Points())
{
actionType=RS2::ActionDrawArc3P;
reset();
}
RS_ActionDrawArc3P::~RS_ActionDrawArc3P() = default;
void RS_ActionDrawArc3P::reset() {
pPoints.reset(new Points{});
}
void RS_ActionDrawArc3P::init(int status) {
RS_PreviewActionInterface::init(status);
//reset();
}
void RS_ActionDrawArc3P::trigger() {
RS_PreviewActionInterface::trigger();
preparePreview();
if (pPoints->data.isValid()) {
RS_Arc* arc = new RS_Arc{container, pPoints->data};
arc->setLayerToActive();
arc->setPenToActive();
container->addEntity(arc);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(arc);
document->endUndoCycle();
}
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(arc->getEndpoint());
setStatus(SetPoint1);
reset();
} else {
//RS_DIALOGFACTORY->requestWarningDialog(tr("Invalid arc data."));
RS_DIALOGFACTORY->commandMessage(tr("Invalid arc data."));
}
}
void RS_ActionDrawArc3P::preparePreview() {
pPoints->data = {};
if (pPoints->point1.valid && pPoints->point2.valid && pPoints->point3.valid) {
RS_Arc arc(NULL, pPoints->data);
bool suc = arc.createFrom3P(pPoints->point1, pPoints->point2, pPoints->point3);
if (suc) {
pPoints->data = arc.getData();
}
}
}
void RS_ActionDrawArc3P::mouseMoveEvent(QMouseEvent* e) {
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
case SetPoint1:
pPoints->point1 = mouse;
break;
case SetPoint2:
pPoints->point2 = mouse;
if (pPoints->point1.valid) {
RS_Line* line = new RS_Line{preview.get(), pPoints->point1, pPoints->point2};
deletePreview();
preview->addEntity(line);
drawPreview();
}
break;
case SetPoint3:
pPoints->point3 = mouse;
preparePreview();
if (pPoints->data.isValid()) {
RS_Arc* arc = new RS_Arc(preview.get(), pPoints->data);
deletePreview();
preview->addEntity(arc);
drawPreview();
}
break;
default:
break;
}
}
void RS_ActionDrawArc3P::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawArc3P::coordinateEvent(RS_CoordinateEvent* e) {
if (e==NULL) {
return;
}
RS_Vector mouse = e->getCoordinate();
switch (getStatus()) {
case SetPoint1:
pPoints->point1 = mouse;
graphicView->moveRelativeZero(mouse);
setStatus(SetPoint2);
break;
case SetPoint2:
pPoints->point2 = mouse;
graphicView->moveRelativeZero(mouse);
setStatus(SetPoint3);
break;
case SetPoint3:
pPoints->point3 = mouse;
trigger();
break;
default:
break;
}
}
void RS_ActionDrawArc3P::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
if (RS_COMMANDS->checkCommand("center", c, rtti())) {
finish(false);
graphicView->setCurrentAction(
new RS_ActionDrawArc(*container, *graphicView));
}
}
QStringList RS_ActionDrawArc3P::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void RS_ActionDrawArc3P::updateMouseButtonHints() {
switch (getStatus()) {
case SetPoint1:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify startpoint or [center]"),
tr("Cancel"));
break;
case SetPoint2:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify second point"), tr("Back"));
break;
case SetPoint3:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify endpoint"), tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawArc3P::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWARC3P_H
#define RS_ACTIONDRAWARC3P_H
#include "rs_previewactioninterface.h"
struct RS_ArcData;
/**
* This action class can handle user events to draw
* arcs with three points given.
*
* @author Andrew Mustun
*/
class RS_ActionDrawArc3P : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetPoint1, /**< Setting the 1st point. */
SetPoint2, /**< Setting the 2nd point. */
SetPoint3 /**< Setting the 3rd point. */
};
public:
RS_ActionDrawArc3P(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawArc3P() override;
void reset();
void init(int status=0) override;
void trigger() override;
void preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
/**
* Arc data defined so far.
*/
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,286 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<cmath>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawarctangential.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_arc.h"
#include "ui_qg_arctangentialoptions.h"
#include "rs_coordinateevent.h"
#include "rs_math.h"
#include "rs_preview.h"
#include "rs_debug.h"
RS_ActionDrawArcTangential::RS_ActionDrawArcTangential(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw arcs tangential",
container, graphicView)
, point(new RS_Vector{})
, data(new RS_ArcData{})
{
actionType=RS2::ActionDrawArcTangential;
reset();
}
RS_ActionDrawArcTangential::~RS_ActionDrawArcTangential() = default;
void RS_ActionDrawArcTangential::reset() {
baseEntity = nullptr;
isStartPoint = false;
*point = {};
}
void RS_ActionDrawArcTangential::setByRadius(bool status) {
byRadius=status;
}
void RS_ActionDrawArcTangential::init(int status) {
RS_PreviewActionInterface::init(status);
//reset();
}
void RS_ActionDrawArcTangential::trigger() {
RS_PreviewActionInterface::trigger();
if (!(point->valid && baseEntity)) {
RS_DEBUG->print("RS_ActionDrawArcTangential::trigger: "
"conditions not met");
return;
}
preparePreview();
RS_Arc* arc = new RS_Arc(container, *data);
arc->setLayerToActive();
arc->setPenToActive();
container->addEntity(arc);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(arc);
document->endUndoCycle();
}
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(arc->getCenter());
setStatus(SetBaseEntity);
reset();
}
void RS_ActionDrawArcTangential::preparePreview() {
if (baseEntity && point->valid) {
RS_Vector startPoint;
double direction;
if (isStartPoint) {
startPoint = baseEntity->getStartpoint();
direction = RS_Math::correctAngle(baseEntity->getDirection1()+M_PI);
} else {
startPoint = baseEntity->getEndpoint();
direction = RS_Math::correctAngle(baseEntity->getDirection2()+M_PI);
}
RS_Arc arc(nullptr, RS_ArcData());
bool suc;
if (byRadius) {
suc = arc.createFrom2PDirectionRadius(startPoint, *point, direction, data->radius);
} else {
suc = arc.createFrom2PDirectionAngle(startPoint, *point, direction, angleLength);
}
if (suc) {
data.reset(new RS_ArcData(arc.getData()));
if (byRadius)
RS_DIALOGFACTORY->updateArcTangentialOptions(arc.getAngleLength()*180./M_PI,true);
else
RS_DIALOGFACTORY->updateArcTangentialOptions(arc.getRadius(),false);
}
}
}
void RS_ActionDrawArcTangential::mouseMoveEvent(QMouseEvent* e) {
if(getStatus() == SetEndAngle) {
*point = snapPoint(e);
preparePreview();
if (data->isValid()) {
RS_Arc* arc = new RS_Arc(preview.get(), *data);
deletePreview();
preview->addEntity(arc);
drawPreview();
}
}
}
void RS_ActionDrawArcTangential::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
switch (getStatus()) {
// set base entity:
case SetBaseEntity: {
RS_Vector coord = graphicView->toGraph(e->x(), e->y());
RS_Entity* entity = catchEntity(coord, RS2::ResolveAll);
if (entity) {
if (entity->isAtomic()) {
baseEntity = static_cast<RS_AtomicEntity*>(entity);
if (baseEntity->getStartpoint().distanceTo(coord) <
baseEntity->getEndpoint().distanceTo(coord)) {
isStartPoint = true;
} else {
isStartPoint = false;
}
setStatus(SetEndAngle);
updateMouseButtonHints();
}
}
}
break;
// set angle (point that defines the angle)
case SetEndAngle: {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
}
break;
}
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawArcTangential::coordinateEvent(RS_CoordinateEvent* e) {
if (e==nullptr) {
return;
}
RS_Vector mouse = e->getCoordinate();
switch (getStatus()) {
case SetBaseEntity:
break;
case SetEndAngle:
*point = mouse;
trigger();
break;
default:
break;
}
}
void RS_ActionDrawArcTangential::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
}
QStringList RS_ActionDrawArcTangential::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void RS_ActionDrawArcTangential::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
updateMouseButtonHints();
}
void RS_ActionDrawArcTangential::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void RS_ActionDrawArcTangential::updateMouseButtonHints() {
switch (getStatus()) {
case SetBaseEntity:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify base entity"),
tr("Cancel"));
break;
case SetEndAngle:
if(byRadius) {
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify end angle"), tr("Back"));
} else {
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify end point"), tr("Back"));
}
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawArcTangential::updateMouseCursor() {
graphicView->setMouseCursor(RS2::SelectCursor);
}
void RS_ActionDrawArcTangential::setRadius(double r){
data->radius = r;
}
double RS_ActionDrawArcTangential::getRadius() const {
return data->radius;
}
// EOF

View File

@@ -0,0 +1,114 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWARCTANGENTIAL_H
#define RS_ACTIONDRAWARCTANGENTIAL_H
#include "rs_previewactioninterface.h"
class RS_AtomicEntity;
struct RS_ArcData;
/**
* This action class can handle user events to draw
* arcs with three points given.
*
* @author Andrew Mustun
*/
class RS_ActionDrawArcTangential : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetBaseEntity, /**< Setting base entity. */
SetEndAngle /**< Setting end angle. */
};
public:
RS_ActionDrawArcTangential(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawArcTangential() override;
void reset();
void init(int status=0) override;
void trigger() override;
void preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
void setRadius(double r);
double getRadius() const;
void setAngle(double r) {
angleLength= r;
}
double getAngle() const {
return angleLength;
}
void setByRadius(bool status=true);
bool getByRadius() const{
return byRadius;
}
protected:
/**
* Base entity.
*/
RS_AtomicEntity* baseEntity;
/**
* Start point of base entity clicked?
*/
bool isStartPoint;
/**
* Point that determines end angle.
*/
std::unique_ptr<RS_Vector> point;
/**
* Arc data calculated.
*/
std::unique_ptr<RS_ArcData> data;
private:
double angleLength;
bool byRadius;
};
#endif

View File

@@ -0,0 +1,231 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawcircle.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_circle.h"
#include "rs_coordinateevent.h"
#include "rs_math.h"
#include "rs_preview.h"
#include "rs_debug.h"
RS_ActionDrawCircle::RS_ActionDrawCircle(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw circles",
container, graphicView)
,data(new RS_CircleData())
{
actionType=RS2::ActionDrawCircle;
reset();
}
RS_ActionDrawCircle::~RS_ActionDrawCircle() = default;
void RS_ActionDrawCircle::reset() {
data.reset(new RS_CircleData{});
}
void RS_ActionDrawCircle::init(int status) {
RS_PreviewActionInterface::init(status);
reset();
}
void RS_ActionDrawCircle::trigger() {
RS_PreviewActionInterface::trigger();
RS_Circle* circle = new RS_Circle(container,
*data);
circle->setLayerToActive();
circle->setPenToActive();
container->addEntity(circle);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(circle);
document->endUndoCycle();
}
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(circle->getCenter());
setStatus(SetCenter);
reset();
RS_DEBUG->print("RS_ActionDrawCircle::trigger(): circle added: %d",
circle->getId());
}
void RS_ActionDrawCircle::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawCircle::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
case SetCenter:
data->center = mouse;
break;
case SetRadius:
if (data->center.valid) {
data->radius = data->center.distanceTo(mouse);
deletePreview();
preview->addEntity(new RS_Circle(preview.get(),
*data));
drawPreview();
}
break;
}
RS_DEBUG->print("RS_ActionDrawCircle::mouseMoveEvent end");
}
void RS_ActionDrawCircle::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawCircle::coordinateEvent(RS_CoordinateEvent* e) {
if (!e){
return;
}
RS_Vector mouse = e->getCoordinate();
switch (getStatus()) {
case SetCenter:
data->center = mouse;
graphicView->moveRelativeZero(mouse);
setStatus(SetRadius);
break;
case SetRadius:
if (data->center.valid) {
graphicView->moveRelativeZero(mouse);
data->radius = data->center.distanceTo(mouse);
trigger();
}
//setStatus(SetCenter);
break;
default:
break;
}
}
void RS_ActionDrawCircle::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetRadius: {
bool ok;
double r = RS_Math::eval(c, &ok);
if (ok) {
data->radius = r;
e->accept();
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
//setStatus(SetCenter);
}
default:
break;
}
}
QStringList RS_ActionDrawCircle::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void RS_ActionDrawCircle::updateMouseButtonHints() {
switch (getStatus()) {
case SetCenter:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify center"), tr("Cancel"));
break;
case SetRadius:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify point on circle"), tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawCircle::showOptions() {
RS_ActionInterface::showOptions();
}
void RS_ActionDrawCircle::hideOptions() {
RS_ActionInterface::hideOptions();
}
void RS_ActionDrawCircle::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWCIRCLE_H
#define RS_ACTIONDRAWCIRCLE_H
#include "rs_previewactioninterface.h"
struct RS_CircleData;
/**
* This action class can handle user events to draw
* circles with a given center and a point on the circle line.
*
* @author Andrew Mustun
*/
class RS_ActionDrawCircle : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetCenter, /**< Setting the center point. */
SetRadius /**< Setting the radius. */
};
public:
RS_ActionDrawCircle(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawCircle() override;
void reset();
void init(int status=0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
/**
* Circle data defined so far.
*/
std::unique_ptr<RS_CircleData> data;
};
#endif

View File

@@ -0,0 +1,227 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawcircle2p.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_circle.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
struct RS_ActionDrawCircle2P::Points {
/**
* 1st point.
*/
RS_Vector point1;
/**
* 2nd point.
*/
RS_Vector point2;
};
RS_ActionDrawCircle2P::RS_ActionDrawCircle2P(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw circles",
container, graphicView)
, data(new RS_CircleData())
, pPoints(new Points{})
{
actionType=RS2::ActionDrawCircle2P;
reset();
}
RS_ActionDrawCircle2P::~RS_ActionDrawCircle2P() = default;
void RS_ActionDrawCircle2P::reset() {
data.reset(new RS_CircleData{});
pPoints->point1 = {};
pPoints->point2 = {};
}
void RS_ActionDrawCircle2P::init(int status) {
RS_PreviewActionInterface::init(status);
reset();
}
void RS_ActionDrawCircle2P::trigger() {
RS_PreviewActionInterface::trigger();
preparePreview();
if (data->isValid()) {
RS_Circle* circle = new RS_Circle(container,
*data);
circle->setLayerToActive();
circle->setPenToActive();
container->addEntity(circle);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(circle);
document->endUndoCycle();
}
RS_Vector rz = graphicView->getRelativeZero();
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(rz);
setStatus(SetPoint1);
reset();
} else
RS_DIALOGFACTORY->requestWarningDialog(tr("Invalid Circle data."));
}
void RS_ActionDrawCircle2P::preparePreview() {
data.reset(new RS_CircleData{});
if (pPoints->point1.valid && pPoints->point2.valid) {
RS_Circle circle(nullptr, *data);
bool suc = circle.createFrom2P(pPoints->point1, pPoints->point2);
if (suc) {
data.reset(new RS_CircleData(circle.getData()));
}
}
}
void RS_ActionDrawCircle2P::mouseMoveEvent(QMouseEvent* e) {
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
case SetPoint1:
pPoints->point1 = mouse;
break;
case SetPoint2:
pPoints->point2 = mouse;
preparePreview();
if (data->isValid()) {
RS_Circle* circle = new RS_Circle(preview.get(), *data);
deletePreview();
preview->addEntity(circle);
drawPreview();
}
break;
default:
break;
}
}
void RS_ActionDrawCircle2P::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawCircle2P::coordinateEvent(RS_CoordinateEvent* e) {
if (e==NULL) {
return;
}
RS_Vector mouse = e->getCoordinate();
switch (getStatus()) {
case SetPoint1:
pPoints->point1 = mouse;
graphicView->moveRelativeZero(mouse);
setStatus(SetPoint2);
break;
case SetPoint2:
pPoints->point2 = mouse;
graphicView->moveRelativeZero(mouse);
trigger();
break;
default:
break;
}
}
void RS_ActionDrawCircle2P::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
}
QStringList RS_ActionDrawCircle2P::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void RS_ActionDrawCircle2P::updateMouseButtonHints() {
switch (getStatus()) {
case SetPoint1:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify first point"), tr("Cancel"));
break;
case SetPoint2:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify second point"), tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawCircle2P::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWCIRCLE2P_H
#define RS_ACTIONDRAWCIRCLE2P_H
#include "rs_previewactioninterface.h"
struct RS_CircleData;
/**
* This action class can handle user events to draw
* simple arcs with the center, radius, start- and endangle given.
*
* @author Andrew Mustun
*/
class RS_ActionDrawCircle2P : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetPoint1, /**< Setting the 1st point. */
SetPoint2 /**< Setting the 2nd point. */
};
public:
RS_ActionDrawCircle2P(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawCircle2P() override;
void reset();
void init(int status=0) override;
void trigger() override;
void preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
/**
* Circle data defined so far.
*/
std::unique_ptr<RS_CircleData> data;
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,232 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawcircle3p.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_circle.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
struct RS_ActionDrawCircle3P::Points {
RS_CircleData data;
/**
* 1st point.
*/
RS_Vector point1;
/**
* 2nd point.
*/
RS_Vector point2;
/**
* 3rd point.
*/
RS_Vector point3;
};
RS_ActionDrawCircle3P::RS_ActionDrawCircle3P(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw circles",
container, graphicView)
,pPoints(new Points{})
{
actionType=RS2::ActionDrawCircle3P;
}
RS_ActionDrawCircle3P::~RS_ActionDrawCircle3P() = default;
void RS_ActionDrawCircle3P::init(int status) {
RS_PreviewActionInterface::init(status);
pPoints.reset(new Points{});
}
void RS_ActionDrawCircle3P::trigger() {
RS_PreviewActionInterface::trigger();
preparePreview();
if (pPoints->data.isValid()) {
RS_Circle* circle = new RS_Circle{container, pPoints->data};
circle->setLayerToActive();
circle->setPenToActive();
container->addEntity(circle);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(circle);
document->endUndoCycle();
}
RS_Vector rz = graphicView->getRelativeZero();
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(rz);
drawSnapper();
setStatus(SetPoint1);
pPoints.reset(new Points{});
} else
RS_DIALOGFACTORY->requestWarningDialog(tr("Invalid circle data."));
}
void RS_ActionDrawCircle3P::preparePreview() {
pPoints->data = RS_CircleData{};
if (pPoints->point1.valid && pPoints->point2.valid && pPoints->point3.valid) {
RS_Circle circle{nullptr, pPoints->data};
bool suc = circle.createFrom3P(pPoints->point1,
pPoints->point2,
pPoints->point3);
if (suc) {
pPoints->data = circle.getData();
}
}
}
void RS_ActionDrawCircle3P::mouseMoveEvent(QMouseEvent* e) {
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
case SetPoint1:
pPoints->point1 = mouse;
break;
case SetPoint2:
pPoints->point2 = mouse;
break;
case SetPoint3:
pPoints->point3 = mouse;
preparePreview();
if (pPoints->data.isValid()) {
RS_Circle* circle = new RS_Circle{preview.get(), pPoints->data};
deletePreview();
preview->addEntity(circle);
drawPreview();
}
break;
}
}
void RS_ActionDrawCircle3P::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawCircle3P::coordinateEvent(RS_CoordinateEvent* e) {
if (e==nullptr) {
return;
}
RS_Vector mouse = e->getCoordinate();
switch (getStatus()) {
case SetPoint1:
pPoints->point1 = mouse;
graphicView->moveRelativeZero(mouse);
setStatus(SetPoint2);
break;
case SetPoint2:
pPoints->point2 = mouse;
graphicView->moveRelativeZero(mouse);
setStatus(SetPoint3);
break;
case SetPoint3:
pPoints->point3 = mouse;
trigger();
break;
default:
break;
}
}
void RS_ActionDrawCircle3P::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
}
QStringList RS_ActionDrawCircle3P::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void RS_ActionDrawCircle3P::updateMouseButtonHints() {
switch (getStatus()) {
case SetPoint1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify first point"),
tr("Cancel"));
break;
case SetPoint2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify second point"),
tr("Back"));
break;
case SetPoint3:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify third point"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawCircle3P::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,81 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWCIRCLE3P_H
#define RS_ACTIONDRAWCIRCLE3P_H
#include "rs_previewactioninterface.h"
struct RS_CircleData;
/**
* This action class can handle user events to draw
* circles with three points given.
*
* @author Andrew Mustun
*/
class RS_ActionDrawCircle3P : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetPoint1, /**< Setting the 1st point. */
SetPoint2, /**< Setting the 2nd point. */
SetPoint3 /**< Setting the 3rd point. */
};
public:
RS_ActionDrawCircle3P(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawCircle3P() override;
void init(int status=0) override;
void trigger() override;
void preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
/**
* Circle data defined so far.
*/
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,258 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawcirclecr.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_circle.h"
#include "rs_coordinateevent.h"
#include "rs_math.h"
#include "rs_preview.h"
#include "rs_debug.h"
/**
* Constructor.
*/
RS_ActionDrawCircleCR::RS_ActionDrawCircleCR(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw circles CR",
container, graphicView)
,data(new RS_CircleData())
{
actionType=RS2::ActionDrawCircleCR;
reset();
}
RS_ActionDrawCircleCR::~RS_ActionDrawCircleCR() = default;
void RS_ActionDrawCircleCR::reset() {
data.reset(new RS_CircleData{RS_Vector{false}, 0.0});
}
void RS_ActionDrawCircleCR::init(int status) {
RS_PreviewActionInterface::init(status);
}
void RS_ActionDrawCircleCR::trigger() {
RS_PreviewActionInterface::trigger();
RS_Circle* circle = new RS_Circle(container,
*data);
circle->setLayerToActive();
circle->setPenToActive();
switch(getStatus()) {
case SetCenter:
container->addEntity(circle);
graphicView->moveRelativeZero(circle->getCenter());
break;
case SetRadius:
break;
}
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(circle);
document->endUndoCycle();
}
graphicView->redraw(RS2::RedrawDrawing);
setStatus(SetCenter);
RS_DEBUG->print("RS_ActionDrawCircleCR::trigger(): circle added: %d",
circle->getId());
}
void RS_ActionDrawCircleCR::setRadius(double r)
{
if(r>RS_TOLERANCE){
data->radius=r;
}else{
RS_DIALOGFACTORY->commandMessage(tr("radius=%1 is invalid").arg(r));
}
}
void RS_ActionDrawCircleCR::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawCircleCR::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
case SetCenter:
data->center = mouse;
deletePreview();
preview->addEntity(new RS_Circle(preview.get(),
*data));
drawPreview();
break;
}
RS_DEBUG->print("RS_ActionDrawCircleCR::mouseMoveEvent end");
}
void RS_ActionDrawCircleCR::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawCircleCR::coordinateEvent(RS_CoordinateEvent* e) {
if (e==NULL) {
return;
}
RS_Vector mouse = e->getCoordinate();
switch (getStatus()) {
case SetCenter:
data->center = mouse;
trigger();
break;
default:
break;
}
}
void RS_ActionDrawCircleCR::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetCenter:
if (checkCommand("radius", c)) {
deletePreview();
setStatus(SetRadius);
}
break;
case SetRadius: {
bool ok;
double r = RS_Math::eval(c, &ok);
if (ok) {
data->radius = r;
e->accept();
trigger();
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
}
break;
default:
break;
}
}
QStringList RS_ActionDrawCircleCR::getAvailableCommands() {
QStringList cmd;
switch (getStatus()) {
case SetCenter:
cmd += command("radius");
break;
default:
break;
}
return cmd;
}
void RS_ActionDrawCircleCR::updateMouseButtonHints() {
switch (getStatus()) {
case SetCenter:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify circle center"),
tr("Cancel"));
break;
case SetRadius:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify circle radius"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawCircleCR::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
}
void RS_ActionDrawCircleCR::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void RS_ActionDrawCircleCR::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
double RS_ActionDrawCircleCR::getRadius() const{
return data->radius;
}
// EOF

View File

@@ -0,0 +1,87 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWCIRCLECR_H
#define RS_ACTIONDRAWCIRCLECR_H
#include "rs_previewactioninterface.h"
struct RS_CircleData;
/**
* This action class can handle user events to draw
* simple arcs with the center, radius, start- and endangle given.
*
* @author Andrew Mustun
*/
class RS_ActionDrawCircleCR : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetCenter, /**< Setting the center point. */
SetRadius /**< Setting radius in command line. */
};
public:
RS_ActionDrawCircleCR(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawCircleCR() override;
void reset();
void init(int status=0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
double getRadius() const;
void setRadius(double r);
protected:
/**
* Circle data defined so far.
*/
std::unique_ptr<RS_CircleData> data;
};
#endif

View File

@@ -0,0 +1,303 @@
/****************************************************************************
**
* Draw circle by foci and a point on circle
Copyright (C) 2011 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include<vector>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawcircleinscribe.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_circle.h"
#include "rs_line.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawCircleInscribe::Points {
RS_CircleData cData;
RS_Vector coord;
std::vector<RS_Line*> lines;
};
/**
* Constructor.
*
*/
RS_ActionDrawCircleInscribe::RS_ActionDrawCircleInscribe(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw circle inscribed",
container, graphicView)
, pPoints(new Points{})
, valid(false)
{
actionType=RS2::ActionDrawCircleInscribe;
}
RS_ActionDrawCircleInscribe::~RS_ActionDrawCircleInscribe() = default;
void RS_ActionDrawCircleInscribe::clearLines(bool checkStatus)
{
while(pPoints->lines.size() ){
if(checkStatus && (int) pPoints->lines.size()<=getStatus() )
break;
pPoints->lines.back()->setHighlighted(false);
graphicView->drawEntity(pPoints->lines.back());
pPoints->lines.pop_back();
}
}
void RS_ActionDrawCircleInscribe::init(int status) {
RS_PreviewActionInterface::init(status);
if(status>=0) {
RS_Snapper::suspend();
}
clearLines(true);
}
void RS_ActionDrawCircleInscribe::finish(bool updateTB){
clearLines();
RS_PreviewActionInterface::finish(updateTB);
}
void RS_ActionDrawCircleInscribe::trigger() {
RS_PreviewActionInterface::trigger();
RS_Circle* circle=new RS_Circle(container, pPoints->cData);
deletePreview();
container->addEntity(circle);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(circle);
document->endUndoCycle();
}
clearLines(false);
setStatus(SetLine1);
RS_DEBUG->print("RS_ActionDrawCircle4Line::trigger():"
" entity added: %d", circle->getId());
}
void RS_ActionDrawCircleInscribe::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawCircle4Line::mouseMoveEvent begin");
if(getStatus() == SetLine3) {
RS_Entity* en = catchEntity(e, RS2::EntityLine, RS2::ResolveAll);
if(!en) return;
if(!(en->isVisible() && en->rtti()== RS2::EntityLine)) return;
for(int i=0;i<getStatus();i++) {
if(en->getId() == pPoints->lines[i]->getId()) return; //do not pull in the same line again
}
if(en->getParent() && en->getParent()->ignoredOnModification())
return;
pPoints->coord= graphicView->toGraph(e->x(), e->y());
deletePreview();
while(pPoints->lines.size()==3){
pPoints->lines.back()->setHighlighted(false);
graphicView->drawEntity(pPoints->lines.back());
pPoints->lines.pop_back();
}
en->setHighlighted(true);
pPoints->lines.push_back(static_cast<RS_Line*>(en));
graphicView->drawEntity(pPoints->lines.back());
if(preparePreview()) {
RS_Circle* e=new RS_Circle(preview.get(), pPoints->cData);
preview->addEntity(e);
drawPreview();
}
}
RS_DEBUG->print("RS_ActionDrawCircle4Line::mouseMoveEvent end");
}
bool RS_ActionDrawCircleInscribe::preparePreview(){
valid=false;
if(getStatus() == SetLine3) {
RS_Circle c(preview.get(), pPoints->cData);
valid= c.createInscribe(pPoints->coord, pPoints->lines);
if(valid){
pPoints->cData = c.getData();
}
}
return valid;
}
void RS_ActionDrawCircleInscribe::mouseReleaseEvent(QMouseEvent* e) {
// Proceed to next status
if (e->button()==Qt::LeftButton) {
if (!e) {
return;
}
RS_Entity* en = catchEntity(e, RS2::EntityLine, RS2::ResolveAll);
if(!en) return;
if(!(en->isVisible() && en->rtti()== RS2::EntityLine)) return;
for(int i=0;i<getStatus();i++) {
if(en->getId() == pPoints->lines[i]->getId()) return; //do not pull in the same line again
}
if(en->getParent()) {
if ( en->getParent()->ignoredOnModification()) return;
}
while((int) pPoints->lines.size()>getStatus()){
pPoints->lines.back()->setHighlighted(false);
graphicView->drawEntity(pPoints->lines.back());
pPoints->lines.pop_back();
}
pPoints->lines.push_back(static_cast<RS_Line*>(en));
pPoints->coord= graphicView->toGraph(e->x(), e->y());
switch (getStatus()) {
case SetLine1:
case SetLine2:
en->setHighlighted(true);
setStatus(getStatus()+1);
graphicView->redraw(RS2::RedrawDrawing);
break;
case SetLine3:
if( preparePreview()) {
trigger();
}
default:
break;
}
} else if (e->button()==Qt::RightButton) {
// Return to last status:
if(getStatus()>0){
clearLines(true);
pPoints->lines.back()->setHighlighted(false);
pPoints->lines.pop_back();
graphicView->redraw(RS2::RedrawDrawing);
deletePreview();
}
init(getStatus()-1);
}
}
//void RS_ActionDrawCircleInscribe::coordinateEvent(RS_CoordinateEvent* e) {
//}
//fixme, support command line
/*
void RS_ActionDrawCircle4Line::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetFocus1: {
bool ok;
double m = RS_Math::eval(c, &ok);
if (ok) {
ratio = m / major.magnitude();
if (!isArc) {
trigger();
} else {
setStatus(SetAngle1);
}
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle1: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle1 = RS_Math::deg2rad(a);
setStatus(SetAngle2);
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle2: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle2 = RS_Math::deg2rad(a);
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
default:
break;
}
}
*/
QStringList RS_ActionDrawCircleInscribe::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void RS_ActionDrawCircleInscribe::updateMouseButtonHints() {
switch (getStatus()) {
case SetLine1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the first line"),
tr("Cancel"));
break;
case SetLine2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the second line"),
tr("Back"));
break;
case SetLine3:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the third line"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawCircleInscribe::updateMouseCursor() {
graphicView->setMouseCursor(RS2::SelectCursor);
}
// EOF

View File

@@ -0,0 +1,79 @@
/****************************************************************************
**
* Draw ellipse by foci and a point on ellipse
Copyright (C) 2011 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef RS_ACTIONDRAWCIRCLEINSCRIBE_H
#define RS_ACTIONDRAWCIRCLEINSCRIBE_H
#include "rs_previewactioninterface.h"
class RS_Line;
struct RS_CircleData;
/**
* Draw ellipse by foci and a point on ellipse
*
* @author Dongxu Li
*/
class RS_ActionDrawCircleInscribe : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetLine1, // Setting the First Line. */
SetLine2, // Setting the Second Line. */
SetLine3 // Setting the Third Line. */
};
public:
RS_ActionDrawCircleInscribe(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawCircleInscribe() override;
void init(int status=0) override;
void trigger() override;
bool preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
// void coordinateEvent(RS_CoordinateEvent* e) override;
// void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void finish(bool updateTB=true) override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
private:
/**
* @brief clearLines unset highlighten lines, and clear the vector "lines"
* @param checkStatus keep lines members according to getStatus()
*/
void clearLines(bool checkStatus=false);
struct Points;
std::unique_ptr<Points> pPoints;
bool valid;
};
#endif

View File

@@ -0,0 +1,474 @@
/****************************************************************************
**
* Draw circle by foci and a point on circle
Copyright (C) 2012 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawcircletan1_2p.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_arc.h"
#include "rs_circle.h"
#include "rs_line.h"
#include "rs_point.h"
#include "lc_quadratic.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawCircleTan1_2P::Points {
std::vector<RS_Vector> points;
RS_CircleData cData;
RS_Vector coord;
double radius = 0.;
bool valid = false;
//keep a list of centers found
RS_VectorSolutions centers;
};
/**
* Constructor.
*
*/
RS_ActionDrawCircleTan1_2P::RS_ActionDrawCircleTan1_2P(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw tangent circle 2P",
container, graphicView)
,circle(nullptr)
,pPoints(new Points{})
{
actionType = RS2::ActionDrawCircleTan1_2P;
}
RS_ActionDrawCircleTan1_2P::~RS_ActionDrawCircleTan1_2P() = default;
void RS_ActionDrawCircleTan1_2P::init(int status) {
RS_PreviewActionInterface::init(status);
if(status>=0) {
RS_Snapper::suspend();
}
if (status<=SetCircle1) {
if(circle) {
if(circle->isHighlighted()){
circle->setHighlighted(false);
graphicView->redraw(RS2::RedrawDrawing);
}
}
pPoints->points.clear();
}
}
void RS_ActionDrawCircleTan1_2P::finish(bool updateTB){
if (circle) {
circle->setHighlighted(false);
graphicView->redraw(RS2::RedrawDrawing);
}
RS_PreviewActionInterface::finish(updateTB);
}
void RS_ActionDrawCircleTan1_2P::trigger() {
// std::cout<<__FILE__<<" : "<<__func__<<" : line "<<__LINE__<<std::endl;
// std::cout<<"begin"<<std::endl;
RS_PreviewActionInterface::trigger();
RS_Circle* c=new RS_Circle(container, pPoints->cData);
container->addEntity(c);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(c);
document->endUndoCycle();
}
circle->setHighlighted(false);
graphicView->redraw(RS2::RedrawDrawing);
// drawSnapper();
setStatus(SetCircle1);
RS_DEBUG->print("RS_ActionDrawCircleTan1_2P::trigger():"
" entity added: %d", c->getId());
}
void RS_ActionDrawCircleTan1_2P::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawCircleTan1_2P::mouseMoveEvent begin");
switch(getStatus() ){
case SetPoint1:
{
RS_Vector&& mouse=snapPoint(e);
pPoints->points.clear();
pPoints->points.push_back(mouse);
switch(circle->rtti()){
case RS2::EntityArc:
case RS2::EntityCircle:
{
RS_Vector const& dvp=mouse - circle->getCenter();
double rvp=dvp.magnitude();
if(rvp<RS_TOLERANCE2) break;
pPoints->cData.radius=(circle->getRadius()+rvp)*0.5;
pPoints->cData.center=circle->getCenter()+dvp*(pPoints->cData.radius/rvp);
pPoints->cData.radius=fabs(circle->getRadius()-pPoints->cData.radius);
}
break;
case RS2::EntityLine:
{
RS_Line* line=static_cast<RS_Line*>(circle);
RS_Vector&& vp=line->getNearestPointOnEntity(pPoints->points[0],false);
if(vp.valid){
pPoints->cData.center=(vp+pPoints->points[0])*0.5;
pPoints->cData.radius=vp.distanceTo(pPoints->cData.center);
}
}
break;
default:
return;
}
deletePreview();
RS_Circle* e=new RS_Circle(preview.get(), pPoints->cData);
preview->addEntity(e);
drawPreview();
break;
}
case SetPoint2: {
RS_Vector const& mouse=snapPoint(e);
pPoints->points.resize(1);
pPoints->points.push_back(mouse);
deletePreview();
pPoints->coord=mouse;
if (!getCenters()) return;
if (preparePreview()) {
RS_Circle* e=new RS_Circle(preview.get(), pPoints->cData);
preview->addEntity(e);
drawPreview();
}
break;
}
case SetCenter: {
// RS_Entity* en = catchEntity(e, enTypeList, RS2::ResolveAll);
pPoints->coord= graphicView->toGraph(e->x(), e->y());
// circles[getStatus()]=static_cast<RS_Line*>(en);
if(preparePreview()) {
deletePreview();
RS_Circle* e=new RS_Circle(preview.get(), pPoints->cData);
for(size_t i=0; i<pPoints->centers.size(); ++i)
preview->addEntity(new RS_Point(preview.get(), RS_PointData(pPoints->centers.at(i))));
preview->addEntity(e);
// double r0=cData.radius*0.1;
// if(centers.size()>1)
// for(unsigned i=0; i< centers.size(); ++i){
// RS_DEBUG->print(RS_Debug::D_ERROR, "center %d: (%g, %g)\n",i,centers.at(i).x,centers.at(i).y);
// preview->addEntity(new RS_Circle(preview, RS_CircleData(centers.at(i), r0)));
// }
drawPreview();
}
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDrawCircleTan1_2P::mouseMoveEvent end");
}
//void RS_ActionDrawCircleTan1_2P::setRadius(const double& r)
//{
// cData.radius=r;
// if(getStatus() == SetPoint2){
// RS_Circle c(nullptr,cData);
// centers=c.createTan1_2P(circle,cData.radius);
// }
//}
bool RS_ActionDrawCircleTan1_2P::getCenters(){
pPoints->centers.clear();
if(getStatus() < SetPoint2) return false;
LC_Quadratic lc0(circle, pPoints->points[0]);
// LC_Quadratic lc1(circle, points[1]);
LC_Quadratic lc1(pPoints->points[1], pPoints->points[0]);
auto list=LC_Quadratic::getIntersection(lc0,lc1);
// DEBUG_HEADER
// std::cout<<"intersections : "<<list<<std::endl;
for(const RS_Vector& vp: list){
//when taking the path of center of tangent circle passing a given point,
// the center is never closer to the circle center than the point, for internal and external tangent circles
double ds0=vp.distanceTo(pPoints->points[0]);
// double ds1=vp.distanceTo(points[1]);
// if( fabs(ds0 - ds1)> RS_TOLERANCE) continue;
if(circle->rtti()==RS2::EntityCircle||circle->rtti()==RS2::EntityArc){
double ds=vp.distanceTo(circle->getCenter());
//condition for tangential to the given circle
if( fabs(ds - (ds0 + circle->getRadius())) > RS_TOLERANCE && fabs(ds - fabs(ds0 - circle->getRadius())) > RS_TOLERANCE ) continue;
}else{
double ds=0.;
circle->getNearestPointOnEntity(vp, false,&ds);
//condition for tangential to the given straight line
if( fabs(ds - ds0)>RS_TOLERANCE) continue;
}
//avoid counting the same center
bool existing=false;
for(auto const& vq: pPoints->centers){
if(vq.squaredTo(vp) < RS_TOLERANCE15 ){
existing=true;
break;
}
}
if(existing) continue;
pPoints->centers.push_back(vp);
}
// DEBUG_HEADER
// std::cout<<"points: "<<points[0]<<" , "<<points[1]<<std::endl;
// std::cout<<"centers.size()="<<centers.size()<<std::endl;
// std::cout<<"centers: "<<centers<<std::endl;
pPoints->valid= (pPoints->centers.size()>0);
return pPoints->valid;
}
bool RS_ActionDrawCircleTan1_2P::preparePreview(){
if (!pPoints->centers.size()) getCenters();
if (!pPoints->centers.size()) return false;
pPoints->cData.center=pPoints->centers.getClosest(pPoints->coord);
pPoints->cData.radius=pPoints->points[0].distanceTo(pPoints->cData.center);
return true;
}
RS_Entity* RS_ActionDrawCircleTan1_2P::catchCircle(QMouseEvent* e) {
RS_Entity* ret=nullptr;
RS_Entity* en = catchEntity(e,enTypeList, RS2::ResolveAll);
if (!en) return ret;
if (!en->isVisible()) return ret;
if (en->getParent()) {
if ( en->getParent()->ignoredOnModification()){
return nullptr;
}
}
return en;
}
void RS_ActionDrawCircleTan1_2P::mouseReleaseEvent(QMouseEvent* e) {
// Proceed to next status
if (e->button()==Qt::LeftButton) {
switch (getStatus()) {
case SetCircle1:
{
RS_Entity* en = catchCircle(e);
if (!en) return;
circle = static_cast<RS_AtomicEntity*>(en);
circle->setHighlighted(true);
graphicView->redraw(RS2::RedrawDrawing);
setStatus(getStatus()+1);
}
break;
case SetPoint1:
case SetPoint2:
{
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
}
break;
case SetCenter:
pPoints->coord=graphicView->toGraph(e->x(),e->y());
if(preparePreview()) trigger();
break;
default:
break;
}
} else if (e->button()==Qt::RightButton) {
// Return to last status:
if(getStatus()>0){
deletePreview();
}
init(getStatus()-1);
}
}
void RS_ActionDrawCircleTan1_2P::coordinateEvent(RS_CoordinateEvent* e) {
RS_Vector mouse = e->getCoordinate();
pPoints->coord=mouse;
switch(getStatus()){
case SetPoint1:
pPoints->points.clear();
pPoints->points.push_back(mouse);
setStatus(getStatus()+1);
break;
case SetPoint2:
// pPoints->points.reserve(1);
pPoints->points.push_back(mouse);
if(getCenters()) {
if(pPoints->centers.size()==1) trigger();
else setStatus(getStatus()+1);
}
break;
}
}
//fixme, support command line
/*
void RS_ActionDrawCircleTan1_2P::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetFocus1: {
bool ok;
double m = RS_Math::eval(c, &ok);
if (ok) {
ratio = m / major.magnitude();
if (!isArc) {
trigger();
} else {
setStatus(SetAngle1);
}
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle1: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle1 = RS_Math::deg2rad(a);
setStatus(SetAngle2);
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle2: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle2 = RS_Math::deg2rad(a);
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
default:
break;
}
}
*/
//void RS_ActionDrawCircleTan1_2P::showOptions() {
// RS_DEBUG->print("RS_ActionDrawCircleTan1_2P::showOptions");
// RS_ActionInterface::showOptions();
// RS_DIALOGFACTORY->requestOptions(this, true);
// RS_DEBUG->print("RS_ActionDrawCircleTan1_2P::showOptions: OK");
//}
//void RS_ActionDrawCircleTan1_2P::hideOptions() {
// RS_ActionInterface::hideOptions();
// RS_DIALOGFACTORY->requestOptions(this, false);
//}
QStringList RS_ActionDrawCircleTan1_2P::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void RS_ActionDrawCircleTan1_2P::updateMouseButtonHints() {
switch (getStatus()) {
case SetCircle1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify a line/arc/circle"),
tr("Cancel"));
break;
case SetPoint1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the first point on the tangent circle"),
tr("Back"));
break;
case SetPoint2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the second point on the tangent circle"),
tr("Back"));
break;
case SetCenter:
RS_DIALOGFACTORY->updateMouseWidget(tr("Select the center of the tangent circle"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawCircleTan1_2P::updateMouseCursor()
{
switch (getStatus())
{
case SetCircle1:
case SetCenter:
graphicView->setMouseCursor(RS2::SelectCursor);
break;
case SetPoint1:
case SetPoint2:
graphicView->setMouseCursor(RS2::CadCursor);
break;
}
}
double RS_ActionDrawCircleTan1_2P::getRadius() const{
return pPoints->cData.radius;
}
// EOF

View File

@@ -0,0 +1,87 @@
/****************************************************************************
**
* Draw ellipse by foci and a point on ellipse
Copyright (C) 2012 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef RS_ACTIONDRAWCIRCLETAN1_2P_H
#define RS_ACTIONDRAWCIRCLETAN1_2P_H
#include "rs_previewactioninterface.h"
class RS_AtomicEntity;
struct RS_CircleData;
/**
* Draw tangential circle passing 2 points
*
* @author Dongxu Li
*/
class RS_ActionDrawCircleTan1_2P : public RS_PreviewActionInterface {
Q_OBJECT
/**
* Action States.
*/
enum Status {
SetCircle1=0, // Setting the First Circle. */
SetPoint1=1, // Setting the First Point. */
SetPoint2=2, // Setting the Second Point. */
SetCenter // Setting the internal or external tangent circle's center. */
};
public:
RS_ActionDrawCircleTan1_2P(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawCircleTan1_2P() override;
void init(int status=0) override;
void trigger() override;
bool getCenters();
bool preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
// void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void finish(bool updateTB=true) override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
// void showOptions() override;
// void hideOptions() override;
// void setRadius(const double& r);
double getRadius() const;
protected:
RS_Entity* catchCircle(QMouseEvent* e);
RS_AtomicEntity* circle;
private:
struct Points;
std::unique_ptr<Points> pPoints;
//list of entity types supported by current action
const EntityTypeList enTypeList = EntityTypeList {RS2::EntityLine, RS2::EntityArc, RS2::EntityCircle};
};
#endif

View File

@@ -0,0 +1,334 @@
/****************************************************************************
**
* Draw circle by foci and a point on circle
Copyright (C) 2012 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include<vector>
#include<QAction>
#include <QMouseEvent>
#include "rs_actiondrawcircletan2.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_circle.h"
#include "rs_point.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawCircleTan2::Points {
RS_CircleData cData;
RS_Vector coord;
double radius{0.};
bool valid{false};
RS_VectorSolutions centers;
std::vector<RS_AtomicEntity*> circles;
};
/**
* Constructor.
*
*/
RS_ActionDrawCircleTan2::RS_ActionDrawCircleTan2(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw circle inscribed",
container, graphicView)
, pPoints(new Points{})
{
actionType=RS2::ActionDrawCircleTan2;
}
RS_ActionDrawCircleTan2::~RS_ActionDrawCircleTan2() = default;
void RS_ActionDrawCircleTan2::init(int status) {
RS_PreviewActionInterface::init(status);
if(status>=0) {
RS_Snapper::suspend();
}
if (status==SetCircle1) {
pPoints->circles.clear();
}
}
void RS_ActionDrawCircleTan2::finish(bool updateTB){
if(pPoints->circles.size()>0){
for(auto p: pPoints->circles){
if(p) p->setHighlighted(false);
}
graphicView->redraw(RS2::RedrawDrawing);
pPoints->circles.clear();
}
RS_PreviewActionInterface::finish(updateTB);
}
void RS_ActionDrawCircleTan2::trigger() {
RS_PreviewActionInterface::trigger();
RS_Circle* circle=new RS_Circle(container, pPoints->cData);
container->addEntity(circle);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(circle);
document->endUndoCycle();
}
for(auto p: pPoints->circles)
p->setHighlighted(false);
graphicView->redraw(RS2::RedrawDrawing);
// drawSnapper();
pPoints->circles.clear();
setStatus(SetCircle1);
RS_DEBUG->print("RS_ActionDrawCircleTan2::trigger():"
" entity added: %d", circle->getId());
}
void RS_ActionDrawCircleTan2::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawCircleTan2::mouseMoveEvent begin");
switch(getStatus() ){
case SetCenter: {
// RS_Entity* en = catchEntity(e, enTypeList, RS2::ResolveAll);
pPoints->coord= graphicView->toGraph(e->x(), e->y());
// circles[getStatus()]=static_cast<RS_Line*>(en);
if(preparePreview()) {
deletePreview();
RS_Circle* e=new RS_Circle(preview.get(), pPoints->cData);
preview->addEntity(e);
for(size_t i=0; i< pPoints->centers.size(); ++i){
preview->addEntity(new RS_Point(preview.get(), RS_PointData(pPoints->centers.at(i))));
}
drawPreview();
}
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDrawCircleTan2::mouseMoveEvent end");
}
void RS_ActionDrawCircleTan2::setRadius(const double& r)
{
pPoints->cData.radius=r;
if(getStatus() == SetCenter){
pPoints->centers=RS_Circle::createTan2(pPoints->circles,
pPoints->cData.radius);
}
}
bool RS_ActionDrawCircleTan2::getCenters(){
if(getStatus() != SetCircle2) return false;
pPoints->centers=RS_Circle::createTan2(pPoints->circles,
pPoints->cData.radius);
pPoints->valid= (pPoints->centers.size()>0);
return pPoints->valid;
}
bool RS_ActionDrawCircleTan2::preparePreview(){
if (pPoints->valid) {
pPoints->cData.center=pPoints->centers.getClosest(pPoints->coord);
}
return pPoints->valid;
}
RS_Entity* RS_ActionDrawCircleTan2::catchCircle(QMouseEvent* e) {
RS_Entity* en = catchEntity(e,enTypeList, RS2::ResolveAll);
if (!en) return nullptr;
if (!en->isVisible()) return nullptr;
for (int i=0;i<getStatus();i++) {
if(en->getId() == pPoints->circles[i]->getId()) return nullptr; //do not pull in the same line again
}
if(en->getParent()) {
if ( en->getParent()->ignoredOnModification()){
return nullptr;
}
}
return en;
}
void RS_ActionDrawCircleTan2::mouseReleaseEvent(QMouseEvent* e) {
// Proceed to next status
if (e->button()==Qt::LeftButton) {
switch (getStatus()) {
case SetCircle1:
case SetCircle2: {
RS_Entity* en = catchCircle(e);
if (!en) return;
pPoints->circles.resize(getStatus());
pPoints->circles.push_back(static_cast<RS_AtomicEntity*>(en));
if(getStatus()==SetCircle1 || getCenters()){
pPoints->circles.at(pPoints->circles.size()-1)->setHighlighted(true);
graphicView->redraw(RS2::RedrawDrawing);
setStatus(getStatus()+1);
}
}
break;
case SetCenter:
pPoints->coord= graphicView->toGraph(e->x(), e->y());
if( preparePreview()) trigger();
break;
default:
break;
}
} else if (e->button()==Qt::RightButton) {
// Return to last status:
if(getStatus()>0){
pPoints->circles[getStatus()-1]->setHighlighted(false);
pPoints->circles.pop_back();
graphicView->redraw(RS2::RedrawDrawing);
deletePreview();
}
init(getStatus()-1);
}
}
//void RS_ActionDrawCircleTan2::coordinateEvent(RS_CoordinateEvent* e) {
//}
//fixme, support command line
/*
void RS_ActionDrawCircleTan2::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetFocus1: {
bool ok;
double m = RS_Math::eval(c, &ok);
if (ok) {
ratio = m / major.magnitude();
if (!isArc) {
trigger();
} else {
setStatus(SetAngle1);
}
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle1: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle1 = RS_Math::deg2rad(a);
setStatus(SetAngle2);
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle2: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle2 = RS_Math::deg2rad(a);
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
default:
break;
}
}
*/
void RS_ActionDrawCircleTan2::showOptions() {
RS_DEBUG->print("RS_ActionDrawCircleTan2::showOptions");
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
RS_DEBUG->print("RS_ActionDrawCircleTan2::showOptions: OK");
}
void RS_ActionDrawCircleTan2::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
QStringList RS_ActionDrawCircleTan2::getAvailableCommands() {
return {};
}
void RS_ActionDrawCircleTan2::updateMouseButtonHints() {
switch (getStatus()) {
case SetCircle1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the first line/arc/circle"),
tr("Cancel"));
break;
case SetCircle2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the second line/arc/circle"),
tr("Back"));
break;
case SetCenter:
RS_DIALOGFACTORY->updateMouseWidget(tr("Select the center of the tangent circle"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawCircleTan2::updateMouseCursor() {
graphicView->setMouseCursor(RS2::SelectCursor);
}
double RS_ActionDrawCircleTan2::getRadius() const{
return pPoints->cData.radius;
}
// EOF

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
* Draw a tangential circle of two given circles, with given radius
Copyright (C) 2012-2015 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef RS_ACTIONDRAWCIRCLETAN2_H
#define RS_ACTIONDRAWCIRCLETAN2_H
#include "rs_previewactioninterface.h"
class RS_AtomicEntity;
struct RS_CircleData;
/**
* Draw a circle tangential to two give circles and with radius
*
* @author Dongxu Li
*/
class RS_ActionDrawCircleTan2 : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetCircle1, // Setting the First Circle. */
SetCircle2, // Setting the Second Circle. */
SetCenter // select the closest tangential Circle. */
};
public:
RS_ActionDrawCircleTan2(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawCircleTan2() override;
void init(int status=0) override;
void trigger() override;
bool getCenters();
bool preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
// void coordinateEvent(RS_CoordinateEvent* e) override;
// void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void finish(bool updateTB=true) override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
void showOptions() override;
void hideOptions() override;
void setRadius(const double& r);
double getRadius() const;
protected:
RS_Entity* catchCircle(QMouseEvent* e);
private:
struct Points;
std::unique_ptr<Points> pPoints;
//list of entity types supported by current action
const EntityTypeList enTypeList = EntityTypeList{RS2::EntityLine, RS2::EntityArc, RS2::EntityCircle};
};
#endif

View File

@@ -0,0 +1,361 @@
/****************************************************************************
**
* Draw circle by foci and a point on circle
Copyright (C) 2012 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include<vector>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawcircletan2_1p.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_arc.h"
#include "rs_circle.h"
#include "lc_quadratic.h"
#include "rs_coordinateevent.h"
#include "rs_point.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawCircleTan2_1P::Points {
RS_Vector point;
RS_CircleData cData;
RS_Vector coord;
double radius = 0.;
bool valid = false;
//keep a list of centers found
RS_VectorSolutions centers;
std::vector<RS_AtomicEntity*> circles;
};
/**
* Constructor.
*
*/
RS_ActionDrawCircleTan2_1P::RS_ActionDrawCircleTan2_1P(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw tangent circle 2P",
container, graphicView)
, pPoints(new Points{})
{
actionType=RS2::ActionDrawCircleTan2_1P;
}
RS_ActionDrawCircleTan2_1P::~RS_ActionDrawCircleTan2_1P() = default;
void RS_ActionDrawCircleTan2_1P::init(int status) {
if(status>=0) {
RS_Snapper::suspend();
}
if(status>(int) pPoints->circles.size()) status=(int) pPoints->circles.size();
RS_PreviewActionInterface::init(status);
for(int i=0; i<status; ++i){
if(!pPoints->circles[i]) {
status=i;
break;
}
}
bool updateNeeded(false);
for(size_t i=status>=0?status:0; i<pPoints->circles.size(); ++i){
if(pPoints->circles[i])
if(pPoints->circles[i]->isHighlighted()){
pPoints->circles[i]->setHighlighted(false);
updateNeeded=true;
}
}
if(updateNeeded) graphicView->redraw(RS2::RedrawDrawing);
pPoints->circles.resize(status>=0?status:0);
}
void RS_ActionDrawCircleTan2_1P::finish(bool updateTB){
if( pPoints->circles.size() >0) {
for(RS_AtomicEntity*const circle: pPoints->circles)
circle->setHighlighted(false);
graphicView->redraw(RS2::RedrawDrawing);
}
RS_PreviewActionInterface::finish(updateTB);
}
void RS_ActionDrawCircleTan2_1P::trigger() {
RS_PreviewActionInterface::trigger();
RS_Circle* c=new RS_Circle(container, pPoints->cData);
container->addEntity(c);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(c);
document->endUndoCycle();
}
for(RS_AtomicEntity*const circle: pPoints->circles)
circle->setHighlighted(false);
graphicView->redraw(RS2::RedrawDrawing);
pPoints->circles.clear();
RS_DEBUG->print("RS_ActionDrawCircleTan2_1P::trigger():"
" entity added: %d", c->getId());
init(SetCircle1);
}
bool RS_ActionDrawCircleTan2_1P::getCenters()
{
if(pPoints->circles.size()<2) return false;
LC_Quadratic lc0(pPoints->circles[0], pPoints->point);
LC_Quadratic lc1(pPoints->circles[1], pPoints->point);
auto const& list=LC_Quadratic::getIntersection(lc0,lc1);
pPoints->centers.clear();
for(const RS_Vector& vp: list){
auto ds=vp.distanceTo(pPoints->point)-RS_TOLERANCE;
bool validBranch(true);
for(int j=0;j<2;j++){
if(pPoints->circles[j]->rtti()==RS2::EntityCircle||pPoints->circles[j]->rtti()==RS2::EntityArc){
if( vp.distanceTo(pPoints->circles[j]->getCenter()) <= ds) {
validBranch=false;
break;
}
}
}
if(validBranch) pPoints->centers.push_back(vp);
}
return pPoints->centers.size()>0;
}
void RS_ActionDrawCircleTan2_1P::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawCircleTan2_1P::mouseMoveEvent begin");
switch( getStatus()){
case SetPoint:
pPoints->coord=snapPoint(e);
pPoints->point=pPoints->coord;
break;
case SetCenter:
pPoints->coord=graphicView->toGraph(e->x(),e->y());
break;
default:
return;
}
deletePreview();
if(preparePreview()){
RS_Circle* e=new RS_Circle(preview.get(), pPoints->cData);
for (auto const& vp: pPoints->centers)
preview->addEntity(new RS_Point(preview.get(), vp));
preview->addEntity(e);
drawPreview();
}
RS_DEBUG->print("RS_ActionDrawCircleTan2_1P::mouseMoveEvent end");
}
bool RS_ActionDrawCircleTan2_1P::preparePreview(){
if (!getCenters()) return false;
pPoints->cData.center=pPoints->centers.getClosest(pPoints->coord);
pPoints->cData.radius=pPoints->point.distanceTo(pPoints->cData.center);
return true;
}
RS_Entity* RS_ActionDrawCircleTan2_1P::catchCircle(QMouseEvent* e) {
RS_Entity* ret=nullptr;
RS_Entity* en = catchEntity(e,enTypeList, RS2::ResolveAll);
if (!en) return ret;
if (!en->isVisible()) return ret;
for(auto p: pPoints->circles){
if(p && en->getId() == p->getId()) return ret; //do not pull in the same line again
}
if(en->getParent() && en->getParent()->ignoredOnModification()){
return nullptr;
}
return en;
}
void RS_ActionDrawCircleTan2_1P::mouseReleaseEvent(QMouseEvent* e) {
// Proceed to next status
if (e->button()==Qt::LeftButton) {
switch (getStatus()) {
case SetCircle1:
case SetCircle2:
{
pPoints->circles.resize(getStatus());
RS_AtomicEntity* en = static_cast<RS_AtomicEntity*>(catchCircle(e));
if (!en) return;
// circle = static_cast<RS_AtomicEntity*>(en);
en->setHighlighted(true);
pPoints->circles.push_back(en);
graphicView->redraw(RS2::RedrawDrawing);
setStatus(getStatus()+1);
}
break;
case SetPoint:
{
RS_Vector snapped = snapPoint(e);
RS_CoordinateEvent ce(snapped);
coordinateEvent(&ce);
}
break;
case SetCenter:
pPoints->coord=graphicView->toGraph(e->x(),e->y());
if(preparePreview()) trigger();
break;
default:
break;
}
} else if (e->button()==Qt::RightButton) {
// Return to last status:
if(getStatus()>0){
deletePreview();
}
init(getStatus()-1);
}
}
void RS_ActionDrawCircleTan2_1P::coordinateEvent(RS_CoordinateEvent* e) {
RS_Vector mouse = e->getCoordinate();
switch(getStatus()){
case SetPoint:
pPoints->point=mouse;
pPoints->coord=mouse;
if(getCenters()) {
if(pPoints->centers.size()==1) trigger();
else setStatus(getStatus()+1);
}
break;
default:
break;
// case SetCenter:
// coord=mouse;
// trigger();
}
}
//fixme, support command line
/*
void RS_ActionDrawCircleTan2_1P::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetFocus1: {
bool ok;
double m = RS_Math::eval(c, &ok);
if (ok) {
ratio = m / major.magnitude();
if (!isArc) {
trigger();
} else {
setStatus(SetAngle1);
}
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle1: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle1 = RS_Math::deg2rad(a);
setStatus(SetAngle2);
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle2: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle2 = RS_Math::deg2rad(a);
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
default:
break;
}
}
*/
QStringList RS_ActionDrawCircleTan2_1P::getAvailableCommands() {
return {};
}
void RS_ActionDrawCircleTan2_1P::updateMouseButtonHints() {
switch (getStatus()) {
case SetCircle1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify a line/arc/circle"),
tr("Cancel"));
break;
case SetCircle2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the another arc/circle"),
tr("Back"));
break;
case SetPoint:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify a point on the tangent circle"),
tr("Back"));
break;
case SetCenter:
RS_DIALOGFACTORY->updateMouseWidget(tr("Select the center of the tangent circle"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawCircleTan2_1P::updateMouseCursor()
{
switch (getStatus())
{
case SetCircle1:
case SetCircle2:
case SetCenter:
graphicView->setMouseCursor(RS2::SelectCursor);
break;
case SetPoint:
graphicView->setMouseCursor(RS2::CadCursor);
break;
}
}
// EOF

View File

@@ -0,0 +1,81 @@
/****************************************************************************
**
* Draw ellipse by foci and a point on ellipse
Copyright (C) 2012 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef RS_ACTIONDRAWCIRCLETAN2_1P_H
#define RS_ACTIONDRAWCIRCLETAN2_1P_H
#include "rs_previewactioninterface.h"
class RS_AtomicEntity;
struct RS_CircleData;
/**
* Given two circles and a point, draw a common tangent circle passing the point
*
* @author Dongxu Li
*/
class RS_ActionDrawCircleTan2_1P : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetCircle1=0, // Setting the first circle. */
SetCircle2=1, // Setting the second circle. */
SetPoint=2, // Setting point on the desired circle. */
SetCenter
};
public:
RS_ActionDrawCircleTan2_1P(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawCircleTan2_1P() override;
void init(int status=0) override;
void trigger() override;
bool getCenters();
bool preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
// void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void finish(bool updateTB=true) override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
RS_Entity* catchCircle(QMouseEvent* e);
private:
struct Points;
std::unique_ptr<Points> pPoints;
//list of entity types supported by current action
const EntityTypeList enTypeList = EntityTypeList {RS2::EntityLine, RS2::EntityArc, RS2::EntityCircle};
};
#endif

View File

@@ -0,0 +1,476 @@
/****************************************************************************
**
* Draw circle by foci and a point on circle
Copyright (C) 2012 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include "rs_actiondrawcircletan3.h"
#include <QAction>
#include <QMouseEvent>
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_circle.h"
#include "rs_line.h"
#include "rs_point.h"
#include "lc_quadratic.h"
#include "rs_information.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawCircleTan3::Points {
std::vector<RS_AtomicEntity*> circles;
std::shared_ptr<RS_CircleData> cData{std::make_shared<RS_CircleData>()};
RS_Vector coord;
bool valid{false};
//keep a list of centers found
std::vector<std::shared_ptr<RS_CircleData> > candidates;
RS_VectorSolutions centers;
};
RS_ActionDrawCircleTan3::~RS_ActionDrawCircleTan3() = default;
/**
* Constructor.
*
*/
RS_ActionDrawCircleTan3::RS_ActionDrawCircleTan3(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw circle inscribed",
container, graphicView)
, pPoints(new Points{})
{
actionType=RS2::ActionDrawCircleTan3;
}
void RS_ActionDrawCircleTan3::init(int status) {
RS_PreviewActionInterface::init(status);
if(status>=0) {
RS_Snapper::suspend();
}
if (status==SetCircle1) {
pPoints->circles.clear();
}
}
void RS_ActionDrawCircleTan3::finish(bool updateTB){
if(pPoints->circles.size()>0){
for(RS_AtomicEntity* const pc: pPoints->circles)
if(pc) pc->setHighlighted(false);
graphicView->redraw(RS2::RedrawDrawing);
pPoints->circles.clear();
}
RS_PreviewActionInterface::finish(updateTB);
}
void RS_ActionDrawCircleTan3::trigger() {
RS_PreviewActionInterface::trigger();
RS_Circle* circle=new RS_Circle(container, *pPoints->cData);
container->addEntity(circle);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(circle);
document->endUndoCycle();
}
for(RS_AtomicEntity* const pc: pPoints->circles)
if(pc) pc->setHighlighted(false);
graphicView->redraw(RS2::RedrawDrawing);
// drawSnapper();
pPoints->circles.clear();
setStatus(SetCircle1);
RS_DEBUG->print("RS_ActionDrawCircleTan3::trigger():"
" entity added: %d", circle->getId());
}
void RS_ActionDrawCircleTan3::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawCircleTan3::mouseMoveEvent begin");
switch(getStatus() ){
case SetCenter: {
// RS_Entity* en = catchEntity(e, enTypeList, RS2::ResolveAll);
pPoints->coord= graphicView->toGraph(e->x(), e->y());
// circles[getStatus()]=static_cast<RS_Line*>(en);
deletePreview();
if(preparePreview()) {
RS_Circle* e=new RS_Circle(preview.get(), *pPoints->cData);
preview->addEntity(e);
for(auto& c: pPoints->candidates){
preview->addEntity(new RS_Point(nullptr, RS_PointData(c->center)));
}
drawPreview();
}
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDrawCircleTan3::mouseMoveEvent end");
}
bool RS_ActionDrawCircleTan3::getData(){
if(getStatus() != SetCircle3) return false;
//find the nearest circle
size_t i=0;
size_t const countLines=std::count_if(pPoints->circles.begin(), pPoints->circles.end(), [](RS_AtomicEntity* e)->bool
{
return e->rtti()==RS2::EntityLine;
});
for(;i<pPoints->circles.size();++i)
if(pPoints->circles[i]->rtti() == RS2::EntityLine) break;
pPoints->candidates.clear();
size_t i1=(i+1)%3;
size_t i2=(i+2)%3;
if(i<pPoints->circles.size() && pPoints->circles[i]->rtti() == RS2::EntityLine){
//one or more lines
LC_Quadratic lc0(pPoints->circles[i],pPoints->circles[i1],false);
LC_Quadratic lc1;
RS_VectorSolutions sol;
//detect degenerate case two circles with the same radius
switch(countLines){
default:
case 0:
//this should not happen
assert(false);
case 1:
//1 line, two circles
{
for(unsigned k=0; k<4; ++k){
//loop through all mirroring cases
lc1=LC_Quadratic(pPoints->circles[i],pPoints->circles[i1], k & 1u);
LC_Quadratic lc2=LC_Quadratic(pPoints->circles[i],pPoints->circles[i2], k & 2u);
sol.push_back(LC_Quadratic::getIntersection(lc1,lc2));
}
}
break;
case 2:
//2 lines, one circle
{
if(pPoints->circles[i2]->rtti()==RS2::EntityLine){
std::swap(i1, i2);
}
//i2 is circle
for(unsigned k=0; k<4; ++k){
//loop through all mirroring cases
lc1=LC_Quadratic(pPoints->circles[i2],pPoints->circles[i], k & 1u);
LC_Quadratic lc2=LC_Quadratic(pPoints->circles[i2],pPoints->circles[i1], k & 2u);
sol.push_back(LC_Quadratic::getIntersection(lc1,lc2));
}
}
break;
case 3:
//3 lines
{
lc0=pPoints->circles[i]->getQuadratic();
lc1=pPoints->circles[i1]->getQuadratic();
auto lc2=pPoints->circles[i2]->getQuadratic();
//attempt to have intersections (lc0, lc1), (lc0, lc2)
auto sol1=LC_Quadratic::getIntersection(lc0,lc1);
if(sol1.size()<1) {
std::swap(lc0, lc2);
std::swap(i, i2);
}
sol1=LC_Quadratic::getIntersection(lc0,lc2);
if(sol1.size()<1) {
std::swap(lc0, lc1);
std::swap(i, i1);
}
RS_Line* line0=static_cast<RS_Line*>(pPoints->circles[i]);
RS_Line* line1=static_cast<RS_Line*>(pPoints->circles[i1]);
RS_Line* line2=static_cast<RS_Line*>(pPoints->circles[i2]);
lc0=line0->getQuadratic();
lc1=line1->getQuadratic();
lc2=line2->getQuadratic();
//intersection 0, 1
sol1=LC_Quadratic::getIntersection(lc0,lc1);
if(!sol1.size()) {
return false;
}
RS_Vector const v1=sol1.at(0);
double angle1=0.5*(line0->getAngle1()+line1->getAngle1());
//intersection 0, 2
sol1=LC_Quadratic::getIntersection(lc0,lc2);
double angle2;
if(sol1.size()<1) {
return false;
}
angle2=0.5*(line0->getAngle1()+line2->getAngle1());
RS_Vector const& v2=sol1.at(0);
//two bisector lines per intersection
for(unsigned j=0; j<2; ++j){
RS_Line l1{v1, v1+RS_Vector{angle1}};
for(unsigned j1=0; j1<2; ++j1){
RS_Line l2{v2, v2+RS_Vector{angle2}};
sol.push_back(RS_Information::getIntersectionLineLine(&l1, &l2));
angle2 += M_PI_2;
}
angle1 += M_PI_2;
}
}
}
double d;
//line passes circle center, need a second parabola as the image of the line
for(int j=1;j<=2;j++){
if(pPoints->circles[(i+j)%3]->rtti() == RS2::EntityCircle){
pPoints->circles[i]->getNearestPointOnEntity(pPoints->circles[(i+j)%3]->getCenter(),
false,&d);
if(d<RS_TOLERANCE) {
LC_Quadratic lc2(pPoints->circles[i],pPoints->circles[(i+j)%3], true);
sol.push_back(LC_Quadratic::getIntersection(lc2,lc1));
}
}
}
//clean up duplicate and invalid
RS_VectorSolutions sol1;
for(const RS_Vector& vp: sol){
if(vp.magnitude()>RS_MAXDOUBLE) continue;
if(sol1.size() && sol1.getClosestDistance(vp)<RS_TOLERANCE) continue;
sol1.push_back(vp);
}
for(auto const& v: sol1){
pPoints->circles[i]->getNearestPointOnEntity(v,false,&d);
auto data = std::make_shared<RS_CircleData>(v,d);
if(pPoints->circles[(i+1)%3]->isTangent(*data)==false) continue;
if(pPoints->circles[(i+2)%3]->isTangent(*data)==false) continue;
pPoints->candidates.push_back(data);
}
} else {
RS_Circle c{nullptr, *pPoints->cData};
auto solutions=c.createTan3(pPoints->circles);
pPoints->candidates.clear();
for(const RS_Circle& s: solutions){
pPoints->candidates.push_back(std::make_shared<RS_CircleData>(s.getData()));
}
}
pPoints->valid = ( pPoints->candidates.size() >0);
return pPoints->valid;
}
bool RS_ActionDrawCircleTan3::preparePreview(){
if(getStatus() != SetCenter || pPoints->valid==false) {
pPoints->valid=false;
return false;
}
//find the nearest circle
size_t index=pPoints->candidates.size();
double dist=RS_MAXDOUBLE*RS_MAXDOUBLE;
for(size_t i=0;i<pPoints->candidates.size();++i){
preview->addEntity(new RS_Point(preview.get(), RS_PointData(pPoints->candidates.at(i)->center)));
double d;
RS_Circle(nullptr, *pPoints->candidates.at(i)).getNearestPointOnEntity(pPoints->coord,false,&d);
double dCenter=pPoints->coord.distanceTo(pPoints->candidates.at(i)->center);
d=std::min(d,dCenter);
if(d<dist){
dist=d;
index=i;
}
}
if( index<pPoints->candidates.size()){
pPoints->cData=pPoints->candidates.at(index);
pPoints->valid=true;
}else{
pPoints->valid=false;
}
return pPoints->valid;
}
RS_Entity* RS_ActionDrawCircleTan3::catchCircle(QMouseEvent* e) {
RS_Entity* ret=nullptr;
RS_Entity* en = catchEntity(e,enTypeList, RS2::ResolveAll);
if (!en) return ret;
if (!en->isVisible()) return ret;
for(int i=0;i<getStatus();++i) {
if(en->getId() == pPoints->circles[i]->getId()) return ret; //do not pull in the same line again
}
if(en->getParent()) {
if ( en->getParent()->ignoredOnModification()){
return nullptr;
}
}
return en;
}
void RS_ActionDrawCircleTan3::mouseReleaseEvent(QMouseEvent* e) {
// Proceed to next status
if (e->button()==Qt::LeftButton) {
switch (getStatus()) {
case SetCircle1:
case SetCircle2:
case SetCircle3: {
RS_Entity* en = catchCircle(e);
if (!en) return;
pPoints->circles.resize(getStatus());
for(const RS_AtomicEntity* const pc: pPoints->circles)
if(pc == en) continue;
pPoints->circles.push_back(static_cast<RS_AtomicEntity*>(en));
if(getStatus()<=SetCircle2 || (getStatus()==SetCircle3 && getData())){
pPoints->circles.at(pPoints->circles.size()-1)->setHighlighted(true);
graphicView->redraw(RS2::RedrawDrawing);
setStatus(getStatus()+1);
}
}
break;
case SetCenter:
pPoints->coord= graphicView->toGraph(e->x(), e->y());
if( preparePreview()) trigger();
break;
default:
break;
}
} else if (e->button()==Qt::RightButton) {
// Return to last status:
if(getStatus()>0){
pPoints->circles[getStatus()-1]->setHighlighted(false);
pPoints->circles.pop_back();
graphicView->redraw(RS2::RedrawDrawing);
deletePreview();
}
init(getStatus()-1);
}
}
//void RS_ActionDrawCircleTan3::coordinateEvent(RS_CoordinateEvent* e) {
//}
//fixme, support command line
/*
void RS_ActionDrawCircleTan3::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetFocus1: {
bool ok;
double m = RS_Math::eval(c, &ok);
if (ok) {
ratio = m / major.magnitude();
if (!isArc) {
trigger();
} else {
setStatus(SetAngle1);
}
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle1: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle1 = RS_Math::deg2rad(a);
setStatus(SetAngle2);
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle2: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle2 = RS_Math::deg2rad(a);
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
default:
break;
}
}
*/
QStringList RS_ActionDrawCircleTan3::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void RS_ActionDrawCircleTan3::updateMouseButtonHints() {
switch (getStatus()) {
case SetCircle1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the first line/arc/circle"),
tr("Cancel"));
break;
case SetCircle2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the second line/arc/circle"),
tr("Back"));
break;
case SetCircle3:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the third line/arc/circle"),
tr("Back"));
break;
case SetCenter:
RS_DIALOGFACTORY->updateMouseWidget(tr("Select the center of the tangent circle"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawCircleTan3::updateMouseCursor() {
graphicView->setMouseCursor(RS2::SelectCursor);
}
// EOF

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
* Draw a common tangent circle of 3 existing circles
* Problem of Appollonius
Copyright (C) 2012 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef RS_ACTIONDRAWCIRCLETAN3_H
#define RS_ACTIONDRAWCIRCLETAN3_H
#include<vector>
#include "rs_previewactioninterface.h"
struct RS_CircleData;
class RS_AtomicEntity;
/**
* Draw Common tangential circle of 3 given circles, i.e. Appollonius's problem
*
* @author Dongxu Li
*/
class RS_ActionDrawCircleTan3 : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetCircle1, // Setting the First Circle. */
SetCircle2, // Setting the Second Circle. */
SetCircle3, // Setting the Third Circle. */
SetCenter // select the closest tangential Circle. */
};
public:
RS_ActionDrawCircleTan3(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawCircleTan3() override;
void init(int status=0) override;
void trigger() override;
bool getData();
bool preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
// void coordinateEvent(RS_CoordinateEvent* e) override;
// void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void finish(bool updateTB=true) override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
//protected:
private:
std::vector<double> verifyCenter(const RS_Vector& center) const;
std::vector<double> getRadii(RS_AtomicEntity* entity, const RS_Vector& center) const;
RS_Entity* catchCircle(QMouseEvent* e);
struct Points;
std::unique_ptr<Points> pPoints;
//list of entity types supported by current action
const EntityTypeList enTypeList = EntityTypeList {RS2::EntityArc, RS2::EntityCircle, RS2::EntityLine, RS2::EntityPoint};
};
#endif

View File

@@ -0,0 +1,319 @@
/****************************************************************************
**
* Draw ellipse by foci and a point on ellipse
Copyright (C) 2011 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawellipse4points.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_circle.h"
#include "rs_ellipse.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawEllipse4Points::Points {
RS_VectorSolutions points;
RS_CircleData cData;
RS_EllipseData eData;
bool valid,evalid;
bool m_bUniqueEllipse{false}; //a message of non-unique ellipse is shown
};
/**
* Constructor.
*
*/
RS_ActionDrawEllipse4Points::RS_ActionDrawEllipse4Points(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw ellipse from 4 points", container,
graphicView)
, pPoints(new Points{})
{
actionType=RS2::ActionDrawEllipse4Points;
}
RS_ActionDrawEllipse4Points::~RS_ActionDrawEllipse4Points() = default;
void RS_ActionDrawEllipse4Points::init(int status) {
RS_PreviewActionInterface::init(status);
if(getStatus() == SetPoint1) pPoints->points.clear();
}
void RS_ActionDrawEllipse4Points::trigger() {
RS_PreviewActionInterface::trigger();
RS_Entity* en;
if(getStatus()==SetPoint4 && pPoints->evalid){
en=new RS_Ellipse(container, pPoints->eData);
}else{
en=new RS_Circle(container, pPoints->cData);
}
// update undo list:
deletePreview();
container->addEntity(en);
if (document) {
document->startUndoCycle();
document->addUndoable(en);
document->endUndoCycle();
}
RS_Vector rz = graphicView->getRelativeZero();
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(rz);
drawSnapper();
setStatus(SetPoint1);
// RS_DEBUG->print("RS_ActionDrawEllipse4Point::trigger():" " entity added: %d", ellipse->getId());
// RS_DEBUG->print("RS_ActionDrawEllipse4Point::trigger():" " entity added: %d", ellipse->getId());
}
void RS_ActionDrawEllipse4Points::mouseMoveEvent(QMouseEvent* e) {
// RS_DEBUG->print("RS_ActionDrawEllipse4Point::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
pPoints->points.set(getStatus(),mouse);
if(preparePreview()) {
switch(getStatus()) {
case SetPoint2:
case SetPoint3:
if(pPoints->valid){
RS_Circle* circle=new RS_Circle(preview.get(), pPoints->cData);
deletePreview();
preview->addEntity(circle);
drawPreview();
}
break;
case SetPoint4:
if(pPoints->evalid){
deletePreview();
RS_Ellipse* e=new RS_Ellipse(preview.get(), pPoints->eData);
preview->addEntity(e);
drawPreview();
}
default:
break;
}
}
// RS_DEBUG->print("RS_ActionDrawEllipse4Point::mouseMoveEvent end");
}
bool RS_ActionDrawEllipse4Points::preparePreview(){
pPoints->valid=false;
switch(getStatus()) {
case SetPoint2:
case SetPoint3:
{
RS_Circle c(preview.get(), pPoints->cData);
pPoints->valid= c.createFrom3P(pPoints->points);
if(pPoints->valid){
pPoints->cData = c.getData();
}
}
break;
case SetPoint4:
{
int j=SetPoint4;
pPoints->evalid=false;
if ((pPoints->points.get(j) - pPoints->points.get(j-1)).squared() <RS_TOLERANCE15){
RS_Circle c(preview.get(), pPoints->cData);
pPoints->valid= c.createFrom3P(pPoints->points);
if (pPoints->valid) {
pPoints->cData = c.getData();
}
} else {
RS_Ellipse e{preview.get(), pPoints->eData};
pPoints->valid= e.createFrom4P(pPoints->points);
if (pPoints->valid) {
pPoints->evalid=pPoints->valid;
pPoints->eData = e.getData();
pPoints->m_bUniqueEllipse=false;
} else {
pPoints->evalid=false;
if (pPoints->m_bUniqueEllipse==false) {
RS_DIALOGFACTORY->commandMessage(tr("Can not determine uniquely an ellipse"));
pPoints->m_bUniqueEllipse=true;
}
}
}
}
break;
default:
break;
}
return pPoints->valid;
}
void RS_ActionDrawEllipse4Points::mouseReleaseEvent(QMouseEvent* e) {
// Proceed to next status
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
}
// Return to last status:
else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawEllipse4Points::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) {
return;
}
RS_Vector mouse = e->getCoordinate();
pPoints->points.alloc(getStatus()+1);
pPoints->points.set(getStatus(),mouse);
switch (getStatus()) {
case SetPoint1:
graphicView->moveRelativeZero(mouse);
setStatus(SetPoint2);
break;
case SetPoint2:
case SetPoint3:
case SetPoint4:
if( preparePreview()) {
graphicView->moveRelativeZero(mouse);
if(getStatus() == SetPoint4 ||
(pPoints->points.get(getStatus()) - pPoints->points.get(getStatus()-1)).squared() <RS_TOLERANCE15) {
//also draw the entity, if clicked on the same point twice
trigger();
}else{
setStatus(getStatus()+1);
}
}
default:
break;
}
}
//fixme, support command line
/*
void RS_ActionDrawEllipse4Point::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetFocus1: {
bool ok;
double m = RS_Math::eval(c, &ok);
if (ok) {
ratio = m / major.magnitude();
if (!isArc) {
trigger();
} else {
setStatus(SetAngle1);
}
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
}
break;
case SetAngle1: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle1 = RS_Math::deg2rad(a);
setStatus(SetAngle2);
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
}
break;
case SetAngle2: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle2 = RS_Math::deg2rad(a);
trigger();
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
}
break;
default:
break;
}
}
*/
QStringList RS_ActionDrawEllipse4Points::getAvailableCommands() {
return {};
}
void RS_ActionDrawEllipse4Points::updateMouseButtonHints() {
switch (getStatus()) {
case SetPoint1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the first point on ellipse"),
tr("Cancel"));
break;
case SetPoint2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the second point on ellipse"),
tr("Back"));
break;
case SetPoint3:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the third point on ellipse"),
tr("Back"));
break;
case SetPoint4:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the fourth point on ellipse"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawEllipse4Points::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
* Draw ellipse by foci and a point on ellipse
Copyright (C) 2011 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef RS_ACTIONDRAWELLIPSE4POINTS_H
#define RS_ACTIONDRAWELLIPSE4POINTS_H
#include "rs_previewactioninterface.h"
struct RS_CircleData;
struct RS_EllipseData;
/**
* Draw ellipse in XY direction by 4 points on ellipse
*
* @author Dongxu Li
*/
class RS_ActionDrawEllipse4Points : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetPoint1, // Setting the First Point. */
SetPoint2, // Setting the Second Point. */
SetPoint3, // Setting the Third Point. */
SetPoint4 // Setting the Last Point. */
};
public:
RS_ActionDrawEllipse4Points(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawEllipse4Points() override;
void init(int status=0) override;
void trigger() override;
bool preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
// void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
// 4 points on ellipse
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,393 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<cmath>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawellipseaxis.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_ellipse.h"
#include "rs_line.h"
#include "rs_coordinateevent.h"
#include "rs_math.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawEllipseAxis::Points {
/** Center of ellipse */
RS_Vector center;
/** Endpoint of major axis */
RS_Vector m_vMajorP;
/** Ratio major / minor */
double ratio;
/** Start angle */
double angle1;
/** End angle */
double angle2;
/** Do we produce an arc (true) or full ellipse (false) */
bool isArc;
};
/**
* Constructor.
*
* @param isArc true if this action will produce an ellipse arc.
* false if it will produce a full ellipse.
*/
RS_ActionDrawEllipseAxis::RS_ActionDrawEllipseAxis(
RS_EntityContainer& container,
RS_GraphicView& graphicView,
bool isArc)
:RS_PreviewActionInterface("Draw ellipse with axis",
container, graphicView)
,pPoints(new Points{{}, {}, 0.5, 0., isArc?2.*M_PI:0., isArc})
{
actionType=isArc?RS2::ActionDrawEllipseArcAxis:RS2::ActionDrawEllipseAxis;
}
RS_ActionDrawEllipseAxis::~RS_ActionDrawEllipseAxis() = default;
void RS_ActionDrawEllipseAxis::init(int status) {
RS_PreviewActionInterface::init(status);
if (status==SetCenter) {
pPoints->center = {};
}
if (status<=SetMajor) {
pPoints->m_vMajorP = {};
}
if (status<=SetMinor) {
pPoints->ratio = 0.5;
}
if (status<=SetAngle1) {
pPoints->angle1 = 0.0;
}
if (status<=SetAngle2) {
pPoints->angle2 = 0.0;
}
}
void RS_ActionDrawEllipseAxis::trigger() {
RS_PreviewActionInterface::trigger();
RS_Ellipse* ellipse = new RS_Ellipse{container,
{pPoints->center, pPoints->m_vMajorP, pPoints->ratio,
pPoints->angle1, pPoints->angle2, false}
};
if (pPoints->ratio > 1.){
ellipse->switchMajorMinor();
}
ellipse->setLayerToActive();
ellipse->setPenToActive();
container->addEntity(ellipse);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(ellipse);
document->endUndoCycle();
}
RS_Vector rz = graphicView->getRelativeZero();
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(rz);
drawSnapper();
setStatus(SetCenter);
RS_DEBUG->print("RS_ActionDrawEllipseAxis::trigger():"
" entity added: %d", ellipse->getId());
}
void RS_ActionDrawEllipseAxis::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawEllipseAxis::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
// case SetCenter:
// break;
case SetMajor:
if (pPoints->center.valid) {
deletePreview();
preview->addEntity(new RS_Ellipse{preview.get(),
{pPoints->center, mouse-pPoints->center, 0.5, 0.0,
pPoints->isArc?2.*M_PI:0.
, false}});
drawPreview();
}
break;
case SetMinor:
if (pPoints->center.valid && pPoints->m_vMajorP.valid) {
deletePreview();
RS_Line line{pPoints->center-pPoints->m_vMajorP, pPoints->center+pPoints->m_vMajorP};
double d = line.getDistanceToPoint(mouse);
pPoints->ratio = d/(line.getLength()/2);
preview->addEntity(new RS_Ellipse{preview.get(),
{pPoints->center, pPoints->m_vMajorP, pPoints->ratio, 0., pPoints->isArc?2.*M_PI:0.
, false}});
drawPreview();
}
break;
case SetAngle1:
if (pPoints->center.valid && pPoints->m_vMajorP.valid) {
deletePreview();
//angle1 = center.angleTo(mouse);
RS_Vector m = mouse;
m.rotate(pPoints->center, -pPoints->m_vMajorP.angle());
RS_Vector v = m-pPoints->center;
v.y /= pPoints->ratio;
pPoints->angle1 = v.angle(); // + m_vMajorP.angle();
preview->addEntity(new RS_Line{preview.get(), pPoints->center, mouse});
preview->addEntity(new RS_Ellipse{preview.get(),
{pPoints->center, pPoints->m_vMajorP, pPoints->ratio, pPoints->angle1, pPoints->angle1+1.0
, false}});
drawPreview();
}
break;
case SetAngle2:
if (pPoints->center.valid && pPoints->m_vMajorP.valid) {
deletePreview();
//angle2 = center.angleTo(mouse);
RS_Vector m = mouse;
m.rotate(pPoints->center, -pPoints->m_vMajorP.angle());
RS_Vector v = m-pPoints->center;
v.y /= pPoints->ratio;
pPoints->angle2 = v.angle(); // + m_vMajorP.angle();
preview->addEntity(new RS_Line{preview.get(), pPoints->center, mouse});
preview->addEntity(new RS_Ellipse{preview.get(),
{pPoints->center, pPoints->m_vMajorP,
pPoints->ratio,
pPoints->angle1, pPoints->angle2
, false}});
drawPreview();
}
default:
break;
}
RS_DEBUG->print("RS_ActionDrawEllipseAxis::mouseMoveEvent end");
}
void RS_ActionDrawEllipseAxis::mouseReleaseEvent(QMouseEvent* e) {
// Proceed to next status
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
}
// Return to last status:
else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawEllipseAxis::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) return;
RS_Vector const& mouse = e->getCoordinate();
switch (getStatus()) {
case SetCenter:
pPoints->center = mouse;
graphicView->moveRelativeZero(mouse);
setStatus(SetMajor);
break;
case SetMajor:
pPoints->m_vMajorP = mouse- pPoints->center;
setStatus(SetMinor);
break;
case SetMinor: {
RS_Line line{pPoints->center-pPoints->m_vMajorP, pPoints->center+pPoints->m_vMajorP};
double d = line.getDistanceToPoint(mouse);
pPoints->ratio = d/(line.getLength()/2);
if (!pPoints->isArc) {
trigger();
setStatus(SetCenter);
} else {
setStatus(SetAngle1);
}
}
break;
case SetAngle1: {
//angle1 = center.angleTo(mouse);
RS_Vector m = mouse;
m.rotate(pPoints->center, -pPoints->m_vMajorP.angle());
RS_Vector v = m-pPoints->center;
v.y /= pPoints->ratio;
pPoints->angle1 = v.angle();
setStatus(SetAngle2);
} break;
case SetAngle2: {
//angle2 = center.angleTo(mouse);
RS_Vector m = mouse;
m.rotate(pPoints->center, -pPoints->m_vMajorP.angle());
RS_Vector v = m-pPoints->center;
v.y /= pPoints->ratio;
pPoints->angle2 = v.angle();
trigger();
}
break;
default:
break;
}
}
void RS_ActionDrawEllipseAxis::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetMinor: {
bool ok;
double m = RS_Math::eval(c, &ok);
if (ok) {
e->accept();
pPoints->ratio = m / pPoints->m_vMajorP.magnitude();
if (!pPoints->isArc) {
trigger();
} else {
setStatus(SetAngle1);
}
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle1: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
e->accept();
pPoints->angle1 = RS_Math::deg2rad(a);
setStatus(SetAngle2);
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle2: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
e->accept();
pPoints->angle2 = RS_Math::deg2rad(a);
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
default:
break;
}
}
QStringList RS_ActionDrawEllipseAxis::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void RS_ActionDrawEllipseAxis::updateMouseButtonHints() {
switch (getStatus()) {
case SetCenter:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify ellipse center"),
tr("Cancel"));
break;
case SetMajor:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify endpoint of major axis"),
tr("Back"));
break;
case SetMinor:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify endpoint or length of minor axis:"),
tr("Back"));
break;
case SetAngle1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify start angle"),
tr("Back"));
break;
case SetAngle2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify end angle"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawEllipseAxis::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,77 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWELLIPSEAXIS_H
#define RS_ACTIONDRAWELLIPSEAXIS_H
#include "rs_previewactioninterface.h"
/**
* This action class can handle user events to draw ellipses
* with a center point and the endpoints of minor and major axis.
*
* @author Andrew Mustun
*/
class RS_ActionDrawEllipseAxis : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetCenter, /**< Setting the center. */
SetMajor, /**< Setting endpoint of major axis. */
SetMinor, /**< Setting minor/major ratio. */
SetAngle1, /**< Setting start angle. */
SetAngle2 /**< Setting end angle. */
};
public:
RS_ActionDrawEllipseAxis(RS_EntityContainer& container,
RS_GraphicView& graphicView,
bool isArc);
~RS_ActionDrawEllipseAxis() override;
void init(int status=0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,311 @@
/****************************************************************************
**
* Draw ellipse by foci and a point on ellipse
Copyright (C) 2011-2015 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawellipsecenter3points.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_circle.h"
#include "rs_ellipse.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
#include <QDebug>
#include "rs_debug.h"
struct RS_ActionDrawEllipseCenter3Points::Points {
RS_VectorSolutions points;
RS_CircleData cData;
RS_EllipseData eData;
bool valid{false};
};
/**
* Constructor.
*
*/
RS_ActionDrawEllipseCenter3Points::RS_ActionDrawEllipseCenter3Points(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw ellipse by center and 3 points",
container, graphicView)
, pPoints(new Points{})
{
actionType=RS2::ActionDrawEllipseCenter3Points;
}
RS_ActionDrawEllipseCenter3Points::~RS_ActionDrawEllipseCenter3Points() = default;
void RS_ActionDrawEllipseCenter3Points::init(int status) {
RS_PreviewActionInterface::init(status);
if (status==SetCenter) {
pPoints->points.clear();
}
drawSnapper();
}
void RS_ActionDrawEllipseCenter3Points::trigger() {
RS_PreviewActionInterface::trigger();
RS_Ellipse* ellipse=new RS_Ellipse(container, pPoints->eData);
deletePreview();
container->addEntity(ellipse);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(ellipse);
document->endUndoCycle();
}
graphicView->moveRelativeZero(ellipse->getCenter());
graphicView->redraw(RS2::RedrawDrawing);
drawSnapper();
setStatus(SetCenter);
RS_DEBUG->print("RS_ActionDrawEllipseCenter3Points::trigger():"
" entity added: %d", ellipse->getId());
}
void RS_ActionDrawEllipseCenter3Points::mouseMoveEvent(QMouseEvent* e) {
// RS_DEBUG->print("RS_ActionDrawEllipseCenter3Points::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
if(getStatus() == SetCenter) return;
pPoints->points.resize(getStatus());
pPoints->points.push_back(mouse);
if(preparePreview()) {
switch(getStatus()) {
case SetPoint1:
{
RS_Circle* circle=new RS_Circle(preview.get(), pPoints->cData);
deletePreview();
preview->addEntity(circle);
drawPreview();
}
break;
case SetPoint2:
case SetPoint3:
{
deletePreview();
RS_Ellipse* e=new RS_Ellipse(preview.get(), pPoints->eData);
preview->addEntity(e);
drawPreview();
}
default:
break;
}
}
RS_DEBUG->print("RS_ActionDrawEllipseCenter3Points::mouseMoveEvent end");
}
bool RS_ActionDrawEllipseCenter3Points::preparePreview(){
pPoints->valid=false;
switch(getStatus()) {
case SetPoint1:
{
RS_Circle c(preview.get(), pPoints->cData);
pPoints->valid= c.createFromCR(pPoints->points.at(0),
pPoints->points.get(0).distanceTo(pPoints->points.get(1)));
if (pPoints->valid){
pPoints->cData = c.getData();
}
}
break;
case SetPoint2:
case SetPoint3:
{
RS_Ellipse e(preview.get(), pPoints->eData);
pPoints->valid= e.createFromCenter3Points(pPoints->points);
if (pPoints->valid){
pPoints->eData = e.getData();
}
}
break;
default:
break;
}
return pPoints->valid;
}
void RS_ActionDrawEllipseCenter3Points::mouseReleaseEvent(QMouseEvent* e) {
// Proceed to next status
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
}
// Return to last status:
else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawEllipseCenter3Points::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) return;
RS_Vector mouse = e->getCoordinate();
pPoints->points.alloc(getStatus()+1);
pPoints->points.set(getStatus(), mouse);
switch (getStatus()) {
case SetCenter:
graphicView->moveRelativeZero(mouse);
setStatus(SetPoint1);
break;
case SetPoint1:
case SetPoint2:
for(int i=0;i<getStatus()-1;i++) {
if( (mouse-pPoints->points.get(i)).squared() < RS_TOLERANCE15) {
return;//refuse to accept points already chosen
}
}
// setStatus(getStatus()+1);
// break;
// fall-through
case SetPoint3:
if( preparePreview()) {
if(getStatus() == SetPoint3) {
trigger();
}else{
setStatus(getStatus()+1);
}
}
break;
default:
break;
}
}
//fixme, support command line
/*
void RS_ActionDrawEllipseCenter3Points::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetFocus1: {
bool ok;
double m = RS_Math::eval(c, &ok);
if (ok) {
ratio = m / major.magnitude();
if (!isArc) {
trigger();
} else {
setStatus(SetAngle1);
}
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
}
break;
case SetAngle1: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle1 = RS_Math::deg2rad(a);
setStatus(SetAngle2);
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle2: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle2 = RS_Math::deg2rad(a);
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
}
break;
default:
break;
}
}
*/
QStringList RS_ActionDrawEllipseCenter3Points::getAvailableCommands() {
return {};
}
void RS_ActionDrawEllipseCenter3Points::updateMouseButtonHints() {
switch (getStatus()) {
case SetCenter:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the center of ellipse"),
tr("Cancel"));
break;
case SetPoint1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the first point on ellipse"),
tr("Cancel"));
break;
case SetPoint2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the second point on ellipse"),
tr("Back"));
break;
case SetPoint3:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the third point on ellipse"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawEllipseCenter3Points::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,71 @@
/****************************************************************************
**
* Draw ellipse by foci and a point on ellipse
Copyright (C) 2011-2015 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef RS_ACTIONDRAWELLIPSECENTER3POINTS_H
#define RS_ACTIONDRAWELLIPSECENTER3POINTS_H
#include "rs_previewactioninterface.h"
/**
* Draw ellipse by center and 3 points on ellipse
*
* @author Dongxu Li
*/
class RS_ActionDrawEllipseCenter3Points : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetCenter=0, // Setting the Center. */
SetPoint1=1, // Setting the First Point. */
SetPoint2=2, // Setting the Second Point. */
SetPoint3=3 // Setting the Third Point. */
};
public:
RS_ActionDrawEllipseCenter3Points(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawEllipseCenter3Points() override;
void init(int status=0) override;
void trigger() override;
bool preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
// void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
private:
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,261 @@
/****************************************************************************
**
* Draw ellipse by foci and a point on ellipse
Copyright (C) 2011 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include "rs_actiondrawellipsefocipoint.h"
#include<cmath>
#include <QAction>
#include <QMouseEvent>
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_ellipse.h"
#include "rs_coordinateevent.h"
#include "rs_math.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawEllipseFociPoint::Points {
// Foci of ellipse
RS_Vector focus1,focus2;
// A point on ellipse
RS_Vector point;
RS_Vector center,major;
double c; //hold half of distance between foci
double d; //hold half of distance
};
/**
* Constructor.
*
*/
RS_ActionDrawEllipseFociPoint::RS_ActionDrawEllipseFociPoint(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw ellipse by foci and a point",
container, graphicView)
, pPoints(new Points{})
{
actionType=RS2::ActionDrawEllipseFociPoint;
}
RS_ActionDrawEllipseFociPoint::~RS_ActionDrawEllipseFociPoint() = default;
void RS_ActionDrawEllipseFociPoint::init(int status) {
RS_PreviewActionInterface::init(status);
if (status==SetFocus1) {
pPoints->focus1.valid=false;
}
}
double RS_ActionDrawEllipseFociPoint::findRatio() const
{
return sqrt(pPoints->d*pPoints->d-pPoints->c*pPoints->c)/pPoints->d;
}
void RS_ActionDrawEllipseFociPoint::trigger() {
RS_PreviewActionInterface::trigger();
RS_Ellipse* ellipse = new RS_Ellipse{container,
{pPoints->center,
pPoints->major*pPoints->d,
findRatio(),
0., 0.,false}
};
ellipse->setLayerToActive();
ellipse->setPenToActive();
container->addEntity(ellipse);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(ellipse);
document->endUndoCycle();
}
// RS_Vector rz = graphicView->getRelativeZero();
graphicView->moveRelativeZero(ellipse->getCenter());
graphicView->redraw(RS2::RedrawDrawing);
drawSnapper();
setStatus(SetFocus1);
RS_DEBUG->print("RS_ActionDrawEllipseFociPoint::trigger():"
" entity added: %d", ellipse->getId());
}
void RS_ActionDrawEllipseFociPoint::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawEllipseFociPoint::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
case SetPoint:
pPoints->point=mouse;
pPoints->d=0.5*(pPoints->focus1.distanceTo(pPoints->point) +
pPoints->focus2.distanceTo(pPoints->point));
if (pPoints->d > pPoints->c+ RS_TOLERANCE) {
deletePreview();
preview->addEntity(new RS_Ellipse{preview.get(),
{pPoints->center,
pPoints->major*pPoints->d,
findRatio(),
0., 0.,false}});
drawPreview();
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDrawEllipseFociPoint::mouseMoveEvent end");
}
void RS_ActionDrawEllipseFociPoint::mouseReleaseEvent(QMouseEvent* e) {
// Proceed to next status
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
}
// Return to last status:
else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawEllipseFociPoint::coordinateEvent(RS_CoordinateEvent* e) {
if (e==NULL) {
return;
}
RS_Vector mouse = e->getCoordinate();
switch (getStatus()) {
case SetFocus1:
graphicView->moveRelativeZero(mouse);
pPoints->focus1=mouse;
setStatus(SetFocus2);
break;
case SetFocus2:
pPoints->c = 0.5*pPoints->focus1.distanceTo(mouse);
if(pPoints->c > RS_TOLERANCE){
graphicView->moveRelativeZero(mouse);
pPoints->focus2=mouse;
pPoints->center=(pPoints->focus1+pPoints->focus2)*0.5;
pPoints->major=pPoints->focus1-pPoints->center;
pPoints->major /= pPoints->c ;
setStatus(SetPoint);
}
break;
case SetPoint:
pPoints->point=mouse;
pPoints->d=0.5*(pPoints->focus1.distanceTo(pPoints->point)+pPoints->focus2.distanceTo(pPoints->point));
if (pPoints->d > pPoints->c+ RS_TOLERANCE) {
graphicView->moveRelativeZero(mouse);
trigger();
}
break;
default:
break;
}
}
void RS_ActionDrawEllipseFociPoint::commandEvent(RS_CommandEvent* e) {
QString cmd = e->getCommand().toLower();
if (checkCommand("help", cmd)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(": ")+
tr("specify a point on ellipse, or total distance to foci")
);
e->accept();
return;
}
if(getStatus()==SetPoint){
bool ok;
double a = RS_Math::eval(cmd, &ok);
if (ok) {
pPoints->d=0.5*fabs(a);
if (pPoints->d > pPoints->c + RS_TOLERANCE) {
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Total distance %1 is smaller than distance between foci").arg(fabs(a)));
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
}
QStringList RS_ActionDrawEllipseFociPoint::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void RS_ActionDrawEllipseFociPoint::updateMouseButtonHints() {
switch (getStatus()) {
case SetFocus1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify first focus of ellipse"),
tr("Cancel"));
break;
case SetFocus2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify second focus of ellipse"),
tr("Back"));
break;
case SetPoint:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify a point on ellipse or total distance to foci"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawEllipseFociPoint::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,71 @@
/****************************************************************************
**
* Draw ellipse by foci and a point on ellipse
Copyright (C) 2011 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef RS_ACTIONDRAWELLIPSEFOCIPOINT_H
#define RS_ACTIONDRAWELLIPSEFOCIPOINT_H
#include "rs_previewactioninterface.h"
/**
* Draw ellipse by foci and a point on ellipse
*
* @author Dongxu Li
*/
class RS_ActionDrawEllipseFociPoint : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetFocus1, // Setting the first focus. */
SetFocus2, // Setting the second focus. */
SetPoint // Setting a point on ellipse
};
public:
RS_ActionDrawEllipseFociPoint(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawEllipseFociPoint() override;
void init(int status=0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
struct Points;
std::unique_ptr<Points> pPoints;
private:
double findRatio() const;
};
#endif

View File

@@ -0,0 +1,306 @@
/****************************************************************************
**
* Draw ellipse by foci and a point on ellipse
Copyright (C) 2011 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawellipseinscribe.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_ellipse.h"
#include "rs_line.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawEllipseInscribe::Points {
std::vector<RS_Line*> lines;
RS_EllipseData eData;
bool valid{false};
};
/**
* Constructor.
*
*/
RS_ActionDrawEllipseInscribe::RS_ActionDrawEllipseInscribe(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw ellipse inscribed",
container, graphicView)
, pPoints(new Points{})
{
actionType=RS2::ActionDrawEllipseInscribe;
}
RS_ActionDrawEllipseInscribe::~RS_ActionDrawEllipseInscribe() = default;
void RS_ActionDrawEllipseInscribe::clearLines(bool checkStatus)
{
while(pPoints->lines.size() ){
if(checkStatus && (int) pPoints->lines.size()<=getStatus() )
break;
pPoints->lines.back()->setHighlighted(false);
graphicView->drawEntity(pPoints->lines.back());
pPoints->lines.pop_back();
}
}
void RS_ActionDrawEllipseInscribe::init(int status) {
RS_PreviewActionInterface::init(status);
if(status>=0) {
RS_Snapper::suspend();
}
clearLines(true);
}
void RS_ActionDrawEllipseInscribe::finish(bool updateTB){
clearLines(false);
RS_PreviewActionInterface::finish(updateTB);
}
void RS_ActionDrawEllipseInscribe::trigger() {
RS_PreviewActionInterface::trigger();
RS_Ellipse* ellipse=new RS_Ellipse(container, pPoints->eData);
deletePreview();
container->addEntity(ellipse);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(ellipse);
document->endUndoCycle();
}
for(RS_Line*const p: pPoints->lines) {
if(!p) continue;
p->setHighlighted(false);
graphicView->drawEntity(p);
}
drawSnapper();
clearLines(false);
setStatus(SetLine1);
RS_DEBUG->print("RS_ActionDrawEllipse4Line::trigger():"
" entity added: %d", ellipse->getId());
}
void RS_ActionDrawEllipseInscribe::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawEllipse4Line::mouseMoveEvent begin");
if(getStatus() == SetLine4) {
RS_Entity* en = catchEntity(e, RS2::EntityLine, RS2::ResolveAll);
if(!en) return;
if(!(en->isVisible() && en->rtti()== RS2::EntityLine)) return;
for(auto p: pPoints->lines){
if(en == p) return; //do not pull in the same line again
}
if(en->getParent() && en->getParent()->ignoredOnModification()){
return;
}
deletePreview();
clearLines(true);
pPoints->lines.push_back(static_cast<RS_Line*>(en));
if(preparePreview()) {
pPoints->lines.back()->setHighlighted(true);
graphicView->drawEntity(pPoints->lines.back());
RS_Ellipse* e=new RS_Ellipse(preview.get(), pPoints->eData);
preview->addEntity(e);
drawPreview();
}
}
RS_DEBUG->print("RS_ActionDrawEllipse4Line::mouseMoveEvent end");
}
bool RS_ActionDrawEllipseInscribe::preparePreview(){
pPoints->valid=false;
if(getStatus() == SetLine4) {
RS_Ellipse e{preview.get(), RS_EllipseData()};
pPoints->valid= e.createInscribeQuadrilateral(pPoints->lines);
if (pPoints->valid){
pPoints->eData = e.getData();
} else if ( RS_DIALOGFACTORY){
RS_DIALOGFACTORY->commandMessage(tr("Can not determine uniquely an ellipse"));
}
}
return pPoints->valid;
}
void RS_ActionDrawEllipseInscribe::mouseReleaseEvent(QMouseEvent* e) {
// Proceed to next status
if (e->button()==Qt::LeftButton) {
if (!e) return;
RS_Entity* en = catchEntity(e, RS2::EntityLine, RS2::ResolveAll);
if(!en) return;
if(!(en->isVisible() && en->rtti()== RS2::EntityLine)) return;
for(int i=0; i<getStatus(); ++i) {
if(en->getId() == pPoints->lines[i]->getId()) return; //do not pull in the same line again
}
if(en->getParent()) {
if ( en->getParent()->ignoredOnModification()) return;
}
clearLines(true);
pPoints->lines.push_back(static_cast<RS_Line*>(en));
switch (getStatus()) {
case SetLine1:
case SetLine2:
case SetLine3:
en->setHighlighted(true);
graphicView->drawEntity(en);
setStatus(getStatus()+1);
break;
case SetLine4:
if( preparePreview()) {
trigger();
}
default:
break;
}
} else if (e->button()==Qt::RightButton) {
// Return to last status:
if(getStatus()>0){
clearLines(true);
pPoints->lines.back()->setHighlighted(false);
graphicView->drawEntity(pPoints->lines.back());
pPoints->lines.pop_back();
deletePreview();
}
init(getStatus()-1);
}
}
//void RS_ActionDrawEllipseInscribe::coordinateEvent(RS_CoordinateEvent* e) {
//}
//fixme, support command line
/*
void RS_ActionDrawEllipse4Line::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetFocus1: {
bool ok;
double m = RS_Math::eval(c, &ok);
if (ok) {
ratio = m / major.magnitude();
if (!isArc) {
trigger();
} else {
setStatus(SetAngle1);
}
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle1: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle1 = RS_Math::deg2rad(a);
setStatus(SetAngle2);
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
case SetAngle2: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
angle2 = RS_Math::deg2rad(a);
trigger();
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
break;
default:
break;
}
}
*/
QStringList RS_ActionDrawEllipseInscribe::getAvailableCommands() {
QStringList cmd;
return cmd;
}
void RS_ActionDrawEllipseInscribe::updateMouseButtonHints() {
switch (getStatus()) {
case SetLine1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the first line"),
tr("Cancel"));
break;
case SetLine2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the second line"),
tr("Back"));
break;
case SetLine3:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the third line"),
tr("Back"));
break;
case SetLine4:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the fourth line"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawEllipseInscribe::updateMouseCursor() {
graphicView->setMouseCursor(RS2::SelectCursor);
}
// EOF

View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
* Draw ellipse by foci and a point on ellipse
Copyright (C) 2011 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef RS_ACTIONDRAWELLIPSEINSCRIBE_H
#define RS_ACTIONDRAWELLIPSEINSCRIBE_H
#include "rs_previewactioninterface.h"
/**
* Draw ellipse by foci and a point on ellipse
*
* @author Dongxu Li
*/
class RS_ActionDrawEllipseInscribe : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetLine1, // Setting the First Line. */
SetLine2, // Setting the Second Line. */
SetLine3, // Setting the Third Line. */
SetLine4 // Setting the Last Line. */
};
public:
RS_ActionDrawEllipseInscribe(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawEllipseInscribe() override;
void init(int status=0) override;
void trigger() override;
bool preparePreview();
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
// void coordinateEvent(RS_CoordinateEvent* e) override;
// void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void finish(bool updateTB=true) override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
// 4 points on ellipse
private:
void clearLines(bool checkStatus=false);
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,238 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <iostream>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawhatch.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_information.h"
#include "rs_hatch.h"
#include "rs_debug.h"
RS_ActionDrawHatch::RS_ActionDrawHatch(RS_EntityContainer& container, RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw Hatch", container, graphicView)
, data{new RS_HatchData{}}
{
actionType = RS2::ActionDrawHatch;
}
RS_ActionDrawHatch::~RS_ActionDrawHatch() = default;
void RS_ActionDrawHatch::setShowArea(bool s){
m_bShowArea=s;
}
void RS_ActionDrawHatch::init(int status) {
RS_ActionInterface::init(status);
RS_Hatch tmp(container, *data);
tmp.setLayerToActive();
tmp.setPenToActive();
if (RS_DIALOGFACTORY->requestHatchDialog(&tmp)) {
*data = tmp.getData();
trigger();
finish(false);
graphicView->redraw(RS2::RedrawDrawing);
} else {
finish(false);
}
}
void RS_ActionDrawHatch::trigger() {
RS_DEBUG->print("RS_ActionDrawHatch::trigger()");
//if (pos.valid) {
//deletePreview();
RS_Entity* e;
// deselect unhatchable entities:
for(auto e: *container){
if (e->isSelected() &&
(e->rtti()==RS2::EntityHatch ||
/* e->rtti()==RS2::EntityEllipse ||*/ e->rtti()==RS2::EntityPoint ||
e->rtti()==RS2::EntityMText || e->rtti()==RS2::EntityText ||
RS_Information::isDimension(e->rtti()))) {
e->setSelected(false);
}
}
for (e=container->firstEntity(RS2::ResolveAll); e;
e=container->nextEntity(RS2::ResolveAll)) {
if (e->isSelected() &&
(e->rtti()==RS2::EntityHatch ||
/* e->rtti()==RS2::EntityEllipse ||*/ e->rtti()==RS2::EntityPoint ||
e->rtti()==RS2::EntityMText || e->rtti()==RS2::EntityText ||
RS_Information::isDimension(e->rtti()))) {
e->setSelected(false);
}
}
// look for selected contours:
bool haveContour = false;
for (e=container->firstEntity(RS2::ResolveAll); e;
e=container->nextEntity(RS2::ResolveAll)) {
if (e->isSelected()) {
haveContour = true;
}
}
if (!haveContour) {
std::cerr << "no contour selected\n";
return;
}
std::unique_ptr<RS_Hatch> hatch{new RS_Hatch{container, *data}};
hatch->setLayerToActive();
hatch->setPenToActive();
RS_EntityContainer* loop = new RS_EntityContainer(hatch.get());
loop->setPen(RS_Pen(RS2::FlagInvalid));
// add selected contour:
for (RS_Entity* e=container->firstEntity(RS2::ResolveAll); e;
e=container->nextEntity(RS2::ResolveAll)) {
if (e->isSelected()) {
e->setSelected(false);
// entity is part of a complex entity (spline, polyline, ..):
if (e->getParent() &&
// RVT - Don't de-delect the parent EntityPolyline, this is messing up the getFirst and getNext iterators
// (e->getParent()->rtti()==RS2::EntitySpline ||
// e->getParent()->rtti()==RS2::EntityPolyline)) {
(e->getParent()->rtti()==RS2::EntitySpline)) {
e->getParent()->setSelected(false);
}
RS_Entity* cp = e->clone();
cp->setPen(RS_Pen(RS2::FlagInvalid));
cp->reparent(loop);
loop->addEntity(cp);
}
}
hatch->addEntity(loop);
if (hatch->validate()) {
container->addEntity(hatch.get());
if (document) {
document->startUndoCycle();
document->addUndoable(hatch.get());
document->endUndoCycle();
}
hatch->update();
graphicView->redraw(RS2::RedrawDrawing);
bool printArea = true;
switch( hatch->getUpdateError()) {
case RS_Hatch::HATCH_OK :
RS_DIALOGFACTORY->commandMessage(tr("Hatch created successfully."));
break;
case RS_Hatch::HATCH_INVALID_CONTOUR :
RS_DIALOGFACTORY->commandMessage(tr("Hatch Error: Invalid contour found!"));
printArea = false;
break;
case RS_Hatch::HATCH_PATTERN_NOT_FOUND :
RS_DIALOGFACTORY->commandMessage(tr("Hatch Error: Pattern not found!"));
break;
case RS_Hatch::HATCH_TOO_SMALL :
RS_DIALOGFACTORY->commandMessage(tr("Hatch Error: Contour or pattern too small!"));
break;
case RS_Hatch::HATCH_AREA_TOO_BIG :
RS_DIALOGFACTORY->commandMessage(tr("Hatch Error: Contour too big!"));
break;
default :
RS_DIALOGFACTORY->commandMessage(tr("Hatch Error: Undefined Error!"));
printArea = false;
break;
}
if(m_bShowArea && printArea){
RS_DIALOGFACTORY->commandMessage(tr("Total hatch area = %1").
arg(hatch->getTotalArea(),10,'g',8));
}
hatch.release();
} else {
hatch.reset();
RS_DIALOGFACTORY->commandMessage(tr("Invalid hatch area. Please check that "
"the entities chosen form one or more closed contours."));
}
//}
}
void RS_ActionDrawHatch::mouseMoveEvent(QMouseEvent*) {
RS_DEBUG->print("RS_ActionDrawHatch::mouseMoveEvent begin");
/*if (getStatus()==SetPos) {
RS_Vector mouse = snapPoint(e);
pos = mouse;
deletePreview();
if (hatch && !hatch->isVisible()) {
hatch->setVisible(true);
}
offset = RS_Vector(graphicView->toGuiDX(pos.x),
-graphicView->toGuiDY(pos.y));
drawPreview();
}*/
RS_DEBUG->print("RS_ActionDrawHatch::mouseMoveEvent end");
}
void RS_ActionDrawHatch::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
snapPoint(e);
switch (getStatus()) {
case ShowDialog:
break;
default:
break;
}
} else if (e->button()==Qt::RightButton) {
//deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawHatch::updateMouseButtonHints() {
RS_DIALOGFACTORY->updateMouseWidget();
}
void RS_ActionDrawHatch::updateMouseCursor() {
graphicView->setMouseCursor(RS2::SelectCursor);
}
// EOF

View File

@@ -0,0 +1,68 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWHATCH_H
#define RS_ACTIONDRAWHATCH_H
#include "rs_previewactioninterface.h"
struct RS_HatchData;
class RS_Hatch;
/**
* This action class can handle user events to draw hatches.
*
* @author Andrew Mustun
*/
class RS_ActionDrawHatch : public RS_PreviewActionInterface {
Q_OBJECT
/**
* Action States.
*/
enum Status {
ShowDialog /**< Showing the hatch dialog. */
};
public:
RS_ActionDrawHatch(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawHatch();
void init(int status=0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
void setShowArea(bool s);
private:
std::unique_ptr<RS_HatchData> data;
bool m_bShowArea{true};
};
#endif

View File

@@ -0,0 +1,332 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<cmath>
#include <QAction>
#include <QImage>
#include <QMouseEvent>
#include "rs_image.h"
#include "rs_line.h"
#include "rs_units.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_creation.h"
#include "rs_actiondrawimage.h"
#include "rs_coordinateevent.h"
#include "rs_math.h"
#include "rs_preview.h"
struct RS_ActionDrawImage::ImageData {
RS_ImageData data;
QImage img;
};
/**
* Constructor.
*/
RS_ActionDrawImage::RS_ActionDrawImage(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Image",
container, graphicView)
, pImg(new ImageData{})
, lastStatus(ShowDialog)
{
actionType=RS2::ActionDrawImage;
}
RS_ActionDrawImage::~RS_ActionDrawImage() = default;
void RS_ActionDrawImage::init(int status) {
RS_PreviewActionInterface::init(status);
reset();
pImg->data.file = RS_DIALOGFACTORY->requestImageOpenDialog();
// RVT_PORT should we really redarw here?? graphicView->redraw();
if (!pImg->data.file.isEmpty()) {
//std::cout << "file: " << pImg->data.file << "\n";
//qDebug() << "file: " << pImg->data.file;
pImg->img = QImage(pImg->data.file);
setStatus(SetTargetPoint);
} else {
setFinished();
//RS_DIALOGFACTORY->requestToolBar(RS2::ToolBarMain);
}
}
void RS_ActionDrawImage::reset() {
pImg->data = {
0,
{0.0,0.0},
{1.0,0.0},
{0.0,1.0},
{1.0,1.0},
"",
50, 50, 0
};
}
void RS_ActionDrawImage::trigger() {
deletePreview();
if (!pImg->data.file.isEmpty()) {
RS_Creation creation(container, graphicView);
creation.createImage(& pImg->data);
}
graphicView->redraw(RS2::RedrawDrawing);
graphicView->zoomAuto();
finish(false);
}
void RS_ActionDrawImage::mouseMoveEvent(QMouseEvent* e) {
if (getStatus() == SetTargetPoint) {
pImg->data.insertionPoint = snapPoint(e);
deletePreview();
//RS_Creation creation(preview, nullptr, false);
//creation.createInsert(data);
double const w=pImg->img.width();
double const h=pImg->img.height();
RS_Line* line = new RS_Line{preview.get(), {0., 0.}, {w, 0.}};
preview->addEntity(line);
line = new RS_Line{preview.get(), {w, 0.}, {w, h}};
preview->addEntity(line);
line = new RS_Line{preview.get(), {w, h}, {0., h}};
preview->addEntity(line);
line = new RS_Line{preview.get(), {0., h}, {0., 0.}};
preview->addEntity(line);
preview->scale({0., 0.},
{pImg->data.uVector.magnitude(), pImg->data.uVector.magnitude()});
preview->rotate({0.,0.}, pImg->data.uVector.angle());
preview->move(pImg->data.insertionPoint);
drawPreview();
}
}
void RS_ActionDrawImage::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
} else if (e->button()==Qt::RightButton) {
//init(getStatus()-1);
finish(false);
}
}
void RS_ActionDrawImage::coordinateEvent(RS_CoordinateEvent* e) {
if (e==nullptr) {
return;
}
pImg->data.insertionPoint = e->getCoordinate();
trigger();
}
void RS_ActionDrawImage::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetTargetPoint:
if (checkCommand("angle", c)) {
deletePreview();
lastStatus = (Status)getStatus();
setStatus(SetAngle);
} else if (checkCommand("factor", c)) {
deletePreview();
lastStatus = (Status)getStatus();
setStatus(SetFactor);
} else if (checkCommand("dpi",c)) {
deletePreview();
lastStatus =(Status)getStatus();
setStatus(SetDPI);
}
break;
case SetAngle: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
setAngle(RS_Math::deg2rad(a));
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
case SetFactor: {
bool ok;
double f = RS_Math::eval(c, &ok);
if (ok) {
setFactor(f);
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
case SetDPI : {
bool ok;
double dpi = RS_Math::eval(c, &ok);
if(ok) {
setFactor(RS_Units::dpiToScale(dpi, document->getGraphicUnit()));
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
default:
break;
}
}
double RS_ActionDrawImage::getAngle() const {
return pImg->data.uVector.angle();
}
void RS_ActionDrawImage::setAngle(double a) const{
double l = pImg->data.uVector.magnitude();
pImg->data.uVector.setPolar(l, a);
pImg->data.vVector.setPolar(l, a+M_PI_2);
}
double RS_ActionDrawImage::getFactor() const {
return pImg->data.uVector.magnitude();
}
void RS_ActionDrawImage::setFactor(double f) const {
double a = pImg->data.uVector.angle();
pImg->data.uVector.setPolar(f, a);
pImg->data.vVector.setPolar(f, a+M_PI_2);
}
double RS_ActionDrawImage::dpiToScale(double dpi) const {
return RS_Units::dpiToScale(dpi, document->getGraphicUnit());
}
double RS_ActionDrawImage::scaleToDpi(double scale) const {
return RS_Units::scaleToDpi(scale, document->getGraphicUnit());
}
void RS_ActionDrawImage::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
QStringList RS_ActionDrawImage::getAvailableCommands() {
QStringList cmd;
switch (getStatus()) {
case SetTargetPoint:
cmd += command("angle");
cmd += command("factor");
cmd += command("dpi");
break;
default:
break;
}
return cmd;
}
void RS_ActionDrawImage::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
}
void RS_ActionDrawImage::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void RS_ActionDrawImage::updateMouseButtonHints() {
switch (getStatus()) {
case SetTargetPoint:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify reference point"),
tr("Cancel"));
break;
case SetAngle:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter angle:"),
"");
break;
case SetFactor:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter factor:"),
"");
break;
case SetDPI:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter dpi:"),
"");
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
// EOF

View File

@@ -0,0 +1,104 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWIMAGE_H
#define RS_ACTIONDRAWIMAGE_H
#include<memory>
#include "rs_previewactioninterface.h"
struct RS_ImageData;
class QImage;
/**
* This action class can handle user events for inserting bitmaps into the
* current drawing.
*
* @author Andrew Mustun
*/
class RS_ActionDrawImage : public RS_PreviewActionInterface {
Q_OBJECT
/**
* Action States.
*/
enum Status {
ShowDialog, /**< Dialog. */
SetTargetPoint, /**< Setting the reference point. */
SetAngle, /**< Setting angle in the command line. */
SetFactor, /**< Setting factor in the command line. */
SetDPI /**< Setting dpi in the command line. */
//SetColumns, /**< Setting columns in the command line. */
//SetRows, /**< Setting rows in the command line. */
//SetColumnSpacing, /**< Setting column spacing in the command line. */
//SetRowSpacing /**< Setting row spacing in the command line. */
};
public:
RS_ActionDrawImage(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawImage() override;
void init(int status=0) override;
void reset();
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void showOptions() override;
void hideOptions() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
// void updateToolBar() override;
double getAngle() const;
void setAngle(double a) const;
double getFactor() const;
void setFactor(double f) const;
double dpiToScale(double dpi) const;
double scaleToDpi(double scale) const;
protected:
struct ImageData;
std::unique_ptr<ImageData> pImg;
/** Last status before entering option. */
Status lastStatus;
};
#endif

View File

@@ -0,0 +1,481 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2019 A. Stebich (librecad@mail.lordofbikes.de)
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <cmath>
#include <vector>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawline.h"
#include "rs_actioneditundo.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commands.h"
#include "rs_commandevent.h"
#include "rs_line.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawLine::History
{
explicit History(RS_ActionDrawLine::HistoryAction a,
const RS_Vector& p,
const RS_Vector& c,
const int s) :
histAct( a),
prevPt( p),
currPt( c),
startOffset( s) {}
explicit History(const History& h) :
histAct( h.histAct),
prevPt( h.prevPt),
currPt( h.currPt),
startOffset( h.startOffset) {}
History& operator=(const History& rho) {
histAct = rho.histAct;
prevPt = rho.prevPt;
currPt = rho.currPt;
startOffset = rho.startOffset;
return *this;
}
RS_ActionDrawLine::HistoryAction histAct; ///< action to undo/redo
RS_Vector prevPt; ///< previous coordinate
RS_Vector currPt; ///< current coordinate
int startOffset;///< offset to start point for close method
};
struct RS_ActionDrawLine::Points
{
/// Line data defined so far
RS_LineData data;
/// Point history (undo/redo pointer)
int historyIndex {-1};
/// start point offset for close method
int startOffset {0};
/// Point history (undo/redo buffer)
std::vector<History> history;
/// wrapper for historyIndex to avoid 'signedness' warnings where std::vector-methods expect size_t
/// also, offset helps in close method to find starting point
size_t index(const int offset = 0);
};
size_t RS_ActionDrawLine::Points::index(const int offset /*= 0*/)
{
return static_cast<size_t>( std::max( 0, historyIndex + offset));
}
RS_ActionDrawLine::RS_ActionDrawLine(RS_EntityContainer& container,
RS_GraphicView& graphicView) :
RS_PreviewActionInterface( "Draw lines", container, graphicView),
pPoints( new Points{})
{
RS_DEBUG->print("RS_ActionDrawLine::RS_ActionDrawLine");
actionType=RS2::ActionDrawLine;
}
RS_ActionDrawLine::~RS_ActionDrawLine() = default;
void RS_ActionDrawLine::reset()
{
RS_DEBUG->print("RS_ActionDrawLine::reset");
pPoints.reset(new Points{});
}
void RS_ActionDrawLine::init(int status)
{
RS_DEBUG->print("RS_ActionDrawLine::init");
RS_PreviewActionInterface::init(status);
reset();
drawSnapper();
}
void RS_ActionDrawLine::trigger()
{
RS_PreviewActionInterface::trigger();
RS_Line* line = new RS_Line(container, pPoints->data);
line->setLayerToActive();
line->setPenToActive();
container->addEntity(line);
// update undo list
if (document) {
document->startUndoCycle();
document->addUndoable(line);
document->endUndoCycle();
}
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(pPoints->history.at(pPoints->index()).currPt);
RS_DEBUG->print("RS_ActionDrawLine::trigger(): line added: %d",
line->getId());
}
void RS_ActionDrawLine::mouseMoveEvent(QMouseEvent* e)
{
RS_Vector mouse = snapPoint(e);
if (getStatus() == SetEndpoint && pPoints->data.startpoint.valid) {
// Snapping to angle(15*) if shift key is pressed
if (e->modifiers() & Qt::ShiftModifier) {
mouse = snapToAngle(mouse, pPoints->data.startpoint, 15.);
}
deletePreview();
RS_Line *line = new RS_Line(pPoints->data.startpoint, mouse);
preview->addEntity(line);
line->setLayerToActive();
line->setPenToActive();
drawPreview();
}
}
void RS_ActionDrawLine::mouseReleaseEvent(QMouseEvent* e)
{
if (e->button() == Qt::LeftButton) {
RS_Vector snapped = snapPoint(e);
// Snapping to angle(15*) if shift key is pressed
if ((e->modifiers() & Qt::ShiftModifier)
&& getStatus() == SetEndpoint ) {
snapped = snapToAngle(snapped, pPoints->data.startpoint, 15.);
}
RS_CoordinateEvent ce(snapped);
coordinateEvent(&ce);
}
else if (e->button() == Qt::RightButton) {
deletePreview();
switch (getStatus()) {
default:
case SetStartpoint:
init( getStatus() - 1);
break;
case SetEndpoint:
next();
break;
}
}
}
void RS_ActionDrawLine::coordinateEvent(RS_CoordinateEvent* e)
{
RS_DEBUG->print("RS_ActionDrawLine::coordinateEvent");
if (nullptr == e) {
RS_DEBUG->print("RS_ActionDrawLine::coordinateEvent: event was nullptr");
return;
}
RS_Vector mouse = e->getCoordinate();
if (pPoints->data.startpoint.valid == false
&& getStatus() == SetEndpoint) {
setStatus(SetStartpoint);
pPoints->startOffset = 0;
}
switch (getStatus()) {
case SetStartpoint:
pPoints->data.startpoint = mouse;
pPoints->startOffset = 0;
addHistory( HA_SetStartpoint, graphicView->getRelativeZero(), mouse, pPoints->startOffset);
setStatus(SetEndpoint);
graphicView->moveRelativeZero(mouse);
updateMouseButtonHints();
break;
case SetEndpoint:
if ((mouse-pPoints->data.startpoint).squared() > RS_TOLERANCE2) {
// refuse zero length lines
pPoints->data.endpoint = mouse;
++pPoints->startOffset;
addHistory( HA_SetEndpoint, pPoints->data.startpoint, mouse, pPoints->startOffset);
trigger();
pPoints->data.startpoint = pPoints->data.endpoint;
if (pPoints->history.size() >= 2) {
updateMouseButtonHints();
}
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDrawLine::coordinateEvent: OK");
}
void RS_ActionDrawLine::commandEvent(RS_CommandEvent* e)
{
RS_DEBUG->print("RS_ActionDrawLine::commandEvent");
QString c = e->getCommand().toLower();
switch (getStatus()) {
case SetStartpoint:
if (checkCommand( "help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
e->accept();
return;
}
break;
case SetEndpoint:
if (checkCommand( "close", c)) {
close();
e->accept();
updateMouseButtonHints();
return;
}
if (checkCommand( "undo", c)) {
undo();
e->accept();
updateMouseButtonHints();
return;
}
break;
default:
return;
}
if (checkCommand( "redo", c)) {
redo();
e->accept();
updateMouseButtonHints();
}
RS_DEBUG->print("RS_ActionDrawLine::commandEvent: OK");
}
QStringList RS_ActionDrawLine::getAvailableCommands()
{
QStringList cmd;
if (pPoints->index() + 1 < pPoints->history.size()) {
cmd += command("redo");
}
switch (getStatus()) {
case SetStartpoint:
break;
case SetEndpoint:
if (pPoints->historyIndex >= 1) {
cmd += command("undo");
}
if (pPoints->startOffset >= 2) {
cmd += command("close");
}
break;
default:
break;
}
return cmd;
}
void RS_ActionDrawLine::updateMouseButtonHints()
{
switch (getStatus()) {
case SetStartpoint:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify first point"),
tr("Cancel"));
break;
case SetEndpoint: {
QString msg = "";
if (pPoints->startOffset >= 2) {
msg += RS_COMMANDS->command("close");
}
if (pPoints->index() + 1 < pPoints->history.size()) {
if (msg.size() > 0) {
msg += "/";
}
msg += RS_COMMANDS->command("redo");
}
if (pPoints->historyIndex >= 1) {
if (msg.size() > 0) {
msg += "/";
}
msg += RS_COMMANDS->command("undo");
}
if (pPoints->historyIndex >= 1) {
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify next point or [%1]").arg(msg),
tr("Back"));
} else {
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify next point"),
tr("Back"));
}
break;
}
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawLine::showOptions()
{
RS_DEBUG->print("RS_ActionDrawLine::showOptions");
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
}
void RS_ActionDrawLine::hideOptions()
{
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void RS_ActionDrawLine::updateMouseCursor()
{
graphicView->setMouseCursor(RS2::CadCursor);
}
void RS_ActionDrawLine::close()
{
if (SetEndpoint != getStatus()) {
return;
}
if (1 < pPoints->startOffset
&& 0 <= pPoints->historyIndex - pPoints->startOffset) {
History h(pPoints->history.at( pPoints->index( -pPoints->startOffset)));
if ((pPoints->data.startpoint - h.currPt).squared() > RS_TOLERANCE2) {
pPoints->data.endpoint = h.currPt;
addHistory( HA_Close, pPoints->data.startpoint, pPoints->data.endpoint, pPoints->startOffset);
trigger();
setStatus(SetStartpoint);
}
}
else {
RS_DIALOGFACTORY->commandMessage(tr("Cannot close sequence of lines: "
"Not enough entities defined yet, or already closed."));
}
}
void RS_ActionDrawLine::next()
{
addHistory( HA_Next, pPoints->data.startpoint, pPoints->data.endpoint, pPoints->startOffset);
setStatus(SetStartpoint);
}
void RS_ActionDrawLine::addHistory(RS_ActionDrawLine::HistoryAction a, const RS_Vector& p, const RS_Vector& c, const int s)
{
if (pPoints->historyIndex < -1) {
pPoints->historyIndex = -1;
}
pPoints->history.erase(pPoints->history.begin() + pPoints->historyIndex + 1, pPoints->history.end());
pPoints->history.push_back( History( a, p, c, s));
pPoints->historyIndex = static_cast<int>(pPoints->history.size() - 1);
}
void RS_ActionDrawLine::undo()
{
if (0 <= pPoints->historyIndex) {
History h( pPoints->history.at( pPoints->index()));
--pPoints->historyIndex;
deletePreview();
graphicView->moveRelativeZero(h.prevPt);
switch (h.histAct) {
case HA_SetStartpoint:
setStatus(SetStartpoint);
break;
case HA_SetEndpoint:
case HA_Close:
graphicView->setCurrentAction( new RS_ActionEditUndo(true, *container, *graphicView));
pPoints->data.startpoint = h.prevPt;
setStatus(SetEndpoint);
break;
case HA_Next:
pPoints->data.startpoint = h.prevPt;
setStatus(SetEndpoint);
break;
}
// get index for close from new current history
h = pPoints->history.at( pPoints->index());
pPoints->startOffset = h.startOffset;
}
else {
RS_DIALOGFACTORY->commandMessage(tr("Cannot undo: "
"Begin of history reached"));
}
}
void RS_ActionDrawLine::redo()
{
if (pPoints->history.size() > (pPoints->index() + 1)) {
++pPoints->historyIndex;
History h( pPoints->history.at( pPoints->index()));
deletePreview();
graphicView->moveRelativeZero(h.currPt);
pPoints->data.startpoint = h.currPt;
pPoints->startOffset = h.startOffset;
switch (h.histAct) {
case HA_SetStartpoint:
setStatus(SetEndpoint);
break;
case HA_SetEndpoint:
graphicView->setCurrentAction( new RS_ActionEditUndo(false, *container, *graphicView));
setStatus(SetEndpoint);
break;
case HA_Close:
graphicView->setCurrentAction( new RS_ActionEditUndo(false, *container, *graphicView));
setStatus(SetStartpoint);
break;
case HA_Next:
setStatus(SetStartpoint);
break;
}
}
else {
RS_DIALOGFACTORY->commandMessage( tr("Cannot redo: "
"End of history reached"));
}
}

View File

@@ -0,0 +1,93 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2019 A. Stebich (librecad@mail.lordofbikes.de)
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWLINE_H
#define RS_ACTIONDRAWLINE_H
#include "rs_previewactioninterface.h"
/**
* This action class can handle user events to draw
* simple lines with the start- and endpoint given.
*
* @author Andrew Mustun
*/
class RS_ActionDrawLine : public RS_PreviewActionInterface
{
Q_OBJECT
public:
/// Action States
enum Status {
SetStartpoint, ///< Setting the startpoint
SetEndpoint ///< Setting the endpoint
};
/// History Actions
enum HistoryAction {
HA_SetStartpoint, ///< Setting the startpoint
HA_SetEndpoint, ///< Setting the endpoint
HA_Close, ///< Close group of lines
HA_Next ///< Start new group of lines
};
public:
RS_ActionDrawLine(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawLine() override;
void reset();
void init(int status=0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void showOptions() override;
void hideOptions() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
void addHistory(RS_ActionDrawLine::HistoryAction a, const RS_Vector& p, const RS_Vector& c, const int s);
void close();
void next();
void undo();
void redo();
protected:
struct History;
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,333 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include<cmath>
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawlineangle.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_settings.h"
#include "rs_line.h"
#include "rs_coordinateevent.h"
#include "rs_math.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawLineAngle::Points {
/**
* Line data defined so far.
*/
RS_LineData data;
/**
* Position.
*/
RS_Vector pos;
/**
* Line angle.
*/
double angle;
/**
* Line length.
*/
double length{1.};
/**
* Is the angle fixed?
*/
bool fixedAngle;
/**
* Snap point (start, middle, end).
*/
int snpPoint{0};
};
RS_ActionDrawLineAngle::RS_ActionDrawLineAngle(RS_EntityContainer& container,
RS_GraphicView& graphicView,
double angle,
bool fixedAngle, RS2::ActionType actionType)
:RS_PreviewActionInterface("Draw lines with given angle",
container, graphicView)
, pPoints(new Points{})
{
this->actionType=actionType;
pPoints->angle = angle;
pPoints->fixedAngle = fixedAngle;
RS_DIALOGFACTORY->requestOptions(this, true,false);
reset();
}
RS_ActionDrawLineAngle::~RS_ActionDrawLineAngle() {
RS_SETTINGS->beginGroup("/Draw");
if (!hasFixedAngle()) {
RS_SETTINGS->writeEntry("/LineAngleAngle", RS_Math::rad2deg(getAngle()));
}
RS_SETTINGS->writeEntry("/LineAngleLength", getLength());
RS_SETTINGS->writeEntry("/LineAngleSnapPoint", getSnapPoint());
RS_SETTINGS->endGroup();
}
void RS_ActionDrawLineAngle::reset() {
pPoints->data = {{}, {}};
}
void RS_ActionDrawLineAngle::init(int status) {
RS_PreviewActionInterface::init(status);
reset();
}
void RS_ActionDrawLineAngle::trigger() {
RS_PreviewActionInterface::trigger();
preparePreview();
RS_Line* line = new RS_Line{container, pPoints->data};
line->setLayerToActive();
line->setPenToActive();
container->addEntity(line);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(line);
document->endUndoCycle();
}
graphicView->moveRelativeZero(pPoints->data.startpoint);
graphicView->redraw(RS2::RedrawDrawing);
RS_DEBUG->print("RS_ActionDrawLineAngle::trigger(): line added: %d",
line->getId());
}
void RS_ActionDrawLineAngle::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawLineAngle::mouseMoveEvent begin");
if (getStatus()==SetPos) {
pPoints->pos = snapPoint(e);
deletePreview();
preparePreview();
preview->addEntity(new RS_Line(preview.get(),
pPoints->data));
drawPreview();
}
RS_DEBUG->print("RS_ActionDrawLineAngle::mouseMoveEvent end");
}
void RS_ActionDrawLineAngle::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
if (getStatus()==SetPos) {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
}
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawLineAngle::preparePreview() {
RS_Vector p1, p2;
// End:
if (pPoints->snpPoint == 2) {
p2.setPolar(-pPoints->length, pPoints->angle);
} else {
p2.setPolar(pPoints->length, pPoints->angle);
}
// Middle:
if (pPoints->snpPoint == 1) {
p1 = pPoints->pos - (p2 / 2);
} else {
p1 = pPoints->pos;
}
p2 += p1;
pPoints->data = {p1, p2};
}
void RS_ActionDrawLineAngle::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) return;
switch (getStatus()) {
case SetPos:
pPoints->pos = e->getCoordinate();
trigger();
break;
default:
break;
}
}
void RS_ActionDrawLineAngle::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetPos:
if (!pPoints->fixedAngle && checkCommand("angle", c)) {
deletePreview();
setStatus(SetAngle);
} else if (checkCommand("length", c)) {
deletePreview();
setStatus(SetLength);
}
break;
case SetAngle: {
bool ok;
double a = RS_Math::eval(c, &ok);
if (ok) {
e->accept();
pPoints->angle = RS_Math::deg2rad(a);
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(SetPos);
}
break;
case SetLength: {
bool ok;
double l = RS_Math::eval(c, &ok);
if (ok) {
e->accept();
pPoints->length = l;
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(SetPos);
}
break;
default:
break;
}
}
void RS_ActionDrawLineAngle::setSnapPoint(int sp) {
pPoints->snpPoint = sp;
}
int RS_ActionDrawLineAngle::getSnapPoint() const{
return pPoints->snpPoint;
}
void RS_ActionDrawLineAngle::setAngle(double a) {
pPoints->angle = a;
}
double RS_ActionDrawLineAngle::getAngle() const{
return pPoints->angle;
}
void RS_ActionDrawLineAngle::setLength(double l) {
pPoints->length = l;
}
double RS_ActionDrawLineAngle::getLength() const{
return pPoints->length;
}
bool RS_ActionDrawLineAngle::hasFixedAngle() const{
switch(rtti()){
case RS2::ActionDrawLineHorizontal:
case RS2::ActionDrawLineVertical:
return true;
default:
return false;
}
}
QStringList RS_ActionDrawLineAngle::getAvailableCommands() {
QStringList cmd;
switch (getStatus()) {
case SetPos:
if (!pPoints->fixedAngle) {
cmd += command("angle");
}
cmd += command("length");
break;
default:
break;
}
return cmd;
}
void RS_ActionDrawLineAngle::updateMouseButtonHints() {
switch (getStatus()) {
case SetPos:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify position"),
tr("Cancel"));
break;
case SetAngle:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter angle:"), tr("Back"));
break;
case SetLength:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter length:"), tr("Back"));
break;
default:
break;
}
}
void RS_ActionDrawLineAngle::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true,true);
}
void RS_ActionDrawLineAngle::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void RS_ActionDrawLineAngle::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,97 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWLINEANGLE_H
#define RS_ACTIONDRAWLINEANGLE_H
#include "rs_previewactioninterface.h"
/**
* This action class can handle user events to draw
* simple lines at a gien angle.
*
* @author Andrew Mustun
*/
class RS_ActionDrawLineAngle : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetPos, /**< Setting the position. */
SetAngle, /**< Setting angle in the command line. */
SetLength /**< Setting length in the command line. */
};
RS_ActionDrawLineAngle(RS_EntityContainer& container,
RS_GraphicView& graphicView,
double angle=0.0,
bool fixedAngle=false,
RS2::ActionType actionType=RS2::ActionDrawLineAngle);
~RS_ActionDrawLineAngle() override;
void reset();
void init(int status=0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void preparePreview();
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
void setSnapPoint(int sp);
int getSnapPoint() const;
void setAngle(double a);
double getAngle() const;
void setLength(double l);
double getLength() const;
bool hasFixedAngle() const;
protected:
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,331 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawlinebisector.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_commandevent.h"
#include "rs_creation.h"
#include "rs_line.h"
#include "rs_math.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawLineBisector::Points {
/** Mouse pos when choosing the 1st line */
RS_Vector coord1;
/** Mouse pos when choosing the 2nd line */
RS_Vector coord2;
};
RS_ActionDrawLineBisector::RS_ActionDrawLineBisector(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw Bisectors", container, graphicView)
,bisector(nullptr)
,line1(nullptr)
,line2(nullptr)
,length(10.)
,number(1)
, pPoints(new Points{})
,lastStatus(SetLine1)
{
actionType=RS2::ActionDrawLineBisector;
}
RS_ActionDrawLineBisector::~RS_ActionDrawLineBisector() = default;
void RS_ActionDrawLineBisector::setLength(double l) {
length = l;
}
double RS_ActionDrawLineBisector::getLength() const{
return length;
}
void RS_ActionDrawLineBisector::setNumber(int n) {
number = n;
}
int RS_ActionDrawLineBisector::getNumber() const {
return number;
}
void RS_ActionDrawLineBisector::init(int status) {
RS_PreviewActionInterface::init(status);
if(status>=0) {
RS_Snapper::suspend();
}
if (status<SetLine2) {
if(line2 && line2->isHighlighted()){
line2->setHighlighted(false);
}
if(status<0 && line1 && line1->isHighlighted()){
line1->setHighlighted(false);
}
graphicView->redraw(RS2::RedrawDrawing);
}
}
void RS_ActionDrawLineBisector::trigger() {
RS_PreviewActionInterface::trigger();
for(auto p: {line1, line2}){
if(p && p->isHighlighted()){
p->setHighlighted(false);
}
}
graphicView->redraw(RS2::RedrawDrawing);
RS_Creation creation(container, graphicView);
creation.createBisector(pPoints->coord1,
pPoints->coord2,
length,
number,
line1,
line2);
}
void RS_ActionDrawLineBisector::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawLineBisector::mouseMoveEvent begin");
RS_Vector mouse = RS_Vector(graphicView->toGraphX(e->x()),
graphicView->toGraphY(e->y()));
switch (getStatus()) {
case SetLine1:
break;
case SetLine2: {
pPoints->coord2 = mouse;
RS_Entity* en = catchEntity(e, RS2::ResolveAll);
if(en==line1) break;
if (en && en->rtti()==RS2::EntityLine) {
if(line2 && line2->isHighlighted()){
line2->setHighlighted(false);
}
line2 = static_cast<RS_Line*>(en);
line2->setHighlighted(true);
graphicView->redraw(RS2::RedrawDrawing);
deletePreview();
RS_Creation creation(preview.get(), nullptr, false);
creation.createBisector(pPoints->coord1,
pPoints->coord2,
length,
number,
line1,
line2);
drawPreview();
}else{
if(line2 && line2->isHighlighted()){
line2->setHighlighted(false);
graphicView->redraw(RS2::RedrawDrawing);
}
line2=nullptr;
}
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDrawLineBisector::mouseMoveEvent end");
}
void RS_ActionDrawLineBisector::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
} else {
RS_Vector mouse = RS_Vector(graphicView->toGraphX(e->x()),
graphicView->toGraphY(e->y()));
switch (getStatus()) {
case SetLine1: {
pPoints->coord1 = mouse;
RS_Entity* en = catchEntity(e, RS2::ResolveAll);
if (en && en->rtti()==RS2::EntityLine) {
line1 = static_cast<RS_Line*>(en);
line1->setHighlighted(true);
graphicView->redraw(RS2::RedrawDrawing);
line2=nullptr;
setStatus(SetLine2);
}
}
break;
case SetLine2:
pPoints->coord2 = mouse;
trigger();
setStatus(SetLine1);
break;
}
}
}
void RS_ActionDrawLineBisector::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetLine1:
case SetLine2:
lastStatus = (Status)getStatus();
if (checkCommand("length", c)) {
deletePreview();
setStatus(SetLength);
} else if (checkCommand("number", c)) {
deletePreview();
setStatus(SetNumber);
}
break;
case SetLength: {
bool ok;
double l = RS_Math::eval(c, &ok);
if (ok) {
e->accept();
length = l;
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
case SetNumber: {
bool ok;
int n = (int)RS_Math::eval(c, &ok);
if (ok) {
e->accept();
if(n>0 && n<=200)
number = n;
else
RS_DIALOGFACTORY->commandMessage(tr("Number sector lines not in range: ", "number of bisector to create must be in [1, 200]")+QString::number(n));
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
default:
break;
}
}
QStringList RS_ActionDrawLineBisector::getAvailableCommands() {
QStringList cmd;
switch (getStatus()) {
case SetLine1:
case SetLine2:
cmd += command("length");
cmd += command("number");
break;
default:
break;
}
return cmd;
}
void RS_ActionDrawLineBisector::updateMouseButtonHints() {
switch (getStatus()) {
case SetLine1:
RS_DIALOGFACTORY->updateMouseWidget(tr("Select first line"),
tr("Cancel"));
break;
case SetLine2:
RS_DIALOGFACTORY->updateMouseWidget(tr("Select second line"),
tr("Back"));
break;
case SetLength:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter bisector length:"),
tr("Back"));
break;
case SetNumber:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter number of bisectors:"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawLineBisector::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
}
void RS_ActionDrawLineBisector::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void RS_ActionDrawLineBisector::updateMouseCursor() {
graphicView->setMouseCursor(RS2::SelectCursor);
}
// EOF

View File

@@ -0,0 +1,94 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWLINEBISECTOR_H
#define RS_ACTIONDRAWLINEBISECTOR_H
#include "rs_previewactioninterface.h"
class RS_Line;
/**
* This action class can handle user events to draw bisectors.
*
* @author Andrew Mustun
*/
class RS_ActionDrawLineBisector : public RS_PreviewActionInterface {
Q_OBJECT
private:
enum Status {
SetLine1, /**< Choose the 1st line. */
SetLine2, /**< Choose the 2nd line. */
SetLength, /**< Set length in command line. */
SetNumber /**< Set number in command line. */
};
public:
RS_ActionDrawLineBisector(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawLineBisector() override;
void init(int status=0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
void setLength(double l);
double getLength() const;
void setNumber(int n);
int getNumber() const;
private:
/** Closest bisector. */
RS_Line* bisector;
/** First chosen entity */
RS_Line* line1;
/** Second chosen entity */
RS_Line* line2;
/** Length of the bisector. */
double length;
/** Number of bisectors to create. */
int number;
struct Points;
std::unique_ptr<Points> pPoints;
/** Last status before entering length or number. */
Status lastStatus;
};
#endif

View File

@@ -0,0 +1,153 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawlinefree.h"
#include "rs_polyline.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_preview.h"
#include "rs_debug.h"
RS_ActionDrawLineFree::RS_ActionDrawLineFree(RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw freehand lines",
container, graphicView)
,vertex(new RS_Vector{})
{
preview->setOwner(false);
actionType=RS2::ActionDrawLineFree;
}
RS_ActionDrawLineFree::~RS_ActionDrawLineFree() = default;
void RS_ActionDrawLineFree::trigger() {
deleteSnapper();
if (polyline.get()) {
deletePreview();
polyline->endPolyline();
RS_VectorSolutions sol=polyline->getRefPoints();
if(sol.getNumber() > 2 ) {
RS_Entity* ent=polyline->clone();
container->addEntity(ent);
if (document) {
document->startUndoCycle();
document->addUndoable(ent);
document->endUndoCycle();
}
graphicView->redraw(RS2::RedrawDrawing);
RS_DEBUG->print("RS_ActionDrawLineFree::trigger():"
" polyline added: %d", ent->getId());
}
polyline.reset();
}
setStatus(SetStartpoint);
}
/*
* 11 Aug 2011, Dongxu Li
*/
void RS_ActionDrawLineFree::mouseMoveEvent(QMouseEvent* e) {
RS_Vector v = snapPoint(e);
drawSnapper();
if (getStatus()==Dragging && polyline.get()) {
if( (graphicView->toGui(v) - graphicView->toGui(*vertex)).squared()< 1. ){
//do not add the same mouse position
return;
}
auto ent = static_cast<RS_Polyline*>(polyline->addVertex(v));
if (ent->count()){
preview->addCloneOf(ent);
drawPreview();
}
*vertex = v;
RS_DEBUG->print("RS_ActionDrawLineFree::%s:"
" line added: %d", __func__, ent->getId());
}
}
void RS_ActionDrawLineFree::mousePressEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
switch(getStatus()){
case SetStartpoint:
setStatus(Dragging);
// fall-through
case Dragging:
*vertex = snapPoint(e);
polyline.reset(new RS_Polyline(container,
RS_PolylineData(*vertex, *vertex, 0))
);
polyline->setLayerToActive();
polyline->setPenToActive();
break;
default:
break;
}
}
//else if (RS2::qtToRsButtonState(e->button())==RS2::RightButton && !vertex.valid) {
//}
}
void RS_ActionDrawLineFree::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
if(getStatus()==Dragging){
*vertex = {};
trigger();
}
} else if (e->button()==Qt::RightButton) {
if (polyline.get()) {
polyline.reset();
}
init(getStatus()-1);
}
}
void RS_ActionDrawLineFree::updateMouseButtonHints() {
switch (getStatus()) {
case SetStartpoint:
case Dragging:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Click and drag to draw a line"), tr("Cancel"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawLineFree::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2011 Dongxu Li (dongxuli2011@gmail.com)
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWLINEFREE_H
#define RS_ACTIONDRAWLINEFREE_H
#include "rs_previewactioninterface.h"
class RS_Polyline;
/**
* This action class can handle user events to draw freehand lines.
*
* @author Andrew Mustun
*/
class RS_ActionDrawLineFree : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetStartpoint, /**< Setting the startpoint. */
Dragging /**< Setting the endpoint. */
};
RS_ActionDrawLineFree(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawLineFree() override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mousePressEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
std::unique_ptr<RS_Vector> vertex;
std::unique_ptr<RS_Polyline> polyline;
};
#endif

View File

@@ -0,0 +1,175 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawlinehorvert.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_line.h"
#include "rs_preview.h"
#include "rs_debug.h"
struct RS_ActionDrawLineHorVert::Points {
/**
* Line data.
*/
RS_LineData data;
/**
* 2 points
*/
RS_Vector p1;
RS_Vector p2;
};
RS_ActionDrawLineHorVert::RS_ActionDrawLineHorVert(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw horizontal/vertical lines",
container, graphicView)
, pPoints(new Points{})
{
reset();
RS_DEBUG->print("RS_ActionDrawLineHorVert::constructor");
}
RS_ActionDrawLineHorVert::~RS_ActionDrawLineHorVert() = default;
void RS_ActionDrawLineHorVert::reset() {
pPoints->data = {{}, {}};
}
void RS_ActionDrawLineHorVert::init(int status) {
RS_PreviewActionInterface::init(status);
reset();
RS_DEBUG->print("RS_ActionDrawLineHorVert::init");
}
void RS_ActionDrawLineHorVert::trigger() {
RS_PreviewActionInterface::trigger();
RS_Line* line = new RS_Line(container, pPoints->data);
line->setLayerToActive();
line->setPenToActive();
container->addEntity(line);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(line);
document->endUndoCycle();
}
graphicView->redraw(RS2::RedrawDrawing);
graphicView->moveRelativeZero(line->getMiddlePoint());
RS_DEBUG->print("RS_ActionDrawLineHorVert::trigger():"
" line added: %d", line->getId());
}
void RS_ActionDrawLineHorVert::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawLineHorVert::mouseMoveEvent begin");
RS_Vector mouse = snapPoint(e);
if (getStatus()==SetEndpoint && pPoints->p1.valid) {
RS_Vector p2x = RS_Vector(mouse.x, pPoints->p1.y);
RS_Vector p2y = RS_Vector(pPoints->p1.x, mouse.y);
if (mouse.distanceTo(p2y) > mouse.distanceTo(p2x))
pPoints->p2 = p2x;
else
pPoints->p2 = p2y;
deletePreview();
pPoints->data = {pPoints->p1, pPoints->p2};
preview->addEntity(new RS_Line{preview.get(), pPoints->data});
drawPreview();
}
RS_DEBUG->print("RS_ActionDrawLineHorVert::mouseMoveEvent end");
}
void RS_ActionDrawLineHorVert::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
RS_Vector mouse = snapPoint(e);
switch (getStatus()) {
case SetStartpoint:
pPoints->p1 = mouse;
setStatus(SetEndpoint);
break;
case SetEndpoint:
pPoints->p2 = mouse;
trigger();
setStatus(SetStartpoint);
break;
default:
break;
}
} else if (e->button()==Qt::RightButton) {
deletePreview();
init(getStatus()-1);
}
}
void RS_ActionDrawLineHorVert::updateMouseButtonHints() {
switch (getStatus()) {
case SetStartpoint:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify first point"),
tr("Cancel"));
break;
case SetEndpoint:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify second point"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawLineHorVert::updateMouseCursor() {
graphicView->setMouseCursor(RS2::CadCursor);
}
// EOF

View File

@@ -0,0 +1,70 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWLINEHORVERT_H
#define RS_ACTIONDRAWLINEHORVERT_H
#include "rs_previewactioninterface.h"
/**
* This action class can handle user events to draw
* horizontal/vertical lines from a given startpoint
* to an endpoint closest to a second given point.
* OBSOLETE
*
* @author Ulf Lehnert
*/
class RS_ActionDrawLineHorVert : public RS_PreviewActionInterface {
Q_OBJECT
public:
/**
* Action States.
*/
enum Status {
SetStartpoint, /**< Setting the 1st point. */
SetEndpoint /**< Setting the 2nd point. */
};
public:
RS_ActionDrawLineHorVert(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawLineHorVert() override;
void reset();
void init(int status=0) override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
protected:
struct Points;
std::unique_ptr<Points> pPoints;
};
#endif

View File

@@ -0,0 +1,208 @@
/****************************************************************************
**
* This action class can handle user events to draw tangents normal to lines
Copyright (C) 2011-2012 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#include<QAction>
#include <QMouseEvent>
#include "rs_actiondrawlineorthtan.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_creation.h"
#include "rs_selection.h"
#include "rs_line.h"
#include "rs_preview.h"
#include "rs_debug.h"
namespace{
auto circleList={RS2::EntityArc, RS2::EntityCircle, RS2::EntityEllipse}; //this holds a list of entity types which supports tangent
}
/**
* This action class can handle user events to draw tangents normal to lines
*
* @author Dongxu Li
*/
RS_ActionDrawLineOrthTan::RS_ActionDrawLineOrthTan(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw Tangent Orthogonal", container, graphicView)
,normal(nullptr)
,tangent(nullptr)
,circle(nullptr)
{
actionType=RS2::ActionDrawLineOrthTan;
}
void RS_ActionDrawLineOrthTan::finish(bool updateTB){
clearLines();
RS_PreviewActionInterface::finish(updateTB);
}
void RS_ActionDrawLineOrthTan::trigger() {
if(!tangent) return;
RS_PreviewActionInterface::trigger();
deletePreview();
if(circle)
circle->setHighlighted(false);
circle=nullptr;
graphicView->redraw(RS2::RedrawDrawing);
RS_Entity* newEntity = new RS_Line(container,
tangent->getData());
newEntity->setLayerToActive();
newEntity->setPenToActive();
container->addEntity(newEntity);
// upd. undo list:
if (document) {
document->startUndoCycle();
document->addUndoable(newEntity);
document->endUndoCycle();
}
graphicView->redraw(RS2::RedrawDrawing);
setStatus(SetCircle);
}
void RS_ActionDrawLineOrthTan::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawLineOrthTan::mouseMoveEvent begin");
e->accept();
RS_Vector mouse(graphicView->toGraphX(e->x()),
graphicView->toGraphY(e->y()));
switch(getStatus()){
case SetLine:
return;
case SetCircle:{
RS_Entity* en = catchEntity(e, circleList, RS2::ResolveAll);
if(!en) return;
deletePreview();
if(circle)
circle->setHighlighted(false);
circle = en;
circle->setHighlighted(true);
graphicView->redraw(RS2::RedrawDrawing);
deletePreview();
RS_Creation creation(preview.get(), graphicView, false);
tangent = creation.createLineOrthTan(mouse,
normal,
circle);
preview->addEntity(tangent);
drawPreview();
}
default:
break;
}
RS_DEBUG->print("RS_ActionDrawLineOrthTan::mouseMoveEvent end");
}
void RS_ActionDrawLineOrthTan::clearLines()
{
for(RS_Entity* p: {(RS_Entity*) normal, circle}){
if(p){
p->setHighlighted(false);
graphicView->drawEntity(p);
}
}
if(circle) circle=nullptr;
deletePreview();
}
void RS_ActionDrawLineOrthTan::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::RightButton) {
clearLines();
if (getStatus() == SetLine) {
finish(true);
}else{
init(getStatus()-1);
}
} else {
switch (getStatus()) {
case SetLine: {
RS_Entity* en=catchEntity(e,RS2::EntityLine);
if(en){
if (en->getLength() < RS_TOLERANCE) {
//ignore lines not long enough
break;
}
if(normal) {
normal->setHighlighted(false);
graphicView->drawEntity(normal);
}
normal=static_cast<RS_Line*>(en);
normal->setHighlighted(true);
graphicView->drawEntity(normal);
setStatus(SetCircle);
}
}
break;
case SetCircle:
if(tangent){
trigger();
}
break;
default:
break;
}
}
}
void RS_ActionDrawLineOrthTan::updateMouseButtonHints() {
switch (getStatus()) {
case SetLine:
RS_DIALOGFACTORY->updateMouseWidget(tr("Select a line"),
tr("Cancel"));
break;
case SetCircle:
RS_DIALOGFACTORY->updateMouseWidget(tr("Select circle, arc or ellipse"),
tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawLineOrthTan::updateMouseCursor() {
if(isFinished()) {
graphicView->setMouseCursor(RS2::ArrowCursor);
}else{
graphicView->setMouseCursor(RS2::SelectCursor);
}
}
// EOF

View File

@@ -0,0 +1,67 @@
/****************************************************************************
**
* This action class can handle user events to draw tangents normal to lines
Copyright (C) 2011 Dongxu Li (dongxuli2011@gmail.com)
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**********************************************************************/
#ifndef RS_ACTIONDRAWLINEORTHTAN_H
#define RS_ACTIONDRAWLINEORTHTAN_H
#include "rs_previewactioninterface.h"
class RS_Line;
/**
* This action class can handle user events to draw tangents normal to lines
*
* @author Dongxu Li
*/
class RS_ActionDrawLineOrthTan : public RS_PreviewActionInterface {
Q_OBJECT
private:
enum Status {
SetLine, /**< Choose the line orthogonal to the tangent line */
SetCircle /**< Choose the arc/circle/ellipse to create its tangent line*/
};
public:
RS_ActionDrawLineOrthTan(RS_EntityContainer& container,
RS_GraphicView& graphicView);
void trigger() override;
void finish(bool updateTB = true) override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void updateMouseButtonHints() override;
void updateMouseCursor() override;
private:
void clearLines();
/** normal to tangent. */
RS_Line* normal; // the select normal line
/** tangent. */
RS_Line* tangent; //holds the tangent line for preview
/** arc/circle/ellipse to generate tangent */
RS_Entity* circle;
};
#endif

View File

@@ -0,0 +1,228 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawlineparallel.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_creation.h"
#include "rs_commands.h"
#include "rs_commandevent.h"
#include "rs_actiondrawlineparallelthrough.h"
#include "rs_math.h"
#include "rs_preview.h"
#include "rs_debug.h"
RS_ActionDrawLineParallel::RS_ActionDrawLineParallel(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw Parallels", container, graphicView)
,parallel(nullptr)
,distance(1.0)
,number(1)
, coord(new RS_Vector{})
,entity(nullptr)
{
actionType=RS2::ActionDrawLineParallel;
}
RS_ActionDrawLineParallel::~RS_ActionDrawLineParallel() = default;
double RS_ActionDrawLineParallel::getDistance() const{
return distance;
}
void RS_ActionDrawLineParallel::setDistance(double d) {
distance = d;
}
int RS_ActionDrawLineParallel::getNumber() const{
return number;
}
void RS_ActionDrawLineParallel::setNumber(int n) {
number = n;
}
void RS_ActionDrawLineParallel::trigger() {
RS_PreviewActionInterface::trigger();
RS_Creation creation(container, graphicView);
RS_Entity* e = creation.createParallel(*coord,
distance, number,
entity);
if (!e) {
RS_DEBUG->print("RS_ActionDrawLineParallel::trigger:"
" No parallels added\n");
}
}
void RS_ActionDrawLineParallel::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawLineParallel::mouseMoveEvent begin");
*coord = {graphicView->toGraphX(e->x()), graphicView->toGraphY(e->y())};
entity = catchEntity(e, RS2::ResolveAll);
switch (getStatus()) {
case SetEntity: {
deletePreview();
RS_Creation creation(preview.get(), nullptr, false);
creation.createParallel(*coord,
distance, number,
entity);
drawPreview();
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDrawLineParallel::mouseMoveEvent end");
}
void RS_ActionDrawLineParallel::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::RightButton) {
init(getStatus()-1);
} else {
trigger();
}
}
void RS_ActionDrawLineParallel::updateMouseButtonHints() {
switch (getStatus()) {
case SetEntity:
RS_DIALOGFACTORY->updateMouseWidget(
tr("Specify Distance <%1> or select entity or [%2]")
.arg(distance).arg(RS_COMMANDS->command("through")),
tr("Cancel"));
break;
case SetNumber:
RS_DIALOGFACTORY->updateMouseWidget(tr("Enter number:"), "");
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawLineParallel::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
updateMouseButtonHints();
}
void RS_ActionDrawLineParallel::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void RS_ActionDrawLineParallel::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetEntity: {
if (checkCommand("through", c)) {
finish(false);
graphicView->setCurrentAction(
new RS_ActionDrawLineParallelThrough(*container,
*graphicView));
} else if (checkCommand("number", c)) {
deletePreview();
setStatus(SetNumber);
} else {
bool ok;
double d = RS_Math::eval(c, &ok);
if(ok) e->accept();
if (ok && d>1.0e-10) {
distance = d;
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
RS_DIALOGFACTORY->requestOptions(this, true, true);
updateMouseButtonHints();
//setStatus(SetEntity);
}
}
break;
case SetNumber: {
bool ok;
int n = c.toInt(&ok);
if (ok) {
e->accept();
if (n>0 && n<100) {
number = n;
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid number. "
"Try 1..99"));
} else
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(SetEntity);
}
break;
default:
break;
}
}
QStringList RS_ActionDrawLineParallel::getAvailableCommands() {
QStringList cmd;
switch (getStatus()) {
case SetEntity:
cmd += command("number");
cmd += command("through");
break;
default:
break;
}
return cmd;
}
void RS_ActionDrawLineParallel::updateMouseCursor() {
graphicView->setMouseCursor(RS2::SelectCursor);
}
// EOF

View File

@@ -0,0 +1,103 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWLINEPARALLEL_H
#define RS_ACTIONDRAWLINEPARALLEL_H
#include "rs_previewactioninterface.h"
class RS_Vector;
/**
* This action class can handle user events to draw parallel
* lines, arcs and circles.
*
* @author Andrew Mustun
*/
class RS_ActionDrawLineParallel : public RS_PreviewActionInterface {
Q_OBJECT
private:
enum Status {
SetEntity, /**< Choose original entity. */
//SetDistance, /**< Setting distance in the command line. */
SetNumber /**< Setting number in the command line. */
//SetThrough /**< Setting a point for the parallel to go through. */
};
public:
RS_ActionDrawLineParallel(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawLineParallel() override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void updateMouseButtonHints() override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void updateMouseCursor() override;
// void updateToolBar() override;
double getDistance() const;
void setDistance(double d);
int getNumber() const;
void setNumber(int n);
private:
/** Closest parallel. */
RS_Entity* parallel;
/** Distance of the parallel. */
double distance;
/** Number of parallels. */
int number;
/** Coordinate of the mouse. */
std::unique_ptr<RS_Vector> coord;
/** Original entity. */
RS_Entity* entity;
/**
* Commands
*/
/*
QString cmdDistance;
QString cmdDistance2;
QString cmdDistance3;
QString cmdNumber;
QString cmdNumber2;
QString cmdNumber3;
*/
};
#endif

View File

@@ -0,0 +1,298 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#include <QAction>
#include <QMouseEvent>
#include "rs_actiondrawlineparallelthrough.h"
#include "rs_dialogfactory.h"
#include "rs_graphicview.h"
#include "rs_creation.h"
#include "rs_commandevent.h"
#include "rs_coordinateevent.h"
#include "rs_preview.h"
#include "rs_debug.h"
RS_ActionDrawLineParallelThrough::RS_ActionDrawLineParallelThrough(
RS_EntityContainer& container,
RS_GraphicView& graphicView)
:RS_PreviewActionInterface("Draw Parallels", container, graphicView)
,coord(new RS_Vector{})
,lastStatus(SetEntity)
{
actionType=RS2::ActionDrawLineParallelThrough;
m_SnapDistance=1.;
}
RS_ActionDrawLineParallelThrough::~RS_ActionDrawLineParallelThrough() = default;
void RS_ActionDrawLineParallelThrough::finish(bool updateTB){
if(entity){
entity->setHighlighted(false);
graphicView->drawEntity(entity);
entity=nullptr;
}
RS_PreviewActionInterface::finish(updateTB);
}
void RS_ActionDrawLineParallelThrough::trigger() {
RS_PreviewActionInterface::trigger();
if (entity) {
RS_Creation creation(container, graphicView);
RS_Entity* e = creation.createParallelThrough(*coord,
number,
entity);
if (!e) {
RS_DEBUG->print("RS_ActionDrawLineParallelThrough::trigger:"
" No parallels added\n");
}
}
}
void RS_ActionDrawLineParallelThrough::mouseMoveEvent(QMouseEvent* e) {
RS_DEBUG->print("RS_ActionDrawLineParallelThrough::mouseMoveEvent begin");
switch (getStatus()) {
case SetEntity: {
entity = catchEntity(e, RS2::ResolveAll);
/*deletePreview();
RS_Creation creation(preview, nullptr, false);
creation.createParallelThrough(*coord,
number,
entity);
drawPreview();*/
}
break;
case SetPos: {
*coord = snapPoint(e);
//RS_Vector(graphicView->toGraphX(e->x()),
// graphicView->toGraphY(e->y()));
deletePreview();
RS_Creation creation(preview.get(), nullptr, false);
creation.createParallelThrough(*coord,
number,
entity);
drawPreview();
}
break;
default:
break;
}
RS_DEBUG->print("RS_ActionDrawLineParallelThrough::mouseMoveEvent end");
}
void RS_ActionDrawLineParallelThrough::mouseReleaseEvent(QMouseEvent* e) {
if (e->button()==Qt::LeftButton) {
switch (getStatus()) {
case SetEntity:
entity = catchEntity(e, RS2::ResolveAll);
if (entity) {
entity->setHighlighted(true);
graphicView->drawEntity(entity);
setStatus(SetPos);
}
break;
case SetPos: {
RS_CoordinateEvent ce(snapPoint(e));
coordinateEvent(&ce);
}
break;
default:
break;
}
} else if (e->button()==Qt::RightButton) {
deletePreview();
if (entity) {
entity->setHighlighted(false);
graphicView->drawEntity(entity);
entity=nullptr;
}
init(getStatus()-1);
}
}
void RS_ActionDrawLineParallelThrough::coordinateEvent(RS_CoordinateEvent* e) {
if (!e) {
return;
}
RS_Vector mouse = e->getCoordinate();
switch (getStatus()) {
case SetPos:
*coord = mouse;
trigger();
break;
default:
break;
}
}
void RS_ActionDrawLineParallelThrough::updateMouseButtonHints() {
switch (getStatus()) {
case SetEntity:
RS_DIALOGFACTORY->updateMouseWidget(tr("Select entity"), tr("Cancel"));
break;
case SetPos:
RS_DIALOGFACTORY->updateMouseWidget(tr("Specify through point"),
tr("Back"));
break;
case SetNumber:
RS_DIALOGFACTORY->updateMouseWidget(tr("Number:"), tr("Back"));
break;
default:
RS_DIALOGFACTORY->updateMouseWidget();
break;
}
}
void RS_ActionDrawLineParallelThrough::showOptions() {
RS_ActionInterface::showOptions();
RS_DIALOGFACTORY->requestOptions(this, true);
updateMouseButtonHints();
}
void RS_ActionDrawLineParallelThrough::hideOptions() {
RS_ActionInterface::hideOptions();
RS_DIALOGFACTORY->requestOptions(this, false);
}
void RS_ActionDrawLineParallelThrough::commandEvent(RS_CommandEvent* e) {
QString c = e->getCommand().toLower();
if (checkCommand("help", c)) {
RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
+ getAvailableCommands().join(", "));
return;
}
switch (getStatus()) {
case SetEntity:
case SetPos: {
if (checkCommand("number", c)) {
deletePreview();
lastStatus = (Status)getStatus();
setStatus(SetNumber);
}
}
break;
case SetNumber: {
bool ok;
int n = c.toInt(&ok);
if (ok) {
e->accept();
if (n>0 && n<100) {
number = n;
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid number. "
"Try 1..99"));
}
} else {
RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
}
RS_DIALOGFACTORY->requestOptions(this, true, true);
setStatus(lastStatus);
}
break;
default:
break;
}
}
QStringList RS_ActionDrawLineParallelThrough::getAvailableCommands() {
QStringList cmd;
switch (getStatus()) {
case SetEntity:
cmd += command("number");
break;
default:
break;
}
return cmd;
}
void RS_ActionDrawLineParallelThrough::updateMouseCursor()
{
switch (getStatus())
{
case SetEntity:
graphicView->setMouseCursor(RS2::SelectCursor);
break;
case SetNumber:
case SetPos:
graphicView->setMouseCursor(RS2::CadCursor);
break;
}
}
int RS_ActionDrawLineParallelThrough::getNumber() const{
return number;
}
void RS_ActionDrawLineParallelThrough::setNumber(int n) {
number = n;
}
// EOF

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/
#ifndef RS_ACTIONDRAWLINEPARALLELTHROUGH_H
#define RS_ACTIONDRAWLINEPARALLELTHROUGH_H
#include "rs_previewactioninterface.h"
class RS_Vector;
/**
* This action class can handle user events to draw parallel
* lines, arcs and circles.
*
* @author Andrew Mustun
*/
class RS_ActionDrawLineParallelThrough : public RS_PreviewActionInterface {
Q_OBJECT
enum Status {
SetEntity, /**< Choose original entity. */
SetPos, /**< Setting point for this parallel to go through. */
SetNumber /**< Setting number in the command line. */
};
public:
RS_ActionDrawLineParallelThrough(RS_EntityContainer& container,
RS_GraphicView& graphicView);
~RS_ActionDrawLineParallelThrough() override;
void trigger() override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void updateMouseButtonHints() override;
void coordinateEvent(RS_CoordinateEvent* e) override;
void commandEvent(RS_CommandEvent* e) override;
QStringList getAvailableCommands() override;
void hideOptions() override;
void showOptions() override;
void finish(bool updateTB=true) override;
void updateMouseCursor() override;
int getNumber() const;
void setNumber(int n);
private:
/** Closest parallel. */
RS_Entity* parallel=nullptr;
/** Number of parallels. */
int number=1;
/** Coordinate of the mouse. */
std::unique_ptr<RS_Vector> coord;
/** Original entity. */
RS_Entity* entity=nullptr;
/** Last status before entering length or number. */
Status lastStatus;
};
#endif

Some files were not shown because too many files have changed in this diff Show More