| <!DOCTYPE html>
|
| <html>
|
| <head>
|
| <meta charset="utf-8">
|
| <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/brython@3.10.7/brython.min.js">
|
| </script>
|
| <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/brython@3.10.7/brython_stdlib.js">
|
| </script>
|
| <style>
|
| .texty {
|
| font-family:monospace;
|
| font-size:1.5em;
|
| fill:white;
|
| stroke:red;
|
| stroke-width:0.01em;
|
| text-shadow:
|
| #0008 0px 0px 2px,
|
| #0008 0px 0px 2px,
|
| #0008 0px 0px 2px,
|
| #0008 0px 0px 2px,
|
| #0008 0px 0px 2px;
|
| }
|
| body {margin:0; padding: 0;}
|
| </style>
|
| </head>
|
| <body onload="brython(1)">
|
|
|
| <!-- <pre>1: rotate 2: scale 3: move</pre> -->
|
| <svg width="1200px" height="1200px" xmlns="http://www.w3.org/2000/svg" id="svg_root" style="background-color:#222">
|
| <g id="the_texts">THETHINGS</g>
|
| <rect id="BackDrop" fill="none" pointer-events="all"></rect>
|
| <!-- <text id="diagnose" x ="20" y="20"
|
| class="texty">THE SOMETHING</text>
|
| <text id="diagnose1" x ="20" y="40" class="texty">THE SOMETHING</text>
|
| <text id="diagnose2" x ="20" y="60" class="texty">THE SOMETHING</text> -->
|
| <g id="intersections"></g>
|
|
|
| <circle id="center_point" r=5 fill="cyan"></circle>
|
| <circle id="tracking_point" r=5 fill="magenta"></circle>
|
| <circle id="starting_point" r=5 fill="yellow"></circle>
|
| <line id="line1" stroke="red"></line>
|
| <line id="line2" stroke="green"></line>
|
| <!-- <text id="the_texts">THETHINGS</text> -->
|
|
|
| </svg>
|
|
|
| <script type="text/python">
|
| """Much of the drag and drop code is copied from a demo by Doug Schepers
|
| at http://svg-whiz.com/svg/DragAndDrop.svg"""
|
|
|
| from browser import document, svg, alert, bind
|
| from math import sin, cos, radians, asin, acos, pi, sqrt
|
| from itertools import combinations as combs
|
| from itertools import groupby
|
| import math, random
|
|
|
| class Vec2(object):
|
| def __init__(self, x, y):
|
| self._x = float(x)
|
| self._y = float(y)
|
|
|
| @property
|
| def x(self):
|
| return self._x
|
|
|
| @x.setter
|
| def x(self, new_x):
|
| self._x = float(new_x)
|
|
|
| @property
|
| def y(self):
|
| return self._y
|
|
|
| @y.setter
|
| def y(self, new_y):
|
| self._y = float(new_y)
|
|
|
| def __add__(self, other):
|
| types = (int, float)
|
| if isinstance(self, types):
|
| return Vec2(self + other.x, self + other.y)
|
| elif isinstance(other, types):
|
| return Vec2(self.x + other, self.y + other)
|
| else:
|
| return Vec2(self.x + other.x, self.y + other.y)
|
|
|
| def __div__(self, other):
|
| types = (int, float)
|
| if isinstance(self, types):
|
| self = Vec2(self, self)
|
| elif isinstance(other, types):
|
| other = Vec2(other, other)
|
| x = self.x / other.x
|
| y = self.y / other.y
|
| return Vec2(x, y)
|
|
|
| def __mul__(self, other):
|
| types = (int, float)
|
| if isinstance(self, types):
|
| return Vec2(self * other.x, self * other.y)
|
| elif isinstance(other, types):
|
| return Vec2(self.x * other, self.y * other)
|
| else:
|
| return Vec2(self.x * other.x, self.y * other.y)
|
|
|
| def __neg__(self):
|
| return Vec2(-self.x, -self.y)
|
|
|
| def __radd__(self, other):
|
| return Vec2(self.x + other, self.y + other)
|
|
|
| def __rdiv__(self, other):
|
| return Vec2(other/self.x, other/self.y)
|
|
|
| def __rmul__(self, other):
|
| return Vec2(other * self.x, other * self.y)
|
|
|
| def __rsub__(self, other):
|
| return Vec2(other - self.x, other - self.y)
|
|
|
| def __repr__(self):
|
| return self.__str__()
|
|
|
| def __str__(self):
|
| return "Vec2: ({0}, {1})".format(self.x, self.y)
|
|
|
| def __sub__(self, other):
|
| types = (int, float)
|
| if isinstance(self, types):
|
| return Vec2(self - other.x, self - other.y)
|
| elif isinstance(other, types):
|
| return Vec2(self.x - other, self.y - other)
|
| else:
|
| return Vec2(self.x - other.x, self.y - other.y)
|
|
|
| def ceil(self):
|
| return Vec2(math.ceil(self.x), math.ceil(self.y))
|
|
|
| def floor(self):
|
| return Vec2(math.floor(self.x), math.floor(self.y))
|
|
|
| def get_data(self):
|
| return (self.x, self.y)
|
|
|
| def inverse(self):
|
| return Vec2(1.0/self.x, 1.0/self.y)
|
|
|
| def length(self):
|
| return math.sqrt(self.square_length())
|
|
|
| def normalize(self):
|
| length = self.length()
|
| if length == 0.0:
|
| return Vec2(0, 0)
|
| return Vec2(self.x/length, self.y/length)
|
|
|
| def round(self):
|
| return Vec2(round(self.x), round(self.y))
|
|
|
| def square_length(self):
|
| return (self.x * self.x) + (self.y * self.y)
|
|
|
| """
|
| def transform(self, matrix):#mat2, mat2d, mat3, mat4
|
| pass
|
|
|
| @classmethod
|
| def cross(cls, a, b):
|
| z = (a.x * b.y) - (a.y * b.x)
|
| return Vec3(0, 0, z)
|
| """
|
|
|
| @classmethod
|
| def distance(cls, a, b):
|
| c = b - a
|
| return c.length()
|
|
|
| @classmethod
|
| def dot(self, a, b):
|
| return (a.x * b.x) + (a.y * b.y)
|
|
|
| @classmethod
|
| def equals(cls, a, b, tolerance=0.0):
|
| diff = a - b
|
| dx = math.fabs(diff.x)
|
| dy = math.fabs(diff.y)
|
| if dx <= tolerance * max(1, math.fabs(a.x), math.fabs(b.x)) and \
|
| dy <= tolerance * max(1, math.fabs(a.y), math.fabs(b.y)):
|
| return True
|
| return False
|
|
|
| @classmethod
|
| def max(cls, a, b):
|
| x = max(a.x, b.x)
|
| y = max(a.y, b.y)
|
| return Vec2(x, y)
|
|
|
| @classmethod
|
| def min(cls, a, b):
|
| x = min(a.x, b.x)
|
| y = min(a.y, b.y)
|
| return Vec2(x, y)
|
|
|
| @classmethod
|
| def mix(cls, a, b, t):
|
| return a * t + b * (1-t)
|
|
|
| @classmethod
|
| def random(cls):
|
| x = random.random()
|
| y = random.random()
|
| return Vec2(x, y)
|
|
|
| @classmethod
|
| def square_distance(cls, a, b):
|
| c = b - a
|
| return c.square_length()
|
|
|
| vec2 = Vec2
|
| def interp(start, end, coef):
|
| return (end - start)*coef + start
|
|
|
| SVGRoot = document["svg_root"]
|
| the_texts = document["the_texts"]
|
|
|
| # svg_intersections = SVGRoot['intersection_group']
|
| intersection_group = svg.g()
|
| SVGRoot <= intersection_group
|
|
|
| svg_lines = []
|
| svg_points = []
|
| svg_texts = {}
|
|
|
| svg_points_by_id = {}
|
| edge_bimap = {}
|
|
|
| selected_elem = None
|
| selected_node_id = None
|
| offset = None
|
| selected_points = []
|
|
|
| nodes_to_reset = []
|
|
|
| edges_by_pt_global = {}
|
| TrueCoords = SVGRoot.createSVGPoint()
|
| GrabPoint = SVGRoot.createSVGPoint()
|
|
|
| BackDrop = document["BackDrop"]
|
|
|
| last_pos = (20,20)
|
| pos_shift = (0, 20)
|
|
|
| # diagnose
|
| line1 = document["line1"]
|
| line2 = document["line2"]
|
| def add_text(key):
|
| global the_texts
|
| global svg_texts
|
| if key in svg_texts:
|
| return svg_texts[key]
|
| global last_pos
|
| global SVGRoot
|
| (x,y) = last_pos
|
|
|
| svg_texts[key] = svg.text(x=x, y=y)
|
| svg_texts[key].attrs['class'] = 'texty'
|
| svg_texts[key].text = '---'
|
|
|
| y+=pos_shift[1]
|
| last_pos = (x,y)
|
| # SVGRoot <= svg_texts[key]
|
| the_texts <= svg_texts[key]
|
| return svg_texts[key]
|
|
|
| # https://www.petercollingridge.co.uk/tutorials/svg/interactive/dragging/
|
| default_color = '#08f'
|
| itsc_color = '#f008'
|
| color_selected = '#f80'
|
| color_sibling = '#0f0'
|
| cell_radius = 10
|
| itsc_radius = 3
|
|
|
| check_itsc = False
|
| def circlepoint(angle, radius = 1):
|
| angle = 2*pi*angle
|
| # return radius*vec2(cos(angle), sin(angle))
|
| return (radius*cos(angle), radius*sin(angle))
|
| def signed_angle_glm(A, B):
|
| Ax, Ay = A
|
| Bx, By = B
|
|
|
| cross = Ax * By - Ay * Bx
|
| dot = Ax*Bx + Ay*By
|
| lenA = vectlen1(A)
|
| lenB = vectlen1(B)
|
| angle = math.acos(dot/(lenA*lenB))
|
| return angle if cross > 0 else -angle
|
| def vecdiff(A,B):
|
| return B[0] - A[0], B[1] - A[1]
|
| 0
|
| def vectlen(A, Babibabo):
|
| Px = Babibabo[0] - A[0]
|
| Py = Babibabo[1] - A[1]
|
| return math.sqrt(Px*Px + Py*Py)
|
| def vectlen1(v):
|
| return math.sqrt(v[0]*v[0] + v[1]*v[1])
|
|
|
| # WARNING WHEN PASTING SAVE FILE: NO LINE RETURN IS MULTI LINE STRING!
|
| # WARNING WHEN PASTING SAVE FILE: NO LINE RETURN IS MULTI LINE STRING!
|
| def extract_sav():
|
| sav_data = '''SAVEFILE:41:Simon Tatham's Portable Puzzle Collection
|
| VERSION :1:1
|
| GAME :8:Untangle
|
| PARAMS :3:200
|
| CPARAMS :3:200
|
| SEED :15:189466783882172
|
| DESC :2642:0-8,0-54,0-123,1-118,1-120,1-141,1-183,2-25,2-74,2-85,2-103,3-4,3-58,3-111,3-125,4-20,4-42,4-125,5-23,5-129,5-178,5-195,6-30,6-94,6-187,6-189,7-45,7-117,7-121,7-127,8-21,8-94,8-189,9-65,9-113,9-156,9-176,10-41,10-54,10-114,10-163,11-56,11-143,11-161,11-171,12-39,12-128,12-143,12-150,13-62,13-63,13-170,13-194,14-19,14-33,14-49,14-148,15-36,15-67,15-91,15-111,16-20,16-53,16-91,16-120,17-31,17-112,18-28,18-50,18-131,19-95,19-153,20-42,20-53,21-102,21-123,21-189,22-108,22-148,22-182,22-186,23-125,23-166,23-178,24-83,24-167,24-180,25-29,25-72,25-85,26-27,26-145,26-167,26-172,27-98,27-99,27-177,28-45,28-50,28-117,29-68,29-105,29-154,30-93,30-94,30-187,31-71,31-82,31-112,32-116,32-142,32-152,33-49,33-108,34-61,34-110,34-166,35-65,35-90,35-97,35-162,36-91,36-100,36-141,37-46,37-73,37-84,38-48,38-135,38-147,38-149,39-150,39-185,39-199,40-50,40-75,40-131,40-195,41-114,41-127,41-157,42-53,42-168,43-80,43-104,43-109,43-190,44-87,44-119,44-139,44-140,45-50,45-117,46-66,46-84,46-133,47-51,47-57,47-64,47-159,48-72,48-105,48-193,49-77,49-95,51-52,51-57,51-89,52-57,52-89,52-146,53-181,54-114,55-78,55-122,55-140,55-144,56-59,56-86,56-171,57-192,58-66,58-67,58-111,59-86,59-171,60-109,60-158,60-182,60-199,61-81,61-179,62-113,62-174,62-175,63-79,63-132,63-194,64-88,64-159,64-168,65-97,65-173,66-102,66-134,67-100,67-107,68-154,68-193,68-197,69-92,69-128,69-199,70-80,70-104,70-147,71-82,71-135,71-191,72-105,72-191,73-84,73-101,73-133,74-101,74-103,74-154,75-129,75-131,75-195,76-109,76-149,76-182,76-197,77-96,77-108,77-197,78-140,78-161,78-184,79-128,79-132,79-184,80-104,80-190,81-168,81-179,81-192,82-112,82-135,83-106,83-146,83-198,84-133,85-137,85-191,86-152,87-90,87-140,87-188,88-115,88-159,88-181,89-106,89-164,90-119,90-162,91-111,92-151,92-186,92-194,93-101,93-137,93-187,94-189,95-107,96-133,96-154,96-197,97-176,98-165,98-172,98-177,99-124,99-145,99-173,100-107,100-153,101-103,102-134,102-187,103-137,104-147,105-193,106-164,106-198,107-153,108-182,109-149,110-166,110-178,110-179,112-147,113-138,113-176,114-157,115-118,115-181,115-183,116-126,116-142,116-190,117-121,118-120,118-183,119-139,119-162,120-181,121-127,122-144,122-188,123-130,123-163,124-169,124-173,124-177,125-166,126-142,126-158,126-185,127-157,128-143,129-131,129-195,130-136,130-160,130-163,132-139,132-184,134-136,135-191,136-160,138-155,138-174,138-196,141-174,141-196,142-152,143-161,144-171,145-173,145-180,146-198,148-151,148-186,149-193,150-152,150-185,151-170,151-175,153-175,155-156,155-165,155-196,156-165,156-169,158-185,158-190,159-164,160-163,161-184,162-176,164-167,165-169,167-180,168-192,169-177,170-175,170-194,172-183,174-196,179-192,186-199
|
| AUXINFO :4830:e368f1353613f074d0a9c2b6598b16b48ba02654432eebe828afa1e4a75b7b695c41c208565c7e1f1e935e7c52925373dd438d24df2bca01cf30dc17c8018f3e0aa9b01b0c3e93c961a19b61e1a19aba235ce545a4caa68aaee5255769b5c7a57e7b8139ca062ca37b166e6bf03cb3845b09d90f771924ee2f0f91f9f12131501cbcd12663798eaaccf044d2bacbbd7ea53f215eb5ea13ec3d47cf13f26b06497a44357055180f34c433052dc3ef2822b69e7881dd7761370cf237841c5080958ce81dbc0d1cd19910c774b7a5fab3d8e5a21c97d708a4b1bd0c03a53d7d6ae15d674d35450a3efa64847fac1d1b21efe7833c4173835bfb4a425c94fd8cdcf689bf785c09cb6c0fc903e14c2b749fd9244dde8f72eac6ba921ce8c1ec1c0f085f6dd2013c944d55a24c4ece17b264e6e76a73b2c72bae84f259cf02f0961c781c3551e1d08e4ce45615bea6a7f0a53128ef06b4f03fa1774b425975f9136c8c4b999c2718ac8b700203809cfe8bb6a14aab6ed3f9a0209d7e19cce081e04e473df62aaa199f642a4ad293cb75f6d0f0ca50359c5f6d9ff3639d1952eaf6bbd887fc9fc3dc232f5fb5ae2180100f40903ba36c0e7b6e7ddf423e1d5306b259c463a374aeaddaaefa02f3b8f53b6fd414590bcebc75b9df0a7df06dbd730f0332dbb985315528ffa68805b7202a02f20efba6e86904309870610cff9faa3f7329afbe1e1bc8eeb0a4633e7ba2a3ca593e94486f5867d729a8476371a533e7266da2172ba93b3c795d82cdf566d18287dbf94352ccd6fb82078128444779a2ad748e4401388541d608c5d7b49ffa3278dcb990743e79f196a256944f96af7fe20d3756106e4ab9b66c84250628d78af30a0370efca34cc1902e6d11b9ed563c3c79ab391f8cb159f7e1cba184500868747e1d41b7a17f2918f8deed200619a9c958a8e26e5d419bc7dd5148cb5aa0def7203ac25e71b7947a2832fb85498c88acc2f716364940aecfe10e01cc85c6abbb6d681d99dd6d168e166eeadb59892b4c90cabc6adf436a04f41940a49d48997fca25c0cff8ba223b29f295ee51e7419e14d1e125fdfa1054d4dcb49abcdc2cb7bd3d5135c869db4462143b1c43b55f33b03a559d5a5e851ccacfbf88c08d26eedb7e8372e5f8d3b4f6ab8ac6dc663e7deb8d8d0aae9311e02e6791a1b81a470cf785bc4e4cae0b0718be44c54c62edebb7e6c61bd863d130848aab594bc2bfbd99472b22a14b3c6e373113b7581e118c5a0bfa6bd33813b4d919dd723a15cbfe7b97958f27e1461e1223c97a5818a4e3b993dffe5c18bc978569b53b6da1a1c35cbad0c41a0c51d4686148a3c3121f84a37bd7e1f6bd8d167890e6d5ec87e2a01146232f596666954057874f3f4f902a2f6068753b30d68b9a47a3ef293175675b5e34b9e3b99b7502b0ee801c41581a799aeb464d5aaee29bce4baff5c22378d22414fa7bf730089f7accd4b27d8f03d6a3012a6ee7c9a4b3d252776c65fdb1668966bdef00d2c1fdef822d1be512a2c9c3b987af8e9ed2741a5f2e36507c01f881245b36b6cf72fcac99b01b99d463b7f3f5944183eb46352ae09ae0c9db01b26c95abc6265e128f9654a044ae4afc854aac24056c250ef13457848b8d1bf23379e9d655b16485b1998e682ff9baf9d1aadb73c4a2838d9da350fa86edfccc35cd35d576150157f9e14cf0e4e1f7d579586a4bad4d5ebf14dcfaa8573b7e3f58571c7bc41b119123abecbc0cbf7629c4822c58f7f04dc4803143fe3f628a79a3e4e4b985c07eac1e7507c89dbc7feddbe4be6fbe420e74a5138482e9f767f32e3d81065c294fbbf0a3443e353b61a1d64009c4952e2a8ee252dc04b5460762598939a0801801fb12961aa2e29362d9e8091cb2d3d40a50020482a94389f3ea5e76de8685688b69a02dcb338d632bebe3d53800bb22d8fc3ad86db0037b7e60ed4b31a9776907d6eeb16494e2e96fc9f2d37d6bac613ed4db1c969bb902f0b54efdc863a864f5551a6af09c59763a1a01d811369a7f2fcdc96ba0a436c7a89604b4c5a78a09e2dd064b25edddeaf21387d6dbc576139b169a7cf573f1bb7e28d3c2dcd4fc7999b24fc11fde393c9ffcd9ced972cd19385d0debf0b0706a40088c2efac2b78c6023dd166fe00b6dc7f28aba1544faf58a7520d3822ca1b0a69d9b59ba068aa9ceeb4405f3887f1010e2d8a139695e1f77854e3a9e2f4b504880eb5ba5940a39b04d2bcd8181fb3f4164d7837475bc9affbd6fb71603a1a8d7e932dc191921f69b112c30683f74db1c96bceb7a1c47e83385f1a5818a0bde6bc6fd56a1196d83854853952d7c4eee7bc07327b990eeb4aff002acf1b251446e79b9ac92faccdcedcee334526a04fd8342965ebe2e360a58a1ca8154cb477eeda6be683e6057f3e03133eb3bededf45b55d835e590e990f8e15e6dff718ebdb7729ad4b2eafabc333ffe4227a477dccf61eda40ec87b4d8a2b82c8482d97cfb5b37204af961a378583c36d033f36dff42370324aa2bb0329a6707ae266556ce1bdeb44d36330ea7f16427448cb679313022b0b3492ff0b2b0272f74e31eba128bdb9c36a17c0cbede30d6993920413c4f8247f5e8cf6046c75c4f03fd1d340b249d1ed11a6f673a9f7596bb9669738f00a7e97acf615355c60fd42331bb805352a0be44f00704a9c875608300693e675e0ede61c48bea34592c60fffaa67ad3791b67fb1f00e11ecf7610a7e8645c5926f483042b1c08cb0490e30d6cddf37ac1f492b063f4532f3a27c9f2c195eea84ad98378dc7c48a9d262c2bdadc19a2630348d8bab4e4623ac0f2de179783a78cec04a0897bc53b07343bed2e138b27a94d18bab328b9e784b859d6a8e616dd27253e83edaa2a2b42e108fb7e5680e250a9583673ab917bf67a13f83584914354aafc97796c9db57a40da23a41642902ca4034c94a276de305a2962e8bb05dc26d6671816deaebff126711dc9cfc73717708be66cbf2d6f495157ecfb1a4c97c64c09038296515307241309c8c5f663fdd75b693adfbf633a203eec32738c8e6a7a66b080446fb69d5808ea4723d32e53b5a5b2fab52256468f55c569b4d1a7e9dc7f1ac2d939520711387875819360f76a37b4056504147d2ba6f4e664b661fe92b488c6efbba2f1911d07dfb49044083e881a5dbe7a71b44c52b21429ee0b49149307874c75efbc222b8c1acdbd855cb470bdf785a2733492865438a00c78ca94f164e748a04f95606b9f410f4aa6b0ef9631dfa0a403dd966fdb9d0664bacd812a83c6bf77cd886c25d1f0b494512a1730ab5cad6620e91b311cdf251f1fd654ab302ac8eb84f831f6f129e36095574203f2019623c133cbeccb31219d916ad11d9a3b4a5447fb93c7b222ece953b6f
|
| NSTATES :1:2
|
| STATEPOS:1:2
|
| MOVE :14:P12:999,175/64'''
|
|
|
| lines = sav_data.split('\n')
|
|
|
| graph = lines[6].split(':')[-1]
|
| # what = lines[7]
|
| moves = lines[10:]
|
| count = int(lines[3].split(':')[-1])
|
| # print(graph[:50])
|
| # print(what[:50])
|
| # print(moves[:50])
|
| # print(count)
|
| # movements = [a.split(':') for a in moves]
|
| # movements = [(move, a1, p, coord) for (move, a1, p, coord) in movements]
|
| # movements = [(p, coord.split('/')[0].split(',')) for (move, a1, p, coord) in movements]
|
| # movements = [(int(p[1:]), int(coord[0]), int(coord[1])) for (p, coord) in movements]
|
|
|
|
|
| movements = [a.split(':') for a in moves]
|
| movements = [(move, a1, p, coord_slash) for (move, a1, p, coord_slash) in movements]
|
|
|
| movements = [(move, a1, p, coord_slash.split('/')) for (move, a1, p, coord_slash) in movements]
|
|
|
| movements = [(move, a1, p, coord_slashval[0].split(','), coord_slashval[1]) for (move, a1, p, coord_slashval) in movements]
|
|
|
| movements = [
|
| (
|
| int(p[1:]),
|
| # int(int(coord[0])/int(slashval)),
|
| # int(int(coord[1])/int(slashval))
|
| int(coord[0])/int(slashval),
|
| int(coord[1])/int(slashval)
|
| )
|
| for (move, a1, p, coord, slashval) in movements]
|
|
|
| position_by_id = {}
|
| for pid, x, y in movements:
|
| position_by_id[pid] = (x,y)
|
| #
|
| graph1 = [a.split('-') for a in graph.split(',')]
|
| graph1 = [(int(a), int(b)) for a,b in graph1]
|
| # print(graph1)
|
| # import itertools
|
|
|
| # edge_set = {
|
| # grk:[i for i in grl]
|
| # for grk, grl in itertools.groupby(sorted(graph1), lambda a: a[0])
|
| # }
|
|
|
| # duping the edges
|
| edge_set = {(a,b) for a,b in graph1}|{(b, a) for a,b in graph1}
|
| edge_set_li = list(edge_set)
|
|
|
| bimap = {
|
| grk:[i[1] for i in grl]
|
| for grk, grl in
|
| # itertools.groupby(sorted(edge_set_li), lambda a: a[0])
|
| groupby(sorted(edge_set_li), lambda a: a[0])
|
| }
|
|
|
| return graph1, bimap, position_by_id, count
|
|
|
| def game500():
|
| raw = ''
|
| # MOVE :14:P65:579,307/22
|
| movements = [a.split(':') for a in movements.split('\n')]
|
| movements = [(move, a1, p, coord) for (move, a1, p, coord) in movements]
|
| movements = [(p, coord.split('/')[0].split(',')) for (move, a1, p, coord) in movements]
|
| movements = [(int(p[1:]), int(coord[0]), int(coord[1])) for (p, coord) in movements]
|
|
|
| position_by_id = {}
|
| for pid, x, y in movements:
|
| position_by_id[pid] = (x,y)
|
| #
|
| graph1 = [a.split('-') for a in raw.split(',')]
|
| graph1 = [(int(a), int(b)) for a,b in graph1]
|
| # print(graph1)
|
| # import itertools
|
|
|
| # edge_set = {
|
| # grk:[i for i in grl]
|
| # for grk, grl in itertools.groupby(sorted(graph1), lambda a: a[0])
|
| # }
|
|
|
| # duping the edges
|
| edge_set = {(a,b) for a,b in graph1}|{(a, b) for a,b in graph1}
|
| edge_set_li = list(edge_set)
|
|
|
| bimap = {
|
| grk:[i[1] for i in grl]
|
| for grk, grl in
|
| # itertools.groupby(sorted(edge_set_li), lambda a: a[0])
|
| groupby(sorted(edge_set_li), lambda a: a[0])
|
| }
|
|
|
| return graph1, bimap, position_by_id
|
|
|
| def rotate_point(point, angle, center_point=(0, 0)):
|
| """Rotates a point around center_point(origin by default)
|
| Angle is in degrees.
|
| Rotation is counter-clockwise
|
| """
|
| angle_rad = radians(angle % 360)
|
| # Shift the point so that center_point becomes the origin
|
| new_point = (point[0] - center_point[0], point[1] - center_point[1])
|
| new_point = (new_point[0] * cos(angle_rad) - new_point[1] * sin(angle_rad),
|
| new_point[0] * sin(angle_rad) + new_point[1] * cos(angle_rad))
|
| # Reverse the shifting we have done
|
| new_point = (new_point[0] + center_point[0], new_point[1] + center_point[1])
|
| return new_point
|
| def rotate(point,center_point,theta): #rotate x,y around xo,yo by theta (rad)
|
| x,y = point
|
| xo, yo = center_point
|
| xr=math.cos(theta)*(x-xo)-math.sin(theta)*(y-yo) + xo
|
| yr=math.sin(theta)*(x-xo)+math.cos(theta)*(y-yo) + yo
|
| return (xr,yr)
|
| def rotate_items(angle, selected_points, center_point):
|
| # unused
|
| for pt in selected_points:
|
| (x, y) = (
|
| float(pt.getAttributeNS(None, 'cx')),
|
| float(pt.getAttributeNS(None, 'cy')))
|
| # (new_x, new_y) = rotate_point((x,y), angle, center_point)
|
| (new_x, new_y) = rotate((x,y), center_point, angle)
|
|
|
| pt.setAttributeNS(None, 'cx', new_x)
|
| pt.setAttributeNS(None, 'cy', new_y)
|
| def rotate_items_mutate(angle, selected_points, previous_pos, center_point):
|
| point_dict = {}
|
| for pt in selected_points:
|
| ident = pt.attrs['id']
|
| prev_pos = previous_pos[ident]
|
|
|
| (new_x, new_y) = rotate(prev_pos, center_point, angle)
|
|
|
| pt.setAttributeNS(None, 'cx', new_x)
|
| pt.setAttributeNS(None, 'cy', new_y)
|
| set_line_coord(pt, new_x, new_y)
|
| def scale_items(scale, selected_points, previous_pos, center_point):
|
| for pt in selected_points:
|
| ident = pt.attrs['id']
|
| prev_pos = previous_pos[ident]
|
| (xdiff, ydiff) = vecdiff(prev_pos, center_point)
|
| # add_text("vecdiff").text = (xdiff, ydiff)
|
| (new_x, new_y) = (
|
| center_point[0]-xdiff * scale,
|
| center_point[1]-ydiff * scale
|
| )
|
|
|
| pt.setAttributeNS(None, 'cx', new_x)
|
| pt.setAttributeNS(None, 'cy', new_y)
|
| set_line_coord(pt, new_x, new_y)
|
| # (x, y) = (
|
| # float(pt.getAttributeNS(None, 'cx')),
|
| # float(pt.getAttributeNS(None, 'cy')))
|
| def GetTrueCoords(evt):
|
| # find the current zoom level and pan setting, and adjust the reported
|
| # mouse position accordingly
|
| newScale = SVGRoot.currentScale
|
| translation = SVGRoot.currentTranslate
|
| x = (evt.clientX - translation.x) / newScale
|
| y = (evt.clientY - translation.y) / newScale
|
| return x,y
|
| def GetRelative(evt):
|
| # find the current zoom level and pan setting, and adjust the reported
|
| # mouse position accordingly
|
| newScale = SVGRoot.currentScale
|
| translation = SVGRoot.currentTranslate
|
| x = (evt.movementX) / newScale
|
| y = (evt.movementY) / newScale
|
| return x,y
|
|
|
| # selection and movement/scaling
|
| class mouse_selector:
|
| # verts = sf.VertexArray(sf.PrimitiveType.LINES)
|
| rect = svg.rect(fill="#0000", stroke="white",stroke_width="2", id='selectador')
|
| dragging = False
|
| startx, starty = 0,0
|
| callback = None
|
| def __init__(self, svgroot):
|
| svgroot <= self.rect
|
|
|
| def rectminmax(self, x,y):
|
| diffx = x-self.startx
|
| diffy = y-self.starty
|
|
|
|
|
| if diffx <=0:
|
| width = -diffx
|
| rectx = x
|
| else:
|
| width = diffx
|
| rectx = self.startx
|
|
|
| if diffy <=0:
|
| height = -diffy
|
| recty = y
|
| else:
|
| height = diffy
|
| recty = self.starty
|
| # print(rectx, recty, width, height)
|
| return (rectx, recty, width, height)
|
|
|
| def mouse_moved(self, pos):
|
| if self.dragging:
|
|
|
| x,y = pos
|
| (rectx, recty, width, height) = self.rectminmax(x,y)
|
|
|
| # self.rect.setAttributeNS(None, 'width', x-self.startx)
|
| # self.rect.setAttributeNS(None, 'height', y-self.starty)
|
|
|
| self.rect.setAttributeNS(None, 'x', rectx)
|
| self.rect.setAttributeNS(None, 'y', recty)
|
| self.rect.setAttributeNS(None, 'width', width)
|
| self.rect.setAttributeNS(None, 'height', height)
|
|
|
|
|
| def mouse_push(self, pos):
|
| self.dragging = True
|
| # print('mouse_push', pos)
|
| x,y = pos
|
| self.rect.setAttributeNS(None, 'x', x)
|
| self.rect.setAttributeNS(None, 'y', y)
|
| self.rect.setAttributeNS(None, 'width', 0)
|
| self.rect.setAttributeNS(None, 'height', 0)
|
|
|
| self.rect.setAttributeNS(None, 'visibility', 'visible')
|
| self.startx = x
|
| self.starty = y
|
| def mouse_release(self, pos):
|
| if self.callback != None:
|
| x,y = pos
|
| (rectx, recty, width, height) = self.rectminmax(x,y)
|
|
|
|
|
|
|
| # self.callback((self.startx, self.starty),pos)
|
| self.callback((rectx, recty),(rectx+width, recty+height))
|
| self.dragging = False
|
| self.rect.setAttributeNS(None, 'visibility', 'hidden')
|
|
|
| class transformer:
|
| '''we use prev_point because there are no transforms available'''
|
| enabled = False
|
| started = False
|
|
|
| starting_point = None
|
| center_point = None
|
| tracking_point = None
|
|
|
| previous_pos = {}
|
|
|
| axe1 = None
|
| which = 0
|
| # def __init__():
|
| # pass
|
| def start(self, which, points):
|
| # called by keyboard
|
| # print('points', len(points))
|
| # we always pick the average point
|
| avg = ( (sum([float(pt.getAttributeNS(None, 'cx')) for pt in points]),
|
| sum([float(pt.getAttributeNS(None, 'cy')) for pt in points])))
|
|
|
| avg_x, avg_y = avg
|
| self.center_point = (avg_x/len(points), avg_y/len(points))
|
| self.which = which
|
| self.enabled = True
|
| add_text("which").text = self.which
|
|
|
| self.previous_pos = {}
|
| for pt in points:
|
| pos = (float(pt.getAttributeNS(None, 'cx')),
|
| float(pt.getAttributeNS(None, 'cy')))
|
| ident = pt.attrs['id']
|
| self.previous_pos[ident] = pos
|
|
|
| center_point_svg = document['center_point']
|
| center_point_svg.setAttributeNS(None, 'cx', self.center_point[0])
|
| center_point_svg.setAttributeNS(None, 'cy', self.center_point[1])
|
|
|
| print('enabled transformer, which =', self.which)
|
| def stop(self):
|
| self.which = 0
|
| add_text("which").text = self.which
|
| self.started = False
|
| self.enabled = False
|
| self.tracking_point = False
|
| self.starting_point = False
|
| print('disabled transformer, which =', self.which)
|
| # def transform(self, new_point):
|
| def transform(self, translation, where):
|
| global selected_points
|
| global diagnose
|
|
|
| # diagnose
|
| if self.started == False:
|
| self.starting_point = where
|
| self.tracking_point = where
|
| self.started = True
|
| # starting_point_svg = document['starting_point']
|
| # starting_point_svg.setAttributeNS(None, 'cx', self.starting_point[0])
|
| # starting_point_svg.setAttributeNS(None, 'cy', self.starting_point[1])
|
|
|
| tpx, tpy = self.tracking_point
|
| tpx += translation[0]
|
| tpy += translation[1]
|
| self.tracking_point = (tpx, tpy)
|
|
|
| tracking_point_svg = document['tracking_point']
|
| tracking_point_svg.setAttributeNS(None, 'cx', self.tracking_point[0])
|
| tracking_point_svg.setAttributeNS(None, 'cy', self.tracking_point[1])
|
|
|
| if self.tracking_point == self.starting_point:
|
| print('self.tracking_point == self.starting_point:')
|
| return
|
| if False:
|
| # for diagnose
|
| line1.setAttributeNS(None, 'x1', self.center_point[0])
|
| line1.setAttributeNS(None, 'y1', self.center_point[1])
|
| line1.setAttributeNS(None, 'x2', self.starting_point[0])
|
| line1.setAttributeNS(None, 'y2', self.starting_point[1])
|
|
|
| line2.setAttributeNS(None, 'x1', self.center_point[0])
|
| line2.setAttributeNS(None, 'y1', self.center_point[1])
|
| line2.setAttributeNS(None, 'x2', self.tracking_point[0])
|
| line2.setAttributeNS(None, 'y2', self.tracking_point[1])
|
| self.axe1 = vecdiff(self.starting_point, self.center_point)
|
| axe2 = vecdiff(self.tracking_point, self.center_point)
|
|
|
| dist_ratio = vectlen1(axe2)/vectlen1(self.axe1)
|
| if self.which == 1: # rotatate
|
| angle_rad = signed_angle_glm(self.axe1, axe2)
|
| # angle_rad =(math.pi*angle_deg/180.)
|
| angle_deg =(180.*angle_rad/math.pi)
|
|
|
| rotate_items_mutate(
|
| angle_rad, selected_points, self.previous_pos, self.center_point)
|
| diagnose.text = f'angle_rad {angle_rad:.2f} angle_deg {angle_deg:.2f}'
|
|
|
| elif self.which == 2: # scale
|
| starting_len = vectlen(self.center_point, self.starting_point)
|
| tracking_len = vectlen(self.center_point, self.tracking_point)
|
| scale_items(tracking_len / starting_len, selected_points, self.previous_pos, self.center_point)
|
| elif self.which == 3: # move
|
| (diff_x, diff_y) = vecdiff(self.starting_point,self.tracking_point)
|
| for pt in selected_points:
|
| ident = pt.attrs['id']
|
| (x,y) = self.previous_pos[ident]
|
| (new_x, new_y) = (x+diff_x, y+diff_y)
|
| pt.setAttributeNS(None, 'cx', new_x)
|
| pt.setAttributeNS(None, 'cy', new_y)
|
| set_line_coord(pt, new_x, new_y)
|
| self.prev_point = self.tracking_point
|
|
|
| mselector = None
|
| transform = None
|
|
|
| # events
|
| def start_drag(evt):
|
| global selected_elem
|
| global offset
|
| global svg_texts
|
| global mselector
|
| if (evt.target == BackDrop
|
| or evt.target.tagName != 'circle'
|
| or 'id' not in evt.target.attrs):
|
|
|
| mselector.mouse_push(GetTrueCoords(evt))
|
| evt.preventDefault()
|
|
|
| else:
|
| selected_elem = evt.target
|
| node_id = selected_elem.attrs['id']
|
| highlight_start(int(node_id))
|
|
|
| m_x, m_y = GetTrueCoords(evt)
|
| cx = float(selected_elem.getAttributeNS(None, 'cx'))
|
| cy = float(selected_elem.getAttributeNS(None, 'cy'))
|
| offset = (cx-m_x, cy-m_y)
|
| evt.preventDefault()
|
| # add_text("selected_elem").text = selected_elem
|
| def end_drag(evt):
|
| global selected_elem
|
| global mselector
|
|
|
| if selected_elem:
|
| selected_elem = None
|
| else:
|
| mselector.mouse_release(GetTrueCoords(evt))
|
| highlight_stop()
|
|
|
| chech_itsc_idx()
|
| def drag2(evt):
|
| global offset
|
| global mselector
|
| global selected_elem
|
| if selected_elem:
|
| evt.preventDefault()
|
| (x,y) = GetTrueCoords(evt)
|
| x_off, y_off = offset
|
| # we transform several points
|
|
|
| if transform.enabled:
|
| # transform.transform((x+x_off,y+y_off))
|
| transform.transform(GetRelative(evt), (x,y))
|
| # transform.transform(offset)
|
| diagnose2.text = f' offset {offset} x {x} y {y}'
|
| else:
|
| selected_elem.setAttributeNS(None, 'cx', x+x_off)
|
| selected_elem.setAttributeNS(None, 'cy', y+y_off)
|
| set_line_coord(selected_elem, x+x_off,y+y_off)
|
| else:
|
| mselector.mouse_moved(GetTrueCoords(evt))
|
|
|
| def highlight_start(node_id):
|
| global edge_bimap
|
| global nodes_to_reset
|
| global selected_node_id
|
| node_id = int(node_id)
|
| for n in nodes_to_reset:
|
| svg_points_by_id[n].setAttributeNS(None, 'fill', default_color)
|
| # print('highlight_start resetting', n)
|
| nodes_to_reset = []
|
| # print('highlight_start', node_id)
|
| if node_id in edge_bimap:
|
| selected_node_id = node_id
|
| add_text('edge_bimap[node_id]').text = edge_bimap[node_id]
|
| svg_points_by_id[node_id].setAttributeNS(None, 'fill', color_selected)
|
| # print(edge_bimap[node_id])
|
| for node_id_friend in edge_bimap[node_id]:
|
| if node_id_friend in svg_points_by_id:
|
| # svg_points_by_id[node_id].fill = color_selected
|
| svg_points_by_id[node_id_friend].setAttributeNS(None, 'fill', color_sibling)
|
| # nodes_to_reset.append(node_id)
|
| nodes_to_reset.append(node_id_friend)
|
| # print('highlight_start sibling', node_id_friend)
|
| # print(nodes_to_reset)
|
| def highlight_stop():
|
| # print('highlight_stop')
|
| global selected_node_id
|
| global nodes_to_reset
|
| if selected_node_id:
|
| node_id = int(selected_node_id)
|
| if node_id in svg_points_by_id:
|
| svg_points_by_id[node_id].setAttributeNS(None, 'fill', default_color)
|
|
|
| for n in nodes_to_reset:
|
| # print('highlight_stop resetting', n)
|
| svg_points_by_id[n].setAttributeNS(None, 'fill', default_color)
|
| nodes_to_reset = []
|
|
|
| # adjusts line coords
|
| def set_line_coord(target_pt, new_x, new_y):
|
| global edges_by_pt_global
|
| global svg_lines
|
|
|
| # line_id = int(target_pt.attrs['class'])
|
| # print(target_pt.attrs)
|
| if 'id' not in target_pt.attrs:
|
| return
|
| point_id = int(target_pt.attrs['id'])
|
|
|
| line_ids = edges_by_pt_global[point_id]
|
| for line_id in line_ids:
|
|
|
| if 'id' not in svg_lines[line_id].attrs:
|
| continue
|
| a,b = svg_lines[line_id].attrs['id'].split('-')
|
| a,b = int(a), int(b)
|
| # print(f'pt_id {point_id} a {a} b {b}')
|
| svg_line = svg_lines[line_id]
|
|
|
|
|
| if a == point_id:
|
| x1,y1,x2,y2 = (
|
| float(svg_line.getAttributeNS(None, "x1")),
|
| float(svg_line.getAttributeNS(None, "y1")),
|
| float(svg_line.getAttributeNS(None, "x2")),
|
| float(svg_line.getAttributeNS(None, "y2")))
|
| # new_x,new_y, x2, y2 = shorten(x1,y1,x2,y2)
|
| # new_x,new_y, x2, y2 = shorten(new_x,new_y,x2,y2)
|
| # new_x,new_y, x2, y2 = shorten(x1,y1,new_x,new_y)
|
| svg_line.setAttributeNS(None, "x1", f"{new_x}")
|
| svg_line.setAttributeNS(None, "y1", f"{new_y}")
|
| elif b == point_id:
|
| x1,y1,x2,y2 = (
|
| float(svg_line.getAttributeNS(None, "x1")),
|
| float(svg_line.getAttributeNS(None, "y1")),
|
| float(svg_line.getAttributeNS(None, "x2")),
|
| float(svg_line.getAttributeNS(None, "y2")))
|
| # x1, y1, new_x,new_y = shorten(x1,y1,x2,y2)
|
| # x1, y1, new_x,new_y = shorten(x1,y1,new_x,new_y)
|
| # x1, y1, new_x,new_y = shorten(new_x,new_y,x2,y2)
|
| svg_line.setAttributeNS(None, "x2", f"{new_x}")
|
| svg_line.setAttributeNS(None, "y2", f"{new_y}")
|
|
|
| # a,b = cl.split('-')
|
| def shorten(Ax, Ay, Bx, By):
|
| diff = (Ax-Bx, Ay-By)
|
| (diff_x, diff_y) = diff
|
| length = math.sqrt(diff_x*diff_x+diff_y*diff_y)
|
| nm_x, nm_y = (10*diff_x/length, 10*diff_y/length)
|
|
|
| Ax -= nm_x
|
| Ay -= nm_y
|
| Bx += nm_x
|
| By += nm_y
|
|
|
| return (Ax, Ay, Bx, By)
|
|
|
| # itsc
|
| def intersects(Ax, Ay, Bx, By, Cx, Cy, Dx, Dy):
|
| # s1, s2 = vec2(), vec2()
|
| # s1 = p1 - p0
|
| # s2 = p3 - p2
|
| s1x = Bx - Ax
|
| s1y = By - Ay
|
| s2x = Dx - Cx
|
| s2y = Dy - Cy
|
|
|
| det = (-s2x * s1y + s1x * s2y)
|
|
|
| if det == 0:
|
| return False, None
|
|
|
| # s = (-s1.y * (p0.x - p2.x) + s1.x * (p0.y - p2.y)) / det;
|
| s = (-s1y * (Ax - Cx) + s1x * (Ay - Cy)) / det;
|
|
|
| # t = (s2.x * (p0.y - p2.y) - s2.y * (p0.x - p2.x)) / det;
|
| t = (s2x * (Ay - Cy) - s2y * (Ax - Cx)) / det;
|
| # i = vec2()
|
| if s >= 0 and s <= 1 and t >= 0 and t <= 1:
|
| # i = vec2(p0.x + (t * s1.x), p0.y + (t * s1.y))
|
| i = (Ax + (t * s1x), Ay + (t * s1y))
|
| return True, i
|
| return False, None
|
| def chech_itsc_idx():
|
| global check_itsc
|
| if not check_itsc:
|
| return
|
| print('chech_itsc_idx')
|
| global intersection_group
|
| global svg_lines
|
| global svg_root
|
| collis_pt_found = []
|
| # print(edge_set)
|
| count = 0
|
| for lineA, lineB in combs(svg_lines,2):
|
| print(count)
|
| if count > 1: break
|
| lineA_x1 = float(lineA.getAttributeNS(None, 'x1'))
|
| lineA_y1 = float(lineA.getAttributeNS(None, 'y1'))
|
| lineA_x2 = float(lineA.getAttributeNS(None, 'x2'))
|
| lineA_y2 = float(lineA.getAttributeNS(None, 'y2'))
|
|
|
| lineB_x1 = float(lineB.getAttributeNS(None, 'x1'))
|
| lineB_y1 = float(lineB.getAttributeNS(None, 'y1'))
|
| lineB_x2 = float(lineB.getAttributeNS(None, 'x2'))
|
| lineB_y2 = float(lineB.getAttributeNS(None, 'y2'))
|
|
|
| does_itsc, itsc_pt = intersects(
|
| lineA_x1, lineA_y1,
|
| lineA_x2, lineA_y2,
|
| lineB_x1, lineB_y1,
|
| lineB_x2, lineB_y2)
|
|
|
|
|
|
|
| if (does_itsc == True
|
| and vectlen((lineA_x1, lineA_y1), itsc_pt) > 1.
|
| and vectlen((lineA_x2, lineA_y2),itsc_pt) > 1.):
|
| found_col = True
|
| collis_pt_found.append(itsc_pt)
|
| count +=1
|
| if not count:
|
| add_text("you won").text = "you won, you little squirel"
|
| # intersection_group.children = ''
|
| rm_this = [i for i in range(len(intersection_group.childNodes))]
|
| for i in rm_this: intersection_group.remove(i)
|
| intersection_group = svg.g()
|
| # print(collis_pt_found)
|
| for it_x, it_y in collis_pt_found:
|
| # it_x, it_y = GetTrueCoords_xy(it_x, it_y)
|
| intersection_group <= svg.circle(
|
| cx=it_x, cy=it_y, r=itsc_radius, fill=itsc_color)
|
| SVGRoot <= intersection_group
|
| print('chech_itsc_idx end')
|
|
|
| def make_svg_circles(points_vec2):
|
| global svg_points_by_id
|
| points = []
|
| for i,(x1,y1) in enumerate(points_vec2):
|
| circ = svg.circle(
|
| cx=x1, cy=y1,
|
| r=cell_radius,
|
| fill=default_color,
|
| # stroke_width = 0.5,
|
| stroke_width = 1.5,
|
| stroke = '#fff',
|
|
|
| )
|
| circ.attrs['id'] = str(i)
|
| points.append(circ)
|
| svg_points_by_id[i] = circ
|
| return points
|
| def make_svg_edges(points_vec2, edge_set):
|
| global edges_by_pt_global
|
| lines = []
|
| for line_id, (a, b) in enumerate(edge_set):
|
| x1, y1 = points_vec2[a]
|
| x2, y2 = points_vec2[b]
|
|
|
| # x1, y1, x2, y2 = shorten(x1, y1, x2, y2)
|
| line = svg.line(
|
| x1=str(x1), y1=str(y1),
|
| x2=str(x2), y2=str(y2),
|
| stroke = "white",
|
| stroke_width = "0.5")
|
| line.attrs['id'] = f'{a}-{b}'
|
| if a not in edges_by_pt_global: edges_by_pt_global[a] = []
|
| if b not in edges_by_pt_global: edges_by_pt_global[b] = []
|
| edges_by_pt_global[a].append(line_id)
|
| edges_by_pt_global[b].append(line_id)
|
| lines.append(line)
|
| return lines
|
| def selectorationer(start,stop):
|
| global svg_points
|
| global color_selected
|
| global default_color
|
| startx, starty = start
|
| stopx, stopy = stop
|
| global selected_points
|
| selected_points = []
|
| print('selectorationer', len(selected_points))
|
| print('selectorationer', len(svg_points))
|
|
|
| for pt in svg_points:
|
| pt.setAttributeNS(None, 'fill', default_color)
|
|
|
| for point in svg_points:
|
| x = float(point.getAttributeNS(None, 'cx'))
|
| y = float(point.getAttributeNS(None, 'cy'))
|
| if (startx < x < stopx
|
| and starty < y < stopy):
|
| selected_points.append(point)
|
| point.setAttributeNS(None, 'fill', color_selected)
|
|
|
| i = point.getAttributeNS(None, 'id')
|
| # print(f' x {startx} < {x} < {stopx} {startx < x < stopx} {i}')
|
| # print(f' y {starty} < {y} < {stopy} {starty < y < stopy} {i}')
|
|
|
| # print('svg_points', len(svg_points))
|
| # print('selected_points', len(selected_points))
|
| for pt in selected_points:
|
| pt.setAttributeNS(None, 'fill', color_selected)
|
| # print(pt)
|
| def init():
|
| # import sys
|
| print('initing')
|
| global svg_lines
|
| global svg_points
|
| global svg_texts
|
| global mselector
|
| global transform
|
| global selected_elem
|
| global offset
|
| global selected_points
|
| global edges_by_pt_global
|
| global edge_bimap
|
| svg_lines = []
|
| svg_points = []
|
| svg_texts = {}
|
|
|
| selected_elem = None
|
| offset = None
|
| selected_points = []
|
|
|
| edges_by_pt_global = {}
|
| # TrueCoords = SVGRoot.createSVGPoint()
|
| # GrabPoint = SVGRoot.createSVGPoint()
|
|
|
| mselector = mouse_selector(SVGRoot)
|
| mselector.callback = selectorationer
|
| transform = transformer()
|
| random.seed(3412212)
|
|
|
| # graph, edge_set = THE_GAMES()[8]
|
| # edge_set, bimap, position_by_id = game500()
|
| edge_set, bimap, position_by_id, count = extract_sav()
|
| # edge_set, bimap, position_by_id, count = game700()
|
|
|
| print(len([1 for k,v in bimap.items() if len(v)<3]))
|
|
|
| def centered_point(angle, radius = 400, origin = (400,600)):
|
| pt = circlepoint(angle, radius)
|
| x,y = pt
|
| orx, ory = origin
|
| return (x+orx, y+ory)
|
| edge_bimap = bimap
|
|
|
| print(edge_bimap)
|
| many = max([max(tup) for tup in edge_set])+1
|
| if position_by_id:
|
| sqrt_thing = math.sqrt(count)
|
| # print(position_by_id)
|
| # return
|
| points_vec2 = [
|
| # position_by_id[i] if i in position_by_id
|
| (
|
| position_by_id[i][0]*20,
|
| position_by_id[i][1]*20
|
| )
|
| if i in position_by_id
|
| # else centered_point(i/count)
|
| else (
|
| interp(100, 1000, (i%sqrt_thing)/sqrt_thing),
|
| interp(100, 1000, (i//sqrt_thing)/sqrt_thing)
|
| )
|
| for i in range(count)
|
| ]
|
| else:
|
| sqrt_thing = math.sqrt(count)
|
| points_vec2 = [
|
| (
|
| interp(100, 1000, (i%sqrt_thing)/sqrt_thing),
|
| interp(100, 1000, (i//sqrt_thing)/sqrt_thing)
|
| )
|
|
|
| for i in range(many)]
|
|
|
|
|
|
|
| svg_lines = make_svg_edges(points_vec2, edge_set)
|
| svg_points = make_svg_circles(points_vec2)
|
|
|
| for p in svg_lines:
|
| SVGRoot <= p
|
| for p in svg_points:
|
| SVGRoot <= p
|
| chech_itsc_idx()
|
| print('finished initing')
|
|
|
| @bind(document, "keydown")
|
| def key_pushed(evt):
|
| global transforn
|
| global selected_points
|
| print(evt.key, evt.code)
|
| if evt.key in ['1', '2', '3']:
|
| if transform.enabled:
|
| transform.stop()
|
| elif selected_points:
|
| transform.start(int(evt.key), selected_points)
|
| elif evt.key == 'q':
|
| init()
|
| # SVGRoot.bind('keydown', key_pushed)
|
|
|
| extract_sav()
|
|
|
| # exit()
|
| init()
|
|
|
| SVGRoot.bind('mousemove', drag2)
|
| SVGRoot.bind("mousedown", start_drag)
|
| SVGRoot.bind("mouseup", end_drag)
|
|
|
| </script>
|
|
|
| </body>
|
|
|
| </html>
|