Ovaj Python program omogućava korisnicima interaktivni rad sa DXF fajlovima direktno sa komandne linije. Program je razvijen korišćenjem ezdxf i matplotlib biblioteka i podržava sledeće ključne funkcionalnosti:
1. Pan (Pomicanje Crteža)
- Pritiskom na točkić miša korisnici mogu da pomeraju crtež na ekranu. Ova funkcionalnost omogućava lakšu navigaciju kroz velike crteže, čineći ih jednostavno preglednim i prilagodljivim.
2. Zumiranje
- Okretanjem točkića miša korisnici mogu da zumiraju crtež, povećavajući ili smanjujući prikaz crteža u određenim područjima, što omogućava detaljan pregled elemenata crteža.
3. Merenje Rastojanja između Dve Tačke
- Pritiskom levog tastera miša na dve tačke, korisnici mogu da izmere rastojanje između tih tačaka.
- Program izračunava euklidsku distancu i prikazuje rezultat u realnom vremenu.
- Svi rezultati merenja (rastojanje) se ispisuju u konzoli.
4. Merenje Površine između VIše Tačaka
- Desnim klikom birate više tačaka za formiranje poligona.
- Kliknite ponovo na prvu tačku da zatvorite poligon.
- Rezultat će biti prikazan u konzoli..
5. Merenje Ugla između Tri Tačke
- Dok držite pritisnut taster CTRL
- Pritiskom na desni taster miša na tri tačke,
- izmerićete ugao između tih tačaka.
- Program prikazuje ugao u stepenima.
- Svi rezultati merenja (ugao) se ispisuju u konzoli.
Naravno! Evo pregleda šta sve program može da iscrta iz DXF fajla, na osnovu trenutne implementacije:
Entiteti koje program prikazuje
Program koristi biblioteku ezdxf za parsiranje DXF fajla i matplotlib za crtanje. U okviru draw_dxf() funkcije, podržani su sledeći entiteti:
1. LINE
Opis: Pravolinijski segment između dve tačke.
Prikazano kao: Plava linija
Kod:
ax.plot([start.x, end.x], [start.y, end.y], 'b')
2. CIRCLE
Opis: Krug definisan centrom i radijusom.
Prikazano kao: Crveni krug (bez ispune)
Kod:
c = plt.Circle((center.x, center.y), radius, color='r', fill=False) ax.add_patch(c)
3. LWPOLYLINE
Opis: Lakša verzija polilinije — niz povezanih tačaka.
Prikazano kao: Magenta linije
Kod:
ax.plot(x_vals, y_vals, 'm')
4. POLYLINE
Opis: Klasična polilinija, često sa dodatnim osobinama (3D, visina, itd.)
Prikazano kao: Cijan (svetloplava) linija
Kod:
ax.plot(x_vals, y_vals, 'c')
Napomena
- Slojevi (Layers): Program prikazuje sve entitete bez obzira na sloj.
- Zatvorene konture: Kod
POLYLINEiLWPOLYLINE, čak i ako su zatvorene, prikazuju se kao obične linije — ne popunjavaju se automatski.
Entiteti koje program ne podržava (još)
Trenutno se ignorišu sledeći elementi (ali ih je moguće dodati):
ARC(luk)ELLIPSE(elipsa)TEXT,MTEXT(tekstualni elementi)SPLINE(krivolinijski oblici)HATCH(šrafura/popunjenost)DIMENSION(dimenzije)BLOCKS(blokovi i referencirane instance)
Ako želište da dodate podršku za još neki od ovih elemenata — možete proširiti funkciju draw_dxf() da ih prepozna i iscrta!
Pokretanje Programa u Konzoli
1. Zahtevi (Zavisnosti)
Pre nego što pokreneš program, uveri se da su instalirani sledeći paketi:
- Python 3 (verzija 3.6+)
ezdxf– za rad sa DXF fajlovimamatplotlib– za crtanje i prikaz grafike
Instalacija paketa
U terminalu pokreni sledeće komande:
sudo apt update sudo apt install python3 python3-pip -y pip3 install ezdxf matplotlib
2. Smeštanje programa
- Otvori terminal.
- Kreiraj novi folder (ako želiš):
mkdir ~/vidi_dxf cd ~/vidi_dxf
Kreiraj novi Python fajl:
nano xdxf.py
(Zalepi ceo Python kod i sačuvaj: CTRL + O, zatim ENTER, pa CTRL + X za izlaz.)
Python kod koji kopiraš u xdxf.py
#xdxf.py
# Instalacija potrebnih zavisnosti:python3 -m pip install ezdxf matplotlib
# The MIT License (MIT)
# Copyright (c) 2025 Aleksandar Maričić
#
# Ovim se omogućava bilo kome da koristi, kopira, menja, spaja, objavljuje,
# distribuira, daje podlicencu i/ili prodaje kopije ovog softverskog programa,
# uz uslov da u svim kopijama ili značajnim delovima softverskog programa bude
# uključena sledeća obavest:
#
# Copyright (c) 2025 Aleksandar Maričić
#
# Ovaj softverski program je pružen "takav kakav jeste", bez bilo kakvih garancija,
# izričitih ili impliciranih, uključujući, ali ne ograničavajući se na, garancije o
# prikladnosti za prodaju ili pogodnosti za određenu svrhu. U svakom slučaju, autori
# ili nosioci prava nisu odgovorni za bilo kakvu štetu ili druge obaveze koje mogu nastati
# usled upotrebe ovog softverskog programa.
"""
import ezdxf
import matplotlib.pyplot as plt
import sys
import os
import math
clicked_points = []
point_markers = []
polygon_patch = None
drag_start = None
is_panning = False
def distance(p1, p2):
return math.hypot(p2[0] - p1[0], p2[1] - p1[1])
def polygon_area(points):
n = len(points)
area = 0.0
for i in range(n):
x1, y1 = points[i]
x2, y2 = points[(i + 1) % n]
area += x1 * y2 - x2 * y1
return abs(area) / 2.0
def draw_point(x, y):
marker, = ax.plot(x, y, 'ko', markersize=5)
point_markers.append(marker)
fig.canvas.draw()
def draw_polygon(points):
global polygon_patch
if polygon_patch:
polygon_patch.remove()
polygon_patch = plt.Polygon(points, closed=True, edgecolor='orange', facecolor='orange', alpha=0.3)
ax.add_patch(polygon_patch)
fig.canvas.draw()
def clear_visuals():
global point_markers, polygon_patch
for m in point_markers:
m.remove()
point_markers.clear()
if polygon_patch:
polygon_patch.remove()
polygon_patch = None
fig.canvas.draw()
def on_click(event):
global is_panning, drag_start
if event.inaxes:
if event.button == 1: # Levim klikom meri rastojanje
x, y = event.xdata, event.ydata
clicked_points.append((x, y))
print(f"Kliknuta tačka: ({x:.2f}, {y:.2f})")
draw_point(x, y)
if len(clicked_points) == 2:
d = distance(clicked_points[0], clicked_points[1])
print(f"Rastojanje između tačaka: {d:.2f} jedinica\n")
clicked_points.clear()
clear_visuals()
elif event.button == 2: # Srednji klik (točkić) za pan
is_panning = True
drag_start = (event.xdata, event.ydata)
elif event.button == 3: # Desni klik za merenje površine ili ugla
x, y = event.xdata, event.ydata
# Detekcija CTRL + 3 desna klika za merenje ugla
if event.key == 'control':
clicked_points.append((x, y))
draw_point(x, y)
if len(clicked_points) == 3:
a, b, c = clicked_points
angle = math.degrees(math.atan2(c[1] - b[1], c[0] - b[0]) -
math.atan2(a[1] - b[1], a[0] - b[0]))
angle = abs(angle)
if angle > 180:
angle = 360 - angle
print(f"Ugao između tri tačke: {angle:.2f} stepeni\n")
clicked_points.clear()
clear_visuals()
return
new_point = (x, y)
if len(clicked_points) >= 3:
first_point = clicked_points[0]
if distance(first_point, new_point) < 5.0:
draw_polygon(clicked_points)
area = polygon_area(clicked_points)
print(f"Površina zatvorenog poligona ({len(clicked_points)} temena): {area:.2f} kv. jedinica\n")
clicked_points.clear()
clear_visuals()
return
clicked_points.append(new_point)
draw_point(x, y)
print(f"Kliknuta tačka za površinu: ({x:.2f}, {y:.2f})")
def on_motion(event):
global drag_start
if event.inaxes and is_panning:
dx = event.xdata - drag_start[0]
dy = event.ydata - drag_start[1]
ax.set_xlim(ax.get_xlim() - dx)
ax.set_ylim(ax.get_ylim() - dy)
drag_start = (event.xdata, event.ydata)
fig.canvas.draw()
def on_release(event):
global is_panning
if event.button == 2:
is_panning = False
def on_scroll(event):
global ax
if event.inaxes:
scale_factor = 1.1 if event.button == 'up' else 0.9
xlim, ylim = ax.get_xlim(), ax.get_ylim()
center_x, center_y = (xlim[0] + xlim[1]) / 2, (ylim[0] + ylim[1]) / 2
ax.set_xlim(center_x - (center_x - xlim[0]) * scale_factor, center_x + (xlim[1] - center_x) * scale_factor)
ax.set_ylim(center_y - (center_y - ylim[0]) * scale_factor, center_y + (ylim[1] - center_y) * scale_factor)
fig.canvas.draw()
def on_key(event):
if event.key == 'escape':
print(" ESC pritisnut – prekid merenja i čišćenje tačaka.\n")
clicked_points.clear()
clear_visuals()
def draw_dxf(file_path):
print(f"Učitavanje DXF fajla: {file_path}")
try:
doc = ezdxf.readfile(file_path)
except IOError:
print(f" Greška: Ne mogu da otvorim fajl '{file_path}'")
return
except ezdxf.DXFStructureError:
print(f" Greška: Fajl '{file_path}' nije validan DXF fajl")
return
msp = doc.modelspace()
global fig, ax
fig, ax = plt.subplots()
for entity in msp:
if entity.dxftype() == 'LINE':
start = entity.dxf.start
end = entity.dxf.end
ax.plot([start.x, end.x], [start.y, end.y], 'b')
elif entity.dxftype() == 'CIRCLE':
center = entity.dxf.center
radius = entity.dxf.radius
c = plt.Circle((center.x, center.y), radius, color='r', fill=False)
ax.add_patch(c)
elif entity.dxftype() == 'LWPOLYLINE':
points = [point[:2] for point in entity]
if len(points) > 1:
x_vals, y_vals = zip(*points)
ax.plot(x_vals, y_vals, 'm')
elif entity.dxftype() == 'POLYLINE':
points = [v.dxf.location for v in entity.vertices()]
if len(points) > 1:
x_vals = [p.x for p in points]
y_vals = [p.y for p in points]
ax.plot(x_vals, y_vals, 'c')
ax.set_aspect('equal')
ax.autoscale()
ax.set_title("Levi klik:rastojanje|Desni klik:površina|CTRL+Desni klik:ugao|Zum:točkić|Pan:srednji klik")
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.grid(True)
fig.canvas.mpl_connect("button_press_event", on_click)
fig.canvas.mpl_connect("motion_notify_event", on_motion)
fig.canvas.mpl_connect("button_release_event", on_release)
fig.canvas.mpl_connect("scroll_event", on_scroll)
fig.canvas.mpl_connect("key_press_event", on_key)
try:
plt.tight_layout()
plt.show()
except Exception as e:
print(f" Greška pri prikazu crteža: {e}")
input("Pritisni Enter za izlaz...")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Upotreba: python vidi_dxf.py <putanja_do_dxf_fajla>")
sys.exit(1)
print("""
- Merenje rastojanja: Pritiskom na levi taster miša na dve tačke,
izmerićete rastojanje između tih tačaka.
Rezultat će biti prikazan u konzoli.
- Merenje površine: Desnim klikom birate više tačaka za formiranje poligona.
Kliknite ponovo na prvu tačku da zatvorite poligon.
Rezultat će biti prikazan u konzoli.
- Pan (Pomicanje crteža): Pritiskom na srednji taster miša (točkić),
možete slobodno pomerati crtež na ekranu
- Zumiranje: Okretanjem točkića miša, možete povećavati
ili smanjivati prikaz crteža.
- Merenje ugla: Dok držite pritisnut taster CTRL
Pritiskom na desni taster miša na tri tačke,
izmerićete ugao između tih tačaka. Rezultat će biti prikazan u konzoli.
- ESC taster prekida sva merenja i čisti ekran od mernih tačaka.
""")
file_path = sys.argv[1]
if not os.path.isfile(file_path):
print(f" Fajl '{file_path}' ne postoji!")
sys.exit(1)
draw_dxf(file_path)
print(" Program završen.")
3. Priprema DXF fajla
U isti folder kopiraj .dxf fajl koji želiš da otvoriš.
Primer (ako se fajl zove primer.dxf):
cp /putanja/do/primer.dxf ~/vidi_dxf/
4. Pokretanje programa
Pokreni program iz terminala na sledeći način:
python3 xdxf.py primer.dxf
5. Uputstvo za korišćenje programa
Kada pokreneš program, u terminalu će se prikazati sledeće uputstvo:
- Merenje rastojanja: Pritiskom na levi taster miša na dve tačke,
izmerićete rastojanje između tih tačaka.
Rezultat će biti prikazan u konzoli.
- Merenje površine: Desnim klikom birate više tačaka za formiranje poligona.
Kliknite ponovo na prvu tačku da zatvorite poligon.
Rezultat će biti prikazan u konzoli.
- Pan (Pomicanje crteža): Pritiskom na srednji taster miša (točkić),
možete slobodno pomerati crtež na ekranu
- Zumiranje: Okretanjem točkića miša, možete povećavati ili smanjivati prikaz crteža.
- Merenje ugla: Dok držite pritisnut taster CTRL Pritiskom na desni taster miša na tri tačke,
izmerićete ugao između tih tačaka. Rezultat će biti prikazan u konzoli.
- ESC taster prekida sva merenja i čisti ekran od mernih tačaka.
Pregled funkcionalnosti
| Radnja | Opis |
|---|---|
| Levi klik (x2) | Izmeri rastojanje između dve tačke. |
| Desni klik (više puta) | Formira poligon, zatvara ga klikom blizu prve tačke. |
| CTRL + 3x desni klik | Izračunava ugao između tri tačke. |
| Srednji klik (točkić) | Panoramsko pomeranje crteža. |
| Točkić miša | Zumiranje u/van. |
6. Zatvaranje programa
Klikom na X u prozoru ili zatvaranjem matplotlib prikaza – program se završava.
Primer Pokretanja Programa:
Na primer, ako želite da otvorite fajl kupola.dxf koji se nalazi u istom direktorijumu kao i skripta, komanda bi izgledala ovako:
python3 xdxf.py kupola.dxf
U prozoru koji se otvori, možete interaktivno pomerati crtež, zumirati, meriti rastojanja, površine i uglove.
Ovaj crtež je rađen u takvoj razmeri da su rezultati merenja dužine u santimetrima. Svi rezultati merenja (rastojanje i ugao) biće prikazani u konzoli, kao na primer:

Ovaj način interakcije omogućava jednostavno i efikasno radno okruženje u komandnoj liniji, bez potrebe za dodatnim grafičkim korisničkim interfejsima. Program je brz, fleksibilan i idealan za rad sa jednostavnim CAD crtežima i merenja u DXF formatu.

