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!!
