/* * This program source code file is part of KICAD, a free EDA CAD application. * * Copyright (C) 2017-2023 Kicad Developers, see AUTHORS.txt for contributors. * * 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, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * or you may search the http://www.gnu.org website for the version 2 license, * or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef PREVIEW_POLYGON_GEOM_MANAGER__H_ #define PREVIEW_POLYGON_GEOM_MANAGER__H_ #include /** * Class that handles the drawing of a polygon, including management of last corner deletion * and drawing of leader lines with various constraints (eg 45 deg only). * * This class handles only the geometry of the process. */ class POLYGON_GEOM_MANAGER { public: /** * "Listener" interface for a class that wants to be updated about * polygon geometry changes */ class CLIENT { public: /** * Called before the first point is added - clients can do * initialization here, and can veto the start of the process * (e.g. if user cancels a dialog) * * @return false to veto start of new polygon */ virtual bool OnFirstPoint( POLYGON_GEOM_MANAGER& aMgr ) = 0; ///< Sent when the polygon geometry changes virtual void OnGeometryChange( const POLYGON_GEOM_MANAGER& aMgr ) = 0; ///< Called when the polygon is complete virtual void OnComplete( const POLYGON_GEOM_MANAGER& aMgr ) = 0; virtual ~CLIENT() { } }; /** * The kind of the leader line */ enum class LEADER_MODE { DIRECT, ///< Unconstrained point-to-point DEG45, ///< 45 Degree only }; /** * @param aClient is the client to pass the results onto */ POLYGON_GEOM_MANAGER( CLIENT& aClient ); /** * Lock in a polygon point. */ bool AddPoint( const VECTOR2I& aPt ); /** * Mark the polygon finished and update the client. */ void SetFinished(); /** * Clear the manager state and start again. */ void Reset(); /** * Set the leader mode to use when calculating the leader/returner lines. */ void SetLeaderMode( LEADER_MODE aMode ); LEADER_MODE GetLeaderMode() const { return m_leaderMode; } /** * Enables/disables self-intersecting polygons. * * @param aEnabled true if self-intersecting polygons are enabled. */ void AllowIntersections( bool aEnabled ) { m_intersectionsAllowed = true; } /** * Check whether self-intersecting polygons are enabled. * * @return true if self-intersecting polygons are enabled. */ bool IntersectionsAllowed() const { return m_intersectionsAllowed; } /** * Check whether the locked points constitute a self-intersecting outline. * * @param aIncludeLeaderPts when true, also the leading points (not placed ones) will be tested. * @return True when the outline is self-intersecting. */ bool IsSelfIntersecting( bool aIncludeLeaderPts ) const; /** * Set the current cursor position */ void SetCursorPosition( const VECTOR2I& aPos ); /** * @return true if the polygon in "in progress", i.e. it has at least * one locked-in point */ bool IsPolygonInProgress() const; int PolygonPointCount() const; /** * @return true if locking in the given point would close the current polygon. */ bool NewPointClosesOutline( const VECTOR2I& aPt ) const; /** * Remove the last-added point from the polygon */ void DeleteLastCorner(); /* ================================================================= * Interfaces for users of the geometry */ /** * Get the "locked-in" points that describe the polygon itself */ const SHAPE_LINE_CHAIN& GetLockedInPoints() const { return m_lockedPoints; } /** * Get the points comprising the leader line (the line from the * last locked-in point to the current cursor position * * How this is drawn will depend on the LEADER_MODE */ const SHAPE_LINE_CHAIN& GetLeaderLinePoints() const { return m_leaderPts; } /** * Get the points from the current cursor position * to the polygon start point */ const SHAPE_LINE_CHAIN& GetLoopLinePoints() const { return m_loopPts; } private: /** * Update the leader and loop lines points based on a new endpoint (probably * a cursor position) */ void updateTemporaryLines( const VECTOR2I& aEndPoint, LEADER_MODE aModifier = LEADER_MODE::DIRECT ); ///< The "user" of the polygon data that is informed when the geometry changes CLIENT& m_client; ///< The current mode of the leader line LEADER_MODE m_leaderMode; ///< Flag enabling self-intersecting polygons bool m_intersectionsAllowed; ///< Point that have been "locked in" SHAPE_LINE_CHAIN m_lockedPoints; ///< Points in the temporary "leader" line(s) SHAPE_LINE_CHAIN m_leaderPts; ///< Points between the cursor and start point SHAPE_LINE_CHAIN m_loopPts; }; #endif // PREVIEW_POLYGON_GEOM_MANAGER__H_