Fri, 15 Sep 2017 18:29:23 +0300
Kupittaa as
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 @property def link_to_map(self): return 'http://www.openstreetmap.org/#map=19/%f/%f' % (self.leveys, 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))