From 3f8090b3fd26bb8b8fa6a76751604efcb8a3f322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6fferlein?= Date: Mon, 11 May 2020 19:24:44 +0200 Subject: [PATCH] Fixed #547 (better error messages on some Shape methods, fixed doc). (#550) --- src/db/db/dbShape.cc | 108 ++++++++++++++----- src/lay/lay/doc/programming/database_api.xml | 6 +- testdata/ruby/dbShapesTest.rb | 44 +++++++- 3 files changed, 126 insertions(+), 32 deletions(-) diff --git a/src/db/db/dbShape.cc b/src/db/db/dbShape.cc index 65fce7364..71e33c35e 100644 --- a/src/db/db/dbShape.cc +++ b/src/db/db/dbShape.cc @@ -24,10 +24,51 @@ #include "dbShape.h" #include "dbBoxConvert.h" #include "dbPolygonTools.h" +#include "tlCpp.h" namespace db { +static NO_RETURN void raise_no_path () +{ + throw tl::Exception (tl::to_string (tr ("Shape is not a path"))); +} + +static NO_RETURN void raise_no_polygon () +{ + throw tl::Exception (tl::to_string (tr ("Shape is not a general or simple polygon"))); +} + +static NO_RETURN void raise_no_general_polygon () +{ + throw tl::Exception (tl::to_string (tr ("Shape is not a general polygon"))); +} + +static NO_RETURN void raise_no_simple_polygon () +{ + throw tl::Exception (tl::to_string (tr ("Shape is not a simple polygon-type"))); +} + +static NO_RETURN void raise_no_box () +{ + throw tl::Exception (tl::to_string (tr ("Shape is not a box"))); +} + +static NO_RETURN void raise_no_text () +{ + throw tl::Exception (tl::to_string (tr ("Shape is not a text"))); +} + +static NO_RETURN void raise_invalid_hole_index_on_polygon () +{ + throw tl::Exception (tl::to_string (tr ("Invalid hole index"))); +} + +static NO_RETURN void raise_invalid_hole_index_on_simple_polygon () +{ + throw tl::Exception (tl::to_string (tr ("A simple polygon doesn't have holes"))); +} + // ------------------------------------------------------------------------------- // Shape implementation @@ -145,7 +186,7 @@ Shape::point_iterator Shape::begin_point () const } else if (m_type == PathRef || m_type == PathPtrArrayMember) { return point_iterator (path_ref ().begin ()); } else { - tl_assert (false); + raise_no_path (); } } @@ -156,7 +197,7 @@ Shape::point_iterator Shape::end_point () const } else if (m_type == PathRef || m_type == PathPtrArrayMember) { return point_iterator (path_ref ().end ()); } else { - tl_assert (false); + raise_no_path (); } } @@ -171,7 +212,7 @@ Shape::point_iterator Shape::begin_hull () const } else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) { return point_iterator (polygon_ref ().begin_hull ()); } else { - tl_assert (false); + raise_no_polygon (); } } @@ -186,37 +227,45 @@ Shape::point_iterator Shape::end_hull () const } else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) { return point_iterator (polygon_ref ().end_hull ()); } else { - tl_assert (false); + raise_no_polygon (); } } Shape::point_iterator Shape::begin_hole (unsigned int hole) const { - if (m_type == SimplePolygon) { - return point_iterator (simple_polygon ().begin_hole (hole)); - } else if (m_type == SimplePolygonRef || m_type == SimplePolygonPtrArrayMember) { - return point_iterator (simple_polygon_ref ().begin_hole (hole)); + if (m_type == SimplePolygon || m_type == SimplePolygonRef || m_type == SimplePolygonPtrArrayMember) { + raise_invalid_hole_index_on_simple_polygon (); } else if (m_type == Polygon) { + if (hole >= polygon ().holes ()) { + raise_invalid_hole_index_on_polygon (); + } return point_iterator (polygon ().begin_hole (hole)); } else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) { + if (hole >= polygon_ref ().obj ().holes ()) { + raise_invalid_hole_index_on_polygon (); + } return point_iterator (polygon_ref ().begin_hole (hole)); } else { - tl_assert (false); + raise_no_polygon (); } } Shape::point_iterator Shape::end_hole (unsigned int hole) const { - if (m_type == SimplePolygon) { - return point_iterator (simple_polygon ().end_hole (hole)); - } else if (m_type == SimplePolygonRef || m_type == SimplePolygonPtrArrayMember) { - return point_iterator (simple_polygon_ref ().end_hole (hole)); + if (m_type == SimplePolygon || m_type == SimplePolygonRef || m_type == SimplePolygonPtrArrayMember) { + raise_invalid_hole_index_on_simple_polygon (); } else if (m_type == Polygon) { + if (hole >= polygon ().holes ()) { + raise_invalid_hole_index_on_polygon (); + } return point_iterator (polygon ().end_hole (hole)); } else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) { + if (hole >= polygon_ref ().obj ().holes ()) { + raise_invalid_hole_index_on_polygon (); + } return point_iterator (polygon_ref ().end_hole (hole)); } else { - tl_assert (false); + raise_no_polygon (); } } @@ -231,7 +280,7 @@ unsigned int Shape::holes () const } else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) { return polygon_ref ().obj ().holes (); } else { - tl_assert (false); + raise_no_polygon (); } } @@ -246,7 +295,7 @@ Shape::polygon_edge_iterator Shape::begin_edge () const } else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) { return polygon_edge_iterator (polygon_ref ().begin_edge ()); } else { - tl_assert (false); + raise_no_polygon (); } } @@ -269,29 +318,31 @@ Shape::polygon_edge_iterator Shape::begin_edge (unsigned int c) const } else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) { return polygon_edge_iterator (polygon_ref ().begin_edge (c)); } else { - tl_assert (false); + raise_no_polygon (); } } Shape::polygon_ref_type Shape::polygon_ref () const { - tl_assert (m_type == PolygonRef || m_type == PolygonPtrArrayMember); if (m_type == PolygonRef) { return *basic_ptr (polygon_ref_type::tag ()); - } else { + } else if (m_type == PolygonPtrArrayMember) { tl_assert (m_trans.rot () == 0); return polygon_ref_type (&basic_ptr (polygon_ptr_array_type::tag ())->object ().obj (), m_trans.disp ()); + } else { + raise_no_general_polygon (); } } Shape::simple_polygon_ref_type Shape::simple_polygon_ref () const { - tl_assert (m_type == SimplePolygonRef || m_type == SimplePolygonPtrArrayMember); if (m_type == SimplePolygonRef) { return *basic_ptr (simple_polygon_ref_type::tag ()); - } else { + } else if (SimplePolygonPtrArrayMember) { tl_assert (m_trans.rot () == 0); return simple_polygon_ref_type (&basic_ptr (simple_polygon_ptr_array_type::tag ())->object ().obj (), m_trans.disp ()); + } else { + raise_no_simple_polygon (); } } @@ -363,12 +414,13 @@ bool Shape::simple_polygon (Shape::simple_polygon_type &p) const Shape::path_ref_type Shape::path_ref () const { - tl_assert (m_type == PathRef || m_type == PathPtrArrayMember); if (m_type == PathRef) { return *basic_ptr (path_ref_type::tag ()); - } else { + } else if (m_type == PathPtrArrayMember) { tl_assert (m_trans.rot () == 0); return path_ref_type (&basic_ptr (path_ptr_array_type::tag ())->object ().obj (), m_trans.disp ()); + } else { + raise_no_path (); } } @@ -423,12 +475,13 @@ bool Shape::path (Shape::path_type &p) const Shape::text_ref_type Shape::text_ref () const { - tl_assert (m_type == TextRef || m_type == TextPtrArrayMember); if (m_type == TextRef) { return *basic_ptr (text_ref_type::tag ()); - } else { + } else if (m_type == TextPtrArrayMember) { tl_assert (m_trans.rot () == 0); return text_ref_type (&basic_ptr (text_ptr_array_type::tag ())->object ().obj (), disp_type (m_trans.disp ())); + } else { + raise_no_text (); } } @@ -503,15 +556,16 @@ db::VAlign Shape::text_valign () const Shape::box_type Shape::box () const { - tl_assert (m_type == Box || m_type == ShortBox || m_type == BoxArrayMember || m_type == ShortBoxArrayMember); if (m_type == Box) { return *basic_ptr (box_type::tag ()); } else if (m_type == ShortBox) { return Shape::box_type (*basic_ptr (short_box_type::tag ())); } else if (m_type == BoxArrayMember) { return m_trans * basic_ptr (box_array_type::tag ())->object (); - } else { + } else if (m_type == ShortBoxArrayMember) { return m_trans * basic_ptr (short_box_array_type::tag ())->object (); + } else { + raise_no_box (); } } diff --git a/src/lay/lay/doc/programming/database_api.xml b/src/lay/lay/doc/programming/database_api.xml index b7dce4f13..3607af938 100644 --- a/src/lay/lay/doc/programming/database_api.xml +++ b/src/lay/lay/doc/programming/database_api.xml @@ -1150,10 +1150,10 @@ end

In every case, the iterator will deliver all edges (connections between points - of the polygon). will deliver every point of the polygon, including that of the - holes. will only deliver the points of the outer (hull) contour and + of the polygon). + will deliver the points of the outer (hull) contour and will deliver the points of a specific hole contour. will deliver - the number of holes. A simple polygon does not have holes. + the number of holes. A simple polygon does not have holes and always gives zero.

The getter delivers a object. The same diff --git a/testdata/ruby/dbShapesTest.rb b/testdata/ruby/dbShapesTest.rb index 2ccac70b8..8e110f5e1 100644 --- a/testdata/ruby/dbShapesTest.rb +++ b/testdata/ruby/dbShapesTest.rb @@ -272,6 +272,24 @@ class DBShapes_TestClass < TestBase assert_equal( arr[0].path.inspect, "nil" ) assert_equal( arr[0].text.inspect, "nil" ) assert_equal( arr[0].is_simple_polygon?, true ) + begin + arr[0].each_point { |x| } + assert_equal(true, false) + rescue => ex + assert_equal(ex.to_s, "Shape is not a path in Shape::each_point") + end + begin + arr[0].each_point_hole(0) { |x| } + assert_equal(true, false) + rescue => ex + assert_equal(ex.to_s, "A simple polygon doesn't have holes in Shape::each_point_hole") + end + begin + arr[0].text_string + assert_equal(true, false) + rescue => ex + assert_equal(ex.to_s, "Shape is not a text in Shape::text_string") + end assert_equal( arr[0].simple_polygon == a, true ) assert_equal( arr[0].polygon == b, true ) assert_equal( arr[0].holes, 0 ) @@ -290,6 +308,7 @@ class DBShapes_TestClass < TestBase # polygons a = RBA::Polygon::new( [ RBA::Point::new( 0, 1 ), RBA::Point::new( 1, 5 ), RBA::Point::new( 5, 5 ) ] ) + a.insert_hole( [ RBA::Point::new( 1, 2 ), RBA::Point::new( 2, 4 ), RBA::Point::new( 4, 4 ) ] ) c1.shapes( lindex ).insert( a ) arr = [] shapes.each( RBA::Shapes::SPolygons ) { |s| arr.push( s ) } @@ -301,14 +320,23 @@ class DBShapes_TestClass < TestBase assert_equal( arr[0].is_polygon?, true ) assert_equal( arr[0].is_simple_polygon?, false ) assert_equal( arr[0].polygon == a, true ) - assert_equal( arr[0].holes, 0 ) + assert_equal( arr[0].holes, 1 ) assert_equal( arr[0].bbox == a.bbox, true ) parr = [] arr[0].each_point_hull { |p| parr.push( p.to_s ) } assert_equal( parr, ["0,1", "1,5", "5,5"] ) + parr = [] + arr[0].each_point_hole(0) { |p| parr.push( p.to_s ) } + assert_equal( parr, ["1,2", "4,4", "2,4"] ) + begin + arr[0].each_point_hole(1) { |x| } + assert_equal(true, false) + rescue => ex + assert_equal(ex.to_s, "Invalid hole index in Shape::each_point_hole") + end earr = [] arr[0].each_edge { |e| earr.push( e.to_s ) } - assert_equal( earr, ["(0,1;1,5)", "(1,5;5,5)", "(5,5;0,1)"] ) + assert_equal( earr, ["(0,1;1,5)", "(1,5;5,5)", "(5,5;0,1)", "(1,2;4,4)", "(4,4;2,4)", "(2,4;1,2)"] ) arr = [] shapes.each( RBA::Shapes::SBoxes ) { |s| arr.push( s ) } assert_equal( arr.size, 1 ) @@ -520,6 +548,18 @@ class DBShapes_TestClass < TestBase assert_equal( arr[0].is_null?, false ) assert_equal( arr[0].type, RBA::Shape::t_path ) assert_equal( arr[0].is_path?, true ) + begin + arr[0].each_point_hull { |x| } + assert_equal(true, false) + rescue => ex + assert_equal(ex.to_s, "Shape is not a general or simple polygon in Shape::each_point_hull") + end + begin + arr[0].each_point_hole(0) { |x| } + assert_equal(true, false) + rescue => ex + assert_equal(ex.to_s, "Shape is not a general or simple polygon in Shape::each_point_hole") + end assert_equal( arr[0].dpolygon.to_s, "(0.012,0.007;-0.012,0.013;-0.002,0.053;0.022,0.047)" ) assert_equal( arr[0].dsimple_polygon.to_s, "(0.012,0.007;-0.012,0.013;-0.002,0.053;0.022,0.047)" ) assert_equal( arr[0].dedge.inspect, "nil" )