dxftosvg1 / app.py
yoon2566's picture
Create app.py
c656ab3 verified
import gradio as gr
import ezdxf
import svgwrite
import os
import tempfile
from pathlib import Path
def dxf_to_svg_content(dxf_file_path):
"""DXF νŒŒμΌμ„ SVG λ‚΄μš©μœΌλ‘œ λ³€ν™˜"""
try:
# DXF 파일 읽기
doc = ezdxf.readfile(dxf_file_path)
msp = doc.modelspace()
# μž„μ‹œ SVG 파일 생성
temp_svg = tempfile.NamedTemporaryFile(mode='w', suffix='.svg', delete=False)
# SVG λ¬Έμ„œ 생성
dwg = svgwrite.Drawing(temp_svg.name, size=('1000px', '1000px'), viewBox='0 0 1000 1000')
# λͺ¨λ“  μ—”ν‹°ν‹° 처리
entity_count = 0
for entity in msp:
entity_count += 1
if entity.dxftype() == 'LINE':
# 직선 처리
start = entity.dxf.start
end = entity.dxf.end
dwg.add(dwg.line(
start=(start.x, start.y),
end=(end.x, end.y),
stroke='black',
stroke_width=1,
fill='none'
))
elif entity.dxftype() == 'LWPOLYLINE':
# 폴리라인 처리
points = []
for point in entity.get_points():
points.append((point[0], point[1]))
if len(points) > 1:
polyline = dwg.polyline(
points=points,
stroke='black',
stroke_width=1,
fill='none'
)
# λ‹«νžŒ 폴리라인인지 확인
if entity.closed:
polyline.attribs['stroke-linejoin'] = 'round'
dwg.add(polyline)
elif entity.dxftype() == 'CIRCLE':
# 원 처리
center = entity.dxf.center
radius = entity.dxf.radius
dwg.add(dwg.circle(
center=(center.x, center.y),
r=radius,
stroke='black',
stroke_width=1,
fill='none'
))
elif entity.dxftype() == 'ARC':
# 호 처리
center = entity.dxf.center
radius = entity.dxf.radius
start_angle = entity.dxf.start_angle
end_angle = entity.dxf.end_angle
import math
start_x = center.x + radius * math.cos(math.radians(start_angle))
start_y = center.y + radius * math.sin(math.radians(start_angle))
end_x = center.x + radius * math.cos(math.radians(end_angle))
end_y = center.y + radius * math.sin(math.radians(end_angle))
large_arc = 1 if abs(end_angle - start_angle) > 180 else 0
sweep = 1 if end_angle > start_angle else 0
path_data = f"M {start_x} {start_y} A {radius} {radius} 0 {large_arc} {sweep} {end_x} {end_y}"
dwg.add(dwg.path(
d=path_data,
stroke='black',
stroke_width=1,
fill='none'
))
# SVG 파일 μ €μž₯
dwg.save()
return temp_svg.name, f"λ³€ν™˜ μ™„λ£Œ! {entity_count}개의 μ—”ν‹°ν‹°λ₯Ό μ²˜λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€."
except Exception as e:
return None, f"λ³€ν™˜ μ‹€νŒ¨: {str(e)}"
def convert_multiple_dxf(dxf_files):
"""μ—¬λŸ¬ DXF νŒŒμΌμ„ 각각 λ³€ν™˜ν•˜μ—¬ κ°œλ³„ λ‹€μš΄λ‘œλ“œ κ°€λŠ₯ν•˜κ²Œ 함"""
if not dxf_files:
return [], "DXF νŒŒμΌλ“€μ„ μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”."
try:
converted_files = []
converted_count = 0
error_files = []
for dxf_file in dxf_files:
try:
svg_file, message = dxf_to_svg_content(dxf_file.name)
if svg_file:
# 원본 파일λͺ…을 기반으둜 μƒˆ 파일λͺ… 생성
original_name = Path(dxf_file.name).stem
new_svg_path = f"{original_name}.svg"
# μž„μ‹œ 디렉토리에 볡사
import shutil
final_svg_path = os.path.join(tempfile.gettempdir(), f"converted_{original_name}.svg")
shutil.copy2(svg_file, final_svg_path)
converted_files.append(final_svg_path)
converted_count += 1
# 원본 μž„μ‹œ 파일 정리
os.unlink(svg_file)
else:
error_files.append(Path(dxf_file.name).name)
except Exception as e:
error_files.append(f"{Path(dxf_file.name).name} (였λ₯˜: {str(e)})")
status_message = f"βœ… {converted_count}개 파일이 μ„±κ³΅μ μœΌλ‘œ λ³€ν™˜λ˜μ—ˆμŠ΅λ‹ˆλ‹€."
if error_files:
status_message += f"\n❌ μ‹€νŒ¨ν•œ νŒŒμΌλ“€: {', '.join(error_files)}"
return converted_files, status_message
except Exception as e:
return [], f"λ³€ν™˜ μ‹€νŒ¨: {str(e)}"
# Gradio μΈν„°νŽ˜μ΄μŠ€ 생성
with gr.Blocks(title="DXF to SVG λ³€ν™˜κΈ°") as demo:
gr.Markdown("# DXF to SVG λ³€ν™˜κΈ°")
gr.Markdown("DXF νŒŒμΌλ“€μ„ SVG ν˜•μ‹μœΌλ‘œ λ³€ν™˜ν•˜μ—¬ 각각 λ‹€μš΄λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€.")
with gr.Row():
with gr.Column(scale=1):
file_input = gr.File(
label="DXF νŒŒμΌλ“€ μ—…λ‘œλ“œ",
file_count="multiple",
file_types=[".dxf"],
type="filepath"
)
convert_btn = gr.Button("λ³€ν™˜ν•˜κΈ°", variant="primary", size="lg")
status_output = gr.Textbox(label="λ³€ν™˜ μƒνƒœ", interactive=False, lines=3)
with gr.Column(scale=2):
gr.Markdown("### λ³€ν™˜λœ SVG νŒŒμΌλ“€")
gr.Markdown("λ³€ν™˜μ΄ μ™„λ£Œλ˜λ©΄ μ•„λž˜μ—μ„œ 각 νŒŒμΌμ„ κ°œλ³„μ μœΌλ‘œ λ‹€μš΄λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€.")
# μ΅œλŒ€ 10개 νŒŒμΌκΉŒμ§€ κ°œλ³„ λ‹€μš΄λ‘œλ“œ 지원
file_outputs = []
for i in range(10):
file_output = gr.File(
label=f"λ³€ν™˜λœ 파일 {i+1}",
visible=False
)
file_outputs.append(file_output)
def update_outputs(dxf_files):
"""λ³€ν™˜ κ²°κ³Όλ₯Ό κ°œλ³„ 파일 좜λ ₯으둜 μ—…λ°μ΄νŠΈ"""
converted_files, status = convert_multiple_dxf(dxf_files)
# λͺ¨λ“  좜λ ₯을 μ΄ˆκΈ°ν™”
outputs = [None] * 10
visibilities = [False] * 10
# λ³€ν™˜λœ νŒŒμΌλ“€μ„ 좜λ ₯에 ν• λ‹Ή
for i, file_path in enumerate(converted_files[:10]): # μ΅œλŒ€ 10κ°œκΉŒμ§€
outputs[i] = file_path
visibilities[i] = True
# κ²°κ³Ό λ°˜ν™˜: μƒνƒœ + νŒŒμΌλ“€ + κ°€μ‹œμ„±
result = [status]
for i in range(10):
result.append(gr.File(value=outputs[i], visible=visibilities[i]))
return result
# 이벀트 μ—°κ²°
convert_btn.click(
fn=update_outputs,
inputs=[file_input],
outputs=[status_output] + file_outputs
)
if __name__ == "__main__":
demo.launch()