~librecad-dev/librecad/librecad

« back to all changes in this revision

Viewing changes to librecad/src/actions/rs_actiondrawcircletan2_1p.cpp

  • Committer: Scott Howard
  • Date: 2014-02-21 19:07:55 UTC
  • Revision ID: showard@debian.org-20140221190755-csjax9wb146hgdq4
first commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
 * Draw circle by foci and a point on circle
 
4
 
 
5
Copyright (C) 2012 Dongxu Li (dongxuli2011@gmail.com)
 
6
Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
 
7
 
 
8
This program is free software; you can redistribute it and/or
 
9
modify it under the terms of the GNU General Public License
 
10
as published by the Free Software Foundation; either version 2
 
11
of the License, or (at your option) any later version.
 
12
 
 
13
This program is distributed in the hope that it will be useful,
 
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
GNU General Public License for more details.
 
17
 
 
18
You should have received a copy of the GNU General Public License
 
19
along with this program; if not, write to the Free Software
 
20
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
21
**********************************************************************/
 
22
 
 
23
#include "rs_actiondrawcircletan2_1p.h"
 
24
 
 
25
#include <QAction>
 
26
#include "rs_dialogfactory.h"
 
27
#include "rs_graphicview.h"
 
28
#include "rs_commandevent.h"
 
29
#include "rs_arc.h"
 
30
#include "rs_circle.h"
 
31
#include "lc_quadratic.h"
 
32
 
 
33
/**
 
34
 * Constructor.
 
35
 *
 
36
 */
 
37
RS_ActionDrawCircleTan2_1P::RS_ActionDrawCircleTan2_1P(
 
38
        RS_EntityContainer& container,
 
39
        RS_GraphicView& graphicView)
 
40
    :RS_PreviewActionInterface("Draw tangent circle 2P",
 
41
                               container, graphicView),
 
42
      cData(RS_Vector(0.,0.),1.),
 
43
      enTypeList()
 
44
{
 
45
    //    supported types
 
46
    enTypeList<<RS2::EntityLine<<RS2::EntityArc<<RS2::EntityCircle;
 
47
}
 
48
 
 
49
 
 
50
 
 
51
RS_ActionDrawCircleTan2_1P::~RS_ActionDrawCircleTan2_1P() {
 
52
}
 
53
 
 
54
 
 
55
 
 
56
QAction* RS_ActionDrawCircleTan2_1P::createGUIAction(RS2::ActionType /*type*/, QObject* /*parent*/) {
 
57
    QAction* action;
 
58
 
 
59
    action = new QAction(tr("Common Tangential Circle 1 Point"), NULL);
 
60
    action->setIcon(QIcon(":/extui/circletan2_1p.png"));
 
61
    return action;
 
62
}
 
63
 
 
64
void RS_ActionDrawCircleTan2_1P::init(int status) {
 
65
    RS_PreviewActionInterface::init(status);
 
66
    if(status>=0) {
 
67
        RS_Snapper::suspend();
 
68
    }
 
69
 
 
70
    if (status<=SetCircle2) {
 
71
        bool updateNeeded(false);
 
72
        if(circles.size()>=2 && circles[1]!=NULL) {
 
73
            if(circles[1]->isHighlighted()){
 
74
                circles[1]->setHighlighted(false);
 
75
                updateNeeded=true;
 
76
            }
 
77
        }
 
78
        if(status<= SetCircle1 && circles.size()>=1&&circles[0]!=NULL) {
 
79
            if(circles[0]->isHighlighted()){
 
80
                circles[0]->setHighlighted(false);
 
81
                updateNeeded=true;
 
82
            }
 
83
        }
 
84
        if(updateNeeded) graphicView->redraw(RS2::RedrawDrawing);
 
85
        circles.clear();
 
86
    }
 
87
}
 
88
 
 
89
 
 
90
void RS_ActionDrawCircleTan2_1P::finish(bool updateTB){
 
91
    if( circles.size() >0) {
 
92
        foreach(RS_AtomicEntity* circle, circles)
 
93
            circle->setHighlighted(false);
 
94
        graphicView->redraw(RS2::RedrawDrawing);
 
95
    }
 
96
    RS_PreviewActionInterface::finish(updateTB);
 
97
}
 
98
 
 
99
//void RS_ActionDrawCircleTan2_1P::finish(bool updateTB){
 
100
////    for(int i=0;i<circles.size();i++) circles[i]->setHighlighted(false);
 
101
////    graphicView->redraw(RS2::RedrawDrawing);
 
102
////    circles.clear();
 
103
//    RS_PreviewActionInterface::finish(updateTB);
 
104
//}
 
105
 
 
106
 
 
107
void RS_ActionDrawCircleTan2_1P::trigger() {
 
108
    //    std::cout<<__FILE__<<" : "<<__FUNCTION__<<" : line "<<__LINE__<<std::endl;
 
109
    //    std::cout<<"begin"<<std::endl;
 
110
 
 
111
    RS_PreviewActionInterface::trigger();
 
112
 
 
113
 
 
114
    RS_Circle* c=new RS_Circle(container, cData);
 
115
 
 
116
    container->addEntity(c);
 
117
 
 
118
    // upd. undo list:
 
119
    if (document!=NULL) {
 
120
        document->startUndoCycle();
 
121
        document->addUndoable(c);
 
122
        document->endUndoCycle();
 
123
    }
 
124
 
 
125
 
 
126
    foreach(RS_AtomicEntity* circle, circles)
 
127
        circle->setHighlighted(false);
 
128
    graphicView->redraw(RS2::RedrawDrawing);
 
129
    circles.clear();
 
130
 
 
131
 
 
132
    RS_DEBUG->print("RS_ActionDrawCircleTan2_1P::trigger():"
 
133
                    " entity added: %d", c->getId());
 
134
    init(SetCircle1);
 
135
}
 
136
 
 
137
 
 
138
bool RS_ActionDrawCircleTan2_1P::getCenters()
 
139
{
 
140
    if(circles.size()<2) return false;
 
141
    LC_Quadratic lc0(circles[0], point);
 
142
    LC_Quadratic lc1(circles[1], point);
 
143
 
 
144
    auto&& list=LC_Quadratic::getIntersection(lc0,lc1);
 
145
    centers.clean();
 
146
    for(unsigned int i=0;i<list.size();i++){
 
147
        auto&& vp=list.get(i);
 
148
        auto&& ds=vp.distanceTo(point)-RS_TOLERANCE;
 
149
        bool validBranch(true);
 
150
        for(int j=0;j<2;j++){
 
151
            if(circles[j]->rtti()==RS2::EntityCircle||circles[j]->rtti()==RS2::EntityArc){
 
152
                if( vp.distanceTo(circles[j]->getCenter()) <= ds) {
 
153
                    validBranch=false;
 
154
                    break;
 
155
                }
 
156
            }
 
157
        }
 
158
        if(validBranch)  centers.push_back(vp);
 
159
    }
 
160
    return centers.size()>0;
 
161
}
 
162
 
 
163
void RS_ActionDrawCircleTan2_1P::mouseMoveEvent(QMouseEvent* e) {
 
164
    RS_DEBUG->print("RS_ActionDrawCircleTan2_1P::mouseMoveEvent begin");
 
165
 
 
166
    switch( getStatus()){
 
167
    case SetPoint:
 
168
        coord=snapPoint(e);
 
169
        point=coord;
 
170
        break;
 
171
    case SetCenter:
 
172
        coord=graphicView->toGraph(e->x(),e->y());
 
173
        break;
 
174
    default:
 
175
        return;
 
176
    }
 
177
    deletePreview();
 
178
    if(preparePreview()){
 
179
        RS_Circle* e=new RS_Circle(preview, cData);
 
180
        preview->addEntity(e);
 
181
        drawPreview();
 
182
    }
 
183
    RS_DEBUG->print("RS_ActionDrawCircleTan2_1P::mouseMoveEvent end");
 
184
}
 
185
 
 
186
//void RS_ActionDrawCircleTan2_1P::setRadius(const double& r)
 
187
//{
 
188
//    cData.radius=r;
 
189
//    if(getStatus() == SetPoint2){
 
190
//        RS_Circle c(NULL,cData);
 
191
//        centers=c.createTan2_1P(circle,cData.radius);
 
192
//    }
 
193
//}
 
194
 
 
195
bool RS_ActionDrawCircleTan2_1P::preparePreview(){
 
196
    if( getCenters() ==false) return false;
 
197
//    for(int i=0;i<centers.size();i++){
 
198
//        double ds2=(centers[i]-point).squared();
 
199
//        if( (centers[i]-circles[0]).squared()<ds2
 
200
//    }
 
201
    cData.center=centers.getClosest(coord);
 
202
    cData.radius=point.distanceTo(cData.center);
 
203
    return true;
 
204
}
 
205
 
 
206
RS_Entity* RS_ActionDrawCircleTan2_1P::catchCircle(QMouseEvent* e) {
 
207
    RS_Entity* ret=NULL;
 
208
    RS_Entity*  en = catchEntity(e,enTypeList, RS2::ResolveAll);
 
209
    if(en == NULL) return ret;
 
210
    if(en->isVisible()==false) return ret;
 
211
    for(int i=0;i<getStatus();i++) {
 
212
        if(en->getId() == circles[i]->getId()) return ret; //do not pull in the same line again
 
213
    }
 
214
    if(en->getParent() != NULL) {
 
215
        if ( en->getParent()->rtti() == RS2::EntityInsert         /**Insert*/
 
216
             || en->getParent()->rtti() == RS2::EntitySpline
 
217
             || en->getParent()->rtti() == RS2::EntityMText        /**< Text 15*/
 
218
             || en->getParent()->rtti() == RS2::EntityText         /**< Text 15*/
 
219
             || en->getParent()->rtti() == RS2::EntityDimAligned   /**< Aligned Dimension */
 
220
             || en->getParent()->rtti() == RS2::EntityDimLinear    /**< Linear Dimension */
 
221
             || en->getParent()->rtti() == RS2::EntityDimRadial    /**< Radial Dimension */
 
222
             || en->getParent()->rtti() == RS2::EntityDimDiametric /**< Diametric Dimension */
 
223
             || en->getParent()->rtti() == RS2::EntityDimAngular   /**< Angular Dimension */
 
224
             || en->getParent()->rtti() == RS2::EntityDimLeader    /**< Leader Dimension */
 
225
             ){
 
226
            return ret;
 
227
        }
 
228
    }
 
229
    return en;
 
230
}
 
231
 
 
232
void RS_ActionDrawCircleTan2_1P::mouseReleaseEvent(QMouseEvent* e) {
 
233
    // Proceed to next status
 
234
    if (e->button()==Qt::LeftButton) {
 
235
 
 
236
        switch (getStatus()) {
 
237
        case SetCircle1:
 
238
        case SetCircle2:
 
239
        {
 
240
            circles.resize(getStatus());
 
241
            RS_AtomicEntity*  en = static_cast<RS_AtomicEntity*>(catchCircle(e));
 
242
            if (en==NULL) return;
 
243
//            circle = static_cast<RS_AtomicEntity*>(en);
 
244
            en->setHighlighted(true);
 
245
            circles<<en;
 
246
            graphicView->redraw(RS2::RedrawDrawing);
 
247
            setStatus(getStatus()+1);
 
248
        }
 
249
            break;
 
250
        case SetPoint:
 
251
        {
 
252
            RS_Vector snapped = snapPoint(e);
 
253
            RS_CoordinateEvent ce(snapped);
 
254
            coordinateEvent(&ce);
 
255
        }
 
256
            break;
 
257
        case SetCenter:
 
258
            coord=graphicView->toGraph(e->x(),e->y());
 
259
            if(preparePreview()) trigger();
 
260
            break;
 
261
 
 
262
        default:
 
263
            break;
 
264
        }
 
265
    } else if (e->button()==Qt::RightButton) {
 
266
        // Return to last status:
 
267
        if(getStatus()>0){
 
268
            deletePreview();
 
269
        }
 
270
        init(getStatus()-1);
 
271
    }
 
272
}
 
273
 
 
274
 
 
275
void RS_ActionDrawCircleTan2_1P::coordinateEvent(RS_CoordinateEvent* e) {
 
276
 
 
277
    RS_Vector mouse = e->getCoordinate();
 
278
    switch(getStatus()){
 
279
 
 
280
    case SetPoint:
 
281
        point=mouse;
 
282
        coord=mouse;
 
283
        if(getCenters()) {
 
284
            if(centers.size()==1) trigger();
 
285
            else setStatus(getStatus()+1);
 
286
        }
 
287
        break;
 
288
        default:
 
289
        break;
 
290
//    case SetCenter:
 
291
//        coord=mouse;
 
292
//        trigger();
 
293
    }
 
294
 
 
295
}
 
296
 
 
297
//fixme, support command line
 
298
 
 
299
/*
 
300
void RS_ActionDrawCircleTan2_1P::commandEvent(RS_CommandEvent* e) {
 
301
    QString c = e->getCommand().toLower();
 
302
 
 
303
    if (checkCommand("help", c)) {
 
304
        if (RS_DIALOGFACTORY!=NULL) {
 
305
            RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
 
306
                                             + getAvailableCommands().join(", "));
 
307
        }
 
308
        return;
 
309
    }
 
310
 
 
311
    switch (getStatus()) {
 
312
    case SetFocus1: {
 
313
            bool ok;
 
314
            double m = RS_Math::eval(c, &ok);
 
315
            if (ok==true) {
 
316
                ratio = m / major.magnitude();
 
317
                if (!isArc) {
 
318
                    trigger();
 
319
                } else {
 
320
                    setStatus(SetAngle1);
 
321
                }
 
322
            } else {
 
323
                if (RS_DIALOGFACTORY!=NULL) {
 
324
                    RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
 
325
                }
 
326
            }
 
327
        }
 
328
        break;
 
329
 
 
330
    case SetAngle1: {
 
331
            bool ok;
 
332
            double a = RS_Math::eval(c, &ok);
 
333
            if (ok==true) {
 
334
                angle1 = RS_Math::deg2rad(a);
 
335
                setStatus(SetAngle2);
 
336
            } else {
 
337
                if (RS_DIALOGFACTORY!=NULL) {
 
338
                    RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
 
339
                }
 
340
            }
 
341
        }
 
342
        break;
 
343
 
 
344
    case SetAngle2: {
 
345
            bool ok;
 
346
            double a = RS_Math::eval(c, &ok);
 
347
            if (ok==true) {
 
348
                angle2 = RS_Math::deg2rad(a);
 
349
                trigger();
 
350
            } else {
 
351
                if (RS_DIALOGFACTORY!=NULL) {
 
352
                    RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
 
353
                }
 
354
            }
 
355
        }
 
356
        break;
 
357
 
 
358
    default:
 
359
        break;
 
360
    }
 
361
}
 
362
*/
 
363
 
 
364
 
 
365
//void RS_ActionDrawCircleTan2_1P::showOptions() {
 
366
//    RS_DEBUG->print("RS_ActionDrawCircleTan2_1P::showOptions");
 
367
//    if(RS_DIALOGFACTORY != NULL){
 
368
//        RS_ActionInterface::showOptions();
 
369
 
 
370
//        RS_DIALOGFACTORY->requestOptions(this, true);
 
371
//    }
 
372
//    RS_DEBUG->print("RS_ActionDrawCircleTan2_1P::showOptions: OK");
 
373
//}
 
374
 
 
375
 
 
376
 
 
377
//void RS_ActionDrawCircleTan2_1P::hideOptions() {
 
378
//    if(RS_DIALOGFACTORY != NULL){
 
379
//        RS_ActionInterface::hideOptions();
 
380
 
 
381
//        RS_DIALOGFACTORY->requestOptions(this, false);
 
382
//    }
 
383
//}
 
384
 
 
385
 
 
386
QStringList RS_ActionDrawCircleTan2_1P::getAvailableCommands() {
 
387
    QStringList cmd;
 
388
    return cmd;
 
389
}
 
390
 
 
391
 
 
392
 
 
393
void RS_ActionDrawCircleTan2_1P::updateMouseButtonHints() {
 
394
    if (RS_DIALOGFACTORY!=NULL) {
 
395
        switch (getStatus()) {
 
396
        case SetCircle1:
 
397
            RS_DIALOGFACTORY->updateMouseWidget(tr("Specify a line/arc/circle"),
 
398
                                                tr("Cancel"));
 
399
            break;
 
400
 
 
401
        case SetCircle2:
 
402
            RS_DIALOGFACTORY->updateMouseWidget(tr("Specify the another arc/circle"),
 
403
                                                tr("Back"));
 
404
            break;
 
405
 
 
406
        case SetPoint:
 
407
            RS_DIALOGFACTORY->updateMouseWidget(tr("Specify a point on the tangent circle"),
 
408
                                                tr("Back"));
 
409
            break;
 
410
        case SetCenter:
 
411
            RS_DIALOGFACTORY->updateMouseWidget(tr("Select the center of the tangent circle"),
 
412
                                                tr("Back"));
 
413
            break;
 
414
        default:
 
415
            RS_DIALOGFACTORY->updateMouseWidget("", "");
 
416
            break;
 
417
        }
 
418
    }
 
419
}
 
420
 
 
421
 
 
422
 
 
423
void RS_ActionDrawCircleTan2_1P::updateMouseCursor() {
 
424
    graphicView->setMouseCursor(RS2::CadCursor);
 
425
}
 
426
 
 
427
 
 
428
 
 
429
//void RS_ActionDrawCircleTan2_1P::updateToolBar() {
 
430
//    if (RS_DIALOGFACTORY!=NULL) {
 
431
//        if (isFinished()) {
 
432
//            RS_DIALOGFACTORY->resetToolBar();
 
433
//        }
 
434
//    }
 
435
//}
 
436
 
 
437
// EOF