Best Python code snippet using tox_python
interpreter.py
Source:interpreter.py
1# ##### BEGIN GPL LICENSE BLOCK #####2#3# This program is free software; you can redistribute it and/or4# modify it under the terms of the GNU General Public License5# as published by the Free Software Foundation; either version 26# of the License, or (at your option) any later version.7#8# This program is distributed in the hope that it will be useful,9# but WITHOUT ANY WARRANTY; without even the implied warranty of10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11# GNU General Public License for more details.12#13# You should have received a copy of the GNU General Public License14# along with this program; if not, write to the Free Software Foundation,15# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.16#17# ##### END GPL LICENSE BLOCK #####18import ast19from math import *20from mathutils.geometry import interpolate_bezier21from mathutils import Vector, Matrix22from sverchok.utils.logging import info, debug, warning23from sverchok.utils.geom import interpolate_quadratic_bezier24from sverchok.utils.sv_curve_utils import Arc25from sverchok.utils.curve import SvCircle, SvLine, SvBezierCurve, SvCubicBezierCurve26from sverchok.utils.curve.nurbs import SvNurbsCurve27def make_functions_dict(*functions):28 return dict([(function.__name__, function) for function in functions])29# Functions30safe_names = make_functions_dict(31 # From math module32 acos, acosh, asin, asinh, atan, atan2,33 atanh, ceil, copysign, cos, cosh, degrees,34 erf, erfc, exp, expm1, fabs, factorial, floor,35 fmod, frexp, fsum, gamma, hypot, isfinite, isinf,36 isnan, ldexp, lgamma, log, log10, log1p, log2, modf,37 pow, radians, sin, sinh, sqrt, tan, tanh, trunc,38 # Additional functions39 abs,40 # From mathutlis module41 Vector, Matrix,42 # Python type conversions43 tuple, list, str44 )45# Constants46safe_names['e'] = e47safe_names['pi'] = pi48##########################################49# Expression classes50##########################################51class Expression(object):52 def __init__(self, expr, string):53 self.expr = expr54 self.string = string55 def __repr__(self):56 return "Expr({})".format(self.string)57 def __eq__(self, other):58 # Proper comparison of ast.Expression would be too complex to implement59 # (it is not implemented in the ast module).60 return isinstance(other, Expression) and self.string == other.string61 @classmethod62 def from_string(cls, string):63 try:64 string = string[1:][:-1]65 expr = ast.parse(string, mode='eval')66 return Expression(expr, string)67 except Exception as e:68 print(e)69 print(string)70 return None71 def eval_(self, variables):72 env = dict()73 env.update(safe_names)74 env.update(variables)75 env["__builtins__"] = {}76 return eval(compile(self.expr, "<expression>", 'eval'), env)77 def get_variables(self):78 result = {node.id for node in ast.walk(self.expr) if isinstance(node, ast.Name)}79 return result.difference(safe_names.keys())80class Const(Expression):81 def __init__(self, value):82 self.value = value83 @classmethod84 def from_string(cls, string):85 try:86 return Const( float(string) )87 except ValueError:88 return None89 def __repr__(self):90 return "Const({})".format(self.value)91 def __eq__(self, other):92 return isinstance(other,Const) and self.value == other.value93 def eval_(self, variables):94 return self.value95 def get_variables(self):96 return set()97class Variable(Expression):98 def __init__(self, name):99 self.name = name100 @classmethod101 def from_string(cls, string):102 return Variable(string)103 def __repr__(self):104 return "Variable({})".format(self.name)105 def __eq__(self, other):106 return isinstance(other, Variable) and self.name == other.name107 def eval_(self, variables):108 value = variables.get(self.name, None)109 if value is not None:110 return value111 else:112 raise SyntaxError("Unknown variable: " + self.name)113 def get_variables(self):114 return set([self.name])115# In general, this does not have very much sense:116# instead of -a one can write {-a}, then it will117# be parsed as Expression and will work fine.118# This is mostly implemented for compatibility119# with older Profile node syntax.120class NegatedVariable(Variable):121 @classmethod122 def from_string(cls, string):123 return NegatedVariable(string)124 def eval_(self, variables):125 value = variables.get(self.name, None)126 if value is not None:127 return -value128 else:129 raise SyntaxError("Unknown variable: " + self.name)130 def __repr__(self):131 return "NegatedVariable({})".format(self.name)132 def __eq__(self, other):133 return isinstance(other, NegatedVariable) and self.name == other.name134############################################135# Statement classes136# Classes for AST of our DSL137############################################138# These classes are responsible for interpretation of specific DSL statements.139# Each of these classes does the following:140# 141# * Stores statement parameters (for example, MoveTo stores x and y).142# * defines get_variables() method, which should return a set of all143# variables used by all expressions in the statement.144# * defines interpret() method, which should calculate all vertices and145# edges according to statement parameters, and pass them to the interpreter.146class Statement(object):147 148 def get_variables(self):149 return set()150 def get_hidden_inputs(self):151 return set()152 def get_optional_inputs(self):153 return set()154 def _interpolate(self, v0, v1, num_segments):155 if num_segments is None or num_segments <= 1:156 return [v0, v1]157 dx_total, dy_total = v1[0] - v0[0], v1[1] - v0[1]158 dx, dy = dx_total / float(num_segments), dy_total / float(num_segments)159 x, y = v0160 dt = 1.0 / float(num_segments)161 result = []162 t = 0163 for i in range(round(num_segments)):164 result.append((x,y))165 x = x + dx166 y = y + dy167 result.append(v1)168 return result169class MoveTo(Statement):170 def __init__(self, is_abs, x, y):171 self.is_abs = is_abs172 self.x = x173 self.y = y174 def __repr__(self):175 letter = "M" if self.is_abs else "m"176 return "{} {} {}".format(letter, self.x, self.y)177 def __eq__(self, other):178 return isinstance(other, MoveTo) and \179 self.is_abs == other.is_abs and \180 self.x == other.x and \181 self.y == other.y182 def get_variables(self):183 variables = set()184 variables.update(self.x.get_variables())185 variables.update(self.y.get_variables())186 return variables187 def interpret(self, interpreter, variables):188 interpreter.assert_not_closed()189 interpreter.start_new_segment()190 pos = interpreter.calc_vertex(self.is_abs, self.x, self.y, variables)191 interpreter.position = pos192 interpreter.new_knot("M.#", *pos)193 interpreter.has_last_vertex = False194class LineTo(Statement):195 def __init__(self, is_abs, pairs, num_segments, close):196 self.is_abs = is_abs197 self.pairs = pairs198 self.num_segments = num_segments199 self.close = close200 def get_variables(self):201 variables = set()202 for x, y in self.pairs:203 variables.update(x.get_variables())204 variables.update(y.get_variables())205 if self.num_segments:206 variables.update(self.num_segments.get_variables())207 return variables208 def __repr__(self):209 letter = "L" if self.is_abs else "l"210 return "{} {} n={} {}".format(letter, self.pairs, self.num_segments, self.close)211 212 def __eq__(self, other):213 return isinstance(other, LineTo) and \214 self.is_abs == other.is_abs and \215 self.pairs == other.pairs and \216 self.num_segments == other.num_segments and \217 self.close == other.close218 def interpret(self, interpreter, variables):219 interpreter.assert_not_closed()220 interpreter.start_new_segment()221 v0 = interpreter.position222 if interpreter.has_last_vertex:223 prev_index = interpreter.get_last_vertex()224 else:225 prev_index = interpreter.new_vertex(*v0)226 if self.num_segments is not None:227 num_segments = interpreter.eval_(self.num_segments, variables)228 else:229 num_segments = None230 for i, (x_expr, y_expr) in enumerate(self.pairs):231 v1 = interpreter.calc_vertex(self.is_abs, x_expr, y_expr, variables)232 interpreter.position = v1233 for vertex in self._interpolate(v0, v1, num_segments)[1:]:234 v_index = interpreter.new_vertex(*vertex)235 interpreter.new_edge(prev_index, v_index)236 prev_index = v_index237 interpreter.new_line_segment(v0, v1)238 v0 = v1239 interpreter.new_knot("L#.{}".format(i), *v1)240 if self.close:241 interpreter.close_segment(v_index)242 interpreter.has_last_vertex = True243class HorizontalLineTo(Statement):244 def __init__(self, is_abs, xs, num_segments):245 self.is_abs = is_abs246 self.xs = xs247 self.num_segments = num_segments248 def get_variables(self):249 variables = set()250 for x in self.xs:251 variables.update(x.get_variables())252 if self.num_segments:253 variables.update(self.num_segments.get_variables())254 return variables255 def __repr__(self):256 letter = "H" if self.is_abs else "h"257 return "{} {} n={};".format(letter, self.xs, self.num_segments)258 def __eq__(self, other):259 return isinstance(other, HorizontalLineTo) and \260 self.is_abs == other.is_abs and \261 self.num_segments == other.num_segments and \262 self.xs == other.xs263 def interpret(self, interpreter, variables):264 interpreter.assert_not_closed()265 interpreter.start_new_segment()266 v0 = interpreter.position267 if interpreter.has_last_vertex:268 prev_index = interpreter.get_last_vertex()269 else:270 prev_index = interpreter.new_vertex(*v0)271 if self.num_segments is not None:272 num_segments = interpreter.eval_(self.num_segments, variables)273 else:274 num_segments = None275 for i, x_expr in enumerate(self.xs):276 x0,y0 = interpreter.position277 x = interpreter.eval_(x_expr, variables)278 if not self.is_abs:279 x = x0 + x280 v1 = (x, y0)281 interpreter.position = v1282 verts = self._interpolate(v0, v1, num_segments)283 #debug("V0 %s, v1 %s, N %s => %s", v0, v1, num_segments, verts)284 for vertex in verts[1:]:285 v_index = interpreter.new_vertex(*vertex)286 interpreter.new_edge(prev_index, v_index)287 prev_index = v_index288 interpreter.new_line_segment(v0, v1)289 v0 = v1290 interpreter.new_knot("H#.{}".format(i), *v1)291 interpreter.has_last_vertex = True292class VerticalLineTo(Statement):293 def __init__(self, is_abs, ys, num_segments):294 self.is_abs = is_abs295 self.ys = ys296 self.num_segments = num_segments297 def get_variables(self):298 variables = set()299 for y in self.ys:300 variables.update(y.get_variables())301 if self.num_segments:302 variables.update(self.num_segments.get_variables())303 return variables304 def __repr__(self):305 letter = "V" if self.is_abs else "v"306 return "{} {} n={};".format(letter, self.ys, self.num_segments)307 def __eq__(self, other):308 return isinstance(other, VerticalLineTo) and \309 self.is_abs == other.is_abs and \310 self.num_segments == other.num_segments and \311 self.ys == other.ys312 def interpret(self, interpreter, variables):313 interpreter.assert_not_closed()314 interpreter.start_new_segment()315 v0 = interpreter.position316 if interpreter.has_last_vertex:317 prev_index = interpreter.get_last_vertex()318 else:319 prev_index = interpreter.new_vertex(*v0)320 if self.num_segments is not None:321 num_segments = interpreter.eval_(self.num_segments, variables)322 else:323 num_segments = None324 for i, y_expr in enumerate(self.ys):325 x0,y0 = interpreter.position326 y = interpreter.eval_(y_expr, variables)327 if not self.is_abs:328 y = y0 + y329 v1 = (x0, y)330 interpreter.position = v1331 for vertex in self._interpolate(v0, v1, num_segments)[1:]:332 v_index = interpreter.new_vertex(*vertex)333 interpreter.new_edge(prev_index, v_index)334 prev_index = v_index335 interpreter.new_line_segment(v0, v1)336 v0 = v1337 interpreter.new_knot("V#.{}".format(i), *v1)338 interpreter.has_last_vertex = True339class CurveTo(Statement):340 class Segment(object):341 def __init__(self, control1, control2, knot2):342 self.control1 = control1343 self.control2 = control2344 self.knot2 = knot2345 def __repr__(self):346 return "{} {} {}".format(self.control1, self.control2, self.knot2)347 def __eq__(self, other):348 return self.control1 == other.control1 and \349 self.control2 == other.control2 and \350 self.knot2 == other.knot2351 def __init__(self, is_abs, segments, num_segments, close):352 self.is_abs = is_abs353 self.segments = segments354 self.num_segments = num_segments355 self.close = close356 def get_variables(self):357 variables = set()358 for segment in self.segments:359 variables.update(segment.control1[0].get_variables())360 variables.update(segment.control1[1].get_variables())361 variables.update(segment.control2[0].get_variables())362 variables.update(segment.control2[1].get_variables())363 variables.update(segment.knot2[0].get_variables())364 variables.update(segment.knot2[1].get_variables())365 if self.num_segments:366 variables.update(self.num_segments.get_variables())367 return variables368 def __repr__(self):369 letter = "C" if self.is_abs else "c"370 segments = " ".join(str(segment) for segment in self.segments)371 return "{} {} n={} {}".format(letter, segments, self.num_segments, self.close)372 def __eq__(self, other):373 return isinstance(other, CurveTo) and \374 self.is_abs == other.is_abs and \375 self.segments == other.segments and \376 self.num_segments == other.num_segments and \377 self.close == other.close378 def interpret(self, interpreter, variables):379 vec = lambda v: Vector((v[0], v[1], 0))380 interpreter.assert_not_closed()381 interpreter.start_new_segment()382 v0 = interpreter.position383 if interpreter.has_last_vertex:384 v0_index = interpreter.get_last_vertex()385 else:386 v0_index = interpreter.new_vertex(*v0)387 knot1 = None388 for i, segment in enumerate(self.segments):389 # For first segment, knot1 is initial pen position;390 # for the following, knot1 is knot2 of previous segment.391 if knot1 is None:392 knot1 = interpreter.position393 else:394 knot1 = knot2395 handle1 = interpreter.calc_vertex(self.is_abs, segment.control1[0], segment.control1[1], variables)396 # In Profile mk2, for "c" handle2 was calculated relative to handle1,397 # and knot2 was calculated relative to handle2.398 # But in SVG specification, 399 # >> ... *At the end of the command*, the new current point becomes400 # >> the final (x,y) coordinate pair used in the polybézier.401 # This is also behaviour of browsers.402 #interpreter.position = handle1403 handle2 = interpreter.calc_vertex(self.is_abs, segment.control2[0], segment.control2[1], variables)404 #interpreter.position = handle2405 knot2 = interpreter.calc_vertex(self.is_abs, segment.knot2[0], segment.knot2[1], variables)406 # Judging by the behaviour of Inkscape and Firefox, by "end of command"407 # SVG spec means "end of segment".408 interpreter.position = knot2409 if self.num_segments is not None:410 r = interpreter.eval_(self.num_segments, variables)411 else:412 r = interpreter.dflt_num_verts413 curve = SvCubicBezierCurve(vec(knot1), vec(handle1), vec(handle2), vec(knot2))414 interpreter.new_curve(curve, self)415 points = interpolate_bezier(vec(knot1), vec(handle1), vec(handle2), vec(knot2), r)416 interpreter.new_knot("C#.{}.h1".format(i), *handle1)417 interpreter.new_knot("C#.{}.h2".format(i), *handle2)418 interpreter.new_knot("C#.{}.k".format(i), *knot2)419 interpreter.prev_bezier_knot = handle2420 for point in points[1:]:421 v1_index = interpreter.new_vertex(point.x, point.y)422 interpreter.new_edge(v0_index, v1_index)423 v0_index = v1_index424 if self.close:425 interpreter.close_segment(v1_index)426 interpreter.has_last_vertex = True427class SmoothCurveTo(Statement):428 class Segment(object):429 def __init__(self, control2, knot2):430 self.control2 = control2431 self.knot2 = knot2432 def __repr__(self):433 return "{} {}".format(self.control2, self.knot2)434 def __eq__(self, other):435 return self.control2 == other.control2 and \436 self.knot2 == other.knot2437 def __init__(self, is_abs, segments, num_segments, close):438 self.is_abs = is_abs439 self.segments = segments440 self.num_segments = num_segments441 self.close = close442 def get_variables(self):443 variables = set()444 for segment in self.segments:445 variables.update(segment.control2[0].get_variables())446 variables.update(segment.control2[1].get_variables())447 variables.update(segment.knot2[0].get_variables())448 variables.update(segment.knot2[1].get_variables())449 if self.num_segments:450 variables.update(self.num_segments.get_variables())451 return variables452 def __repr__(self):453 letter = "S" if self.is_abs else "s"454 segments = " ".join(str(segment) for segment in self.segments)455 return "{} {} n={} {}".format(letter, segments, self.num_segments, self.close)456 def __eq__(self, other):457 return isinstance(other, SmoothCurveTo) and \458 self.is_abs == other.is_abs and \459 self.segments == other.segments and \460 self.num_segments == other.num_segments and \461 self.close == other.close462 def interpret(self, interpreter, variables):463 vec = lambda v: Vector((v[0], v[1], 0))464 interpreter.assert_not_closed()465 interpreter.start_new_segment()466 v0 = interpreter.position467 if interpreter.has_last_vertex:468 v0_index = interpreter.get_last_vertex()469 else:470 v0_index = interpreter.new_vertex(*v0)471 knot1 = None472 for i, segment in enumerate(self.segments):473 # For first segment, knot1 is initial pen position;474 # for the following, knot1 is knot2 of previous segment.475 if knot1 is None:476 knot1 = interpreter.position477 else:478 knot1 = knot2479 if interpreter.prev_bezier_knot is None:480 # If there is no previous command or if the previous command was481 # not an C, c, S or s, assume the first control point is coincident482 # with the current point.483 handle1 = knot1484 else:485 # The first control point is assumed to be the reflection of the486 # second control point on the previous command relative to the487 # current point. 488 prev_knot_x, prev_knot_y = interpreter.prev_bezier_knot489 x0, y0 = knot1490 dx, dy = x0 - prev_knot_x, y0 - prev_knot_y491 handle1 = x0 + dx, y0 + dy492 # I assume that handle2 should be relative to knot1, not to handle1.493 # interpreter.position = handle1494 handle2 = interpreter.calc_vertex(self.is_abs, segment.control2[0], segment.control2[1], variables)495 # interpreter.position = handle2496 knot2 = interpreter.calc_vertex(self.is_abs, segment.knot2[0], segment.knot2[1], variables)497 interpreter.position = knot2498 if self.num_segments is not None:499 r = interpreter.eval_(self.num_segments, variables)500 else:501 r = interpreter.dflt_num_verts502 curve = SvCubicBezierCurve(vec(knot1), vec(handle1), vec(handle2), vec(knot2))503 interpreter.new_curve(curve, self)504 points = interpolate_bezier(vec(knot1), vec(handle1), vec(handle2), vec(knot2), r)505 interpreter.new_knot("S#.{}.h1".format(i), *handle1)506 interpreter.new_knot("S#.{}.h2".format(i), *handle2)507 interpreter.new_knot("S#.{}.k".format(i), *knot2)508 interpreter.prev_bezier_knot = handle2509 for point in points[1:]:510 v1_index = interpreter.new_vertex(point.x, point.y)511 interpreter.new_edge(v0_index, v1_index)512 v0_index = v1_index513 if self.close:514 interpreter.close_segment(v1_index)515 interpreter.has_last_vertex = True516class QuadraticCurveTo(Statement):517 class Segment(object):518 def __init__(self, control, knot2):519 self.control = control520 self.knot2 = knot2521 def __repr__(self):522 return "{} {}".format(self.control, self.knot2)523 def __eq__(self, other):524 return self.control == other.control and \525 self.knot2 == other.knot2526 def __init__(self, is_abs, segments, num_segments, close):527 self.is_abs = is_abs528 self.segments = segments529 self.num_segments = num_segments530 self.close = close531 def get_variables(self):532 variables = set()533 for segment in self.segments:534 variables.update(segment.control[0].get_variables())535 variables.update(segment.control[1].get_variables())536 variables.update(segment.knot2[0].get_variables())537 variables.update(segment.knot2[1].get_variables())538 if self.num_segments:539 variables.update(self.num_segments.get_variables())540 return variables541 def __repr__(self):542 letter = "Q" if self.is_abs else "q"543 segments = " ".join(str(segment) for segment in self.segments)544 return "{} {} n={} {}".format(letter, segments, self.num_segments, self.close)545 def __eq__(self, other):546 return isinstance(other, QuadraticCurveTo) and \547 self.is_abs == other.is_abs and \548 self.segments == other.segments and \549 self.num_segments == other.num_segments and \550 self.close == other.close551 def interpret(self, interpreter, variables):552 vec = lambda v: Vector((v[0], v[1], 0))553 interpreter.assert_not_closed()554 interpreter.start_new_segment()555 v0 = interpreter.position556 if interpreter.has_last_vertex:557 v0_index = interpreter.get_last_vertex()558 else:559 v0_index = interpreter.new_vertex(*v0)560 knot1 = None561 for i, segment in enumerate(self.segments):562 # For first segment, knot1 is initial pen position;563 # for the following, knot1 is knot2 of previous segment.564 if knot1 is None:565 knot1 = interpreter.position566 else:567 knot1 = knot2568 handle = interpreter.calc_vertex(self.is_abs, segment.control[0], segment.control[1], variables)569 knot2 = interpreter.calc_vertex(self.is_abs, segment.knot2[0], segment.knot2[1], variables)570 interpreter.position = knot2571 if self.num_segments is not None:572 r = interpreter.eval_(self.num_segments, variables)573 else:574 r = interpreter.dflt_num_verts575 curve = SvBezierCurve([vec(knot1), vec(handle), vec(knot2)])576 interpreter.new_curve(curve, self)577 points = interpolate_quadratic_bezier(vec(knot1), vec(handle), vec(knot2), r)578 interpreter.new_knot("Q#.{}.h".format(i), *handle)579 interpreter.new_knot("Q#.{}.k".format(i), *knot2)580 interpreter.prev_quad_bezier_knot = handle581 for point in points[1:]:582 v1_index = interpreter.new_vertex(point.x, point.y)583 interpreter.new_edge(v0_index, v1_index)584 v0_index = v1_index585 if self.close:586 interpreter.close_segment(v1_index)587 interpreter.has_last_vertex = True588class SmoothQuadraticCurveTo(Statement):589 class Segment(object):590 def __init__(self, knot2):591 self.knot2 = knot2592 def __repr__(self):593 return str(self.knot2)594 def __eq__(self, other):595 return self.knot2 == other.knot2596 def __init__(self, is_abs, segments, num_segments, close):597 self.is_abs = is_abs598 self.segments = segments599 self.num_segments = num_segments600 self.close = close601 def get_variables(self):602 variables = set()603 for segment in self.segments:604 variables.update(segment.knot2[0].get_variables())605 variables.update(segment.knot2[1].get_variables())606 if self.num_segments:607 variables.update(self.num_segments.get_variables())608 return variables609 def __repr__(self):610 letter = "T" if self.is_abs else "t"611 segments = " ".join(str(segment) for segment in self.segments)612 return "{} {} n={} {}".format(letter, segments, self.num_segments, self.close)613 def __eq__(self, other):614 return isinstance(other, SmoothQuadraticCurveTo) and \615 self.is_abs == other.is_abs and \616 self.segments == other.segments and \617 self.num_segments == other.num_segments and \618 self.close == other.close619 def interpret(self, interpreter, variables):620 vec = lambda v: Vector((v[0], v[1], 0))621 interpreter.assert_not_closed()622 interpreter.start_new_segment()623 v0 = interpreter.position624 if interpreter.has_last_vertex:625 v0_index = interpreter.get_last_vertex()626 else:627 v0_index = interpreter.new_vertex(*v0)628 knot1 = None629 for i, segment in enumerate(self.segments):630 # For first segment, knot1 is initial pen position;631 # for the following, knot1 is knot2 of previous segment.632 if knot1 is None:633 knot1 = interpreter.position634 else:635 knot1 = knot2636 if interpreter.prev_quad_bezier_knot is None:637 # If there is no previous command or if the previous command was638 # not a Q, q, T or t, assume the control point is coincident with639 # the current point.640 handle = knot1641 else:642 # The first control point is assumed to be the reflection of the643 # second control point on the previous command relative to the644 # current point. 645 prev_knot_x, prev_knot_y = interpreter.prev_quad_bezier_knot646 x0, y0 = knot1647 dx, dy = x0 - prev_knot_x, y0 - prev_knot_y648 handle = x0 + dx, y0 + dy649 knot2 = interpreter.calc_vertex(self.is_abs, segment.knot2[0], segment.knot2[1], variables)650 interpreter.position = knot2651 if self.num_segments is not None:652 r = interpreter.eval_(self.num_segments, variables)653 else:654 r = interpreter.dflt_num_verts655 curve = SvBezierCurve([vec(knot1), vec(handle), vec(knot2)])656 interpreter.new_curve(curve, self)657 points = interpolate_quadratic_bezier(vec(knot1), vec(handle), vec(knot2), r)658 interpreter.new_knot("T#.{}.h".format(i), *handle)659 interpreter.new_knot("T#.{}.k".format(i), *knot2)660 interpreter.prev_quad_bezier_knot = handle661 for point in points[1:]:662 v1_index = interpreter.new_vertex(point.x, point.y)663 interpreter.new_edge(v0_index, v1_index)664 v0_index = v1_index665 if self.close:666 interpreter.close_segment(v1_index)667 interpreter.has_last_vertex = True668class ArcTo(Statement):669 def __init__(self, is_abs, radii, rot, flag1, flag2, end, num_verts, close):670 self.is_abs = is_abs671 self.radii = radii672 self.rot = rot673 self.flag1 = flag1674 self.flag2 = flag2675 self.end = end676 self.num_verts = num_verts677 self.close = close678 def get_variables(self):679 variables = set()680 variables.update(self.radii[0].get_variables())681 variables.update(self.radii[1].get_variables())682 variables.update(self.rot.get_variables())683 variables.update(self.flag1.get_variables())684 variables.update(self.flag2.get_variables())685 variables.update(self.end[0].get_variables())686 variables.update(self.end[1].get_variables())687 if self.num_verts:688 variables.update(self.num_verts.get_variables())689 return variables690 def __repr__(self):691 letter = "A" if self.is_abs else "a"692 return "{} {} {} {} {} {} n={} {}".format(letter, self.radii, self.rot, self.flag1, self.flag2, self.end, self.num_verts, self.close)693 def __eq__(self, other):694 return isinstance(other, ArcTo) and \695 self.is_abs == other.is_abs and \696 self.radii == other.radii and \697 self.rot == other.rot and \698 self.flag1 == other.flag1 and \699 self.flag2 == other.flag2 and \700 self.end == other.end and \701 self.num_verts == other.num_verts and \702 self.close == other.close703 def interpret(self, interpreter, variables):704 interpreter.assert_not_closed()705 interpreter.start_new_segment()706 v0 = interpreter.position707 if interpreter.has_last_vertex:708 v0_index = interpreter.get_last_vertex()709 else:710 v0_index = interpreter.new_vertex(*v0)711 start = complex(*v0)712 rad_x_expr, rad_y_expr = self.radii713 rad_x = interpreter.eval_(rad_x_expr, variables)714 rad_y = interpreter.eval_(rad_y_expr, variables)715 radius = complex(rad_x, rad_y)716 xaxis_rot = interpreter.eval_(self.rot, variables)717 flag1 = interpreter.eval_(self.flag1, variables)718 flag2 = interpreter.eval_(self.flag2, variables)719 # numverts, requires -1 else it means segments (21 verts is 20 segments).720 if self.num_verts is not None:721 num_verts = interpreter.eval_(self.num_verts, variables)722 else:723 num_verts = interpreter.dflt_num_verts724 num_verts -= 1725 end = interpreter.calc_vertex(self.is_abs, self.end[0], self.end[1], variables)726 end = complex(*end)727 arc = Arc(start, radius, xaxis_rot, flag1, flag2, end)728 theta = 1/num_verts729 for i in range(1, num_verts+1):730 v1 = x, y = arc.point(theta * i)731 v1_index = interpreter.new_vertex(x, y)732 interpreter.new_edge(v0_index, v1_index)733 v0_index = v1_index734 curve = SvCircle.from_arc(arc, z_axis=interpreter.z_axis)735 interpreter.new_curve(curve, self)736 interpreter.position = v1737 interpreter.new_knot("A.#", *v1)738 if self.close:739 interpreter.close_segment(v1_index)740 interpreter.has_last_vertex = True741class CloseAll(Statement):742 def __init__(self):743 pass744 def __repr__(self):745 return "X"746 def __eq__(self, other):747 return isinstance(other, CloseAll)748 def get_variables(self):749 return set()750 def interpret(self, interpreter, variables):751 interpreter.assert_not_closed()752 if not interpreter.has_last_vertex:753 info("X statement: no current point, do nothing")754 return755 v0 = interpreter.vertices[0]756 v1 = interpreter.vertices[-1]757 distance = (Vector(v0) - Vector(v1)).length758 if distance < interpreter.close_threshold:759 interpreter.pop_last_vertex()760 v1_index = interpreter.get_last_vertex()761 interpreter.new_edge(v1_index, 0)762 interpreter.new_line_segment(v1, v0)763 interpreter.closed = True764class ClosePath(Statement):765 def __init__(self):766 pass767 def __repr__(self):768 return "x"769 def __eq__(self, other):770 return isinstance(other, ClosePath)771 def get_variables(self):772 return set()773 def interpret(self, interpreter, variables):774 interpreter.assert_not_closed()775 if not interpreter.has_last_vertex:776 info("X statement: no current point, do nothing")777 return778 v0 = interpreter.vertices[interpreter.close_first_index]779 v1 = interpreter.vertices[-1]780 distance = (Vector(v0) - Vector(v1)).length781 if distance < interpreter.close_threshold:782 interpreter.pop_last_vertex()783 v1_index = interpreter.get_last_vertex()784 interpreter.new_edge(v1_index, interpreter.close_first_index)785 interpreter.new_line_segment(v1_index, interpreter.close_first_index)786 interpreter.close_first_index = interpreter.next_vertex_index787class Default(Statement):788 def __init__(self, name, value):789 self.name = name790 self.value = value791 def __repr__(self):792 return "default {} = {}".format(self.name, self.value)793 def __eq__(self, other):794 return isinstance(other, Default) and \795 self.name == other.name and \796 self.value == other.value797 def get_variables(self):798 return self.value.get_variables()799 def get_optional_inputs(self):800 return set([self.name])801 def interpret(self, interpreter, variables):802 if self.name in interpreter.defaults:803 raise Exception("Value for the `{}' variable has been already assigned!".format(self.name))804 if self.name not in interpreter.input_names:805 value = interpreter.eval_(self.value, variables)806 interpreter.defaults[self.name] = value807class Assign(Default):808 def __repr__(self):809 return "let {} = {}".format(self.name, self.value)810 def __eq__(self, other):811 return isinstance(other, Assign) and \812 self.name == other.name and \813 self.value == other.value814 def get_hidden_inputs(self):815 return set([self.name])816#################################817# DSL Interpreter818#################################819# This class does the following:820#821# * Stores the "drawing" state, such as "current pen position"822# * Provides API for Statement classes to add vertices, edges to the current823# drawing824# * Contains the interpret() method, which runs the whole interpretation process.825class Interpreter(object):826 NURBS = 'NURBS'827 BEZIER = 'BEZIER'828 def __init__(self, node, input_names, curves_form = None, force_curves_form = False, z_axis='Z'):829 self.position = (0, 0)830 self.next_vertex_index = 0831 self.segment_start_index = 0832 self.segment_continues_line = False833 self.segment_number = 0834 self.has_last_vertex = False835 self.closed = False836 self.close_first_index = 0837 self.prev_bezier_knot = None838 self.prev_quad_bezier_knot = None839 self.curves = []840 self.vertices = []841 self.edges = []842 self.knots = []843 self.knotnames = []844 self.dflt_num_verts = node.curve_points_count845 self.close_threshold = node.close_threshold846 self.defaults = dict()847 self.input_names = input_names848 self.curves_form = curves_form849 self.force_curves_form = force_curves_form850 self.z_axis = z_axis851 def to3d(self, vertex):852 if self.z_axis == 'X':853 return Vector((0, vertex[0], vertex[1]))854 elif self.z_axis == 'Y':855 return Vector((vertex[0], 0, vertex[1]))856 else: # self.z_axis == 'Z':857 return Vector((vertex[0], vertex[1], 0))858 def assert_not_closed(self):859 if self.closed:860 raise Exception("Path was already closed, will not process any further directives!")861 def relative(self, x, y):862 x0, y0 = self.position863 return x0+x, y0+y864 def calc_vertex(self, is_abs, x_expr, y_expr, variables):865 x = self.eval_(x_expr, variables)866 y = self.eval_(y_expr, variables)867 if is_abs:868 return x,y869 else:870 return self.relative(x,y)871 def new_vertex(self, x, y):872 index = self.next_vertex_index873 vertex = (x, y)874 self.vertices.append(vertex)875 self.next_vertex_index += 1876 return index877 def new_edge(self, v1, v2):878 self.edges.append((v1, v2))879 def new_knot(self, name, x, y):880 self.knots.append((x, y))881 name = name.replace("#", str(self.segment_number))882 self.knotnames.append(name)883 def new_curve(self, curve, statement):884 if self.curves_form == Interpreter.NURBS:885 if hasattr(curve, 'to_nurbs'):886 curve = curve.to_nurbs()887 else:888 if self.force_curves_form:889 raise Exception(f"Cannot convert curve to NURBS: {statement}")890 elif self.curves_form == Interpreter.BEZIER:891 if not isinstance(curve, (SvBezierCurve, SvCubicBezierCurve)):892 if hasattr(curve, 'to_bezier'):893 curve = curve.to_bezier()894 else:895 if self.force_curves_form:896 raise Exception("Cannot convert curve to Bezier: {statement}")897 self.curves.append(curve)898 def new_line_segment(self, v1, v2):899 if isinstance(v1, int):900 v1, v2 = self.vertices[v1], self.vertices[v2]901 v1, v2 = self.to3d(v1), self.to3d(v2)902 if (v1 - v2).length < self.close_threshold:903 return904 curve = SvLine.from_two_points(v1, v2)905 self.new_curve(curve, None)906 def start_new_segment(self):907 self.segment_start_index = self.next_vertex_index908 self.segment_continues_line = self.has_last_vertex909 self.segment_number += 1910 def close_segment(self, v_index):911 if self.segment_continues_line:912 start_index = self.segment_start_index-1913 else:914 start_index = self.segment_start_index915 self.new_edge(v_index, start_index)916 def get_last_vertex(self):917 return self.next_vertex_index - 1918 def pop_last_vertex(self):919 self.vertices.pop()920 self.next_vertex_index -= 1921 is_not_last = lambda e: e[0] != self.next_vertex_index and e[1] != self.next_vertex_index922 self.edges = list(filter(is_not_last, self.edges))923 def eval_(self, expr, variables):924 variables_ = self.defaults.copy()925 for name in variables:926 value = variables[name]927 if value is not None:928 variables_[name] = value929 return expr.eval_(variables_)930 def interpret(self, profile, variables):931 if not profile:932 return933 for statement in profile:934 debug("Interpret: %s", statement)...
parser.py
Source:parser.py
1# ##### BEGIN GPL LICENSE BLOCK #####2#3# This program is free software; you can redistribute it and/or4# modify it under the terms of the GNU General Public License5# as published by the Free Software Foundation; either version 26# of the License, or (at your option) any later version.7#8# This program is distributed in the hope that it will be useful,9# but WITHOUT ANY WARRANTY; without even the implied warranty of10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11# GNU General Public License for more details.12#13# You should have received a copy of the GNU General Public License14# along with this program; if not, write to the Free Software Foundation,15# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.16#17# ##### END GPL LICENSE BLOCK #####18import re19from sverchok.utils.parsec import *20from sverchok.utils.logging import info, debug, warning21from sverchok.utils.modules.profile_mk3.interpreter import *22#########################################23# DSL parsing24#########################################25# Compare these definitions with BNF definition at the top of profile_mk3.py.26expr_regex = re.compile(r"({[^}]+})\s*", re.DOTALL)27def parse_expr(src):28 for string, rest in parse_regexp(expr_regex)(src):29 expr = Expression.from_string(string)30 if expr is not None:31 yield expr, rest32identifier_regexp = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*")33parse_semicolon = parse_word(";")34def parse_identifier(src):35 for (name, _), rest in sequence(parse_regexp(identifier_regexp), parse_whitespace)(src):36 yield name, rest37def parse_negated_variable(src):38 for (_, name, _), rest in sequence(parse_word("-"), parse_regexp(identifier_regexp), parse_whitespace)(src):39 yield NegatedVariable(name), rest40def parse_value(src):41 for smth, rest in one_of(parse_number, parse_identifier, parse_negated_variable, parse_expr)(src):42 if isinstance(smth, (int, float)):43 yield Const(smth), rest44 elif isinstance(smth, str):45 yield Variable(smth), rest46 else:47 yield smth, rest48def parse_pair(src):49 parser = sequence(parse_value, parse_word(","), parse_value)50 for (x, _, y), rest in parser(src):51 yield (x,y), rest52def parse_letter(absolute, relative):53 def parser(src):54 for smth, rest in one_of(parse_word(absolute), parse_word(relative))(src):55 is_abs = smth == absolute56 yield is_abs, rest57 return parser58def parse_MoveTo(src):59 parser = sequence(parse_letter("M", "m"), parse_pair, optional(parse_semicolon))60 for (is_abs, (x, y), _), rest in parser(src):61 yield MoveTo(is_abs, x, y), rest62def parse_LineTo(src):63 parser = sequence(64 parse_letter("L", "l"),65 many(parse_pair),66 optional(parse_parameter("n")),67 optional(parse_word("z")),68 optional(parse_semicolon))69 for (is_abs, pairs, num_segments, z, _), rest in parser(src):70 yield LineTo(is_abs, pairs, num_segments, z is not None), rest71def parse_parameter(name):72 def parser(src):73 for (_, _, value), rest in sequence(parse_word(name), parse_word("="), parse_value)(src):74 yield value, rest75 return parser76def parse_CurveTo(src):77 def parse_segment(src):78 parser = sequence(parse_pair, parse_pair, parse_pair)79 for (control1, control2, knot2), rest in parser(src):80 yield CurveTo.Segment(control1, control2, knot2), rest81 parser = sequence(82 parse_letter("C", "c"),83 many(parse_segment),84 optional(parse_parameter("n")),85 optional(parse_word("z")),86 optional(parse_semicolon)87 )88 for (is_abs, segments, num_segments, z, _), rest in parser(src):89 yield CurveTo(is_abs, segments, num_segments, z is not None), rest90def parse_SmoothCurveTo(src):91 def parse_segment(src):92 parser = sequence(parse_pair, parse_pair)93 for (control2, knot2), rest in parser(src):94 yield SmoothCurveTo.Segment(control2, knot2), rest95 parser = sequence(96 parse_letter("S", "s"),97 many(parse_segment),98 optional(parse_parameter("n")),99 optional(parse_word("z")),100 optional(parse_semicolon)101 )102 for (is_abs, segments, num_segments, z, _), rest in parser(src):103 yield SmoothCurveTo(is_abs, segments, num_segments, z is not None), rest104def parse_QuadCurveTo(src):105 def parse_segment(src):106 parser = sequence(parse_pair, parse_pair)107 for (control, knot2), rest in parser(src):108 yield QuadraticCurveTo.Segment(control, knot2), rest109 parser = sequence(110 parse_letter("Q", "q"),111 many(parse_segment),112 optional(parse_parameter("n")),113 optional(parse_word("z")),114 optional(parse_semicolon)115 )116 for (is_abs, segments, num_segments, z, _), rest in parser(src):117 yield QuadraticCurveTo(is_abs, segments, num_segments, z is not None), rest118def parse_SmoothQuadCurveTo(src):119 def parse_segment(src):120 for knot2, rest in parse_pair(src):121 yield SmoothQuadraticCurveTo.Segment(knot2), rest122 parser = sequence(123 parse_letter("T", "t"),124 many(parse_segment),125 optional(parse_parameter("n")),126 optional(parse_word("z")),127 optional(parse_semicolon)128 )129 for (is_abs, knot2, num_segments, z, _), rest in parser(src):130 yield SmoothQuadraticCurveTo(is_abs, knot2, num_segments, z is not None), rest131def parse_ArcTo(src):132 parser = sequence(133 parse_letter("A", "a"),134 parse_pair,135 parse_value,136 parse_value,137 parse_value,138 parse_pair,139 optional(parse_parameter("n")),140 optional(parse_word("z")),141 optional(parse_semicolon)142 )143 for (is_abs, radii, rot, flag1, flag2, end, num_verts, z, _), rest in parser(src):144 yield ArcTo(is_abs, radii, rot, flag1, flag2, end, num_verts, z is not None), rest145def parse_HorLineTo(src):146 # NB: H/h command MUST end with semicolon, otherwise we will not be able to147 # understand where it ends, i.e. does the following letter begin a new statement148 # or is it just next X value denoted by variable.149 parser = sequence(parse_letter("H", "h"),150 many(parse_value, backtracking=True),151 optional(parse_parameter("n")),152 parse_semicolon)153 for (is_abs, xs, num_segments, _), rest in parser(src):154 yield HorizontalLineTo(is_abs, xs, num_segments), rest155def parse_VertLineTo(src):156 # NB: V/v command MUST end with semicolon, otherwise we will not be able to157 # understand where it ends, i.e. does the following letter begin a new statement158 # or is it just next X value denoted by variable.159 parser = sequence(parse_letter("V", "v"),160 many(parse_value, backtracking=True),161 optional(parse_parameter("n")),162 parse_semicolon)163 for (is_abs, ys, num_segments, _), rest in parser(src):164 yield VerticalLineTo(is_abs, ys, num_segments), rest165parse_CloseAll = parse_word("X", CloseAll())166parse_ClosePath = parse_word("x", ClosePath())167def parse_Default(src):168 parser = sequence(169 parse_word("default"),170 parse_identifier,171 parse_word("="),172 parse_value,173 optional(parse_semicolon)174 )175 for (_, name, _, value, _), rest in parser(src):176 yield Default(name, value), rest177def parse_Assign(src):178 parser = sequence(179 parse_word("let"),180 parse_identifier,181 parse_word("="),182 parse_value,183 optional(parse_semicolon)184 )185 for (_, name, _, value, _), rest in parser(src):186 yield Assign(name, value), rest187parse_statement = one_of(188 parse_Default,189 parse_Assign,190 parse_MoveTo,191 parse_LineTo,192 parse_HorLineTo,193 parse_VertLineTo,194 parse_CurveTo,195 parse_SmoothCurveTo,196 parse_QuadCurveTo,197 parse_SmoothQuadCurveTo,198 parse_ArcTo,199 parse_ClosePath,200 parse_CloseAll201 )202parse_definition = many(parse_statement)203def parse_profile(src):204 # Strip comments205 # (hope no one uses # in expressions)206 cleaned = ""207 for line in src.split("\n"):208 comment_idx = line.find('#')209 if comment_idx != -1:210 line = line[:comment_idx]211 cleaned = cleaned + " " + line212 213 profile = parse(parse_definition, cleaned)214 debug(profile)...
iterative.py
Source:iterative.py
1"""2Copyright 2013 Steven Diamond3Licensed under the Apache License, Version 2.0 (the "License");4you may not use this file except in compliance with the License.5You may obtain a copy of the License at6 http://www.apache.org/licenses/LICENSE-2.07Unless required by applicable law or agreed to in writing, software8distributed under the License is distributed on an "AS IS" BASIS,9WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.10See the License for the specific language governing permissions and11limitations under the License.12THIS FILE IS DEPRECATED AND MAY BE REMOVED WITHOUT WARNING!13DO NOT CALL THESE FUNCTIONS IN YOUR CODE!14"""15# Methods for SCS iterative solver.16from cvxpy.lin_ops.tree_mat import mul, tmul, sum_dicts17import numpy as np18def get_mul_funcs(sym_data):19 def accAmul(x, y, is_abs=False):20 # y += A*x21 rows = y.shape[0]22 var_dict = vec_to_dict(x, sym_data.var_offsets,23 sym_data.var_sizes)24 y += constr_mul(sym_data.constraints, var_dict, rows, is_abs)25 def accATmul(x, y, is_abs=False):26 # y += A.T*x27 terms = constr_unpack(sym_data.constraints, x)28 val_dict = constr_tmul(sym_data.constraints, terms, is_abs)29 y += dict_to_vec(val_dict, sym_data.var_offsets,30 sym_data.var_sizes, sym_data.x_length)31 return (accAmul, accATmul)32def constr_unpack(constraints, vector):33 """Unpacks a vector into a list of values for constraints.34 """35 values = []36 offset = 037 for constr in constraints:38 rows, cols = constr.size39 val = np.zeros((rows, cols))40 for col in range(cols):41 val[:, col] = vector[offset:offset+rows]42 offset += rows43 values.append(val)44 return values45def vec_to_dict(vector, var_offsets, var_sizes):46 """Converts a vector to a map of variable id to value.47 Parameters48 ----------49 vector : NumPy matrix50 The vector of values.51 var_offsets : dict52 A map of variable id to offset in the vector.53 var_sizes : dict54 A map of variable id to variable size.55 Returns56 -------57 dict58 A map of variable id to variable value.59 """60 val_dict = {}61 for id_, offset in var_offsets.items():62 size = var_sizes[id_]63 value = np.zeros(size)64 offset = var_offsets[id_]65 for col in range(size[1]):66 value[:, col] = vector[offset:size[0]+offset]67 offset += size[0]68 val_dict[id_] = value69 return val_dict70def dict_to_vec(val_dict, var_offsets, var_sizes, vec_len):71 """Converts a map of variable id to value to a vector.72 Parameters73 ----------74 val_dict : dict75 A map of variable id to value.76 var_offsets : dict77 A map of variable id to offset in the vector.78 var_sizes : dict79 A map of variable id to variable size.80 vector : NumPy matrix81 The vector to store the values in.82 """83 # TODO take in vector.84 vector = np.zeros(vec_len)85 for id_, value in val_dict.items():86 size = var_sizes[id_]87 offset = var_offsets[id_]88 for col in range(size[1]):89 # Handle scalars separately.90 if np.isscalar(value):91 vector[offset:size[0]+offset] = value92 else:93 vector[offset:size[0]+offset] = np.squeeze(value[:, col])94 offset += size[0]95 return vector96def constr_mul(constraints, var_dict, vec_size, is_abs):97 """Multiplies a vector by the matrix implied by the constraints.98 Parameters99 ----------100 constraints : list101 A list of linear constraints.102 var_dict : dict103 A dictionary mapping variable id to value.104 vec_size : int105 The length of the product vector.106 is_abs : bool107 Multiply by the absolute value of the matrix?108 """109 product = np.zeros(vec_size)110 offset = 0111 for constr in constraints:112 result = mul(constr.expr, var_dict, is_abs)113 rows, cols = constr.size114 for col in range(cols):115 # Handle scalars separately.116 if np.isscalar(result):117 product[offset:offset+rows] = result118 else:119 product[offset:offset+rows] = np.squeeze(result[:, col])120 offset += rows121 return product122def constr_tmul(constraints, values, is_abs):123 """Multiplies a vector by the transpose of the constraints matrix.124 Parameters125 ----------126 constraints : list127 A list of linear constraints.128 values : list129 A list of NumPy matrices.130 is_abs : bool131 Multiply by the absolute value of the matrix?132 Returns133 -------134 dict135 A mapping of variable id to value.136 """137 products = []138 for constr, val in zip(constraints, values):139 products.append(tmul(constr.expr, val, is_abs))...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!