mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-19 23:21:41 +00:00
Eeschema: point editor: edit polygons as on PCB
This includes edge dragging which is useful for rule areas.
This commit is contained in:
parent
c3794aee95
commit
970d9b3615
common
eeschema/tools
include/tool
pcbnew/tools
@ -632,6 +632,7 @@ set( COMMON_SRCS
|
||||
tool/grid_menu.cpp
|
||||
tool/library_editor_control.cpp
|
||||
tool/picker_tool.cpp
|
||||
tool/point_editor_behavior.cpp
|
||||
tool/properties_tool.cpp
|
||||
tool/selection.cpp
|
||||
tool/selection_tool.cpp
|
||||
|
101
common/tool/point_editor_behavior.cpp
Normal file
101
common/tool/point_editor_behavior.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#include "tool/point_editor_behavior.h"
|
||||
|
||||
#include <geometry/shape_poly_set.h>
|
||||
|
||||
|
||||
void POLYGON_POINT_EDIT_BEHAVIOR::BuildForPolyOutline( EDIT_POINTS& aPoints,
|
||||
const SHAPE_POLY_SET& aOutline )
|
||||
{
|
||||
const int cornersCount = aOutline.TotalVertices();
|
||||
|
||||
for( auto iterator = aOutline.CIterateWithHoles(); iterator; iterator++ )
|
||||
{
|
||||
aPoints.AddPoint( *iterator );
|
||||
|
||||
if( iterator.IsEndContour() )
|
||||
aPoints.AddBreak();
|
||||
}
|
||||
|
||||
// Lines have to be added after creating edit points, as they use EDIT_POINT references
|
||||
for( int i = 0; i < cornersCount - 1; ++i )
|
||||
{
|
||||
if( aPoints.IsContourEnd( i ) )
|
||||
aPoints.AddLine( aPoints.Point( i ), aPoints.Point( aPoints.GetContourStartIdx( i ) ) );
|
||||
else
|
||||
aPoints.AddLine( aPoints.Point( i ), aPoints.Point( i + 1 ) );
|
||||
|
||||
aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
|
||||
}
|
||||
|
||||
// The last missing line, connecting the last and the first polygon point
|
||||
aPoints.AddLine( aPoints.Point( cornersCount - 1 ),
|
||||
aPoints.Point( aPoints.GetContourStartIdx( cornersCount - 1 ) ) );
|
||||
|
||||
aPoints.Line( aPoints.LinesSize() - 1 )
|
||||
.SetConstraint( new EC_PERPLINE( aPoints.Line( aPoints.LinesSize() - 1 ) ) );
|
||||
}
|
||||
|
||||
|
||||
void POLYGON_POINT_EDIT_BEHAVIOR::UpdatePointsFromOutline( const SHAPE_POLY_SET& aOutline,
|
||||
EDIT_POINTS& aPoints )
|
||||
{
|
||||
// No size check here, as we can and will rebuild if that fails
|
||||
|
||||
if( aPoints.PointsSize() != (unsigned) aOutline.TotalVertices() )
|
||||
{
|
||||
// Rebuild the points list
|
||||
aPoints.Clear();
|
||||
BuildForPolyOutline( aPoints, aOutline );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < aOutline.TotalVertices(); ++i )
|
||||
{
|
||||
aPoints.Point( i ).SetPosition( aOutline.CVertex( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void POLYGON_POINT_EDIT_BEHAVIOR::UpdateOutlineFromPoints( SHAPE_POLY_SET& aOutline,
|
||||
const EDIT_POINT& aEditedPoint,
|
||||
EDIT_POINTS& aPoints )
|
||||
{
|
||||
CHECK_POINT_COUNT_GE( aPoints, (unsigned) aOutline.TotalVertices() );
|
||||
|
||||
for( int i = 0; i < aOutline.TotalVertices(); ++i )
|
||||
{
|
||||
aOutline.SetVertex( i, aPoints.Point( i ).GetPosition() );
|
||||
}
|
||||
|
||||
for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
|
||||
{
|
||||
if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
|
||||
{
|
||||
aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
|
||||
}
|
||||
}
|
||||
}
|
@ -22,10 +22,11 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "ee_point_editor.h"
|
||||
|
||||
#include <functional>
|
||||
using namespace std::placeholders;
|
||||
|
||||
#include "ee_point_editor.h"
|
||||
#include <ee_grid_helper.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <sch_commit.h>
|
||||
@ -33,6 +34,7 @@ using namespace std::placeholders;
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <geometry/seg.h>
|
||||
#include <geometry/shape_utils.h>
|
||||
#include <tool/point_editor_behavior.h>
|
||||
#include <tools/ee_actions.h>
|
||||
#include <tools/ee_selection_tool.h>
|
||||
#include <sch_edit_frame.h>
|
||||
@ -951,55 +953,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class POLYGON_POINT_EDIT_BEHAVIOR : public POINT_EDIT_BEHAVIOR
|
||||
{
|
||||
public:
|
||||
POLYGON_POINT_EDIT_BEHAVIOR( SCH_SHAPE& aPoly ) : m_poly( aPoly ) {}
|
||||
|
||||
void MakePoints( EDIT_POINTS& aPoints ) override
|
||||
{
|
||||
for( const VECTOR2I& pt : m_poly.GetPolyShape().Outline( 0 ).CPoints() )
|
||||
aPoints.AddPoint( pt );
|
||||
}
|
||||
|
||||
void UpdatePoints( EDIT_POINTS& aPoints ) override
|
||||
{
|
||||
if( aPoints.PointsSize() != (unsigned) m_poly.GetPointCount() )
|
||||
{
|
||||
aPoints.Clear();
|
||||
MakePoints( aPoints );
|
||||
}
|
||||
else
|
||||
{
|
||||
int ii = 0;
|
||||
|
||||
for( const VECTOR2I& pt : m_poly.GetPolyShape().Outline( 0 ).CPoints() )
|
||||
{
|
||||
aPoints.Point( ii++ ).SetPosition( pt );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
|
||||
std::vector<EDA_ITEM*>& aUpdatedItems ) override
|
||||
{
|
||||
m_poly.GetPolyShape().RemoveAllContours();
|
||||
m_poly.GetPolyShape().NewOutline();
|
||||
|
||||
for( unsigned i = 0; i < aPoints.PointsSize(); ++i )
|
||||
{
|
||||
VECTOR2I pt = aPoints.Point( i ).GetPosition();
|
||||
m_poly.GetPolyShape().Append( pt.x, pt.y, -1, -1, true );
|
||||
}
|
||||
|
||||
aUpdatedItems.push_back( &m_poly );
|
||||
}
|
||||
|
||||
private:
|
||||
SCH_SHAPE& m_poly;
|
||||
};
|
||||
|
||||
|
||||
void EE_POINT_EDITOR::makePointsAndBehavior( EDA_ITEM* aItem )
|
||||
{
|
||||
m_editBehavior = nullptr;
|
||||
@ -1027,7 +980,7 @@ void EE_POINT_EDITOR::makePointsAndBehavior( EDA_ITEM* aItem )
|
||||
m_editBehavior = std::make_unique<RECTANGLE_POINT_EDIT_BEHAVIOR>( *shape, *m_frame );
|
||||
break;
|
||||
case SHAPE_T::POLY:
|
||||
m_editBehavior = std::make_unique<POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
|
||||
m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
|
||||
break;
|
||||
case SHAPE_T::BEZIER:
|
||||
m_editBehavior = std::make_unique<BEZIER_POINT_EDIT_BEHAVIOR>( *shape );
|
||||
@ -1042,7 +995,7 @@ void EE_POINT_EDITOR::makePointsAndBehavior( EDA_ITEM* aItem )
|
||||
{
|
||||
SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
|
||||
// Implemented directly as a polygon
|
||||
m_editBehavior = std::make_unique<POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
|
||||
m_editBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
|
||||
break;
|
||||
}
|
||||
case SCH_TEXTBOX_T:
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <tool/selection.h>
|
||||
|
||||
class EE_SELECTION_TOOL;
|
||||
class POINT_EDIT_BEHAVIOR;
|
||||
class SCH_BASE_FRAME;
|
||||
class SCH_COMMIT;
|
||||
|
||||
|
@ -589,90 +589,4 @@ private:
|
||||
bool m_allowPoints; ///< If false, only allow editing of EDIT_LINES.
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A helper class interface to manage the edit points for a single item.
|
||||
* Create one ofthese, and it will provide a way to keep a list of points
|
||||
* updated.
|
||||
*
|
||||
* For the moment this is implemented such that it mutates an external
|
||||
* EDIT_POINTS object, but it might be able to also own the points.
|
||||
*/
|
||||
class POINT_EDIT_BEHAVIOR
|
||||
{
|
||||
public:
|
||||
virtual ~POINT_EDIT_BEHAVIOR() = default;
|
||||
|
||||
/**
|
||||
* Construct the initial set of edit points for the item
|
||||
* and append to the given list.
|
||||
*
|
||||
* @param aPoints The list of edit points to fill.
|
||||
*/
|
||||
virtual void MakePoints( EDIT_POINTS& aPoints ) = 0;
|
||||
|
||||
/**
|
||||
* Update the list of the edit points for the item.
|
||||
*
|
||||
* Be very careful not to overrun the list of points -
|
||||
* this class knows how bug there are because it made them
|
||||
* in the first place.
|
||||
*
|
||||
* If item has changed such that that number of points needs to
|
||||
* change, this method has to handle that (probably by clearing
|
||||
* the list and refilling it).
|
||||
*
|
||||
* @param aPoints The list of edit points to update.
|
||||
*/
|
||||
virtual void UpdatePoints( EDIT_POINTS& aPoints ) = 0;
|
||||
|
||||
/**
|
||||
* Update the item with the new positions of the edit points.
|
||||
*
|
||||
* This method should all commit and add to the update list anything that
|
||||
* is NOT the parent item of the EDIT_POINTs. For example, connected lines,
|
||||
* parent tables, etc. The item itself is already handled (most behaviors
|
||||
* don't need more than that).
|
||||
*
|
||||
* @param aEditedPoint The point that was dragged.
|
||||
* You can use this to check by address which point to update.
|
||||
* @param aPoints The new positions of the edit points.
|
||||
* @param aCommit The commit object to use to modify the item.
|
||||
* @param aUpdatedItems The list of items that were updated by the edit (not only the
|
||||
* item that was being edited, but also any other items that were
|
||||
* affected, e.g. by being conneted to the edited item).
|
||||
*/
|
||||
virtual void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
|
||||
std::vector<EDA_ITEM*>& aUpdatedItems ) = 0;
|
||||
|
||||
/**
|
||||
* Get the 45-degree constrainer for the item, when the given point is moved.
|
||||
* Return std::nullopt if not, and the caller can decide.
|
||||
*
|
||||
* If you want to actively disable constraining, return the aEditedPoint
|
||||
* position.
|
||||
*/
|
||||
virtual OPT_VECTOR2I Get45DegreeConstrainer( const EDIT_POINT& aEditedPoint,
|
||||
EDIT_POINTS& aPoints ) const
|
||||
{
|
||||
// By default, no constrainer is defined and the caller must decide
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Checks if two points are the same instance - which means the point is being edited.
|
||||
*/
|
||||
static bool isModified( const EDIT_POINT& aEditedPoint, const EDIT_POINT& aPoint )
|
||||
{
|
||||
return &aEditedPoint == &aPoint;
|
||||
}
|
||||
};
|
||||
|
||||
// Helper macros to check the number of points in the edit points object
|
||||
// Still a bug, but at least it won't segfault if the number of points is wrong
|
||||
#define CHECK_POINT_COUNT(aPoints, aExpected) wxCHECK( aPoints.PointsSize() == aExpected, /* void */ )
|
||||
#define CHECK_POINT_COUNT_GE(aPoints, aExpected) wxCHECK( aPoints.PointsSize() >= aExpected, /* void */ )
|
||||
|
||||
|
||||
#endif /* EDIT_POINTS_H_ */
|
||||
|
185
include/tool/point_editor_behavior.h
Normal file
185
include/tool/point_editor_behavior.h
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wx/debug.h>
|
||||
|
||||
#include <eda_shape.h>
|
||||
#include <tool/edit_points.h>
|
||||
|
||||
class SHAPE_POLY_SET;
|
||||
|
||||
/**
|
||||
* A helper class interface to manage the edit points for a single item.
|
||||
* Create one ofthese, and it will provide a way to keep a list of points
|
||||
* updated.
|
||||
*
|
||||
* For the moment this is implemented such that it mutates an external
|
||||
* EDIT_POINTS object, but it might be able to also own the points.
|
||||
*/
|
||||
class POINT_EDIT_BEHAVIOR
|
||||
{
|
||||
public:
|
||||
virtual ~POINT_EDIT_BEHAVIOR() = default;
|
||||
|
||||
/**
|
||||
* Construct the initial set of edit points for the item
|
||||
* and append to the given list.
|
||||
*
|
||||
* @param aPoints The list of edit points to fill.
|
||||
*/
|
||||
virtual void MakePoints( EDIT_POINTS& aPoints ) = 0;
|
||||
|
||||
/**
|
||||
* Update the list of the edit points for the item.
|
||||
*
|
||||
* Be very careful not to overrun the list of points -
|
||||
* this class knows how bug there are because it made them
|
||||
* in the first place.
|
||||
*
|
||||
* If item has changed such that that number of points needs to
|
||||
* change, this method has to handle that (probably by clearing
|
||||
* the list and refilling it).
|
||||
*
|
||||
* @param aPoints The list of edit points to update.
|
||||
*/
|
||||
virtual void UpdatePoints( EDIT_POINTS& aPoints ) = 0;
|
||||
|
||||
/**
|
||||
* Update the item with the new positions of the edit points.
|
||||
*
|
||||
* This method should all commit and add to the update list anything that
|
||||
* is NOT the parent item of the EDIT_POINTs. For example, connected lines,
|
||||
* parent tables, etc. The item itself is already handled (most behaviors
|
||||
* don't need more than that).
|
||||
*
|
||||
* @param aEditedPoint The point that was dragged.
|
||||
* You can use this to check by address which point to update.
|
||||
* @param aPoints The new positions of the edit points.
|
||||
* @param aCommit The commit object to use to modify the item.
|
||||
* @param aUpdatedItems The list of items that were updated by the edit (not only the
|
||||
* item that was being edited, but also any other items that were
|
||||
* affected, e.g. by being conneted to the edited item).
|
||||
*/
|
||||
virtual void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
|
||||
std::vector<EDA_ITEM*>& aUpdatedItems ) = 0;
|
||||
|
||||
/**
|
||||
* Get the 45-degree constrainer for the item, when the given point is moved.
|
||||
* Return std::nullopt if not, and the caller can decide.
|
||||
*
|
||||
* If you want to actively disable constraining, return the aEditedPoint
|
||||
* position.
|
||||
*/
|
||||
virtual OPT_VECTOR2I Get45DegreeConstrainer( const EDIT_POINT& aEditedPoint,
|
||||
EDIT_POINTS& aPoints ) const
|
||||
{
|
||||
// By default, no constrainer is defined and the caller must decide
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Checks if two points are the same instance - which means the point is being edited.
|
||||
*/
|
||||
static bool isModified( const EDIT_POINT& aEditedPoint, const EDIT_POINT& aPoint )
|
||||
{
|
||||
return &aEditedPoint == &aPoint;
|
||||
}
|
||||
};
|
||||
|
||||
// Helper macros to check the number of points in the edit points object
|
||||
// Still a bug, but at least it won't segfault if the number of points is wrong
|
||||
#define CHECK_POINT_COUNT(aPoints, aExpected) wxCHECK( aPoints.PointsSize() == aExpected, /* void */ )
|
||||
#define CHECK_POINT_COUNT_GE(aPoints, aExpected) wxCHECK( aPoints.PointsSize() >= aExpected, /* void */ )
|
||||
|
||||
|
||||
/**
|
||||
* Class that implements "standard" polygon editing behavior.
|
||||
*
|
||||
* You still need to implement the POINT_EDIT_BEHAVIOR interface (in particular,
|
||||
* you may need to construct a poly set from or apply the poly set to an actual
|
||||
* object) but you can use the helper methods in this class to do the actual work.
|
||||
*/
|
||||
class POLYGON_POINT_EDIT_BEHAVIOR : public POINT_EDIT_BEHAVIOR
|
||||
{
|
||||
public:
|
||||
POLYGON_POINT_EDIT_BEHAVIOR( SHAPE_POLY_SET& aPolygon ) : m_polygon( aPolygon ) {}
|
||||
|
||||
/**
|
||||
* Build the edit points for the given polygon outline.
|
||||
*/
|
||||
static void BuildForPolyOutline( EDIT_POINTS& aPoints, const SHAPE_POLY_SET& aOutline );
|
||||
|
||||
/**
|
||||
* Update the edit points with the current polygon outline.
|
||||
*
|
||||
* If the point sizes differ, the points are rebuilt entirely (in-place)
|
||||
*/
|
||||
static void UpdatePointsFromOutline( const SHAPE_POLY_SET& aOutline, EDIT_POINTS& aPoints );
|
||||
|
||||
/**
|
||||
* Update the polygon outline with the new positions of the edit points.
|
||||
*/
|
||||
static void UpdateOutlineFromPoints( SHAPE_POLY_SET& aOutline, const EDIT_POINT& aEditedPoint,
|
||||
EDIT_POINTS& aPoints );
|
||||
|
||||
void MakePoints( EDIT_POINTS& aPoints ) override
|
||||
{
|
||||
BuildForPolyOutline( aPoints, m_polygon );
|
||||
}
|
||||
|
||||
void UpdatePoints( EDIT_POINTS& aPoints ) override
|
||||
{
|
||||
UpdatePointsFromOutline( m_polygon, aPoints );
|
||||
}
|
||||
|
||||
void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
|
||||
std::vector<EDA_ITEM*>& aUpdatedItems ) override
|
||||
{
|
||||
UpdateOutlineFromPoints( m_polygon, aEditedPoint, aPoints );
|
||||
}
|
||||
|
||||
private:
|
||||
SHAPE_POLY_SET& m_polygon;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* "Standard" polygon editing behavior for EDA_SHAPE polygons.
|
||||
*
|
||||
* As long as updating the EDA_SHAPE's SHAPE_POLY_SET in-place is enough,
|
||||
* this will do the job.
|
||||
*/
|
||||
class EDA_POLYGON_POINT_EDIT_BEHAVIOR : public POLYGON_POINT_EDIT_BEHAVIOR
|
||||
{
|
||||
public:
|
||||
// Editing the underlying polygon shape in-place is enough
|
||||
EDA_POLYGON_POINT_EDIT_BEHAVIOR( EDA_SHAPE& aPolygon ) :
|
||||
POLYGON_POINT_EDIT_BEHAVIOR( aPolygon.GetPolyShape() )
|
||||
{
|
||||
wxASSERT( aPolygon.GetShape() == SHAPE_T::POLY );
|
||||
}
|
||||
};
|
@ -29,7 +29,6 @@
|
||||
using namespace std::placeholders;
|
||||
#include <advanced_config.h>
|
||||
#include <kiplatform/ui.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <view/view_controls.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <geometry/corner_operations.h>
|
||||
@ -37,6 +36,8 @@ using namespace std::placeholders;
|
||||
#include <geometry/seg.h>
|
||||
#include <geometry/vector_utils.h>
|
||||
#include <confirm.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tool/point_editor_behavior.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <tools/pcb_selection_tool.h>
|
||||
#include <tools/pcb_point_editor.h>
|
||||
@ -899,137 +900,21 @@ private:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Construct the points for the given polygon outline into the
|
||||
* EDIT_POINTS container.
|
||||
*/
|
||||
static void buildForPolyOutline( EDIT_POINTS& aPoints, const SHAPE_POLY_SET& aOutline )
|
||||
{
|
||||
const int cornersCount = aOutline.TotalVertices();
|
||||
|
||||
for( auto iterator = aOutline.CIterateWithHoles(); iterator; iterator++ )
|
||||
{
|
||||
aPoints.AddPoint( *iterator );
|
||||
|
||||
if( iterator.IsEndContour() )
|
||||
aPoints.AddBreak();
|
||||
}
|
||||
|
||||
// Lines have to be added after creating edit points, as they use EDIT_POINT references
|
||||
for( int i = 0; i < cornersCount - 1; ++i )
|
||||
{
|
||||
if( aPoints.IsContourEnd( i ) )
|
||||
aPoints.AddLine( aPoints.Point( i ), aPoints.Point( aPoints.GetContourStartIdx( i ) ) );
|
||||
else
|
||||
aPoints.AddLine( aPoints.Point( i ), aPoints.Point( i + 1 ) );
|
||||
|
||||
aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
|
||||
}
|
||||
|
||||
// The last missing line, connecting the last and the first polygon point
|
||||
aPoints.AddLine( aPoints.Point( cornersCount - 1 ),
|
||||
aPoints.Point( aPoints.GetContourStartIdx( cornersCount - 1 ) ) );
|
||||
|
||||
aPoints.Line( aPoints.LinesSize() - 1 )
|
||||
.SetConstraint( new EC_PERPLINE( aPoints.Line( aPoints.LinesSize() - 1 ) ) );
|
||||
}
|
||||
|
||||
|
||||
class POLYGON_POINT_EDIT_BEHAVIOR : public POINT_EDIT_BEHAVIOR
|
||||
class ZONE_POINT_EDIT_BEHAVIOR : public POLYGON_POINT_EDIT_BEHAVIOR
|
||||
{
|
||||
public:
|
||||
POLYGON_POINT_EDIT_BEHAVIOR( PCB_SHAPE& aPolygon ) : m_polygon( aPolygon )
|
||||
ZONE_POINT_EDIT_BEHAVIOR( ZONE& aZone ) :
|
||||
POLYGON_POINT_EDIT_BEHAVIOR( *aZone.Outline() ), m_zone( aZone )
|
||||
{
|
||||
wxASSERT( m_polygon.GetShape() == SHAPE_T::POLY );
|
||||
}
|
||||
|
||||
void MakePoints( EDIT_POINTS& aPoints ) override
|
||||
{
|
||||
buildForPolyOutline( aPoints, m_polygon.GetPolyShape() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the edit points with the current polygon outline.
|
||||
*
|
||||
* If the point sizes differ, the points are rebuilt entirely (in-place)
|
||||
*/
|
||||
static void UpdatePointsFromOutline( const SHAPE_POLY_SET& aOutline, EDIT_POINTS& aPoints )
|
||||
{
|
||||
if( aPoints.PointsSize() != (unsigned) aOutline.TotalVertices() )
|
||||
{
|
||||
aPoints.Clear();
|
||||
buildForPolyOutline( aPoints, aOutline );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < aOutline.TotalVertices(); ++i )
|
||||
{
|
||||
aPoints.Point( i ).SetPosition( aOutline.CVertex( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateOutlineFromPoints( SHAPE_POLY_SET& aOutline, const EDIT_POINT& aEditedPoint,
|
||||
EDIT_POINTS& aPoints )
|
||||
{
|
||||
CHECK_POINT_COUNT_GE( aPoints, (unsigned) aOutline.TotalVertices() );
|
||||
|
||||
for( int i = 0; i < aOutline.TotalVertices(); ++i )
|
||||
{
|
||||
aOutline.SetVertex( i, aPoints.Point( i ).GetPosition() );
|
||||
}
|
||||
|
||||
for( unsigned i = 0; i < aPoints.LinesSize(); ++i )
|
||||
{
|
||||
if( !isModified( aEditedPoint, aPoints.Line( i ) ) )
|
||||
{
|
||||
aPoints.Line( i ).SetConstraint( new EC_PERPLINE( aPoints.Line( i ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePoints( EDIT_POINTS& aPoints ) override
|
||||
{
|
||||
// No size check here, as we can and will rebuild if that fails
|
||||
UpdatePointsFromOutline( m_polygon.GetPolyShape(), aPoints );
|
||||
}
|
||||
|
||||
void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
|
||||
std::vector<EDA_ITEM*>& aUpdatedItems ) override
|
||||
{
|
||||
UpdateOutlineFromPoints( m_polygon.GetPolyShape(), aEditedPoint, aPoints );
|
||||
}
|
||||
|
||||
private:
|
||||
PCB_SHAPE& m_polygon;
|
||||
};
|
||||
|
||||
|
||||
class ZONE_POINT_EDIT_BEHAVIOR : public POINT_EDIT_BEHAVIOR
|
||||
{
|
||||
public:
|
||||
ZONE_POINT_EDIT_BEHAVIOR( ZONE& aZone ) : m_zone( aZone ) {}
|
||||
|
||||
void MakePoints( EDIT_POINTS& aPoints ) override
|
||||
{
|
||||
buildForPolyOutline( aPoints, *m_zone.Outline() );
|
||||
}
|
||||
|
||||
void UpdatePoints( EDIT_POINTS& aPoints ) override
|
||||
{
|
||||
// No size check here, as we can and will rebuild if that fails;
|
||||
POLYGON_POINT_EDIT_BEHAVIOR::UpdatePointsFromOutline( *m_zone.Outline(), aPoints );
|
||||
}
|
||||
|
||||
void UpdateItem( const EDIT_POINT& aEditedPoint, EDIT_POINTS& aPoints, COMMIT& aCommit,
|
||||
std::vector<EDA_ITEM*>& aUpdatedItems ) override
|
||||
{
|
||||
SHAPE_POLY_SET& outline = *m_zone.Outline();
|
||||
CHECK_POINT_COUNT( aPoints, (unsigned) outline.TotalVertices() );
|
||||
|
||||
m_zone.UnFill();
|
||||
|
||||
POLYGON_POINT_EDIT_BEHAVIOR::UpdateOutlineFromPoints( outline, aEditedPoint, aPoints );
|
||||
// Defer to the base class to update the polygon
|
||||
POLYGON_POINT_EDIT_BEHAVIOR::UpdateItem( aEditedPoint, aPoints, aCommit, aUpdatedItems );
|
||||
|
||||
m_zone.HatchBorder();
|
||||
}
|
||||
@ -2240,7 +2125,7 @@ std::shared_ptr<EDIT_POINTS> PCB_POINT_EDITOR::makePoints( EDA_ITEM* aItem )
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLY:
|
||||
m_editorBehavior = std::make_unique<POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
|
||||
m_editorBehavior = std::make_unique<EDA_POLYGON_POINT_EDIT_BEHAVIOR>( *shape );
|
||||
break;
|
||||
|
||||
case SHAPE_T::BEZIER:
|
||||
|
Loading…
Reference in New Issue
Block a user