z Stack description language enhanced.

This commit is contained in:
Matthias Koefferlein 2021-04-02 17:27:38 +02:00
parent 25b978f39f
commit 773fcb6b67
4 changed files with 188 additions and 49 deletions

View File

@ -119,6 +119,7 @@ D25TechnologyComponent::D25TechnologyComponent ()
// provide some explanation for the initialization
m_src =
"# Provide z stack information here\n"
"#\n"
"# Each line is one layer. The specification consists of a layer specification, a colon and arguments.\n"
"# The arguments are named (like \"x=...\") or in serial. Parameters are separated by comma or blanks.\n"
"# Named arguments are:\n"
@ -127,7 +128,7 @@ D25TechnologyComponent::D25TechnologyComponent ()
"# zstop The upper z position of the extruded layer in µm\n"
"# height The height of the extruded layer in µm\n"
"#\n"
"# 'height', 'zstart' and 'zstop' can be used in any combination. If no value is given for 'zstart', "
"# 'height', 'zstart' and 'zstop' can be used in any combination. If no value is given for 'zstart',\n"
"# the upper level of the previous layer will be used.\n"
"#\n"
"# If a single unnamed parameter is given, it corresponds to 'height'. Two parameters correspond to\n"
@ -139,6 +140,30 @@ D25TechnologyComponent::D25TechnologyComponent ()
"# 1: zstop=1.5, zstart=0.5 # same with named parameters\n"
"# 1: height=1.0, zstop=1.5 # same with z stop minus height\n"
"# 1: 1.0 zstop=1.5 # same with height as unnamed parameter\n"
"#\n"
"# VARIABLES\n"
"#\n"
"# You can declare variables with:\n"
"# var name = value\n"
"#\n"
"# You can use variables inside numeric expressions.\n"
"# Example:\n"
"# var hmetal = 0.48\n"
"# 7/0: 0.5 0.5+hmetal*2 # 2x thick metal\n"
"#\n"
"# You cannot use variables inside layer specifications currently.\n"
"#\n"
"# CONDITIONALS\n"
"#\n"
"# You can enable or disable branches of the table using 'if', 'else', 'elseif' and 'end':\n"
"# Example:\n"
"# var thick_m1 = true\n"
"# if thickm1\n"
"# 1: 0.5 1.5\n"
"# else\n"
"# 1: 0.5 1.2\n"
"# end\n"
"\n"
;
}
@ -157,6 +182,9 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
try {
tl::Eval eval;
std::vector<bool> conditional_stack;
std::vector<std::string> lines = tl::split (src, "\n");
for (std::vector<std::string>::const_iterator l = lines.begin (); l != lines.end (); ++l) {
@ -168,6 +196,64 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
// ignore comments
} else if (ex.at_end ()) {
// ignore empty lines
} else if (ex.test ("if")) {
tl::Expression x;
eval.parse (x, ex);
conditional_stack.push_back (x.execute ().to_bool ());
ex.expect_end ();
} else if (ex.test ("else")) {
if (conditional_stack.empty ()) {
throw tl::Exception (tl::to_string (tr ("'else' without 'if'")));
}
conditional_stack.back () = ! conditional_stack.back ();
ex.expect_end ();
} else if (ex.test ("end")) {
if (conditional_stack.empty ()) {
throw tl::Exception (tl::to_string (tr ("'end' without 'if'")));
}
conditional_stack.pop_back ();
ex.expect_end ();
} else if (ex.test ("elsif")) {
if (conditional_stack.empty ()) {
throw tl::Exception (tl::to_string (tr ("'elsif' without 'if'")));
}
tl::Expression x;
eval.parse (x, ex);
conditional_stack.back () = x.execute ().to_bool ();
ex.expect_end ();
} else if (! conditional_stack.empty () && ! conditional_stack.back ()) {
continue;
} else if (ex.test ("var")) {
std::string n;
ex.read_name (n);
ex.expect ("=");
tl::Expression x;
eval.parse (x, ex);
eval.set_var (n, x.execute ());
ex.expect_end ();
} else {
db::D25LayerInfo info;
@ -191,16 +277,18 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
break;
}
double pv = 0.0;
tl::Expression pvx;
std::string pn;
if (ex.try_read_name (pn)) {
ex.expect ("=");
ex.read (pv);
eval.parse (pvx, ex);
} else {
ex.read (pv);
eval.parse (pvx, ex);
}
double pv = pvx.execute ().to_double ();
ex.test (",");
if (pn.empty ()) {
@ -239,28 +327,28 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
} else if (args.size () == 1) {
if (! h.is_nil ()) {
if (! z0.is_nil ()) {
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstart already given")));
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstart already given")));
}
if (! z1.is_nil ()) {
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop implicitly given")));
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop implicitly given")));
}
info.set_zstart (args[0]);
info.set_zstop (args[0] + h.to_double ());
} else {
if (! z1.is_nil ()) {
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop implicitly given")));
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop implicitly given")));
}
info.set_zstop ((! z0.is_nil () ? z0.to_double () : info.zstart ()) + args[0]);
}
} else if (args.size () == 2) {
if (! z0.is_nil ()) {
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstart already given")));
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstart already given")));
}
if (! z1.is_nil ()) {
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: zstop already given")));
throw tl::Exception (tl::to_string (tr ("Redundant parameters: zstop already given")));
}
if (! h.is_nil ()) {
throw tl::Exception (tl::to_string (tr ("Rundundant parameters: height implicitly given")));
throw tl::Exception (tl::to_string (tr ("Redundant parameters: height implicitly given")));
}
info.set_zstart (args[0]);
info.set_zstop (args[1]);
@ -268,12 +356,14 @@ D25TechnologyComponent::compile_from_source (const std::string &src)
throw tl::Exception (tl::to_string (tr ("Too many parameters (max 2)")));
}
m_layers.push_back (info);
}
}
if (! conditional_stack.empty ()) {
throw tl::Exception (tl::to_string (tr ("'if', 'else' or 'elsif' without matching 'end'")));
}
} catch (tl::Exception &ex) {
throw tl::Exception (ex.msg () + tl::sprintf (tl::to_string (tr (" in line %d")), current_line));
}

View File

@ -44,6 +44,12 @@
<family>Monospace</family>
</font>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="acceptRichText">
<bool>false</bool>
</property>
</widget>
</item>
</layout>

View File

@ -5,13 +5,33 @@
<highlighting>
<list name="Control Keywords">
<item> zstart </item>
<item> zstop </item>
<item> height </item>
</list>
<list name="Expression Keywords">
<item> true </item>
<item> false </item>
<item> nil </item>
</list>
<contexts>
<context name="Normal" attribute="Normal Text">
<context name="Normal" attribute="Normal Text" fallthrough="true" fallthroughContext="Error" lineEndContext="Normal">
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
<StringDetect attribute="Symbol" String="var" context="Expect Assignment"/>
<StringDetect attribute="Symbol" String="if" context="Expression"/>
<StringDetect attribute="Symbol" String="elsif" context="Expression"/>
<StringDetect attribute="Symbol" String="else" context="Expect Lineend"/>
<StringDetect attribute="Symbol" String="end" context="Expect Lineend"/>
<DetectChar attribute="String" char="&quot;" context="Quoted String"/>
<DetectChar attribute="String" char="'" context="Apostrophed String"/>
<DetectChar attribute="Comment" char="#" context="Comment"/>
<DetectChar attribute="Raw String" char="'" context="Apostrophed String"/>
<RegExpr attribute="Normal" String=":" context="After LD"/>
@ -22,22 +42,52 @@
<DetectChar attribute="Normal" char="/" context="#stay"/>
<RegExpr attribute="Raw String" String="[_a-zA-Z]\w*" context="#stay"/>
<RegExpr attribute="Error" String="[^\s]" context="Error"/>
</context>
<context name="Comment" attribute="Comment" lineEndContext="Normal">
</context>
<context name="After LD" attribute="Normal" lineEndContext="Normal">
<context name="Expect Lineend" attribute="Normal" lineEndContext="Normal" fallthrough="true" fallthroughContext="Error">
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
<DetectChar attribute="Comment" char="#" context="Comment"/>
</context>
<context name="Expression" fallthrough="true" fallthroughContext="Error" lineEndContext="Normal">
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
<DetectChar attribute="Comment" char="#" context="Comment"/>
<keyword attribute="Symbol" String="Expression Keywords" context="#stay"/>
<keyword attribute="Symbol" String="Control Keywords" context="Expect Expression"/>
<DetectChar attribute="String" char="&quot;" context="Quoted String"/>
<DetectChar attribute="String" char="'" context="Apostrophed String"/>
<RegExpr attribute="Name" String="[_a-zA-Z]\w*" context="#stay"/>
<RegExpr attribute="Float" String="\-?[0-9]([0-9]|_[0-9])*(\.[0-9]([0-9]|_[0-9])*)?([eE]\-?[1-9]([0-9]|_[0-9])*(\.[0-9]*)?)?" context="#stay"/>
<DetectChar attribute="Normal" char="," context="#stay"/>
<DetectChar attribute="Normal" char="=" context="#stay"/>
<StringDetect attribute="Symbol" String="zstart" context="#stay"/>
<StringDetect attribute="Symbol" String="zstop" context="#stay"/>
<StringDetect attribute="Symbol" String="height" context="#stay"/>
<RegExpr attribute="Error" String="[^\s]" context="Error"/>
<DetectChar attribute="Normal" char="(" context="#stay"/>
<DetectChar attribute="Normal" char=")" context="#stay"/>
<DetectChar attribute="Normal" char="[" context="#stay"/>
<DetectChar attribute="Normal" char="]" context="#stay"/>
<RegExpr attribute="Normal" String="[\^\*\.\+\-%/!=&lt;&gt;&amp;|,\?:]" context="#stay"/>
</context>
<context name="Expect Expression" attribute="Normal" lineEndContext="Error" fallthrough="true" fallthroughContext="Error">
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
<DetectChar attribute="Normal" char="=" context="Expression"/>
</context>
<context name="Expect Assignment" attribute="Normal" lineEndContext="Error" fallthrough="true" fallthroughContext="Error">
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
<RegExpr attribute="Name" String="[_a-zA-Z]\w*" context="Expect Expression"/>
</context>
<context name="After LD" attribute="Normal" lineEndContext="Error" fallthrough="true" fallthroughContext="Expression">
<RegExpr attribute="Normal" String="\s*" context="#stay"/>
<DetectChar attribute="Comment" char="#" context="Error"/>
</context>
<context name="Error" attribute="Error" lineEndContext="Normal">
@ -46,19 +96,21 @@
<context name="Quoted String" attribute="String" lineEndContext="Error">
<StringDetect attribute="String" String="\\" context="#stay"/>
<RegExpr attribute="String" String="\\\&quot;" context="#stay"/>
<DetectChar char="&quot;" attribute="String" context="Normal"/>
<DetectChar char="&quot;" attribute="String" context="#pop"/>
</context>
<context name="Apostrophed String" attribute="Raw String" lineEndContext="Error">
<StringDetect attribute="String" String="\\" context="#stay"/>
<RegExpr attribute="String" String="\\\'" context="#stay"/>
<DetectChar char="'" attribute="Raw String" context="Normal"/>
<DetectChar char="'" attribute="Raw String" context="#pop"/>
</context>
</contexts>
<itemDatas>
<itemData name="Normal Text" defStyleNum="dsNormal"/>
<itemData name="Name" defStyleNum="dsNormal"/>
<itemData name="Comment" defStyleNum="dsComment"/>
<itemData name="Float" defStyleNum="dsFloat"/>
@ -73,4 +125,12 @@
</itemDatas>
</highlighting>
<general>
<comments>
<comment name="singleLine" start="#"/>
</comments>
<keywords casesensitive="1" weakDeliminator="!?"/>
</general>
</language>

View File

@ -246,40 +246,23 @@ D25ViewWidget::wheelEvent (QWheelEvent *event)
} else {
// compute vector of line of sight
std::pair<QVector3D, QVector3D> ray = camera_normal (cam_perspective () * cam_trans (), px, py);
// by definition the ray goes through the camera position
QVector3D hp = hit_point_with_scene (ray.second);
double d = event->angleDelta ().y () * (1.0 / (90 * 16));
if (! (event->modifiers () & Qt::ControlModifier)) {
// No Ctrl is closeup
// No Ctrl is "move horizontally along the azimuth axis"
double f = event->angleDelta ().y () * (1.0 / (90 * 8));
m_displacement += -((f / m_scale_factor) * std::min (cam_dist (), double ((cam_position () - hp).length ()))) * ray.second;
QMatrix4x4 t;
t.rotate (cam_azimuth (), 0.0, 1.0, 0.0);
QVector3D cd = t.inverted ().map (QVector3D (0, 0, cam_dist ()));
m_displacement += (d / m_scale_factor) * cd;
} else {
// "Ctrl" is zoom
double f = exp (event->angleDelta ().y () * (1.0 / (90 * 8)));
QVector3D initial_displacement = m_displacement;
QVector3D displacement = m_displacement;
m_scale_factor *= f;
displacement += hp * (1.0 - f) / m_scale_factor;
// normalize the scene translation so the scene does not "flee"
QMatrix4x4 ct = cam_trans ();
initial_displacement = ct.map (initial_displacement);
displacement = ct.map (displacement);
lay::normalize_scene_trans (cam_perspective (), displacement, m_scale_factor, initial_displacement.z ());
m_displacement = ct.inverted ().map (displacement);
m_scale_factor *= exp (d);
emit scale_factor_changed (m_scale_factor);