Files
newspark110/lib/actions/rs_snapper.h
Chenwenxuan edac2715f0 init
2024-03-06 14:54:30 +08:00

238 lines
7.9 KiB
C++

/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2015 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_SNAPPER_H
#define RS_SNAPPER_H
#include<memory>
#include "rs.h"
class RS_Entity;
class RS_GraphicView;
class RS_Vector;
class RS_Preview;
class QMouseEvent;
class RS_EntityContainer;
/**
* This class holds information on how to snap the mouse.
*
* @author Kevin Cox
*/
struct RS_SnapMode {
/* SnapModes for RS_SnapMode to Int conversion and vice versa
*
* The conversion is only used for save/restore of active snap modes in application settings.
* Don't change existing mode order, because this will mess up settings on upgrades
*
* When adding new values, take care for correct implementation in \p toInt() and \p fromInt()
*/
enum SnapModes {
SnapIntersection = 1 << 0,
SnapOnEntity = 1 << 1,
SnapCenter = 1 << 2,
SnapDistance = 1 << 3,
SnapMiddle = 1 << 4,
SnapEndpoint = 1 << 5,
SnapGrid = 1 << 6,
SnapFree = 1 << 7,
RestrictHorizontal = 1 << 8,
RestrictVertical = 1 << 9,
RestrictOrthogonal = RestrictHorizontal | RestrictVertical,
SnapAngle = 1 << 10
};
bool snapIntersection {false}; //< Whether to snap to intersections or not.
bool snapOnEntity {false}; //< Whether to snap to entities or not.
bool snapCenter {false}; //< Whether to snap to centers or not.
bool snapDistance {false}; //< Whether to snap to distance from endpoints or not.
bool snapMiddle {false}; //< Whether to snap to midpoints or not.
bool snapEndpoint {false}; //< Whether to snap to endpoints or not.
bool snapGrid {false}; //< Whether to snap to grid or not.
bool snapFree {false}; //< Whether to snap freely
bool snapAngle {false}; //< Whether to snap along line under certain angle
RS2::SnapRestriction restriction {RS2::RestrictNothing}; /// The restriction on the free snap.
double distance {5.0}; //< The distance to snap before defaulting to free snapping.
/**
* Disable all snapping.
*
* This effectively puts the object into free snap mode.
*
* @returns A reference to itself.
*/
RS_SnapMode const & clear(void);
bool operator == (RS_SnapMode const& rhs) const;
static uint toInt(const RS_SnapMode& s); //< convert to int, to save settings
static RS_SnapMode fromInt(unsigned int); //< convert from int, to restore settings
};
typedef std::initializer_list<RS2::EntityType> EntityTypeList;
/**
* This class is used for snapping functions in a graphic view.
* Actions are usually derived from this base class if they need
* to catch entities or snap to coordinates. Use the methods to
* retrieve a graphic coordinate from a mouse coordinate.
*
* Possible snapping functions are described in RS_SnapMode.
*
* @author Andrew Mustun
*/
class RS_Snapper {
public:
RS_Snapper() = delete;
RS_Snapper(RS_EntityContainer& container, RS_GraphicView& graphicView);
virtual ~RS_Snapper();
void init();
//!
//! \brief finish stop using snapper
//!
void finish();
/**
* @return Pointer to the entity which was the key entity for the
* last successful snapping action. If the snap mode is "end point"
* the key entity is the entity whose end point was caught.
* If the snap mode didn't require an entity (e.g. free, grid) this
* method will return NULL.
*/
RS_Entity* getKeyEntity() const {
return keyEntity;
}
/** Sets a new snap mode. */
void setSnapMode(const RS_SnapMode& snapMode);
RS_SnapMode const* getSnapMode() const;
RS_SnapMode* getSnapMode();
/** Sets a new snap restriction. */
void setSnapRestriction(RS2::SnapRestriction /*snapRes*/) {
//this->snapRes = snapRes;
}
/**
* Sets the snap range in pixels for catchEntity().
*
* @see catchEntity()
*/
void setSnapRange(int r) {
snapRange = r;
}
/**manually set snapPoint*/
RS_Vector snapPoint(const RS_Vector& coord, bool setSpot = false);
RS_Vector snapPoint(QMouseEvent* e);
RS_Vector snapFree(QMouseEvent* e);
RS_Vector snapFree(const RS_Vector& coord);
RS_Vector snapGrid(const RS_Vector& coord);
RS_Vector snapEndpoint(const RS_Vector& coord);
RS_Vector snapOnEntity(const RS_Vector& coord);
RS_Vector snapCenter(const RS_Vector& coord);
RS_Vector snapMiddle(const RS_Vector& coord);
RS_Vector snapDist(const RS_Vector& coord);
RS_Vector snapIntersection(const RS_Vector& coord);
//RS_Vector snapDirect(RS_Vector coord, bool abs);
RS_Vector snapToAngle(const RS_Vector &coord, const RS_Vector &ref_coord, const double ang_res);
RS_Vector restrictOrthogonal(const RS_Vector& coord);
RS_Vector restrictHorizontal(const RS_Vector& coord);
RS_Vector restrictVertical(const RS_Vector& coord);
//RS_Entity* catchLeafEntity(const RS_Vector& pos);
//RS_Entity* catchLeafEntity(QMouseEvent* e);
RS_Entity* catchEntity(const RS_Vector& pos,
RS2::ResolveLevel level=RS2::ResolveNone);
RS_Entity* catchEntity(QMouseEvent* e,
RS2::ResolveLevel level=RS2::ResolveNone);
// catch Entity closest to pos and of the given entity type of enType, only search for a particular entity type
RS_Entity* catchEntity(const RS_Vector& pos, RS2::EntityType enType,
RS2::ResolveLevel level=RS2::ResolveNone);
RS_Entity* catchEntity(QMouseEvent* e, RS2::EntityType enType,
RS2::ResolveLevel level=RS2::ResolveNone);
RS_Entity* catchEntity(QMouseEvent* e, const EntityTypeList& enTypeList,
RS2::ResolveLevel level=RS2::ResolveNone);
/**
* Suspends this snapper while another action takes place.
*/
virtual void suspend();
/**
* Resumes this snapper after it has been suspended.
*/
virtual void resume() {
drawSnapper();
}
virtual void hideOptions();
virtual void showOptions();
void drawSnapper();
protected:
void deleteSnapper();
double getSnapRange() const;
RS_EntityContainer* container;
RS_GraphicView* graphicView;
RS_Entity* keyEntity;
RS_SnapMode snapMode;
//RS2::SnapRestriction snapRes;
/**
* Snap distance for snapping to points with a
* given distance from endpoints.
*/
double m_SnapDistance;
/**
* Snap to equidistant middle points
* default to 1, i.e., equidistant to start/end points
*/
int middlePoints;
/**
* Snap range for catching entities.
*/
int snapRange;
bool finished{false};
private:
struct ImpData;
std::unique_ptr<ImpData> pImpData;
struct Indicator;
Indicator* snap_indicator{nullptr};
};
#endif
//EOF