KiCad PCB EDA Suite
Loading...
Searching...
No Matches
nearest.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include "geometry/nearest.h"
25
26#include <wx/debug.h>
27
28#include <core/type_helpers.h>
29
31
32
33namespace
34{
35
36VECTOR2I NearestPoint( const BOX2I& aBox, const VECTOR2I& aPt )
37{
38 VECTOR2I nearest;
39 int bestDistance = std::numeric_limits<int>::max();
40
41 for( const SEG& seg : KIGEOM::BoxToSegs( aBox ) )
42 {
43 const VECTOR2I nearestSegPt = seg.NearestPoint( aPt );
44 const int thisDistance = nearestSegPt.Distance( aPt );
45
46 if( thisDistance <= bestDistance )
47 {
48 nearest = nearestSegPt;
49 bestDistance = thisDistance;
50 }
51 }
52 return nearest;
53};
54
55} // namespace
56
57
59{
60 VECTOR2I nearest;
61
62 std::visit(
63 [&]( const auto& geom )
64 {
65 using GeomType = std::decay_t<decltype( geom )>;
66
67 if constexpr( std::is_same_v<GeomType, LINE>
68 || std::is_same_v<GeomType, HALF_LINE>
69 || std::is_same_v<GeomType, SEG>
70 || std::is_same_v<GeomType, CIRCLE>
71 || std::is_same_v<GeomType, SHAPE_ARC> )
72 {
73 // Same signatures for all these types
74 // But they're not in the same polymorphic hierarchy
75 nearest = geom.NearestPoint( aPt );
76 }
77 else if constexpr( std::is_same_v<GeomType, BOX2I> )
78 {
79 // Defer to the utils function
80 nearest = NearestPoint( geom, aPt );
81 }
82 else if constexpr( std::is_same_v<GeomType, VECTOR2I> )
83 {
84 nearest = geom;
85 }
86 else
87 {
88 static_assert( always_false<GeomType>::value, "non-exhaustive visitor" );
89 }
90 },
91 aGeom );
92
93 return nearest;
94}
95
96OPT_VECTOR2I GetNearestPoint( const std::vector<NEARABLE_GEOM>& aGeoms, const VECTOR2I& aPt )
97{
98 OPT_VECTOR2I nearestPointOnAny;
99 int bestDistance = std::numeric_limits<int>::max();
100
101 for( const NEARABLE_GEOM& geom : aGeoms )
102 {
103 const VECTOR2I thisNearest = GetNearestPoint( geom, aPt );
104 const int thisDistance = thisNearest.Distance( aPt );
105
106 if( !nearestPointOnAny || thisDistance < bestDistance )
107 {
108 nearestPointOnAny = thisNearest;
109 bestDistance = thisDistance;
110 }
111 }
112
113 return nearestPointOnAny;
114}
Definition: seg.h:42
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
Definition: vector2d.h:557
std::array< SEG, 4 > BoxToSegs(const BOX2I &aBox)
Decompose a BOX2 into four segments.
Definition: shape_utils.cpp:66
VECTOR2I GetNearestPoint(const NEARABLE_GEOM &aGeom, const VECTOR2I &aPt)
Get the nearest point on a geometry to a given point.
Definition: nearest.cpp:58
std::variant< LINE, HALF_LINE, SEG, CIRCLE, SHAPE_ARC, BOX2I, VECTOR2I > NEARABLE_GEOM
A variant type that can hold any of the supported geometry types for nearest point calculations.
Definition: nearest.h:43
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
Utility functions for working with shapes.
A type that is always false.
Definition: type_helpers.h:46