3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
10 // JLH = James L. Hammons <jlhamm@acm.org>
13 // --- ---------- -----------------------------------------------------------
14 // JLH 05/21/2010 Added this text. :-)
15 // JLH 10/18/2010 Commented out all functions in preparation for deprecating
21 #include "dialogfactory.h"
23 #include "entitycontainer.h"
24 #include "graphicview.h"
26 #include "information.h"
27 #include "paintinterface.h"
33 Snapper::Snapper(EntityContainer & c, GraphicView & gv):
34 container(&c), graphicView(&gv), finished(false)
41 Snapper::Snapper(void):
42 container(NULL), graphicView(NULL), finished(false)
57 * Initialize (called by all constructors)
64 snapMode = graphicView->getDefaultSnapMode();
65 snapRes = graphicView->getSnapRestriction();
69 snapSpot = Vector(false);
70 snapCoord = Vector(false);
74 settings.beginGroup("Snap");
75 snapRange = settings.value("Range", 20).toInt();
77 settings.beginGroup("Appearance");
78 showCrosshairs = settings.value("ShowCrosshairs", true).toBool();
87 void Snapper::finish()
95 void Snapper::SetContainer(EntityContainer * c)
103 void Snapper::SetGraphicView(GraphicView * v)
111 * @return Pointer to the entity which was the key entity for the last
112 * successful snapping action. If the snap mode is "end point" the key entity
113 * is the entity whose end point was caught. If the snap mode didn't require an
114 * entity (e.g. free, grid) this method will return NULL.
116 Entity * Snapper::getKeyEntity()
124 /** Sets a new snap mode. */
125 void Snapper::setSnapMode(RS2::SnapMode snapMode)
128 this->snapMode = snapMode;
132 /** Sets a new snap restriction. */
133 void Snapper::setSnapRestriction(RS2::SnapRestriction snapRes)
136 this->snapRes = snapRes;
140 RS2::SnapMode Snapper::getSnapMode(void)
145 return RS2::SnapFree;
148 RS2::SnapRestriction Snapper::getSnapRestriction(void)
153 return RS2::RestrictNothing;
157 * Sets the snap range in pixels for catchEntity().
161 void Snapper::setSnapRange(int r)
169 This should get moved into GraphicView...
172 * Snap to a coordinate in the drawing using the current snap mode.
174 * @param e A mouse event.
175 * @return The coordinates of the point or an invalid vector.
177 Vector Snapper::snapPoint(QMouseEvent * e)
180 DEBUG->print("Snapper::snapPoint");
181 snapSpot = Vector(false);
185 DEBUG->print(Debug::D_WARNING, "Snapper::snapPoint: event is NULL");
189 Vector mouseCoord = graphicView->toGraph(e->x(), e->y());
194 snapSpot = snapFree(mouseCoord);
197 case RS2::SnapEndpoint:
198 snapSpot = snapEndpoint(mouseCoord);
202 snapSpot = snapGrid(mouseCoord);
205 case RS2::SnapOnEntity:
206 snapSpot = snapOnEntity(mouseCoord);
209 case RS2::SnapCenter:
210 snapSpot = snapCenter(mouseCoord);
213 case RS2::SnapMiddle:
214 snapSpot = snapMiddle(mouseCoord);
218 snapSpot = snapDist(mouseCoord);
221 case RS2::SnapIntersection:
222 snapSpot = snapIntersection(mouseCoord);
229 // Handle snap restrictions that can be activated in addition to the ones above:
232 case RS2::RestrictOrthogonal:
233 snapCoord = restrictOrthogonal(snapSpot);
235 case RS2::RestrictHorizontal:
236 snapCoord = restrictHorizontal(snapSpot);
238 case RS2::RestrictVertical:
239 snapCoord = restrictVertical(snapSpot);
242 case RS2::RestrictNothing:
243 snapCoord = snapSpot;
248 DIALOGFACTORY->updateCoordinateWidget(snapCoord, snapCoord - graphicView->getRelativeZero());
250 DEBUG->print("Snapper::snapPoint: OK");
254 return Vector(false);
258 * Snaps to a free coordinate.
260 * @param coord The mouse coordinate.
261 * @return The coordinates of the point or an invalid vector.
263 Vector Snapper::snapFree(Vector coord)
269 return Vector(false);
273 * Snaps to the closest endpoint.
275 * @param coord The mouse coordinate.
276 * @return The coordinates of the point or an invalid vector.
278 Vector Snapper::snapEndpoint(Vector coord)
282 vec = container->getNearestEndpoint(coord, NULL);
286 return Vector(false);
290 * Snaps to a grid point.
292 * @param coord The mouse coordinate.
293 * @return The coordinates of the point or an invalid vector.
295 Vector Snapper::snapGrid(Vector coord)
298 DEBUG->print("Snapper::snapGrid begin");
303 Grid * grid = graphicView->getGrid();
305 DEBUG->print("Snapper::snapGrid 001");
309 DEBUG->print("Snapper::snapGrid 002");
310 Vector * pts = grid->getPoints();
311 DEBUG->print("Snapper::snapGrid 003");
314 DEBUG->print("Snapper::snapGrid 004");
316 for(int i=0; i<grid->count(); ++i)
318 double d = pts[i].distanceTo(coord);
327 DEBUG->print("Snapper::snapGrid 005");
332 DEBUG->print("Snapper::snapGrid 006");
337 DEBUG->print("Snapper::snapGrid end");
341 return Vector(false);
345 * Snaps to a point on an entity.
347 * @param coord The mouse coordinate.
348 * @return The coordinates of the point or an invalid vector.
350 Vector Snapper::snapOnEntity(Vector coord)
354 vec = container->getNearestPointOnEntity(coord, true, NULL, &keyEntity);
358 return Vector(false);
362 * Snaps to the closest center.
364 * @param coord The mouse coordinate.
365 * @return The coordinates of the point or an invalid vector.
367 Vector Snapper::snapCenter(Vector coord)
371 vec = container->getNearestCenter(coord, NULL);
375 return Vector(false);
379 * Snaps to the closest middle.
381 * @param coord The mouse coordinate.
382 * @return The coordinates of the point or an invalid vector.
384 Vector Snapper::snapMiddle(Vector coord)
388 vec = container->getNearestMiddle(coord, NULL);
392 return Vector(false);
396 * Snaps to the closest point with a given distance to the endpoint.
398 * @param coord The mouse coordinate.
399 * @return The coordinates of the point or an invalid vector.
401 Vector Snapper::snapDist(Vector coord)
405 vec = container->getNearestDist(distance, coord, NULL);
409 return Vector(false);
413 * Snaps to the closest intersection point.
415 * @param coord The mouse coordinate.
416 * @return The coordinates of the point or an invalid vector.
418 Vector Snapper::snapIntersection(Vector coord)
422 vec = container->getNearestIntersection(coord, NULL);
426 return Vector(false);
430 * 'Corrects' the given coordinates to 0, 90, 180, 270 degrees relative to
431 * the current relative zero point.
433 * @param coord The uncorrected coordinates.
434 * @return The corrected coordinates.
436 Vector Snapper::restrictOrthogonal(Vector coord)
439 Vector rz = graphicView->getRelativeZero();
442 Vector retx = Vector(rz.x, ret.y);
443 Vector rety = Vector(ret.x, rz.y);
445 if (retx.distanceTo(ret) > rety.distanceTo(ret))
452 return Vector(false);
456 * 'Corrects' the given coordinates to 0, 180 degrees relative to
457 * the current relative zero point.
459 * @param coord The uncorrected coordinates.
460 * @return The corrected coordinates.
462 Vector Snapper::restrictHorizontal(Vector coord)
465 Vector rz = graphicView->getRelativeZero();
467 return Vector(coord.x, rz.y);
469 return Vector(false);
473 * 'Corrects' the given coordinates to 90, 270 degrees relative to
474 * the current relative zero point.
476 * @param coord The uncorrected coordinates.
477 * @return The corrected coordinates.
479 Vector Snapper::restrictVertical(Vector coord)
482 Vector rz = graphicView->getRelativeZero();
484 return Vector(rz.x, coord.y);
486 return Vector(false);
490 * Catches an entity which is close to the given position 'pos'.
492 * @param pos A graphic coordinate.
493 * @param level The level of resolving for iterating through the entity
495 * @return Pointer to the entity or NULL.
497 Entity * Snapper::catchEntity(const Vector & pos, RS2::ResolveLevel level)
500 DEBUG->print("Snapper::catchEntity");
502 // Set default distance for points inside solids
503 double dist = graphicView->toGraphDX(snapRange) * 0.9;
504 Entity * entity = container->getNearestEntity(pos, &dist, level);
507 if (entity && entity->getParent())
508 idx = entity->getParent()->findEntity(entity);
510 if (entity && dist <= graphicView->toGraphDX(snapRange))
513 DEBUG->print("Snapper::catchEntity: found: %d", idx);
518 DEBUG->print("Snapper::catchEntity: not found");
522 // DEBUG->print("Snapper::catchEntity: OK");
528 * Catches an entity which is close to the mouse cursor.
530 * @param e A mouse event.
531 * @param level The level of resolving for iterating through the entity
533 * @return Pointer to the entity or NULL.
535 Entity * Snapper::catchEntity(QMouseEvent * e, RS2::ResolveLevel level)
538 return catchEntity(Vector(graphicView->toGraphX(e->x()),
539 graphicView->toGraphY(e->y())), level);
545 I think that these suspend() & resume() functions are not used anymore...
548 * Suspends this snapper while another action takes place.
550 /*virtual*/ void Snapper::suspend()
553 #warning "!!! This may need to have SetVisibility() called !!!"
555 snapSpot = snapCoord = Vector(false);
560 * Resumes this snapper after it has been suspended.
562 /*virtual*/ void Snapper::resume()
565 #warning "!!! This may need to have SetVisibility() called !!!"
571 * Hides the snapper options.
573 /*virtual*/ void Snapper::hideOptions()
576 if (snapMode == RS2::SnapDist && DIALOGFACTORY)
577 DIALOGFACTORY->requestSnapDistOptions(distance, false);
582 * Shows the snapper options.
584 /*virtual*/ void Snapper::showOptions()
587 if (snapMode == RS2::SnapDist && DIALOGFACTORY)
588 DIALOGFACTORY->requestSnapDistOptions(distance, true);
592 void Snapper::SetVisible(bool visibility/*= true*/)
595 visible = visibility;
599 bool Snapper::Visible(void)
607 We need to figure out how to kick the GraphicView out of this class. Perhaps we
608 need to move the toGuiX/Y() functions into another class as static functions.
609 Further inspection seems to rule this out as they are pretty well coupled to the
610 GraphicView class... What to do?
612 void Snapper::Draw(GraphicView * view, PaintInterface * painter)
615 if (finished || !snapSpot.valid || !snapCoord.valid)
618 //hm, I don't like graphicView kicking around in here, especially since it now
619 //lives inside GraphicView... How to !!! FIX !!!?
620 //We'll pass it in for now...
621 // Snap point (need to make sure the brush is NULL!)
622 // painter->setPen(Pen(Color(0, 127, 255), RS2::Width00, RS2::DashLine));
623 painter->setPen(Pen(Color(255, 127, 0), RS2::Width00, RS2::DashLine));
624 painter->drawCircle(view->toGui(snapCoord), 4);
629 painter->setPen(Pen(Color(0, 255, 255), RS2::Width00, RS2::DashLine));
630 painter->drawLine(Vector(0, view->toGuiY(snapCoord.y)),
631 Vector(view->getWidth(), view->toGuiY(snapCoord.y)));
632 painter->drawLine(Vector(view->toGuiX(snapCoord.x), 0),
633 Vector(view->toGuiX(snapCoord.x), view->getHeight()));
636 if (snapCoord != snapSpot)
638 painter->drawLine(view->toGui(snapSpot) + Vector(-5, 0),
639 view->toGui(snapSpot) + Vector(-1, 4));
640 painter->drawLine(view->toGui(snapSpot) + Vector(0, 5),
641 view->toGui(snapSpot) + Vector(4, 1));
642 painter->drawLine(view->toGui(snapSpot) + Vector(5, 0),
643 view->toGui(snapSpot) + Vector(1, -4));
644 painter->drawLine(view->toGui(snapSpot) + Vector(0, -5),
645 view->toGui(snapSpot) + Vector(-4, -1));