klayout/src/ant/antObject.cc

617 lines
15 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2017 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 "antObject.h"
#include "antTemplate.h"
#include "antConfig.h"
#include "tlString.h"
#include "tlExpression.h"
#include <string.h>
namespace ant
{
Object::Object ()
: m_p1 (), m_p2 (), m_id (-1),
m_fmt_x ("$X"), m_fmt_y ("$Y"), m_fmt ("$D"),
m_style (STY_ruler), m_outline (OL_diag),
m_snap (true), m_angle_constraint (lay::AC_Global),
m_main_position (POS_auto),
m_main_xalign (AL_auto), m_main_yalign (AL_auto),
m_xlabel_xalign (AL_auto), m_xlabel_yalign (AL_auto),
m_ylabel_xalign (AL_auto), m_ylabel_yalign (AL_auto)
{
// .. nothing yet ..
}
Object::Object (const db::DPoint &p1, const db::DPoint &p2, int id, const std::string &fmt_x, const std::string &fmt_y, const std::string &fmt, style_type style, outline_type outline, bool snap, lay::angle_constraint_type angle_constraint)
: m_p1 (p1), m_p2 (p2), m_id (id),
m_fmt_x (fmt_x), m_fmt_y (fmt_y), m_fmt (fmt),
m_style (style), m_outline (outline),
m_snap (snap), m_angle_constraint (angle_constraint),
m_main_position (POS_auto),
m_main_xalign (AL_auto), m_main_yalign (AL_auto),
m_xlabel_xalign (AL_auto), m_xlabel_yalign (AL_auto),
m_ylabel_xalign (AL_auto), m_ylabel_yalign (AL_auto)
{
// .. nothing else ..
}
Object::Object (const db::DPoint &p1, const db::DPoint &p2, int id, const ant::Template &t)
: m_p1 (p1), m_p2 (p2), m_id (id),
m_fmt_x (t.fmt_x ()), m_fmt_y (t.fmt_y ()), m_fmt (t.fmt ()),
m_style (t.style ()), m_outline (t.outline ()),
m_snap (t.snap ()), m_angle_constraint (t.angle_constraint ()),
m_main_position (t.main_position ()),
m_main_xalign (t.main_xalign ()), m_main_yalign (t.main_yalign ()),
m_xlabel_xalign (t.xlabel_xalign ()), m_xlabel_yalign (t.xlabel_yalign ()),
m_ylabel_xalign (t.ylabel_xalign ()), m_ylabel_yalign (t.ylabel_yalign ())
{
// .. nothing else ..
}
Object::Object (const ant::Object &d)
: m_p1 (d.m_p1), m_p2 (d.m_p2), m_id (d.m_id),
m_fmt_x (d.m_fmt_x), m_fmt_y (d.m_fmt_y), m_fmt (d.m_fmt),
m_style (d.m_style), m_outline (d.m_outline),
m_snap (d.m_snap), m_angle_constraint (d.m_angle_constraint),
m_category (d.m_category),
m_main_position (d.m_main_position),
m_main_xalign (d.m_main_xalign), m_main_yalign (d.m_main_yalign),
m_xlabel_xalign (d.m_xlabel_xalign), m_xlabel_yalign (d.m_xlabel_yalign),
m_ylabel_xalign (d.m_ylabel_xalign), m_ylabel_yalign (d.m_ylabel_yalign)
{
// .. nothing else ..
}
Object &
Object::operator= (const ant::Object &d)
{
if (this != &d) {
m_p1 = d.m_p1;
m_p2 = d.m_p2;
m_id = d.m_id;
m_fmt_x = d.m_fmt_x;
m_fmt_y = d.m_fmt_y;
m_fmt = d.m_fmt;
m_style = d.m_style;
m_outline = d.m_outline;
m_snap = d.m_snap;
m_angle_constraint = d.m_angle_constraint;
m_category = d.m_category;
m_main_position = d.m_main_position;
m_main_xalign = d.m_main_xalign;
m_main_yalign = d.m_main_yalign;
m_xlabel_xalign = d.m_xlabel_xalign;
m_xlabel_yalign = d.m_xlabel_yalign;
m_ylabel_xalign = d.m_ylabel_xalign;
m_ylabel_yalign = d.m_ylabel_yalign;
property_changed ();
}
return *this;
}
bool
Object::operator< (const ant::Object &b) const
{
if (m_id != b.m_id) {
return m_id < b.m_id;
}
if (m_p1 != b.m_p1) {
return m_p1 < b.m_p1;
}
if (m_p2 != b.m_p2) {
return m_p2 < b.m_p2;
}
if (m_fmt_x != b.m_fmt_x) {
return m_fmt_x < b.m_fmt_x;
}
if (m_fmt_y != b.m_fmt_y) {
return m_fmt_y < b.m_fmt_y;
}
if (m_fmt != b.m_fmt) {
return m_fmt < b.m_fmt;
}
if (m_style != b.m_style) {
return m_style < b.m_style;
}
if (m_outline != b.m_outline) {
return m_outline < b.m_outline;
}
if (m_snap != b.m_snap) {
return m_snap < b.m_snap;
}
if (m_angle_constraint != b.m_angle_constraint) {
return m_angle_constraint < b.m_angle_constraint;
}
if (m_category != b.m_category) {
return m_category < b.m_category;
}
if (m_main_position != b.m_main_position) {
return m_main_position < b.m_main_position;
}
if (m_main_xalign != b.m_main_xalign) {
return m_main_xalign < b.m_main_xalign;
}
if (m_main_yalign != b.m_main_yalign) {
return m_main_yalign < b.m_main_yalign;
}
if (m_xlabel_xalign != b.m_xlabel_xalign) {
return m_xlabel_xalign < b.m_xlabel_xalign;
}
if (m_xlabel_yalign != b.m_xlabel_yalign) {
return m_xlabel_yalign < b.m_xlabel_yalign;
}
if (m_ylabel_xalign != b.m_ylabel_xalign) {
return m_ylabel_xalign < b.m_ylabel_xalign;
}
if (m_ylabel_yalign != b.m_ylabel_yalign) {
return m_ylabel_yalign < b.m_ylabel_yalign;
}
return false;
}
bool
Object::equals (const db::DUserObjectBase *d) const
{
const ant::Object *ruler = dynamic_cast<const ant::Object *> (d);
if (ruler) {
return *this == *ruler;
} else {
return false;
}
}
bool
Object::operator== (const ant::Object &d) const
{
return m_p1 == d.m_p1 && m_p2 == d.m_p2 && m_id == d.m_id &&
m_fmt_x == d.m_fmt_x && m_fmt_y == d.m_fmt_y && m_fmt == d.m_fmt &&
m_style == d.m_style && m_outline == d.m_outline &&
m_snap == d.m_snap && m_angle_constraint == d.m_angle_constraint &&
m_main_position == d.m_main_position &&
m_main_xalign == d.m_main_xalign && m_main_yalign == d.m_main_yalign &&
m_xlabel_xalign == d.m_xlabel_xalign && m_xlabel_yalign == d.m_xlabel_yalign &&
m_ylabel_xalign == d.m_ylabel_xalign && m_ylabel_yalign == d.m_ylabel_yalign
;
}
bool
Object::less (const db::DUserObjectBase *d) const
{
const ant::Object *ruler = dynamic_cast<const ant::Object *> (d);
if (ruler) {
return *this < *ruler;
} else {
return class_id () < d->class_id ();
}
}
unsigned int
Object::class_id () const
{
static unsigned int cid = db::get_unique_user_object_class_id ();
return cid;
}
db::DUserObjectBase *
Object::clone () const
{
return new ant::Object (*this);
}
db::DBox
Object::box () const
{
return db::DBox (m_p1, m_p2);
}
class AnnotationEval
: public tl::Eval
{
public:
AnnotationEval (const Object &obj, const db::DFTrans &t)
: m_obj (obj), m_trans (t)
{ }
const Object &obj () const { return m_obj; }
const db::DFTrans &trans () const { return m_trans; }
private:
const Object &m_obj;
db::DFTrans m_trans;
};
static double
delta_x (const Object &obj, const db::DFTrans &t)
{
double dx = ((t * obj.p2 ()).x () - (t * obj.p1 ()).x ());
// avoid "almost 0" outputs
if (fabs (dx) < 1e-5 /*micron*/) {
dx = 0;
}
return dx;
}
static double
delta_y (const Object &obj, const db::DFTrans &t)
{
double dy = ((t * obj.p2 ()).y () - (t * obj.p1 ()).y ());
// avoid "almost 0" outputs
if (fabs (dy) < 1e-5 /*micron*/) {
dy = 0;
}
return dy;
}
class AnnotationEvalFunction
: public tl::EvalFunction
{
public:
AnnotationEvalFunction (char function, const AnnotationEval *eval)
: m_function (function), mp_eval (eval)
{
// .. nothing yet ..
}
void execute (const tl::ExpressionParserContext &context, tl::Variant &out, const std::vector <tl::Variant> &vv) const
{
if (vv.size () != 0) {
throw tl::EvalError (tl::to_string (QObject::tr ("Annotation function must not have arguments")), context);
}
const Object &obj = mp_eval->obj ();
const db::DFTrans &trans = mp_eval->trans ();
if (m_function == 'L') {
out = fabs (delta_x (obj, trans)) + fabs (delta_y (obj, trans));
} else if (m_function == 'D') {
out = sqrt (delta_x (obj, trans) * delta_x (obj, trans) + delta_y (obj, trans) * delta_y (obj, trans));
} else if (m_function == 'A') {
out = delta_x (obj, trans) * delta_y (obj, trans) * 1e-6;
} else if (m_function == 'X') {
out = delta_x (obj, trans);
} else if (m_function == 'Y') {
out = delta_y (obj, trans);
} else if (m_function == 'U') {
out = (trans * obj.p1 ()).x ();
} else if (m_function == 'V') {
out = (trans * obj.p1 ()).y ();
} else if (m_function == 'P') {
out = (trans * obj.p2 ()).x ();
} else if (m_function == 'Q') {
out = (trans * obj.p2 ()).y ();
} else {
out = tl::Variant ();
}
}
private:
char m_function;
const AnnotationEval *mp_eval;
};
std::string
Object::formatted (const std::string &fmt, const db::DFTrans &t) const
{
AnnotationEval eval (*this, t);
eval.define_function ("L", new AnnotationEvalFunction('L', &eval)); // manhattan length
eval.define_function ("D", new AnnotationEvalFunction('D', &eval)); // euclidian distance
eval.define_function ("X", new AnnotationEvalFunction('X', &eval)); // x delta
eval.define_function ("Y", new AnnotationEvalFunction('Y', &eval)); // y delta
eval.define_function ("U", new AnnotationEvalFunction('U', &eval)); // p1.x
eval.define_function ("V", new AnnotationEvalFunction('V', &eval)); // p1.y
eval.define_function ("P", new AnnotationEvalFunction('P', &eval)); // p2.x
eval.define_function ("Q", new AnnotationEvalFunction('Q', &eval)); // p2.y
eval.define_function ("A", new AnnotationEvalFunction('A', &eval)); // area mm2
return eval.interpolate (fmt);
}
const char *
Object::class_name () const
{
return "ant::Object";
}
void
Object::from_string (const char *s)
{
printf("@@@ %s\n", s); fflush(stdout);
tl::Extractor ex (s);
while (! ex.at_end ()) {
if (ex.test ("id=")) {
int i = 0;
ex.read (i);
id (i);
} else if (ex.test ("category=")) {
std::string s;
ex.read_word_or_quoted (s);
set_category (s);
} else if (ex.test ("fmt=")) {
std::string s;
ex.read_word_or_quoted (s);
fmt (s);
} else if (ex.test ("fmt_x=")) {
std::string s;
ex.read_word_or_quoted (s);
fmt_x (s);
} else if (ex.test ("fmt_y=")) {
std::string s;
ex.read_word_or_quoted (s);
fmt_y (s);
} else if (ex.test ("x1=")) {
double q = 0;
ex.read (q);
db::DPoint p (p1 ());
p.set_x (q);
p1 (p);
} else if (ex.test ("y1=")) {
double q = 0;
ex.read (q);
db::DPoint p (p1 ());
p.set_y (q);
p1 (p);
} else if (ex.test ("x2=")) {
double q = 0;
ex.read (q);
db::DPoint p (p2 ());
p.set_x (q);
p2 (p);
} else if (ex.test ("y2=")) {
double q = 0;
ex.read (q);
db::DPoint p (p2 ());
p.set_y (q);
p2 (p);
} else if (ex.test ("position=")) {
std::string s;
ex.read_word (s);
ant::PositionConverter pc;
ant::Object::position_type pos;
pc.from_string (s, pos);
set_main_position (pos);
ex.test (",");
} else if (ex.test ("xalign=")) {
std::string s;
ex.read_word (s);
ant::AlignmentConverter ac;
ant::Object::alignment_type a;
ac.from_string (s, a);
set_main_xalign (a);
ex.test (",");
} else if (ex.test ("yalign=")) {
std::string s;
ex.read_word (s);
ant::AlignmentConverter ac;
ant::Object::alignment_type a;
ac.from_string (s, a);
set_main_yalign (a);
ex.test (",");
} else if (ex.test ("xlabel_xalign=")) {
std::string s;
ex.read_word (s);
ant::AlignmentConverter ac;
ant::Object::alignment_type a;
ac.from_string (s, a);
set_xlabel_xalign (a);
ex.test (",");
} else if (ex.test ("xlabel_yalign=")) {
std::string s;
ex.read_word (s);
ant::AlignmentConverter ac;
ant::Object::alignment_type a;
ac.from_string (s, a);
set_xlabel_yalign (a);
ex.test (",");
} else if (ex.test ("ylabel_xalign=")) {
std::string s;
ex.read_word (s);
ant::AlignmentConverter ac;
ant::Object::alignment_type a;
ac.from_string (s, a);
set_ylabel_xalign (a);
ex.test (",");
} else if (ex.test ("ylabel_yalign=")) {
std::string s;
ex.read_word (s);
ant::AlignmentConverter ac;
ant::Object::alignment_type a;
ac.from_string (s, a);
set_ylabel_yalign (a);
ex.test (",");
} else if (ex.test ("style=")) {
std::string s;
ex.read_word (s);
ant::StyleConverter sc;
ant::Object::style_type st;
sc.from_string (s, st);
style (st);
} else if (ex.test ("outline=")) {
std::string s;
ex.read_word (s);
ant::OutlineConverter oc;
ant::Object::outline_type ot;
oc.from_string (s, ot);
outline (ot);
} else if (ex.test ("snap=")) {
bool f = false;
ex.read (f);
snap (f);
} else if (ex.test ("angle_constraint=")) {
std::string s;
ex.read_word (s);
ant::ACConverter sc;
lay::angle_constraint_type sm;
sc.from_string (s, sm);
angle_constraint (sm);
} else {
break;
}
ex.test (",");
}
}
std::string
Object::to_string () const
{
std::string r;
r += "id=";
r += tl::to_string (id ());
r += ",";
r += "x1=";
r += tl::to_string (p1 ().x ());
r += ",";
r += "y1=";
r += tl::to_string (p1 ().y ());
r += ",";
r += "x2=";
r += tl::to_string (p2 ().x ());
r += ",";
r += "y2=";
r += tl::to_string (p2 ().y ());
r += ",";
r += "category=";
r += tl::to_word_or_quoted_string (category ());
r += ",";
r += "fmt=";
r += tl::to_word_or_quoted_string (fmt ());
r += ",";
r += "fmt_x=";
r += tl::to_word_or_quoted_string (fmt_x ());
r += ",";
r += "fmt_y=";
r += tl::to_word_or_quoted_string (fmt_y ());
r += ",";
r += "position=";
ant::PositionConverter pc;
r += pc.to_string (main_position ());
r += ",";
ant::AlignmentConverter ac;
r += "xalign=";
r += ac.to_string (main_xalign ());
r += ",";
r += "yalign=";
r += ac.to_string (main_yalign ());
r += ",";
r += "xlabel_xalign=";
r += ac.to_string (xlabel_xalign ());
r += ",";
r += "xlabel_yalign=";
r += ac.to_string (xlabel_yalign ());
r += ",";
r += "ylabel_xalign=";
r += ac.to_string (ylabel_xalign ());
r += ",";
r += "ylabel_yalign=";
r += ac.to_string (ylabel_yalign ());
r += ",";
r += "style=";
ant::StyleConverter sc;
r += sc.to_string (style ());
r += ",";
r += "outline=";
ant::OutlineConverter oc;
r += oc.to_string (outline ());
r += ",";
r += "snap=";
r += tl::to_string (snap ());
r += ",";
r += "angle_constraint=";
ant::ACConverter acc;
r += acc.to_string (angle_constraint ());
return r;
}
void
Object::property_changed ()
{
// .. nothing yet ..
}
/**
* @brief Registration of the ant::Object class in the DUserObject space
*/
static db::DUserObjectDeclaration class_registrar (new db::user_object_factory_impl<ant::Object, db::DCoord> ("ant::Object"));
} // namespace ant