diff -r 88cfb916c852 -r f3791dccfd03 geometry.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/geometry.py Sat Jun 10 16:45:41 2017 +0300 @@ -0,0 +1,121 @@ +from math import sqrt, hypot, radians, sin, cos, atan2 + +class Sijainti: + def __init__(self, leveys, pituus): + self.leveys, self.pituus = leveys, pituus + def etäisyys(tämä, toinen): + # https://stackoverflow.com/a/365853 + a = sin(radians(tämä.leveys - toinen.leveys) / 2) ** 2 + a += sin(radians(tämä.pituus - toinen.pituus) / 2) ** 2 * cos(radians(tämä.leveys)) * cos(radians(toinen.leveys)) + return 6371 * 2 * atan2(sqrt(a), sqrt(1 - a)) + def __repr__(self): + return '%s(%r, %r)' % (type(self).__name__, self.leveys, self.pituus) + def __str__(self): + return '%.5f, %.5f' % (self.leveys, self.pituus) + @property + def x(self): + return self.leveys + @property + def y(self): + return self.pituus + +class Rengas: + def __init__(tämä, säiliö): + tämä.säiliö = säiliö + def __getitem__(tämä, indeksi): + while indeksi < 0: + indeksi += len(tämä.säiliö) + while indeksi >= len(tämä.säiliö): + indeksi -= len(tämä.säiliö) + return tämä.säiliö[indeksi] + def __iter__(tämä): + return iter(tämä.säiliö) + def __len__(tämä): + return len(tämä.säiliö) + +class Monikulmio: + def __init__(self, *pisteet): + self.pisteet = pisteet + def __repr__(self): + return '%s(%s)' % (type(self).__name__, ', '.join(map(repr, self.pisteet))) + def pinta_ala(self): + rengas = Rengas(self.pisteet) + return sum( + rengas[i].x * rengas[i + 1].y - rengas[i + 1].x * rengas[i].y + for i in range(len(rengas)) + ) / 2 + def piiri(self): + rengas = Rengas(self.pisteet) + return sum( + sqrt((rengas[i + 1].x - rengas[i].x)**2 + (rengas[i + 1].y - rengas[i].y)**2) + for i in range(len(rengas)) + ) + def painopiste(self): + rengas = Rengas(self.pisteet) + x = sum( + (rengas[i].x + rengas[i + 1].x) * (rengas[i].x * rengas[i + 1].y - rengas[i + 1].x * rengas[i].y) + for i in range(len(rengas)) + ) / 6 / self.pinta_ala() + y = sum( + (rengas[i].y + rengas[i + 1].y) * (rengas[i].x * rengas[i + 1].y - rengas[i + 1].x * rengas[i].y) + for i in range(len(rengas)) + ) / 6 / self.pinta_ala() + return self.pistetyyppi()(x, y) + def pistetyyppi(self): + if len(self.pisteet): + return type(self.pisteet[0]) + else: + return Piste + def piiri_janat(self): + rengas = Rengas(self.pisteet) + for i in range(len(rengas)): + yield Jana(rengas[i], rengas[i + 1]) + def sisältää_pisteen(self, piste): + ulkopiste = self.pistetyyppi()( + min(piste.x for piste in self.pisteet) - 1, + min(piste.y for piste in self.pisteet) - 1 + ) + ulkojana = Jana(piste, ulkopiste) + leikkauksia = 0 + for jana in self.piiri_janat(): + if jana.leikkauspiste(ulkojana) is not None: + leikkauksia += 1 + return bool(leikkauksia & 1) + +class Jana: + def __init__(self, alkupiste, päätepiste): + self.alkupiste, self.päätepiste = alkupiste, päätepiste + def __repr__(self): + return 'Jana(%r, %r)' % (self.alkupiste, self.päätepiste) + def pituus(self): + return hypot(self.alkupiste.x - self.päätepiste.x, self.alkupiste.y - self.päätepiste.y) + def leikkauspiste(tämä, toinen): + pistetyyppi = type(tämä.alkupiste) + x = (tämä.alkupiste.x, tämä.päätepiste.x, toinen.alkupiste.x, toinen.päätepiste.x) + y = (tämä.alkupiste.y, tämä.päätepiste.y, toinen.alkupiste.y, toinen.päätepiste.y) + try: + jakaja = (x[0] - x[1]) * (y[2] - y[3]) - (y[0] - y[1]) * (x[2] - x[3]) + Px = ((x[0] * y[1] - y[0] * x[1]) * (x[2] - x[3]) - (x[0] - x[1]) * (x[2] * y[3] - y[2] * x[3])) / jakaja + Py = ((x[0] * y[1] - y[0] * x[1]) * (y[2] - y[3]) - (y[0] - y[1]) * (x[2] * y[3] - y[2] * x[3])) / jakaja + etäisyys = lambda n: (Px - x[n]) ** 2 + (Py - y[n]) ** 2 + if max(etäisyys(0), etäisyys(1)) <= tämä.pituus() ** 2 and max(etäisyys(2), etäisyys(3)) <= toinen.pituus() ** 2: + return pistetyyppi(Px, Py) + else: + return None + except ZeroDivisionError: + return None + +class Piste: + def __init__(self, x, y): + self.x, self.y = x, y + def __repr__(self): + return 'Piste(%r, %r)' % (self.x, self.y) + +A = Monikulmio( + Piste(2,3), + Piste(1,1), + Piste(4,0), + Piste(6,2), + Piste(4,4)) +L1 = Jana(Piste(1, 1), Piste(-1, 5)) +L2 = Jana(Piste(1, 5), Piste(5, 1))