Keşişen Doğruların Sınırladığı Alanın Hesabı

Soru: x sayıda, keşişen doğruların sınırladığı alanı hesaplayan program.(x rastgele belirlenen bir tam sayı)

Bence analitik olarak konumlarını bilmeden sadece doğru sayısı bilgisiyle alan hesaplanamaz. Çünkü parametrik bir denkleme dönüştüremiyoruz doğruları. Ama yine de, belki araştırırken gözümden kaçan bir formül, bilmediğim bir çözüm yolu vardır diye sizlere de sormak istedim. Cevaplar için şimdiden teşekkür ederim.

1 Beğeni

Kesinlikle.

  • Doğrular sonsuzda kesişiyor olabilirler.
  • Doğrular üst üste binerek sonsuz kez kesişiyor olabilirler.
  • Açı değerlerini bilsek bile kesiştikleri noktaları tam bilmeden alanı hesaplamak imkansız.
1 Beğeni

Doğruların formülleri veriliyorsa hesaplanabilir gibi hissettim.

Doğruların formülleri veriliyorsa hesaplanabilir gibi hissettim.

Soruda yazdıklarımdan başka bir şey verilmiyor.

Şuan bu soru programlamadan çok, analitik geometri hatta zorlarsak topoloji sorusu sayılır.

Ama çokgenlerin bile mantığı ile başlamadan, şu sorun aklımızda belirir: “Bu doğrular tek bir alanı mi oluşturuyor?” Zira pek cok doğru kesiştiğinde birden fazla alan oluşturabilir.

Ben bu soruya verdiğin cevabı evet olarak kabul ediyorum ve ek olarak bu doğruların kestiştiği alanı oluşturan doğru parçaları eş olmalı, yani alan bir düzgün çokgenin alani olmalı öyle değilse, lineer interpolasyon devreye girer ve doğru parcalarını uydurmalar ile çokgene benzeterek yaklaşık bir değer bulabilirsin.

Ek olarak, kenar sayısı değişkeninin yaklaşık olarak bulunabilmesi için, dış ya da iç açısı da aynı şekilde yaklaşık olarak bilinmeli. Ki çokgen kenar/açi formüllerinden birini ya da birdiğer değişkeni bulabilesin.

Bunu buldukatan sonra yapman gereken, “yaklaşık” düzgün çokgenin köşegen sayısını bulur ve üçgenlere ayırırsın. Sonra da “multaka” bilinen “yaklaşık” eş açıların sinüsü ile birlikte, “mutlaka” bilinen yaklaşık eş kenarların çarpımından ve bulunan "yaklaşık üçgen alanları"nın toplamından, bu bahsettiğin imajinasyonel alanı, bulabilirsin.

Bence.

1 Beğeni

x sayıda diyor hadi 3 verelim işimiz bare üçgen olsun.
Rastgele bu doğruları belirle (x,y).
Keşiştikleri noktaları bul hepsinin. Onları al ve üçgen oluştur.
ondan sonra alanı hesapla

Önce küçüğü yap sonra büyüt işlemi.

1 Beğeni

Doğruları rastgele belirledikten sonra alanı hesaplamanın bize faydası nedir? Sonsuz tane ihtimalden yalnızca birini hesaplamış olacağız.

Yani fonksiyon(3), bize her seferinde farklı bir sonuç verecek.

Açıları bilmek hiç bir şeyi değiştirmez. Küçük bir not kağıdının her bir açısı 90 derece olduğu gibi A4 kağıdının da her bir açısı 90 derecedir. Bunlar 'Benzer’lik gösterir ama 'Eş’lik göstermezler. Dolayısıyla açılarını bildiğimiz bir alan, bu ekrana sığmayacak kadar fazla basamak içeren bir büyüklükte dahi olabilir.

1 Beğeni

Demek ki koordinat sistemini de bilmek gerekiyor. Zira, meşhur fizikçi, sevgili Walter Lewin’in, 1.Fizik ders videosunda da söylediği gibi “Belirsizliği belirtmeksizin yapmış olduğunuz herhangi bir ölçümün hiçbir anlamı yoktur.” Bu belirsizliği ben yaratmadım ey Yüce Gök.

Farkettiysen hep varsayımdan bahsediyorum.

1 Beğeni

Aslında noktalar (doğruların birbiri ile kesiştiği noktalar) belli olursa pick teoremiyle alan kolayca bulunabilir.(belki de değil, input büyüdükçe zaman karmaşıklığına bakmak lazım aslında) Ama malum, noktaların koordinatlarının bilinmesi lazım.

1 Beğeni

Belirlenen bir formülü yükseltmek için önce onu alt tabakasından yapman lazım. Üzerine bunun programından bahsediyoruz. Sınırsızlığından değil. Programların belirlenen ölçekteki sınırı ile çözülmek zorunda. Belirlenen sayı program dilinde verebileceğimiz sayıdan fazla olamaz. Yani benim mantığıma göre 64 bit tutuluyorsa eğer sayı 18446744073709551615 sayısından fazla olamaz. Ben böyle düşünüyorum :smiley:

Pick noktaları kesikli sayı olarak kabul ederek bu işi yapıyor. Peki ya noktalar sürekli sayı ise?

Hımm, evet, doğru didin.

Ama Pick teoremi için tamsayı kullanmamız gerektiğini sanmıyorum. Sonuçta elimizde birim olması lazım. Bizim elimizdeki birim ne kadar küçükse bulacağımız alan ile gerçek alan arasındaki hata payı daha az olacaktır. Ben bu birimi 10^-9 olarak bile belirleyebilirim.

  1. Eğer ben birimi 10^-9 olarak belirlersem gerçek alanı hiçbir zaman doğru bir şekilde ölçemem.

  2. Ama pratikteki ölçümden kaynaklanan hata payını ihmal edersem çok da bir şey olmaz. Yani pratikte ölçülen alanı, gerçek alan olarak kabul edebilirim.

Hadi diyelim alanı kusursuz hesaplayan bir formül kullandık. Bu sefer de float sayılarda işlem yaparken illaki hata payları olacak. İncelemek istersen şöyle bir şey yazmıştım. link

Hatasız dost arayan dostsuz kalır aga :upside_down_face:.
O yüzden bazı hataları hoşgörmek gerek.

diye düşünüyorum.

Ha yine de kusursuz bir şekilde hesaplamak istiyorum diyorsan da doğru diyon yani, pick işine yaramayabilir. (Yanlış hatırlamıyorsam py de decimal kütüphanesi mi ne vardı.)

3 Beğeni

Yok ya, çok da büyük problem değil. Unutma, toplama, teknik anlamda "kesikli toplama"dır. “Sürekli toplayacaksak” integral diye bir şey var.

Merhabalar,

Bütün bilgi bu kadarsa, programın geri kalanı bizim emeğimize kalacaksa neden olmasın.

Haklısınız. Doğruların denklemlerini biliyor olsak, birbirlerini kestikleri noktaları kullanarak alanı hesaplayabiliriz.

Ama varsayalım elimizde doğrusal denklemler üreten bir fonksiyon var.

import numpy as np


def linear_equations(n):
    for i in range(n):
        sign = np.random.choice(["", "-"])
        a = str(np.random.randint(0, 10))
        op = np.random.choice(["+", "-"])
        b = str(np.random.randint(0, 10))
        yield sign + a + "x" + op + b

Bu fonksiyonu 5 kez çağırdığımızda aşağıdaki gibi çıktılar alırız.

for equation in linear_equations(5):
    print(equation)
0x+10
9x+2
-3x+1
7x+3
3x+10

Bu doğruları göstermek için ifadeleri fonksiyona dönüştüren bir fonksiyon yazacağım.

def linear_equations_to_functions(*equations):
    for equation in equations:
        yield eval(f"lambda x: {equation.replace('x', '* x')}")

Şimdi, kesişim kümelerini bulmak için izleyebileceğimiz farklı yöntemler var. Benim izleyeceğim yöntemde a ve b katsayılarını kullanarak iki elemanlı fonksiyon kombinasyonlarını eşitlemeye çalışacağız. İfadelerdeki a ve b değerlerini ayıklamak için re kütüphanesini kullanabiliriz:

import re


def islinear(expr):
    match = re.findall(r"(^-?\d*\.?\d*)x ?([+-]?) ?(-?\d*\.?\d*$)", expr)
    if len(match) == 1:
        match = list(match[0])
        if match[0] == "-":
            match[0] = "-1"
        elif match[0] == "":
            match[0] = "1"
        a = match[0]
        b = match[1] + match[2]
        if b:
            return float(a), float(b)
        else:
            return float(a)
    raise SyntaxError(f"f'{expr}' is not a valid linear equation expression.")

Buradaki regex kalıbı, ifadenin ax+b, ax + b ve türevlerinde olup olmadığını denetliyor ve şayet bu yapıya uygun bir ifade varsa, bu ifadeyi parçalarına ayırıyor ve geriye a ve b değerlerini döndürüyor.

Şimdi, kesişim noktalarını bulan fonksiyonu yazabiliriz.

import itertools


def intersect(*exprs):
    for comb in itertools.combinations(exprs, 2):
        f, g = map(islinear, comb)
        try:
            yield (x := (g[1] - f[1]) / (f[0] - g[0])), f[0] * x + f[1]
        except ZeroDivisionError:
            yield (x := g[1] - f[1]), f[0] * x + f[1]

Şimdi bir örnek yapalım; 5 tane doğru oluşturacağım ve bunların kesişim kümelerini göstereceğim:

import numpy as np
import matplotlib.pyplot as plt

equations = list(linear_equations(n=5))
functions = list(linear_equations_to_functions(*equations))
points = list(intersect(*equations))

x = np.linspace(-10, 10, 100)

for f in functions:
    plt.plot(x, f(x))

for p in points:
    plt.scatter(*p, lw=.1, color="red")

plt.show()

Figure_2
Figure_3

Kesişim kümelerini bulduk, şimdi sıra geldi, poligon hesabı yapmaya. Konuyla alakalı araştırma yaparsanız, dışbükey poligonların alanının hesabının daha kolay yapıldığını görürsünüz. Ancak yukardaki gibi içbükey poligonlarda, içbükey örtü (convex hull) hesabı yapmak gerekir. Yani noktaları çevreleyebilecek en kısa yolu gösteren özel noktaları bulan bir algoritmaya ihtiyacımız var.

Algoritmalara göz atmak için şu linki inceleyebilirsiniz. Convex hull algorithms - Wikipedia

Aşağıda, Monotone Chain algoritması kullanıldı.

def convex_hull(points):
    def cross(o, a, b):
        return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])

    def hull(pts):
        h = []
        for p in pts:
            while len(h) >= 2 and cross(h[-2], h[-1], p) <= 0:
                h.pop()
            h.append(p)
        return h

    points = sorted(set(points))
    if len(points) <= 1:
        return points
    return hull(points)[:-1] + hull(points[::-1])[:-1]

Şimdi, vertice’leri bulabiliriz.

vertices = convex_hull(points)
for p in points:
    plt.scatter(*p, s=10, color="red")

for v in vertices:
    plt.scatter(*v, s=10, color="blue")

plt.show()

Figure_4
Figure_5

Bu aşamadan sonra, artık alan hesaplayabiliriz:

def area(*p):
    return sum(((p[i][0] * p[(i + 1) % len(p)][1]) - (p[i][1] * p[(i + 1) % len(p)][0])) / 2 for i in range(len(p)))


print(area(*vertices))

Yukardaki noktaların oluşturduğu üçgenin alanını 28.4375 olarak hesapladı.

Tüm kodlar:

import re
import itertools
import numpy as np
import matplotlib.pyplot as plt


def linear_equations(n):
    for i in range(n):
        sign = np.random.choice(["", "-"])
        a = str(np.random.randint(0, 10))
        op = np.random.choice(["+", "-"])
        b = str(np.random.randint(0, 10))
        yield sign + a + "x" + op + b


def linear_equations_to_functions(*equations):
    for equation in equations:
        yield eval(f"lambda x: {equation.replace('x', '* x')}")


def islinear(expr):
    match = re.findall(r"(^-?\d*\.?\d*)x ?([+-]?) ?(-?\d*\.?\d*$)", expr)
    if len(match) == 1:
        match = list(match[0])
        if match[0] == "-":
            match[0] = "-1"
        elif match[0] == "":
            match[0] = "1"
        a = match[0]
        b = match[1] + match[2]
        if b:
            return float(a), float(b)
        else:
            return float(a)
    raise SyntaxError(f"f'{expr}' is not a valid linear equation expression.")


def intersect(*exprs):
    for comb in itertools.combinations(exprs, 2):
        f, g = map(islinear, comb)
        try:
            yield (x := (g[1] - f[1]) / (f[0] - g[0])), f[0] * x + f[1]
        except ZeroDivisionError:
            yield (x := g[1] - f[1]), f[0] * x + f[1]


def convex_hull(points):
    def cross(o, a, b):
        return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])

    def hull(pts):
        h = []
        for p in pts:
            while len(h) >= 2 and cross(h[-2], h[-1], p) <= 0:
                h.pop()
            h.append(p)
        return h

    points = sorted(set(points))
    if len(points) <= 1:
        return points
    return hull(points)[:-1] + hull(points[::-1])[:-1]


def area(*p):
    return sum(((p[i][0] * p[(i + 1) % len(p)][1]) - (p[i][1] * p[(i + 1) % len(p)][0])) / 2 for i in range(len(p)))


equations = list(linear_equations(n=10))
functions = list(linear_equations_to_functions(*equations))
points = list(intersect(*equations))
vertices = convex_hull(points)

print(area(*vertices))

x = np.linspace(-100, 100, 100)

for f in functions:
    plt.plot(x, f(x), lw=1, color="black")

for p in points:
    plt.scatter(*p, s=10, color="red")

for v in vertices:
    plt.scatter(*v, s=10, color="blue")

plt.show()

Herkese iyi çalışmalar.

2 Beğeni

X=1 area?
X=2 area?

X=3 ve üçü de tek noktada kesişiyorsa area?

X=4 ve dördü de tek noktada kesişiyorsa area?

Bu durumda bu kesişim konusuna bir açıklama getirilmeli anlamlı bir alan tanımı yapabilmek için.

Kesişim için bir kriter daha gerekecek.

Kesicişim oluşacak konvektes konkav yada konveks olabilir. Bu konuda bir kısıt var mı belli değil.

Geometrik tanımlama yok ucu açık.

Ama imkansız diye bir şey yoktur.

Doğru tanımlanmamış soru vardır.

Peki madem…

Area of a polygon with given n ordered vertices - GeeksforGeeks

Shoelace formula - Wikipedia