Skip to content

Commit be4ad06

Browse files
committed
finished offsetPolyline
1 parent efa7793 commit be4ad06

File tree

7 files changed

+56
-78
lines changed

7 files changed

+56
-78
lines changed

docs/homog2d_history.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ now all of these return the number of points that the primitive has, as a `size_
3030
- added `getBisectorLines()` for polyline objects
3131
- added `getOSegment()` to Polyline class
3232
- changed normalization of closed polyline: now constant orientation
33-
- `getLmPoint()` and associated functions now return a `std::pair`, so user can fetch its position in the container.
33+
- `getLmPoint()` and associated functions now return a `std::pair`, so user can fetch its position in the container.
3434
The downside is that it is now not possible to use a `std::list` as input container.
3535
See [details here](homog2d_manual.md#extremum_points).
3636
- renamed `getOrthogonalLine()` to `getOrthogLine()` so it's similar to `getOrthogSegment()`
37+
- added member function `getPointAt()` to class `OSegment`
38+
3739

3840
- [v2.12](https://github.com/skramm/homog2d/releases/tag/v2.12), released on 2025-01-26
3941
- **heavy architectural change**: runtime polymorphism is now achieved in a more modern way, using `std::variant`, [see here](homog2d_manual.md#section_rtp).

docs/homog2d_manual.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,19 @@ The minimum value for `nb` is 3 (will generate an equilateral triangle), the fun
10721072
10731073
[source](../misc/figures_src/src/polyline_rcp_1.cpp)
10741074
1075-
#### 3.4.12 - Importing from boost::geometry
1075+
1076+
#### 3.4.12 - Offsetted polyline
1077+
1078+
For closed Polyline objects, the member function `getOffsetPoly()` can compute a new polyline at a given distance.
1079+
Its argument is a distance (numerical value).
1080+
If positive, the returned polyline will be "outside", if negative, il will be inside.
1081+
1082+
An optional second argument of type `OffsetPolyParams` holds a boolean value `_angleSplit` that can be set to `true` to "smoothen" the return polyline, by adding some points on sharp angles
1083+
(applies only to "outside" computation).
1084+
1085+
See [showcase 22](homog2d_showcase.md#sc22)
1086+
1087+
#### 3.4.13 - Importing from boost::geometry
10761088
<a name="boost_geom_1"></a>
10771089
10781090
If the symbol `HOMOG2D_USE_BOOSTGEOM` is defined (see [build options](#build_options)), you can import a Polyline from a boost Polygon type.
@@ -1159,7 +1171,7 @@ bool b2 = isCircle( ell, 1E-15 );
11591171
<a name="p_commonf"></a>
11601172

11611173
All the types above share some common functions, that are also declared as virtual in the root class `Root`.
1162-
Thus, this enable classical pointer-based runtime polymorphism, [see here](#section_rtp).
1174+
Thus, this enables classical pointer-based runtime polymorphism, [see here](#section_rtp).
11631175

11641176
All of these are `const`.
11651177
The names of these functions are:

homog2d.hpp

Lines changed: 24 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5990,17 +5990,6 @@ struct OffsetPolyParams
59905990
bool _angleSplit = false;
59915991
};
59925992

5993-
#if 1
5994-
struct TmpDebug
5995-
{
5996-
Point2d_<double> pt1;
5997-
Point2d_<double> pt_cut;
5998-
Point2d_<double> ptnew;
5999-
std::vector<Segment_<double>> segs;
6000-
std::pair<Line2d_<double>,Line2d_<double>> plines;
6001-
std::pair<OSegment_<double>,OSegment_<double>> psegs;
6002-
};
6003-
#endif
60045993

60055994
namespace base {
60065995

@@ -6607,8 +6596,7 @@ Sfinae should resolve ONLY for CPolyline
66076596
public:
66086597
template<typename T>
66096598
PolylineBase<typ::IsClosed,FPT>
6610-
getOffsetPoly( T value, TmpDebug&, OffsetPolyParams p=OffsetPolyParams{} ) const;
6611-
// getOffsetPoly( T value, OffsetPolyParams p=OffsetPolyParams{} ) const;
6599+
getOffsetPoly( T value, OffsetPolyParams p=OffsetPolyParams{} ) const;
66126600

66136601
std::vector<Line2d_<HOMOG2D_INUMTYPE>>
66146602
getBisectorLines() const
@@ -6624,29 +6612,6 @@ Sfinae should resolve ONLY for CPolyline
66246612
}; // class PolylineBase
66256613

66266614

6627-
//------------------------------------------------------------------
6628-
/// Helper function for cutting angles, used in getOffsetPoly()
6629-
/// Issue: output points are in wrong order when angle not convex
6630-
template<typename FP1,typename FP2>
6631-
PointPair_<HOMOG2D_INUMTYPE>
6632-
p_computeAngleCut(
6633-
Point2d_<FP1> pt1, ///< source polyline point
6634-
Point2d_<HOMOG2D_INUMTYPE> pt2, ///< intersection point that we want to "cut"
6635-
const std::pair<Line2d_<FP2>,Line2d_<FP2>>& pli ///< pair of lines that we want to joint before the point pt2
6636-
// TmpDebug& debug
6637-
)
6638-
{
6639-
Segment_<HOMOG2D_INUMTYPE> seg( pt1, pt2 );
6640-
// debug.seg= seg;
6641-
auto mid = seg.getCenter();
6642-
auto oline = seg.getLine().getOrthogLine( mid );
6643-
auto inters1 = oline.intersects(pli.first);
6644-
auto inters2 = oline.intersects(pli.second);
6645-
return std::make_pair(
6646-
inters1.get(),
6647-
inters2.get()
6648-
);
6649-
}
66506615
//------------------------------------------------------------------
66516616
/// Return an "offsetted" closed polyline, requires simple polygon (CPolyline AND no crossings) as input
66526617
/**
@@ -6658,11 +6623,11 @@ On failure (for whatever reason), will return an empty CPolyline
66586623
template<typename PLT,typename FPT>
66596624
template<typename T>
66606625
PolylineBase<typ::IsClosed,FPT>
6661-
PolylineBase<PLT,FPT>::getOffsetPoly( T dist, TmpDebug& dbg, OffsetPolyParams params ) const
6662-
//PolylineBase<PLT,FPT>::getOffsetPoly( T dist, OffsetPolyParams params ) const
6626+
PolylineBase<PLT,FPT>::getOffsetPoly( T dist, OffsetPolyParams params ) const
66636627
{
66646628
HOMOG2D_CHECK_IS_NUMBER(T);
6665-
auto dist0 = (HOMOG2D_INUMTYPE)dist;
6629+
auto dist0 = (HOMOG2D_INUMTYPE)dist; // casting
6630+
66666631
bool valid = true;
66676632
if( homog2d_abs(dist) < thr::nullDistance() )
66686633
{
@@ -6684,24 +6649,19 @@ PolylineBase<PLT,FPT>::getOffsetPoly( T dist, TmpDebug& dbg, OffsetPolyParams pa
66846649

66856650
p_normalizePoly();
66866651

6687-
auto side = (dist<0 ? PointSide::Left : PointSide::Right);
6688-
66896652
size_t current = 0;
6690-
bool paraLines = false;
6653+
// bool paraLines = false;
66916654

66926655
std::vector<Point2d_<FPT>> v_out;
66936656
auto osegs = getOSegs();
66946657
auto oseg1 = osegs.at(current);
66956658
do
66966659
{
6697-
auto next1 = (current==size()-1 ? 0 : current+1);
6698-
auto next2 = (current==size()-1 ? 0 : current+1);
6660+
auto next = (current==size()-1 ? 0 : current+1);
66996661

6700-
auto pt1 = getPoint(current);
6701-
auto pt2 = getPoint(next1);
6702-
auto pt3 = getPoint(next2);
6662+
auto pt1 = getPoint(next);
67036663

6704-
auto oseg2 = osegs.at(next1);
6664+
auto oseg2 = osegs.at(next);
67056665

67066666
auto psegs1 = oseg1.getParallelSegs(homog2d_abs(dist0));
67076667
auto psegs2 = oseg2.getParallelSegs(homog2d_abs(dist0));
@@ -6718,37 +6678,34 @@ PolylineBase<PLT,FPT>::getOffsetPoly( T dist, TmpDebug& dbg, OffsetPolyParams pa
67186678
auto li2 = pseg2->getLine();
67196679
if( !areParallel(li1,li2) )
67206680
{
6721-
auto pt = li1 * li2;
6722-
if( !params._angleSplit || getAngle(oseg1,oseg2)>0 )
6681+
auto pt_int = li1 * li2;
6682+
if( !params._angleSplit || getAngle(oseg1,oseg2)>0 || dist < 0 )
67236683
{
6724-
v_out.push_back( pt ); // add point intersection of the two lines
6684+
v_out.push_back( pt_int ); // add point intersection of the two lines
67256685
}
67266686
else
67276687
{
6728-
auto sseg = OSegment_<HOMOG2D_INUMTYPE>( pt, pt2 );
6729-
std::cout << "seg=" << oseg << '\n';
6730-
dbg.segs.push_back( oseg );
6731-
6688+
auto oseg = OSegment_<HOMOG2D_INUMTYPE>( pt1, pt_int );
6689+
auto dist_cut = std::min( oseg.length(), dist0 );
67326690

6733-
auto dist2 = pt2.distTo( seg.getCenter() );
6734-
auto dist_cut = std::min( dist2, dist0 );
6735-
std::cout << "current:" << current << " d0=" << dist0 << " d2=" << dist2 << " dist_cut="<<dist_cut << '\n';
67366691
auto pt_cut = oseg.getPointAt( dist_cut );
6737-
dbg.pt_cut = pt_cut;
6738-
auto oli = seg.getLine().getOrthogLine( pt_cut );
6692+
auto oli = oseg.getLine().getOrthogLine( pt_cut );
6693+
67396694
auto pt_cut1 = oli * li1;
67406695
auto pt_cut2 = oli * li2;
6696+
67416697
v_out.push_back( pt_cut1 );
6742-
v_out.push_back( pt_cut2 );
6698+
if( pt_cut1 != pt_cut2 ) // so we don't add two identical pts (in case they were computed as such)
6699+
v_out.push_back( pt_cut2 );
67436700
}
67446701
}
6745-
else
6746-
std::cout << "parallel!\n";
6702+
// else
6703+
// std::cout << "parallel!\n";
67476704

67486705
current++;
67496706
oseg1 = oseg2;
67506707
}
6751-
while( current<size() && !paraLines );
6708+
while( current<size() ); //&& !paraLines );
67526709

67536710
return PolylineBase<typ::IsClosed,FPT>( v_out );
67546711
}
@@ -6966,6 +6923,9 @@ getTmPoint( const T& t )
69666923
/**
69676924
- first: the point
69686925
- second: the distance (index) from begin position
6926+
6927+
\todo 20250222: CHANGE RETURN TYPE! => should return an iterator, not a pair
6928+
(so this allows usage of any non-random access container)
69696929
*/
69706930
template<
69716931
typename T,

misc/demo_opencv.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2004,12 +2004,8 @@ void process_PO( IM& im, const POL& pol, Param_PO& data )
20042004

20052005
if( pol.isSimple() )
20062006
{
2007-
TmpDebug dbg;
2008-
auto cpoly_off = pol.getOffsetPoly( (data._side?1:-1)*data._offsetDist, dbg, data._params );
2009-
draw( im, cpoly_off , img::DrawParams().showPoints().setColor(0,0,250) );
2010-
2011-
draw( im, dbg.segs, img::DrawParams().showPoints().setColor(0,250,0) );
2012-
draw( im, dbg.pt_cut, img::DrawParams().showPoints().setColor(250,0,200) );
2007+
auto cpoly_off = pol.getOffsetPoly( (data._side?1:-1)*data._offsetDist, data._params );
2008+
draw( im, cpoly_off , img::DrawParams().showPoints(false).setColor(0,0,250) );
20132009

20142010
draw( im, dbg.psegs );
20152011
auto centr = pol.centroid();

misc/homog2d_test.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2566,6 +2566,15 @@ TEST_CASE( "Ellipse", "[ell1]" )
25662566
CHECK( el.isCircle() == false );
25672567
}
25682568
}
2569+
2570+
TEST_CASE( "OSegment getPointAt()", "[oseg-pt-at]" )
2571+
{
2572+
OSegment_<NUMTYPE> s1( 0,0,10,0);
2573+
CHECK( s1.getPointAt(0) == Point2d_<NUMTYPE>(0,0) );
2574+
CHECK( s1.getPointAt(5) == Point2d_<NUMTYPE>(5,0) );
2575+
CHECK( s1.getPointAt(10) == Point2d_<NUMTYPE>(10,0) );
2576+
CHECK( s1.getPointAt(20) == Point2d_<NUMTYPE>(20,0) );
2577+
}
25692578

25702579
TEST_CASE( "OSegment point side", "[oseg-pt-side]" )
25712580
{

misc/showcase/showcase13.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ int main( int, const char** )
3838
cir.set( vec ); // Minimum Enclosing Circle (MEC)
3939
cir.draw( im, img::DrawParams().setColor(0,100,150) );
4040

41-
getTmPoint(vec).draw( im, extr_col );
42-
getRmPoint(vec).draw( im, extr_col );
43-
getLmPoint(vec).draw( im, extr_col );
44-
getBmPoint(vec).draw( im, extr_col );
41+
getTmPoint(vec).first.draw( im, extr_col );
42+
getRmPoint(vec).first.draw( im, extr_col );
43+
getLmPoint(vec).first.draw( im, extr_col );
44+
getBmPoint(vec).first.draw( im, extr_col );
4545

4646
std::ostringstream oss;
4747
oss << "showcase13_" << std::setfill('0') << std::setw(2) << i << ".svg";

misc/showcase/showcase22.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ int main( int, const char** )
2525
auto pol2 = H2 * p0;
2626

2727
auto delta = 5.6;
28-
// img::Image<img::SvgImage> im( 500, 250 );
2928
img::Image<img::SvgImage> im( 500, 250 );
3029

3130
std::vector<CPolyline> v_poly1, v_poly2;

0 commit comments

Comments
 (0)