1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2018-2020 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
23  */
24 
25 /**
26  * @file marker_base.cpp
27  * @brief Implementation of MARKER_BASE class.
28  * Markers are used to show something (usually a drc/erc problem).
29  * Markers in Pcbnew and Eeschema are derived from this base class.
30  */
31 
32 
33 #include "base_screen.h"
34 #include "marker_base.h"
35 #include <core/arraydim.h>
36 #include <geometry/shape_line_chain.h>
37 #include <render_settings.h>
38 #include "dialogs/dialog_display_html_text_base.h"
39 
40 
41 /* The graphic shape of markers is a polygon.
42  * MarkerShapeCorners contains the coordinates of corners of the polygonal default shape
43  * they are arbitrary units to make coding shape easy.
44  * internal units coordinates are these values scaled by .m_ScalingFactor
45  */
46 static const VECTOR2I MarkerShapeCorners[] =
47 {
48     VECTOR2I( 0,  0 ),
49     VECTOR2I( 8,  1 ),
50     VECTOR2I( 4,  3 ),
51     VECTOR2I( 13, 8 ),
52     VECTOR2I( 9, 9 ),
53     VECTOR2I( 8,  13 ),
54     VECTOR2I( 3,  4 ),
55     VECTOR2I( 1,  8 ),
56     VECTOR2I( 0,  0 )
57 };
58 const unsigned CORNERS_COUNT = arrayDim( MarkerShapeCorners );
59 
60 
MARKER_BASE(int aScalingFactor,std::shared_ptr<RC_ITEM> aItem,TYPEMARKER aType)61 MARKER_BASE::MARKER_BASE( int aScalingFactor, std::shared_ptr<RC_ITEM> aItem, TYPEMARKER aType ) :
62         m_markerType( aType ),
63         m_excluded( false ),
64         m_rcItem( aItem ),
65         m_scalingFactor( aScalingFactor )
66 {
67     const VECTOR2I* point_shape = MarkerShapeCorners;
68     wxPoint start( point_shape->x, point_shape->y );
69     wxPoint end = start;
70 
71     for( unsigned ii = 1; ii < CORNERS_COUNT; ii++ )
72     {
73         ++point_shape;
74         start.x = std::min( start.x, point_shape->x);
75         start.y = std::min( start.y, point_shape->y);
76         end.x = std::max( end.x, point_shape->x);
77         end.y = std::max( end.y, point_shape->y);
78     }
79 
80     m_shapeBoundingBox.SetOrigin( start);
81     m_shapeBoundingBox.SetEnd( end);
82 }
83 
84 
~MARKER_BASE()85 MARKER_BASE::~MARKER_BASE()
86 {
87 }
88 
89 
HitTestMarker(const wxPoint & aHitPosition,int aAccuracy) const90 bool MARKER_BASE::HitTestMarker( const wxPoint& aHitPosition, int aAccuracy ) const
91 {
92     EDA_RECT bbox = GetBoundingBoxMarker();
93     bbox.Inflate( aAccuracy );
94 
95     // Fast hit test using boundary box. A finer test will be made if requested
96     bool hit = bbox.Contains( aHitPosition );
97 
98     if( hit )   // Fine test
99     {
100         SHAPE_LINE_CHAIN polygon;
101         ShapeToPolygon( polygon );
102         VECTOR2I rel_pos( aHitPosition - m_Pos );
103         hit = polygon.PointInside( rel_pos, aAccuracy );
104     }
105 
106     return hit;
107 }
108 
109 
ShapeToPolygon(SHAPE_LINE_CHAIN & aPolygon,int aScale) const110 void MARKER_BASE::ShapeToPolygon( SHAPE_LINE_CHAIN& aPolygon, int aScale ) const
111 {
112     if( aScale < 0 )
113         aScale = MarkerScale();
114 
115     for( const VECTOR2I& corner : MarkerShapeCorners )
116         aPolygon.Append( corner * aScale );
117 
118     // Be sure aPolygon is seen as a closed polyline:
119     aPolygon.SetClosed( true );
120 }
121 
122 
GetBoundingBoxMarker() const123 EDA_RECT MARKER_BASE::GetBoundingBoxMarker() const
124 {
125     wxSize size_iu = m_shapeBoundingBox.GetSize();
126     wxPoint position_iu = m_shapeBoundingBox.GetPosition();
127     size_iu.x *= m_scalingFactor;
128     size_iu.y *= m_scalingFactor;
129     position_iu.x *= m_scalingFactor;
130     position_iu.y *= m_scalingFactor;
131     position_iu += m_Pos;
132 
133     return EDA_RECT( position_iu, size_iu );
134 }
135 
136 
PrintMarker(const RENDER_SETTINGS * aSettings,const wxPoint & aOffset)137 void MARKER_BASE::PrintMarker( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset )
138 {
139     wxDC* DC = aSettings->GetPrintDC();
140 
141     // Build the marker shape polygon in internal units:
142     std::vector<wxPoint> shape;
143     shape.reserve( CORNERS_COUNT );
144 
145     for( const VECTOR2I& corner : MarkerShapeCorners )
146         shape.emplace_back( corner * MarkerScale() + m_Pos + aOffset );
147 
148     GRClosedPoly( nullptr, DC, CORNERS_COUNT, &shape[0], true, 0, getColor(), getColor() );
149 }
150