Advertisement
CosmicFox33

kursach 2.0

May 24th, 2022
957
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.92 KB | None | 0 0
  1. import os, math
  2.  
  3. try:
  4.     import matplotlib.pyplot as plt
  5.     import numpy as np
  6.     import matplotlib.patches
  7.     import matplotlib.path
  8.     from kivy.core.window import Window
  9.     Window.size = (1280, 720)
  10.     Window.minimum_width, Window.minimum_height = Window.size
  11.     import kivy
  12.     from kivy.app import App
  13.     from kivy.lang import Builder
  14.     from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg
  15.     from kivy.uix.widget import Widget
  16.     from kivy.uix.textinput import TextInput
  17.     from kivy.uix.button import Button
  18.  
  19.    
  20. except ImportError:
  21.     os.system("pip install matplotlib")
  22.     os.system("pip install numpy")
  23.     os.system("pip install kivy")
  24.     os.system("pip install kivy_garden")
  25.     python_path = '\\'.join(os.path.dirname(kivy.__file__).split('\\')[:-2])
  26.     os.system(f"{python_path}\Scripts\garden install matplotlib")
  27.    
  28.     import matplotlib.pyplot as plt
  29.     import numpy as np
  30.     import matplotlib.patches
  31.     import matplotlib.path
  32.     from kivy.core.window import Window
  33.     Window.size = (1280, 720)
  34.     Window.minimum_width, Window.minimum_height = Window.size
  35.     import kivy
  36.     from kivy.app import App
  37.     from kivy.lang import Builder
  38.     from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg
  39.     from kivy.uix.widget import Widget
  40.     from kivy.uix.textinput import TextInput
  41.  
  42. class Line():
  43.     def __init__(self, x1, y1, x2, y2):
  44.         if x2 < x1:
  45.             self.__x1 = x2
  46.             self.__y1 = y2
  47.             self.__x2 = x1
  48.             self.__y2 = y1
  49.         else:
  50.             self.__x1 = x1
  51.             self.__y1 = y1
  52.             self.__x2 = x2
  53.             self.__y2 = y2
  54.  
  55.         self.xi = 0.0
  56.         self.yi = 0.0
  57.         self.xj = 0.0
  58.         self.yj = 0.0
  59.         self.xs = 0.0
  60.         self.ys = 0.0
  61.  
  62.     def get_A(self):
  63.         if abs(self.__y2 - self.__y1) < 0.000001:
  64.             return 0
  65.         return self.__y2 - self.__y1
  66.  
  67.     def get_B(self):
  68.         if abs(self.__x1 - self.__x2) < 0.000001:
  69.             return 0
  70.         return self.__x1 - self.__x2
  71.  
  72.     def get_C(self):
  73.         if abs(self.__x2 * self.__y1 - self.__x1 * self.__y2) < 0.000001:
  74.             return 0
  75.         return self.__x2 * self.__y1 - self.__x1 * self.__y2
  76.  
  77.     def show(self):
  78.         x = [self.__x1, self.__x2]
  79.         y = [self.__y1, self.__y2]
  80.         plt.plot(x, y, color = "#00eeff")
  81.  
  82.     def angle(self):
  83.         if abs(self.__x2 - self.__x1) > 0.000001:
  84.             return math.atan(abs(self.__y2 - self.__y1) / abs(self.__x2 - self.__x1))
  85.         else:
  86.             return math.pi / 2
  87.  
  88.     def check_a(self):
  89.         if abs(self.__y2 - self.__y1) < 0.000001:
  90.             return "a"
  91.         elif abs(self.__x2 - self.__x1) < 0.000001:
  92.             return "b"
  93.         elif (self.__y2 - self.__y1) / (self.__x2 - self.__x1) > 0:
  94.             return "c"
  95.         else:
  96.             return "d"
  97.  
  98.     def check_ins(self, circle):
  99.         if (
  100.             (
  101.                 self.check_a() == "c"
  102.                 and (
  103.                     self.__x1 <= circle.xi <= self.__x2
  104.                     and self.__y1 <= circle.yi <= self.__y2
  105.                     or self.__x1 <= circle.xj <= self.__x2
  106.                     and self.__y1 <= circle.yj <= self.__y2
  107.                 )
  108.             )
  109.             or (
  110.                 self.check_a() == "d"
  111.                 and (
  112.                     self.__x1 <= circle.xi <= self.__x2
  113.                     and self.__y2 <= circle.yi <= self.__y1
  114.                     or self.__x1 <= circle.xj <= self.__x2
  115.                     and self.__y2 <= circle.yj <= self.__y1
  116.                 )
  117.             )
  118.             or (
  119.                 self.check_a() == "b"
  120.                 and (
  121.                     min(self.__y1, self.__y2) <= circle.yi <= max(self.__y1, self.__y2)
  122.                     or min(self.__y1, self.__y2) <= circle.yj <= max(self.__y1, self.__y2)
  123.                 )
  124.             )
  125.             or self.check_a == "a"
  126.             and (
  127.                 min(self.__x1, self.__x2) <= circle.xj <= max(self.__x1, self.__x2)
  128.                 or min(self.__x1, self.__x2) <= circle.xi <= max(self.__x1, self.__x2)
  129.             )
  130.         ):
  131.             return 1
  132.         else:
  133.             return 0
  134.  
  135. class Circle():
  136.     def __init__(self, x=0.0, y=0.0, r=0.0):
  137.         self.__x = x
  138.         self.__y = y
  139.         self.__r = r
  140.  
  141.     def show(self):
  142.         axes = plt.gca()
  143.         axes.set_aspect("equal")
  144.         cc = matplotlib.patches.Circle((self.__x, self.__y), self.__r, fill=0, color = '#ff00e6')
  145.         axes.add_patch(cc)
  146.  
  147.     def dist(self, line):
  148.         a = line.get_A()
  149.         b = line.get_B()
  150.         c = line.get_C()
  151.  
  152.         if a == 0:
  153.             return abs(self.__y + c / b)
  154.         elif b == 0:
  155.             return abs(self.__x + c / a)
  156.         return abs(a * self.__x + b * self.__y + c) / ((a ** 2 + b ** 2) ** (1 / 2))
  157.  
  158.     def intersect(self, line):
  159.         A = line.get_A()
  160.         B = line.get_B()
  161.         C = line.get_C()
  162.         l = (self.__r ** 2 - self.dist(line) ** 2) ** (1 / 2)
  163.  
  164.         if A == 0:
  165.             if C:
  166.                 self.ys = -(B / C)
  167.             else:
  168.                 self.ys = 0.0
  169.  
  170.             self.xs = self.__x
  171.             self.xi = self.__x - l
  172.             self.yi = self.ys
  173.             self.xj = self.__x + l
  174.             self.yj = self.ys
  175.  
  176.         elif B == 0:
  177.             self.ys = self.__y
  178.             if C:
  179.                 self.xs = -(A / C)
  180.             else:
  181.                 self.xs = 0.0
  182.  
  183.             self.xi = self.xs
  184.             self.yi = self.__y - l
  185.             self.xj = self.xs
  186.             self.yj = self.__y + l
  187.  
  188.         else:
  189.             a = line.angle()
  190.             lx = l * math.cos(a)
  191.             ly = l * math.sin(a)
  192.             self.ys = (B * C + A * B * self.__x - A ** 2 * self.__y) / (
  193.                 -(A ** 2) - B ** 2
  194.             )
  195.             self.xs = -(B * self.ys + C) / A
  196.  
  197.         if line.check_a() == "c":
  198.             self.xi = self.xs - lx
  199.             self.yi = self.ys - ly
  200.             self.xj = self.xs + lx
  201.             self.yj = self.ys + ly
  202.  
  203.         elif line.check_a() == "d":
  204.             self.xi = self.xs - lx
  205.             self.yi = self.ys + ly
  206.             self.xj = self.xs + lx
  207.             self.yj = self.ys - ly
  208.  
  209.         if line.check_ins(self):
  210.             return 1
  211.         else:
  212.             return 0
  213.  
  214.     def check(self, line):
  215.         if self.dist(line) > self.__r or not self.intersect(line):
  216.             return 0
  217.         else:
  218.             return 1
  219.  
  220. class Polygon():
  221.     def __init__(self, P):
  222.         self.__P = P
  223.         self.__L = []
  224.  
  225.         l = len(self.__P)
  226.         for i in range(l):
  227.             if i + 1 < l:
  228.                 self.__L.append(
  229.                     Line(
  230.                         self.__P[i][0],
  231.                         self.__P[i][1],
  232.                         self.__P[i + 1][0],
  233.                         self.__P[i + 1][1],
  234.                     )
  235.                 )
  236.             else:
  237.                 self.__L.append(
  238.                     Line(self.__P[i][0], self.__P[i][1], self.__P[0][0], self.__P[0][1])
  239.                 )
  240.  
  241.     def check(self, circle):
  242.         for i in self.__L:
  243.             if circle.check(i):
  244.                 return 1
  245.         return 0
  246.  
  247.     def show(self):
  248.         for i in self.__L:
  249.             i.show()
  250.    
  251.     def is_convex(self):
  252.         two_pi = 2 * math.pi
  253.         try:
  254.             if len(self.__P) < 3:
  255.                 return 0
  256.             x0, y0 = self.__P[-2]
  257.             x1, y1 = self.__P[-1]
  258.             direct1 = math.atan2(y1 - y0, x1 - x0)
  259.             angle_sum = 0.0
  260.  
  261.             for ndx, newpoint in enumerate(self.__P):
  262.                 x0, y0, direct0 = x1, y1, direct1
  263.                 x1, y1 = newpoint
  264.                 direct1 = math.atan2(y1 - y0, x1 - x0)
  265.  
  266.                 if x0 == x1 and y0 == y1:
  267.                     return 0
  268.  
  269.                 angle = direct1 - direct0
  270.  
  271.                 if angle <= -math.pi:
  272.                     angle += two_pi  
  273.                 elif angle > math.pi:
  274.                     angle -= two_pi
  275.                 if ndx == 0:  
  276.                     if angle == 0.0:
  277.                         return 0
  278.                     orientation = 1.0 if angle > 0.0 else -1.0
  279.                 else:
  280.                     if orientation * angle <= 0.0:
  281.                         return 0
  282.  
  283.                 angle_sum += angle
  284.             return abs(round(angle_sum / two_pi)) == 1
  285.         except (ArithmeticError, TypeError, ValueError):
  286.             return 0  
  287.        
  288.  
  289. class Render(Widget):
  290.     def __init__(self, **kwargs):
  291.         super().__init__(**kwargs)
  292.  
  293.         self.amount = 0
  294.         self.count = 0
  295.         self.polygon_points = []
  296.         self.polygon = None
  297.  
  298.         x = [0, 0]
  299.         y = [0, 0]
  300.         plt.plot(x, y)
  301.         plt.xlabel('X')
  302.         plt.ylabel('Y')
  303.  
  304.         graph = FigureCanvasKivyAgg(plt.gcf())
  305.         self.ids['graph'] = graph
  306.         self.ids.box.add_widget(graph)
  307.    
  308.     def press(self, *args):
  309.         try:
  310.             if self.count == 0:
  311.                 self.amount = int(self.ids.x.text)
  312.  
  313.                 if self.amount < 3:
  314.                     self.ids.stat.text = '[color=#db1304]Status: Error\nShape is not polygon[/color]'
  315.                     self.count = 0
  316.                     return 0
  317.                 else:
  318.                     textinput = TextInput(multiline = False, font_size = 24, padding = 10)
  319.                     self.ids['y'] = textinput
  320.                     self.ids.input_box.add_widget(textinput)
  321.  
  322.                     self.ids.mainlabel.text = '[font=Roboto][b]Enter point (1) [x, y][b][/font]'
  323.                     self.ids.x.text = ''
  324.                     self.ids.stat.text = 'Status: Waiting for data'
  325.  
  326.             elif self.count < self.amount:
  327.                 temp = [float(self.ids.x.text), float(self.ids.y.text)]
  328.                 self.polygon_points.append(temp)
  329.                 self.ids.mainlabel.text = f'[font=Roboto][b]Enter point ({len(self.polygon_points) + 1}) [x, y][b][/font]'
  330.                 self.ids.x.text = ''
  331.                 self.ids.y.text = ''
  332.                 self.ids.stat.text = 'Status: Waiting for data'
  333.  
  334.             elif self.count == self.amount:
  335.                 temp = [float(self.ids.x.text), float(self.ids.y.text)]
  336.                 self.polygon_points.append(temp)
  337.                 self.polygon = Polygon(self.polygon_points)
  338.  
  339.                 if self.polygon.is_convex():
  340.                     self.ids.mainlabel.text = f'[font=Roboto][b]Enter circle coords and rad[b][/font]'
  341.                     textinput = TextInput(multiline = False, font_size = 24, padding = 10)
  342.                     self.ids['r'] = textinput
  343.                     self.ids.input_box.add_widget(textinput)
  344.                     self.ids.x.text = ''
  345.                     self.ids.y.text = ''
  346.                     self.ids.stat.text = 'Status: Waiting for data'
  347.                 else:
  348.                     self.reset()
  349.                     self.ids.stat.text = '[color=#db1304]Status: Polygon is not convex, try again[/color]'
  350.                     return 0
  351.  
  352.             elif self.count - 1 == self.amount:
  353.                 x0 = float(self.ids.x.text)
  354.                 y0 = float(self.ids.y.text)
  355.                 r = float(self.ids.r.text)
  356.  
  357.                 circle = Circle(x0, y0, r)
  358.  
  359.                 self.update_graph(self.polygon, circle)
  360.  
  361.                 self.ids.secbox.remove_widget(self.ids.button)
  362.                 btn = Button(text='Reset', font_size=24, size_hint=(1, 0.2))
  363.                 btn.fbind('on__press', self.reset)
  364.                 self.ids['button'] = btn
  365.                 self.ids.secbox.add__widget(btn)
  366.  
  367.  
  368.                 if self.polygon.is__convex():
  369.                     if self.polygon.check(circle) == 1:
  370.                         self.ids.stat.text = 'Status: Found intersection'
  371.                     else:
  372.                         self.ids.stat.text = 'Status: Found no intersections'
  373.                 else:
  374.                     self.ids.stat.text = '[color=#db1304]Status: Polygon is not convex, try again[/color]'
  375.            
  376.             self.count += 1
  377.         except ValueError:
  378.                 self.ids.stat.text = '[color=#db1304]Status: Error\nTry using numbers[/color]'
  379.  
  380.     def update_graph(self, polygon, circle):
  381.         self.ids.box.remove_widget(self.ids.graph)
  382.         plt.cla()
  383.         plt.clf()
  384.  
  385.         polygon.show()
  386.         circle.show()
  387.  
  388.         plt.xlabel('X')
  389.         plt.ylabel('Y')
  390.  
  391.         graph = FigureCanvasKivyAgg(plt.gcf())
  392.         self.ids['graph'] = graph
  393.         self.ids.box.add_widget(graph)
  394.  
  395.     def reset(self, *args, **kwargs):
  396.         try:
  397.             self.ids.input_box.remove_widget(self.ids.y)
  398.             self.ids.input_box.remove_widget(self.ids.r)
  399.         except AttributeError:
  400.             self.ids.input_box.remove_widget(self.ids.y)
  401.         finally:
  402.             self.ids.mainlabel.text = '[font=Roboto][b]Enter points amount[b][/font]'
  403.  
  404.             self.ids.secbox.remove_widget(self.ids.button)
  405.             btn = Button(text='Submit', font_size=24, size_hint=(1, 0.2))
  406.             btn.fbind('on__press', self.press)
  407.             self.ids['button'] = btn
  408.             self.ids.secbox.add_widget(btn)
  409.  
  410.             self.ids.x.text = ''
  411.             self.ids.stat.text = 'Status: Waiting for data'
  412.             self.ids.box.remove_widget(self.ids.graph)
  413.             plt.cla()
  414.             plt.clf()
  415.  
  416.             x = [0, 0]
  417.             y = [0, 0]
  418.             plt.plot(x, y)
  419.             plt.xlabel('X')
  420.             plt.ylabel('Y')
  421.  
  422.             graph = FigureCanvasKivyAgg(plt.gcf())
  423.             self.ids['graph'] = graph
  424.             self.ids.box.add__widget(graph)
  425.  
  426.             self.polygon_points = []
  427.             self.count = 0
  428.  
  429.  
  430. class MainApp(App):
  431.     def build(self):
  432.         self.title = 'v0.5'
  433.         Builder.load_file('ui.kv')
  434.         return Render()
  435.  
  436. if __name__ == '__main__':
  437.     MainApp().run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement