mirror of https://github.com/KLayout/klayout.git
958 lines
26 KiB
C++
958 lines
26 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2024 Matthias Koefferlein
|
|
|
|
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, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
#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
|
|
|
|
db::properties_id_type Shape::prop_id () const
|
|
{
|
|
if (m_with_props) {
|
|
if (m_stable) {
|
|
switch (m_type) {
|
|
case Polygon:
|
|
return (**((ppolygon_iter_type *) m_generic.iter)).properties_id ();
|
|
case PolygonRef:
|
|
return (**((ppolygon_ref_iter_type *) m_generic.iter)).properties_id ();
|
|
case PolygonPtrArray:
|
|
case PolygonPtrArrayMember:
|
|
return (**((ppolygon_ptr_array_iter_type *) m_generic.iter)).properties_id ();
|
|
case SimplePolygon:
|
|
return (**((psimple_polygon_iter_type *) m_generic.iter)).properties_id ();
|
|
case SimplePolygonRef:
|
|
return (**((psimple_polygon_ref_iter_type *) m_generic.iter)).properties_id ();
|
|
case SimplePolygonPtrArray:
|
|
case SimplePolygonPtrArrayMember:
|
|
return (**((psimple_polygon_ptr_array_iter_type *) m_generic.iter)).properties_id ();
|
|
case Edge:
|
|
return (**((pedge_iter_type *) m_generic.iter)).properties_id ();
|
|
case EdgePair:
|
|
return (**((pedge_pair_iter_type *) m_generic.iter)).properties_id ();
|
|
case Point:
|
|
return (**((ppoint_iter_type *) m_generic.iter)).properties_id ();
|
|
case Path:
|
|
return (**((ppath_iter_type *) m_generic.iter)).properties_id ();
|
|
case PathRef:
|
|
return (**((ppath_ref_iter_type *) m_generic.iter)).properties_id ();
|
|
case PathPtrArray:
|
|
case PathPtrArrayMember:
|
|
return (**((ppath_ptr_array_iter_type *) m_generic.iter)).properties_id ();
|
|
case Box:
|
|
return (**((pbox_iter_type *) m_generic.iter)).properties_id ();
|
|
case BoxArray:
|
|
case BoxArrayMember:
|
|
return (**((pbox_array_iter_type *) m_generic.iter)).properties_id ();
|
|
case ShortBox:
|
|
return (**((pshort_box_iter_type *) m_generic.iter)).properties_id ();
|
|
case ShortBoxArray:
|
|
case ShortBoxArrayMember:
|
|
return (**((pshort_box_array_iter_type *) m_generic.iter)).properties_id ();
|
|
case Text:
|
|
return (**((ptext_iter_type *) m_generic.iter)).properties_id ();
|
|
case TextRef:
|
|
return (**((ptext_ref_iter_type *) m_generic.iter)).properties_id ();
|
|
case TextPtrArray:
|
|
case TextPtrArrayMember:
|
|
return (**((ptext_ptr_array_iter_type *) m_generic.iter)).properties_id ();
|
|
case UserObject:
|
|
return (**((puser_object_iter_type *) m_generic.iter)).properties_id ();
|
|
default:
|
|
return 0;
|
|
}
|
|
} else {
|
|
switch (m_type) {
|
|
case Polygon:
|
|
return m_generic.ppolygon->properties_id ();
|
|
case PolygonRef:
|
|
return m_generic.ppolygon_ref->properties_id ();
|
|
case PolygonPtrArray:
|
|
case PolygonPtrArrayMember:
|
|
return m_generic.ppolygon_aref->properties_id ();
|
|
case SimplePolygon:
|
|
return m_generic.psimple_polygon->properties_id ();
|
|
case SimplePolygonRef:
|
|
return m_generic.psimple_polygon_ref->properties_id ();
|
|
case SimplePolygonPtrArray:
|
|
case SimplePolygonPtrArrayMember:
|
|
return m_generic.psimple_polygon_aref->properties_id ();
|
|
case Edge:
|
|
return m_generic.pedge->properties_id ();
|
|
case EdgePair:
|
|
return m_generic.pedge_pair->properties_id ();
|
|
case Point:
|
|
return m_generic.ppoint->properties_id ();
|
|
case Path:
|
|
return m_generic.ppath->properties_id ();
|
|
case PathRef:
|
|
return m_generic.ppath_ref->properties_id ();
|
|
case PathPtrArray:
|
|
case PathPtrArrayMember:
|
|
return m_generic.ppath_aref->properties_id ();
|
|
case Box:
|
|
return m_generic.pbox->properties_id ();
|
|
case BoxArray:
|
|
case BoxArrayMember:
|
|
return m_generic.pbox_array->properties_id ();
|
|
case ShortBox:
|
|
return m_generic.pshort_box->properties_id ();
|
|
case ShortBoxArray:
|
|
case ShortBoxArrayMember:
|
|
return m_generic.pshort_box_array->properties_id ();
|
|
case Text:
|
|
return m_generic.ptext->properties_id ();
|
|
case TextRef:
|
|
return m_generic.ptext_ref->properties_id ();
|
|
case TextPtrArray:
|
|
case TextPtrArrayMember:
|
|
return m_generic.ptext_aref->properties_id ();
|
|
case UserObject:
|
|
return m_generic.puser_object->properties_id ();
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Shape::point_iterator Shape::begin_point () const
|
|
{
|
|
if (m_type == Path) {
|
|
return point_iterator (path ().begin ());
|
|
} else if (m_type == PathRef || m_type == PathPtrArrayMember) {
|
|
return point_iterator (path_ref ().begin ());
|
|
} else {
|
|
raise_no_path ();
|
|
}
|
|
}
|
|
|
|
Shape::point_iterator Shape::end_point () const
|
|
{
|
|
if (m_type == Path) {
|
|
return point_iterator (path ().end ());
|
|
} else if (m_type == PathRef || m_type == PathPtrArrayMember) {
|
|
return point_iterator (path_ref ().end ());
|
|
} else {
|
|
raise_no_path ();
|
|
}
|
|
}
|
|
|
|
Shape::point_iterator Shape::begin_hull () const
|
|
{
|
|
if (m_type == SimplePolygon) {
|
|
return point_iterator (simple_polygon ().begin_hull ());
|
|
} else if (m_type == SimplePolygonRef || m_type == SimplePolygonPtrArrayMember) {
|
|
return point_iterator (simple_polygon_ref ().begin_hull ());
|
|
} else if (m_type == Polygon) {
|
|
return point_iterator (polygon ().begin_hull ());
|
|
} else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) {
|
|
return point_iterator (polygon_ref ().begin_hull ());
|
|
} else {
|
|
raise_no_polygon ();
|
|
}
|
|
}
|
|
|
|
Shape::point_iterator Shape::end_hull () const
|
|
{
|
|
if (m_type == SimplePolygon) {
|
|
return point_iterator (simple_polygon ().end_hull ());
|
|
} else if (m_type == SimplePolygonRef || m_type == SimplePolygonPtrArrayMember) {
|
|
return point_iterator (simple_polygon_ref ().end_hull ());
|
|
} else if (m_type == Polygon) {
|
|
return point_iterator (polygon ().end_hull ());
|
|
} else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) {
|
|
return point_iterator (polygon_ref ().end_hull ());
|
|
} else {
|
|
raise_no_polygon ();
|
|
}
|
|
}
|
|
|
|
Shape::point_iterator Shape::begin_hole (unsigned int hole) const
|
|
{
|
|
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 {
|
|
raise_no_polygon ();
|
|
}
|
|
}
|
|
|
|
Shape::point_iterator Shape::end_hole (unsigned int hole) const
|
|
{
|
|
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 {
|
|
raise_no_polygon ();
|
|
}
|
|
}
|
|
|
|
unsigned int Shape::holes () const
|
|
{
|
|
if (m_type == SimplePolygon) {
|
|
return simple_polygon ().holes ();
|
|
} else if (m_type == SimplePolygonRef || m_type == SimplePolygonPtrArrayMember) {
|
|
return simple_polygon_ref ().obj ().holes ();
|
|
} else if (m_type == Polygon) {
|
|
return polygon ().holes ();
|
|
} else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) {
|
|
return polygon_ref ().obj ().holes ();
|
|
} else {
|
|
raise_no_polygon ();
|
|
}
|
|
}
|
|
|
|
Shape::polygon_edge_iterator Shape::begin_edge () const
|
|
{
|
|
if (m_type == SimplePolygon) {
|
|
return polygon_edge_iterator (simple_polygon ().begin_edge ());
|
|
} else if (m_type == SimplePolygonRef || m_type == SimplePolygonPtrArrayMember) {
|
|
return polygon_edge_iterator (simple_polygon_ref ().begin_edge ());
|
|
} else if (m_type == Polygon) {
|
|
return polygon_edge_iterator (polygon ().begin_edge ());
|
|
} else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) {
|
|
return polygon_edge_iterator (polygon_ref ().begin_edge ());
|
|
} else {
|
|
raise_no_polygon ();
|
|
}
|
|
}
|
|
|
|
Shape::polygon_edge_iterator Shape::begin_edge (unsigned int c) const
|
|
{
|
|
if (m_type == SimplePolygon) {
|
|
if (c > 0) {
|
|
return polygon_edge_iterator ();
|
|
} else {
|
|
return polygon_edge_iterator (simple_polygon ().begin_edge ());
|
|
}
|
|
} else if (m_type == SimplePolygonRef || m_type == SimplePolygonPtrArrayMember) {
|
|
if (c > 0) {
|
|
return polygon_edge_iterator ();
|
|
} else {
|
|
return polygon_edge_iterator (simple_polygon_ref ().begin_edge ());
|
|
}
|
|
} else if (m_type == Polygon) {
|
|
return polygon_edge_iterator (polygon ().begin_edge (c));
|
|
} else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) {
|
|
return polygon_edge_iterator (polygon_ref ().begin_edge (c));
|
|
} else {
|
|
raise_no_polygon ();
|
|
}
|
|
}
|
|
|
|
Shape::polygon_ref_type Shape::polygon_ref () const
|
|
{
|
|
if (m_type == PolygonRef) {
|
|
return *basic_ptr (polygon_ref_type::tag ());
|
|
} 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
|
|
{
|
|
if (m_type == SimplePolygonRef) {
|
|
return *basic_ptr (simple_polygon_ref_type::tag ());
|
|
} else if (m_type == 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 ();
|
|
}
|
|
}
|
|
|
|
bool Shape::polygon (Shape::polygon_type &p) const
|
|
{
|
|
if (m_type == Polygon) {
|
|
p = polygon ();
|
|
return true;
|
|
} else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) {
|
|
polygon_ref ().instantiate (p);
|
|
return true;
|
|
} else if (m_type == SimplePolygon) {
|
|
p.clear ();
|
|
const simple_polygon_type &sp = simple_polygon ();
|
|
p.assign_hull (sp.hull ());
|
|
return true;
|
|
} else if (m_type == SimplePolygonRef || m_type == SimplePolygonPtrArrayMember) {
|
|
p.clear ();
|
|
const simple_polygon_ref_type &sp = simple_polygon_ref ();
|
|
p.assign_hull (sp.obj ().begin_hull (), sp.obj ().end_hull (), sp.trans (), false /*no additional compression*/);
|
|
return true;
|
|
} else if (m_type == Path) {
|
|
p = path ().polygon ();
|
|
return true;
|
|
} else if (m_type == PathRef || m_type == PathPtrArrayMember) {
|
|
p = path_ref ().obj ().polygon ();
|
|
p.transform (path_ref ().trans (), false /*no additional compression*/);
|
|
return true;
|
|
} else if (is_box ()) {
|
|
p = Shape::polygon_type (box ());
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Shape::simple_polygon (Shape::simple_polygon_type &p) const
|
|
{
|
|
if (m_type == Polygon) {
|
|
Shape::polygon_type pp = polygon ();
|
|
p = db::polygon_to_simple_polygon (pp);
|
|
return true;
|
|
} else if (m_type == PolygonRef || m_type == PolygonPtrArrayMember) {
|
|
Shape::polygon_type pp;
|
|
polygon_ref ().instantiate (pp);
|
|
p = db::polygon_to_simple_polygon (pp);
|
|
return true;
|
|
} else if (m_type == SimplePolygon) {
|
|
p = simple_polygon ();
|
|
return true;
|
|
} else if (m_type == SimplePolygonRef || m_type == SimplePolygonPtrArrayMember) {
|
|
p.clear ();
|
|
p.assign_hull (simple_polygon_ref ().obj ().begin_hull (), simple_polygon_ref ().obj ().end_hull (), simple_polygon_ref ().trans (), false /*no additional compression*/);
|
|
return true;
|
|
} else if (m_type == Path) {
|
|
p = path ().simple_polygon ();
|
|
return true;
|
|
} else if (m_type == PathRef || m_type == PathPtrArrayMember) {
|
|
p = path_ref ().obj ().simple_polygon ();
|
|
p.transform (path_ref ().trans (), false /*no additional compression*/);
|
|
return true;
|
|
} else if (is_box ()) {
|
|
p = Shape::simple_polygon_type (box ());
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Shape::path_ref_type Shape::path_ref () const
|
|
{
|
|
if (m_type == PathRef) {
|
|
return *basic_ptr (path_ref_type::tag ());
|
|
} 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 ();
|
|
}
|
|
}
|
|
|
|
Shape::coord_type Shape::path_width () const
|
|
{
|
|
if (m_type == Path) {
|
|
return path ().width ();
|
|
} else {
|
|
return path_ref ().obj ().width ();
|
|
}
|
|
}
|
|
|
|
Shape::distance_type Shape::path_length () const
|
|
{
|
|
if (m_type == Path) {
|
|
return path ().length ();
|
|
} else {
|
|
return path_ref ().obj ().length ();
|
|
}
|
|
}
|
|
|
|
std::pair<Shape::coord_type, Shape::coord_type> Shape::path_extensions () const
|
|
{
|
|
if (m_type == Path) {
|
|
return path ().extensions ();
|
|
} else {
|
|
return path_ref ().obj ().extensions ();
|
|
}
|
|
}
|
|
|
|
bool Shape::round_path () const
|
|
{
|
|
if (m_type == Path) {
|
|
return path ().round ();
|
|
} else {
|
|
return path_ref ().obj ().round ();
|
|
}
|
|
}
|
|
|
|
bool Shape::path (Shape::path_type &p) const
|
|
{
|
|
if (m_type == Path) {
|
|
p = path ();
|
|
return true;
|
|
} else if (m_type == PathRef || m_type == PathPtrArrayMember) {
|
|
path_ref ().instantiate (p);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Shape::text_ref_type Shape::text_ref () const
|
|
{
|
|
if (m_type == TextRef) {
|
|
return *basic_ptr (text_ref_type::tag ());
|
|
} 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 ();
|
|
}
|
|
}
|
|
|
|
bool Shape::text (Shape::text_type &t) const
|
|
{
|
|
if (m_type == Text) {
|
|
t = text ();
|
|
t.resolve_ref ();
|
|
return true;
|
|
} else if (m_type == TextRef || m_type == TextPtrArrayMember) {
|
|
text_ref ().instantiate (t);
|
|
t.resolve_ref ();
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const char *Shape::text_string () const
|
|
{
|
|
if (m_type == Text) {
|
|
return text ().string ();
|
|
} else {
|
|
return text_ref ().obj ().string ();
|
|
}
|
|
}
|
|
|
|
Shape::text_type::trans_type Shape::text_trans () const
|
|
{
|
|
if (m_type == Text) {
|
|
return text ().trans ();
|
|
} else {
|
|
return trans_type (text_ref ().trans ()) * text_ref ().obj ().trans ();
|
|
}
|
|
}
|
|
|
|
Shape::coord_type Shape::text_size () const
|
|
{
|
|
if (m_type == Text) {
|
|
return text ().size ();
|
|
} else {
|
|
return text_ref ().obj ().size ();
|
|
}
|
|
}
|
|
|
|
db::Font Shape::text_font () const
|
|
{
|
|
if (m_type == Text) {
|
|
return text ().font ();
|
|
} else {
|
|
return text_ref ().obj ().font ();
|
|
}
|
|
}
|
|
|
|
db::HAlign Shape::text_halign () const
|
|
{
|
|
if (m_type == Text) {
|
|
return text ().halign ();
|
|
} else {
|
|
return text_ref ().obj ().halign ();
|
|
}
|
|
}
|
|
|
|
db::VAlign Shape::text_valign () const
|
|
{
|
|
if (m_type == Text) {
|
|
return text ().valign ();
|
|
} else {
|
|
return text_ref ().obj ().valign ();
|
|
}
|
|
}
|
|
|
|
Shape::box_type Shape::box () const
|
|
{
|
|
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 if (m_type == ShortBoxArrayMember) {
|
|
return m_trans * basic_ptr (short_box_array_type::tag ())->object ();
|
|
} else if (m_type == Point) {
|
|
point_type pt = point ();
|
|
return m_trans * box_type (pt, pt);
|
|
} else {
|
|
raise_no_box ();
|
|
}
|
|
}
|
|
|
|
Shape::perimeter_type Shape::perimeter () const
|
|
{
|
|
switch (m_type) {
|
|
case Null:
|
|
return distance_type ();
|
|
case Polygon:
|
|
return polygon ().perimeter ();
|
|
case PolygonRef:
|
|
case PolygonPtrArrayMember:
|
|
return polygon_ref ().perimeter ();
|
|
case PolygonPtrArray:
|
|
{
|
|
const polygon_ptr_array_type *arr = basic_ptr (polygon_ptr_array_type::tag ());
|
|
return arr->size () * arr->object ().perimeter ();
|
|
}
|
|
case SimplePolygon:
|
|
return simple_polygon ().perimeter ();
|
|
case SimplePolygonRef:
|
|
case SimplePolygonPtrArrayMember:
|
|
return simple_polygon_ref ().perimeter ();
|
|
case SimplePolygonPtrArray:
|
|
{
|
|
const simple_polygon_ptr_array_type *arr = basic_ptr (simple_polygon_ptr_array_type::tag ());
|
|
return arr->size () * arr->object ().perimeter ();
|
|
}
|
|
case Path:
|
|
return path ().perimeter ();
|
|
case PathRef:
|
|
case PathPtrArrayMember:
|
|
return path_ref ().obj ().perimeter ();
|
|
case PathPtrArray:
|
|
{
|
|
const path_ptr_array_type *arr = basic_ptr (path_ptr_array_type::tag ());
|
|
return arr->size () * arr->object ().obj ().perimeter ();
|
|
}
|
|
case BoxArray:
|
|
{
|
|
const box_array_type *arr = basic_ptr (box_array_type::tag ());
|
|
return arr->size () * arr->object ().perimeter ();
|
|
}
|
|
case ShortBoxArray:
|
|
{
|
|
const short_box_array_type *arr = basic_ptr (short_box_array_type::tag ());
|
|
return arr->size () * arr->object ().perimeter ();
|
|
}
|
|
case Point:
|
|
return 0;
|
|
case Edge:
|
|
return edge ().length ();
|
|
case EdgePair:
|
|
return edge_pair ().perimeter ();
|
|
case Box:
|
|
case ShortBox:
|
|
case BoxArrayMember:
|
|
case ShortBoxArrayMember:
|
|
return box ().perimeter ();
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
size_t Shape::array_size () const
|
|
{
|
|
switch (m_type) {
|
|
case Null:
|
|
return 0;
|
|
case Point:
|
|
case Edge:
|
|
case EdgePair:
|
|
case Polygon:
|
|
case PolygonRef:
|
|
case PolygonPtrArrayMember:
|
|
return 1;
|
|
case PolygonPtrArray:
|
|
{
|
|
const polygon_ptr_array_type *arr = basic_ptr (polygon_ptr_array_type::tag ());
|
|
return arr->size ();
|
|
}
|
|
case SimplePolygon:
|
|
case SimplePolygonRef:
|
|
case SimplePolygonPtrArrayMember:
|
|
return 1;
|
|
case SimplePolygonPtrArray:
|
|
{
|
|
const simple_polygon_ptr_array_type *arr = basic_ptr (simple_polygon_ptr_array_type::tag ());
|
|
return arr->size ();
|
|
}
|
|
case Path:
|
|
case PathRef:
|
|
case PathPtrArrayMember:
|
|
return 1;
|
|
case PathPtrArray:
|
|
{
|
|
const path_ptr_array_type *arr = basic_ptr (path_ptr_array_type::tag ());
|
|
return arr->size ();
|
|
}
|
|
case BoxArray:
|
|
{
|
|
const box_array_type *arr = basic_ptr (box_array_type::tag ());
|
|
return arr->size ();
|
|
}
|
|
case ShortBoxArray:
|
|
{
|
|
const short_box_array_type *arr = basic_ptr (short_box_array_type::tag ());
|
|
return arr->size ();
|
|
}
|
|
case Box:
|
|
case ShortBox:
|
|
case BoxArrayMember:
|
|
case ShortBoxArrayMember:
|
|
return 1;
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
Shape::area_type Shape::area () const
|
|
{
|
|
switch (m_type) {
|
|
case Null:
|
|
return area_type ();
|
|
case Point:
|
|
case Edge:
|
|
return 0;
|
|
case EdgePair:
|
|
return edge_pair ().area ();
|
|
case Polygon:
|
|
return polygon ().area ();
|
|
case PolygonRef:
|
|
case PolygonPtrArrayMember:
|
|
return polygon_ref ().area ();
|
|
case PolygonPtrArray:
|
|
{
|
|
const polygon_ptr_array_type *arr = basic_ptr (polygon_ptr_array_type::tag ());
|
|
return arr->size () * arr->object ().area ();
|
|
}
|
|
case SimplePolygon:
|
|
return simple_polygon ().area ();
|
|
case SimplePolygonRef:
|
|
case SimplePolygonPtrArrayMember:
|
|
return simple_polygon_ref ().area ();
|
|
case SimplePolygonPtrArray:
|
|
{
|
|
const simple_polygon_ptr_array_type *arr = basic_ptr (simple_polygon_ptr_array_type::tag ());
|
|
return arr->size () * arr->object ().area ();
|
|
}
|
|
case Path:
|
|
return path ().area ();
|
|
case PathRef:
|
|
case PathPtrArrayMember:
|
|
return path_ref ().obj ().area ();
|
|
case PathPtrArray:
|
|
{
|
|
const path_ptr_array_type *arr = basic_ptr (path_ptr_array_type::tag ());
|
|
return arr->size () * arr->object ().obj ().area ();
|
|
}
|
|
case BoxArray:
|
|
{
|
|
const box_array_type *arr = basic_ptr (box_array_type::tag ());
|
|
return arr->size () * arr->object ().area ();
|
|
}
|
|
case ShortBoxArray:
|
|
{
|
|
const short_box_array_type *arr = basic_ptr (short_box_array_type::tag ());
|
|
return arr->size () * arr->object ().area ();
|
|
}
|
|
case Box:
|
|
case ShortBox:
|
|
case BoxArrayMember:
|
|
case ShortBoxArrayMember:
|
|
return box ().area ();
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Shape::box_type Shape::bbox () const
|
|
{
|
|
switch (m_type) {
|
|
case Null:
|
|
return box_type ();
|
|
case Polygon:
|
|
return polygon ().box ();
|
|
case PolygonRef:
|
|
case PolygonPtrArrayMember:
|
|
return polygon_ref ().box ();
|
|
case PolygonPtrArray:
|
|
return basic_ptr (polygon_ptr_array_type::tag ())->bbox (db::box_convert<polygon_ptr_type> ());
|
|
case SimplePolygon:
|
|
return simple_polygon ().box ();
|
|
case SimplePolygonRef:
|
|
case SimplePolygonPtrArrayMember:
|
|
return simple_polygon_ref ().box ();
|
|
case SimplePolygonPtrArray:
|
|
return basic_ptr (simple_polygon_ptr_array_type::tag ())->bbox (db::box_convert<simple_polygon_ptr_type> ());
|
|
case Text:
|
|
return text ().box ();
|
|
case TextRef:
|
|
case TextPtrArrayMember:
|
|
return text_ref ().box ();
|
|
case TextPtrArray:
|
|
return basic_ptr (text_ptr_array_type::tag ())->bbox (db::box_convert<text_ptr_type> ());
|
|
case Edge:
|
|
return box_type (edge ().p1 (), edge ().p2 ());
|
|
case EdgePair:
|
|
return edge_pair ().bbox ();
|
|
case Point:
|
|
return box_type (point (), point ());
|
|
case Path:
|
|
return path ().box ();
|
|
case PathRef:
|
|
case PathPtrArrayMember:
|
|
return path_ref ().box ();
|
|
case PathPtrArray:
|
|
return basic_ptr (path_ptr_array_type::tag ())->bbox (db::box_convert<path_ptr_type> ());
|
|
case BoxArray:
|
|
return basic_ptr (box_array_type::tag ())->bbox (db::box_convert<box_type> ());
|
|
case ShortBoxArray:
|
|
return basic_ptr (short_box_array_type::tag ())->bbox (db::box_convert<short_box_type> ());
|
|
case Box:
|
|
case ShortBox:
|
|
case BoxArrayMember:
|
|
case ShortBoxArrayMember:
|
|
return box ();
|
|
case UserObject:
|
|
return user_object ().box ();
|
|
default:
|
|
return box_type ();
|
|
}
|
|
}
|
|
|
|
Shape::box_type Shape::rectangle () const
|
|
{
|
|
if (is_box ()) {
|
|
return box ();
|
|
}
|
|
|
|
switch (m_type) {
|
|
case db::Shape::Polygon:
|
|
return polygon ().is_box () ? polygon ().box () : box_type ();
|
|
case db::Shape::PolygonRef:
|
|
case db::Shape::PolygonPtrArrayMember:
|
|
return polygon_ref ().is_box () ? polygon_ref ().box () : box_type ();
|
|
case db::Shape::SimplePolygon:
|
|
return simple_polygon ().is_box () ? simple_polygon ().box () : box_type ();
|
|
case db::Shape::SimplePolygonRef:
|
|
case db::Shape::SimplePolygonPtrArrayMember:
|
|
return simple_polygon_ref ().is_box () ? simple_polygon_ref ().box () : box_type ();
|
|
case db::Shape::Path:
|
|
{
|
|
const path_type &p = path ();
|
|
if (! p.round () && p.points () <= 2 && p.points () > 0) {
|
|
point_type p1 = *p.begin ();
|
|
point_type p2 = p1;
|
|
if (p.points () == 2) {
|
|
p2 = *++p.begin ();
|
|
}
|
|
if (p1.x () == p2.x () || p1.y () == p2.y ()) {
|
|
return p.box ();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case db::Shape::PathRef:
|
|
case db::Shape::PathPtrArrayMember:
|
|
{
|
|
const path_ref_type &p = path_ref ();
|
|
if (! p.ptr ()->round () && p.ptr ()->points () <= 2 && p.ptr ()->points () > 0) {
|
|
point_type p1 = *p.begin ();
|
|
point_type p2 = p1;
|
|
if (p.ptr ()->points () == 2) {
|
|
p2 = *++p.begin ();
|
|
}
|
|
if (p1.x () == p2.x () || p1.y () == p2.y ()) {
|
|
return p.box ();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return box_type ();
|
|
}
|
|
|
|
std::string
|
|
Shape::to_string () const
|
|
{
|
|
std::string r;
|
|
|
|
switch (m_type) {
|
|
case Null:
|
|
r = "null";
|
|
break;
|
|
case Polygon:
|
|
case PolygonRef:
|
|
case PolygonPtrArrayMember:
|
|
{
|
|
polygon_type p;
|
|
polygon (p);
|
|
r = "polygon " + p.to_string ();
|
|
}
|
|
break;
|
|
case PolygonPtrArray:
|
|
r = "polygon_array";
|
|
break;
|
|
case SimplePolygon:
|
|
case SimplePolygonRef:
|
|
case SimplePolygonPtrArrayMember:
|
|
{
|
|
simple_polygon_type p;
|
|
simple_polygon (p);
|
|
r = "simple_polygon " + p.to_string ();
|
|
}
|
|
break;
|
|
case SimplePolygonPtrArray:
|
|
r = "simple_polygon_array";
|
|
break;
|
|
case Text:
|
|
case TextRef:
|
|
case TextPtrArrayMember:
|
|
{
|
|
text_type p;
|
|
text (p);
|
|
r = "text " + p.to_string ();
|
|
}
|
|
break;
|
|
case TextPtrArray:
|
|
r = "text_array";
|
|
break;
|
|
case Edge:
|
|
r = "edge " + edge ().to_string ();
|
|
break;
|
|
case EdgePair:
|
|
r = "edge_pair " + edge_pair ().to_string ();
|
|
break;
|
|
case Point:
|
|
r = "point " + point ().to_string ();
|
|
break;
|
|
case Path:
|
|
case PathRef:
|
|
case PathPtrArrayMember:
|
|
{
|
|
path_type p;
|
|
path (p);
|
|
r = "path " + p.to_string ();
|
|
}
|
|
break;
|
|
case PathPtrArray:
|
|
r = "path_array";
|
|
break;
|
|
case BoxArray:
|
|
r = "box_array";
|
|
break;
|
|
case ShortBoxArray:
|
|
r = "short_box_array";
|
|
break;
|
|
case Box:
|
|
case ShortBox:
|
|
case BoxArrayMember:
|
|
case ShortBoxArrayMember:
|
|
r = "box " + box ().to_string ();
|
|
break;
|
|
case UserObject:
|
|
r = "user_object";
|
|
break;
|
|
default:
|
|
r = "invalid";
|
|
}
|
|
|
|
if (has_prop_id ()) {
|
|
r += " prop_id=" + tl::to_string (prop_id ());
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
}
|