Python/Matplotlib: Kendi belirlediğimiz x, y koordinatlarına nasıl resim ekleyebiliriz?

Merhaba arkadaşlar. Bir astroloji uygulamasıyla ilgileniyorum şu sıralar. Kullanıcının girdiği, yıl, ay, gün, saat, dakika, enlem ve boylam bilgilerine göre astrolojik haritalar oluşturuyor program. Programın tasarımına devam edeceğim ama önce başlıkta bahsettiğim sorunu halletmem lazım.

Sorunu şu şekilde anlatmaya çalışayım:

Örneğin aşağıdaki grafikte, burç isimleri, olması gereken yerde görünütüleniyor. Ama bu grafikte kullanılan burç isimleri yerine, burç sembolleri kullanmayı düşünüyorum.

Burç sembollerini, burç isimleri yerine kullanarak bir grafik oluşturmaya çalıştığımda ise aşağıdaki grafiği elde ettim.

İkinci grafikten de anlaşılacağı üzere, ev konumları ve bazı burç sembolleri de tersine dönmüş ve ayrıca burç sembolleri de bozulmuş şekilde gösteriliyor. Ayrıca ev konumları neden değişti anlamadım, halbuki resim veya yazı ekleme fonksiyonunun ev numaraları üzerinde bir etkisi yok.

Grafiğe, burç isimlerini veya burç sembollerini eklemek ile alakalı fonksiyon aşağıdadır.

    def draw_sign_names(self):
        asc = self.house_cusps()[1]
        for i, j in enumerate(self.SIGNS):
            end = 30 - (asc % 30) + 180
            start = end - 30
            start += (30 * i)
            end += (30 * i)
            if start > 360:
                start -= 360
            if end > 360:
                end -= 360
            if start > 330:
                midpoint = (start + end + 360) / 2
            else:
                midpoint = (start + end) / 2
            if midpoint > 360:
                midpoint -= 360
            _x1, _y1 = self.x_y(angle=midpoint, r1=480, r2=400)
            # img = plt.imread(f"{self.sign_pos()[1][i]}.png")
            # plt.imshow(img, aspect="auto", interpolation="gaussian", extent=[_x1[0], _x1[1], _y1[1], _y1[0]])
            plt.text(sum(_x1) / 2, sum(_y1) / 2, self.sign_pos()[1][i], color="black", size=8, rotation=-10)

Yukarıdaki kodlarda yoruma alınmış kısımlar, yazı yerine resim eklemek ile alakalı olan kodlar. Fakat bu kodları kullandığım zaman, 2. grafikteki gibi bir görüntü elde ediyorum.

Benim görüntülemek istediğim ilk grafiğe benziyor, sadece burç isimleri yerine burç sembolleri kullanılacak. Bunu nasıl yapabilirim, yardımcı olacak arkadaşlara şimdiden teşekkür ederim.

Yardım etmek isteyebilecek olan arkadaşların tüm kodlara ihtiyacı olursa, aşağıdaki adresten kodlara ulaşabilirler. Linkte ayrıca burç sembollerinin png dosyaları da mevcut.

Neyse, sorunu matplotlib modülü yerine tkinter modülünü kullanarak çözdüm.

Kodlar:

#!/usr/bin/python3.6
# -*- coding: utf-8 -*-

import swisseph as swe
import tkinter as tk
from math import cos, sin, radians
from PIL import ImageTk

root = tk.Tk()
root.title("Astro-Python")
root.resizable(width=False, height=False)

canvas = tk.Canvas(master=root, bg="white", width=800, height=600)
canvas.pack(fill="both", expand=True)


def oval_object(x, y, r):
    canvas.create_oval(
        x - r,
        y - r,
        x + r,
        y + r,
        fill="white",
        width=2
    )


def line_object(x1, y1, x2, y2, width=2):
    canvas.create_line(x1, y1, x2, y2, width=width)


def text_object(x, y, text, width=0):
    canvas.create_text(x, y, text=text, width=width)


def image_object(x, y, image):
    canvas.create_image(x, y, image=image)


class Chart:
    SIGNS = ["Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo",
             "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces"]
    FILES = [f"images/{i}.png" for i in SIGNS]
    IMAGE_FILES = {i[:-4]: ImageTk.PhotoImage(file=i) for i in FILES}
    MIDPOINT_OF_HOUSES = []

    def __init__(self, year, month, day, hour, minute, longitude, latitude):
        self.year = year
        self.month = month
        self.day = day
        self.hour = hour
        self.minute = minute
        self.longitude = longitude
        self.latitude = latitude
        oval_object(x=400, y=300, r=200)
        oval_object(x=400, y=300, r=150)
        oval_object(x=400, y=300, r=50)
        self.draw_houses()
        self.draw_signs()
        self.draw_house_numbers()
        self.draw_sign_symbols()

    @staticmethod
    def dd_to_dms(dd):
        degree = int(dd)
        minute = int((dd - degree) * 60)
        second = float((dd - degree - minute / 60) * 3600)
        return f"{degree}\u00b0 {minute}' {second}\""

    @staticmethod
    def dms_to_dd(dms):
        degree = int(dms.split(" ")[0])
        minute = float(dms.split(" ")[1]) / 60
        second = float(dms.split(" ")[2]) / 3600
        return degree + minute + second

    def utc_time(self):
        longitude = int(self.longitude)
        hour = float(self.hour)
        if longitude == 0:
            return hour
        elif longitude in range(1, 16):
            return hour - 1
        elif longitude in range(-16, -1):
            return hour + 1
        elif longitude in range(16, 31):
            return hour - 2
        elif longitude in range(-31, -16):
            return hour + 2
        elif longitude in range(31, 46):
            return hour - 3
        elif longitude in range(-46, -31):
            return hour + 3
        elif longitude in range(46, 61):
            return hour - 4
        elif longitude in range(-61, -46):
            return hour + 4
        elif longitude in range(61, 76):
            return hour - 5
        elif longitude in range(-76, -61):
            return hour + 5
        elif longitude in range(76, 91):
            return hour - 6
        elif longitude in range(-91, -76):
            return hour + 6
        elif longitude in range(91, 106):
            return hour - 7
        elif longitude in range(-106, -91):
            return hour + 7
        elif longitude in range(106, 121):
            return hour - 8
        elif longitude in range(-121, -106):
            return hour + 8
        elif longitude in range(121, 136):
            return hour - 9
        elif longitude in range(-136, -121):
            return hour + 9
        elif longitude in range(136, 151):
            return hour - 10
        elif longitude in range(-151, -136):
            return hour + 10
        elif longitude in range(151, 166):
            return hour - 11
        elif longitude in range(-166, -151):
            return hour + 11
        elif longitude in range(166, 181):
            return hour - 12
        elif longitude in range(-181, -166):
            return hour + 12

    def julday(self):
        jd = swe.julday(
            self.year, self.month, self.day, self.utc_time() + self.minute / 60)
        deltat = swe.deltat(jd)
        return round(jd + deltat, 6)

    @staticmethod
    def convert_angle(angle):
        if 0 < angle < 30:
            return angle, "Aries"
        elif 30 < angle < 60:
            return angle - 30, "Taurus"
        elif 60 < angle < 90:
            return angle - 60, "Gemini"
        elif 90 < angle < 120:
            return angle - 90, "Cancer"
        elif 120 < angle < 150:
            return angle - 120, "Leo"
        elif 150 < angle < 180:
            return angle - 150, "Virgo"
        elif 180 < angle < 210:
            return angle - 180, "Libra"
        elif 210 < angle < 240:
            return angle - 210, "Scorpio"
        elif 240 < angle < 270:
            return angle - 240, "Sagittarius"
        elif 270 < angle < 300:
            return angle - 270, "Capricorn"
        elif 300 < angle < 330:
            return angle - 300, "Aquarius"
        elif 330 < angle < 360:
            return angle - 330, "Pisces"

    def planet_pos(self, planet):
        calc = self.convert_angle(swe.calc_ut(self.julday(), planet)[0])
        return self.dd_to_dms(calc[0]), calc[1]

    def house_cusps(self):
        houses = []
        asc = 0
        angle = []
        for i, j in enumerate(swe.houses(self.julday(), self.latitude, self.longitude)[0]):
            if i == 0:
                asc += j
            angle.append(j)
            houses.append((
                f"House {i + 1}:",
                f"{self.dd_to_dms(self.convert_angle(j)[0])}",
                f"{self.convert_angle(j)[1]}"))
        return houses, asc, angle

    def house_pos(self):
        return self.house_cusps()[2]

    def sign_pos(self):
        asc = self.house_cusps()[1]
        degree = self.house_cusps()[0][0][1].replace("'", "").replace('"', "").replace("\u00b0", "")
        end = 30 - self.dms_to_dd(degree) + asc
        start = end - 30
        signs = []
        for i, j in enumerate(self.house_cusps()[0]):
            signs.append(j[2])
        for i in self.SIGNS:
            if i not in signs:
                index_1 = self.SIGNS.index(i) + 1
                sign = self.SIGNS[index_1]
                index_2 = signs.index(sign)
                signs.insert(index_2, i)
        for i in signs:
            count = signs.count(i)
            if count > 1:
                signs.pop(signs.index(i, 1))
        _signs_ = []
        for i, j in enumerate(signs):
            _start = start + (i * 30)
            _end = end + (i * 30)
            if _start > 360:
                _start -= 360
            if _end > 360:
                _end -= 360
            _signs_.append(_start)
        return _signs_, signs

    @staticmethod
    def line_components(angle, r):
        x1, y1 = 400, 300
        x2 = x1 + (r * cos(radians(angle)))
        y2 = y1 - (r * sin(radians(angle)))
        return x1, y1, x2, y2

    def x_y(self, angle, r1, r2):
        x1, y1, x2, y2 = self.line_components(angle=angle, r=r1)
        _x1, _y1, _x2, _y2 = self.line_components(angle=angle, r=r2)
        return x2, y2, _x2, _y2

    def draw_houses(self):
        for i, j in enumerate(self.house_pos()):
            _degree = j - (self.house_pos()[0] - 180)
            if _degree < 0:
                _degree += 360
            elif _degree > 360:
                _degree -= 360
            self.MIDPOINT_OF_HOUSES.append(_degree)
            x1, y1, x2, y2 = self.x_y(angle=_degree, r1=50, r2=150)
            if i == 0 or i == 3 or i == 6 or i == 9:
                line_object(x1, y1, x2, y2, width=4)
            else:
                line_object(x1, y1, x2, y2, width=2)

    def draw_signs(self):
        sign_pos = self.sign_pos()[0]
        for i in sign_pos:
            _degree = i - (self.house_pos()[0] - sign_pos[1])
            if _degree > 360:
                _degree -= 360
            x1, y1, x2, y2 = self.x_y(angle=_degree, r1=150, r2=200)
            line_object(x1, y1, x2, y2, width=2)

    def draw_house_numbers(self):
        for i, j in enumerate(self.MIDPOINT_OF_HOUSES):
            if i == 11:
                midpoint = (self.MIDPOINT_OF_HOUSES[i] + self.MIDPOINT_OF_HOUSES[0]) / 2
            else:
                if self.MIDPOINT_OF_HOUSES[i] == 360:
                    midpoint = self.MIDPOINT_OF_HOUSES[i + 1] / 2
                else:
                    if self.MIDPOINT_OF_HOUSES[i + 1] == 0:
                        midpoint = (self.MIDPOINT_OF_HOUSES[i] + self.MIDPOINT_OF_HOUSES[i + 1] + 360) / 2
                    else:
                        midpoint = (self.MIDPOINT_OF_HOUSES[i] + self.MIDPOINT_OF_HOUSES[i + 1]) / 2
            x1, y1, x2, y2 = self.x_y(angle=midpoint, r1=50, r2=150)
            x = (x1 + x2) / 2
            y = (y1 + y2) / 2
            text_object(x=x, y=y, text=f"{i + 1}")

    def draw_sign_symbols(self):
        asc = self.house_cusps()[1]
        for i, j in enumerate(self.SIGNS):
            end = 30 - (asc % 30) + 180
            start = end - 30
            start += (30 * i)
            end += (30 * i)
            if start > 360:
                start -= 360
            if end > 360:
                end -= 360
            if start > 330:
                midpoint = (start + end + 360) / 2
            else:
                midpoint = (start + end) / 2
            if midpoint > 360:
                midpoint -= 360
            x1, y1, x2, y2 = self.x_y(angle=midpoint, r1=150, r2=200)
            x = (x1 + x2) / 2
            y = (y1 + y2) / 2
            image_object(
                x=x,
                y=y,
                image=self.IMAGE_FILES[f"images/{self.sign_pos()[1][i]}"]
            )


chart = Chart(1985, 12, 30, 5, 5, 8.32, 47.31)
root.mainloop()

Edit: Burçların ve gezegenlerin grafik dosyaları yerine unicode karakterleri de kullanılabilir.

2 Beğeni