본문 바로가기
코딩(php,javascript,mysql)

Python으로 AutoCAD 치수선에 문구 추가하기 (ezdxf 활용)

by mylife365 2024. 12. 12.

Python으로 AutoCAD 치수선에 문구 추가하기 (ezdxf 활용)

AutoCAD의 치수선 앞에 "직선거리 1000"과 같은 문구를 추가하고 싶으신가요? Python의 강력한 라이브러리인 ezdxf를 활용하면 이런 기능을 손쉽게 구현할 수 있습니다. 이번 포스팅에서는 "문구 + 치수값" 구조를 가진 살아있는 치수선을 만드는 방법을 초보자도 이해할 수 있도록 소개하겠습니다.

 


준비물

ezdxf는 Python에서 DXF 파일을 생성하거나 수정할 수 있는 라이브러리입니다. 설치는 간단합니다:

```bash pip install ezdxf

 


구현 목표

우리는 "직선거리 1000"처럼 고정된 문구와 치수값을 결합하여, 선의 길이가 변하면 치수값도 자동으로 갱신되는 치수선을 생성하려 합니다.


Python 코드

아래는 ezdxf를 활용해 "직선거리"와 치수값을 결합한 치수선을 생성하는 함수입니다:

def ds(doc, x1, y1, x2, y2, dis, text="직선거리", text_height=0.30, text_gap=0.05, direction="up"):
    # 치수선 위치 계산
    if direction == "up":
        distance = max(y1, y2) + dis
    elif direction == "down":
        distance = min(y1, y2) - dis
    elif direction == "left":
        distance = min(x1, x2) - dis
    elif direction == "right":
        distance = max(x1, x2) + dis
    else:
        distance = 0

    # 모델 공간 접근
    msp = doc.modelspace()

    # 치수선 생성
    dim = msp.add_linear_dim(
        base=((x1 + x2) / 2, distance),
        p1=(x1, y1),
        p2=(x2, y2),
        override={
            'dimpost': f"{text} <>",  # 문구 + 치수값
            'dimtxt': text_height,   # 텍스트 크기
            'dimdec': 1,             # 소수점 자리수
            'dimgap': text_gap       # 텍스트 간격
        }
    )

    # 렌더링
    dim.render()
    return dim

코드 설명

  1. 문구와 치수값 결합:
    • dimpost 속성을 f"{text} <>"로 설정하여 "직선거리 1000"과 같은 텍스트를 표시합니다.
    • <>"는 측정값이 들어가는 자리입니다.
  2. 소수점 자리수 설정:
    • dimdec 속성을 1로 설정해 소수점 1자리로 표시합니다.
  3. 치수선 렌더링:
    • dim.render()를 호출해 치수선 정보를 DXF 파일 구조에 반영합니다.

사용 예시

아래 코드를 실행하면 "직선거리 1000" 텍스트가 포함된 치수선을 생성합니다:

doc = ezdxf.new()
ds(doc, 0, 0, 1000, 0, dis=50, direction="up", text="직선거리")
doc.saveas("dimension_with_text.dxf")

결과

DXF 파일을 AutoCAD로 열면, "직선거리 1000"과 같은 텍스트가 포함된 치수선이 생성됩니다. 선의 길이를 변경하면 치수값도 자동으로 갱신됩니다.


아래는 요청하신 대로 ds라는 이름으로 수정된 함수입니다. text 값이 있을 경우, dimpost에 "직선거리 <>" 형식으로 적용되도록 구현했습니다.

def ds(doc, x1, y1, x2, y2, dis, text_height=0.30, text_gap=0.05, direction="up", option=None, starbottomtion=None, text=None, dim_style=None):
    global saved_DimXpos, saved_DimYpos, saved_text_height, saved_text_gap, saved_direction, dimdistance, dim_horizontalbase, dim_verticalbase, distanceXpos, distanceYpos

    text_height = 0.80  # 강제로 크게 해봄
    # Option 처리
    if option == 'reverse':
        x1, x2 = x2, x1
        y1, y2 = y2, y1
        saved_DimXpos, saved_DimYpos = x1, y1
    else:
        saved_DimXpos, saved_DimYpos = x2, y2

    dimdistance = dis
    saved_text_height = text_height
    saved_text_gap = text_gap
    saved_direction = direction

    # 연속선 구현을 위한 구문
    if starbottomtion is None:
        if direction == "left":
            distance = min(x1, x2) - dis
            dim_horizontalbase = distance
        elif direction == "right":
            distance = max(x1, x2) + dis
            dim_horizontalbase = distance
        elif direction == "up":
            distance = max(y1, y2) + dis
            dim_verticalbase = distance
        elif direction == "down":
            distance = min(y1, y2) - dis
            dim_horizontalbase = distance
    else:
        if direction == "left":
            distance = distanceXpos
        elif direction == "right":
            distance = distanceXpos
        elif direction == "up":
            distance = distanceYpos
        elif direction == "down":
            distance = distanceYpos

    msp = doc.modelspace()
    layer = selected_dimstyle
    if dim_style is None:
        dim_style = selected_dimstyle
    else:
        dim_style = dim_style

    # 치수값 계산
    dimension_value = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)

    # 소수점 확인
    dimdec = 1 if dimension_value % 1 != 0 else 0

    # override 설정
    override_settings = {
        'dimtxt': text_height,
        'dimgap': text_gap if text_gap is not None else 0.05,
        'dimscl': 1,
        'dimlfac': 1,
        'dimclrt': 7,
        'dimdec': dimdec,
        'dimtix': 1,
        'dimtad': 1,
        'dimtmove': 0 if text is not None else 2,  # 텍스트 이동 옵션
    }

    # 텍스트 값이 있는 경우, dimpost 설정
    if text is not None:
        override_settings['dimpost'] = f"{text} <>"

    base_point = ((x1 + x2) / 2, distance)
    add_dim_args = {
        'dimstyle': dim_style,
        'base': base_point,
        'p1': (x1, y1),
        'p2': (x2, y2),
        'override': override_settings
    }

    if direction in ["up", "down"]:
        add_dim_args['base'] = ((x1 + x2) / 2, distance)
    elif direction in ["left", "right"]:
        add_dim_args['base'] = (distance, (y1 + y2) / 2)
        add_dim_args['angle'] = 90

    if starbottomtion is None:
        if direction == "up":
            distanceYpos = max(y1, y2) + dis
        elif direction == "down":
            distanceYpos = min(y1, y2) - dis
        elif direction == "left":
            distanceXpos = min(x1, x2) - dis
        elif direction == "right":
            distanceXpos = max(x1, x2) + dis

    if text is not None:
        add_dim_args['text'] = text  # 추가 텍스트만 설정

    if option != 'noprint':
        return msp.add_linear_dim(**add_dim_args)
    else:
        return

주요 변경점

  1. text 값이 있을 때:
    • dimpost 속성에 f"{text} <>"를 설정하여 "직선거리"와 같은 텍스트를 추가하고 실제 측정값과 함께 표시되도록 구성.
  2. override_settings에 dimpost를 동적으로 추가.
  3. 나머지 로직은 기존 구조를 유지하면서 text가 없을 경우 기본 설정을 유지하도록 구현.

사용 예시

ds(doc, 0, 0, 1000, 0, dis=5, text="직선거리", direction="up")

이렇게 호출하면 치수선에 "직선거리 1000"과 같은 형식으로 표시됩니다.

 

ezdxf의 DimStyleOverride.set_text_format() 메서드는 post와 같은 키워드를 직접 지원하지 않습니다. 대신, 텍스트 템플릿은 dimpost 속성을 override로 설정하여 처리해야 합니다.

아래는 수정된 함수입니다:


수정된 코드

def ds(doc, x1, y1, x2, y2, dis, text_height=0.30, text_gap=0.05, direction="up", option=None, starbottomtion=None, text=None, dim_style=None):
    global saved_DimXpos, saved_DimYpos, saved_text_height, saved_text_gap, saved_direction, dimdistance, dim_horizontalbase, dim_verticalbase, distanceXpos, distanceYpos

    text_height = 0.80  # 강제로 크게 설정
    if option == 'reverse':
        x1, x2 = x2, x1
        y1, y2 = y2, y1

    # 치수선 방향 및 위치 계산
    if direction == "up":
        distance = max(y1, y2) + dis
    elif direction == "down":
        distance = min(y1, y2) - dis
    elif direction == "left":
        distance = min(x1, x2) - dis
    elif direction == "right":
        distance = max(x1, x2) + dis
    else:
        distance = 0

    # 모델 공간 접근
    msp = doc.modelspace()

    # 치수선 생성 및 설정
    dim = msp.add_linear_dim(
        base=((x1 + x2) / 2, distance),
        p1=(x1, y1),
        p2=(x2, y2),
        dimstyle=dim_style or "Standard",
        override={
            'dimpost': f"{text} <>" if text else "<>",  # 문구 + 치수값
            'dimtxt': text_height,  # 텍스트 높이
            'dimdec': 1,  # 소수점 자리수 (1자리)
            'dimgap': text_gap,  # 텍스트와 치수선 간격
        }
    )

    # 렌더링
    dim.render()

    return dim

주요 수정 사항

  1. dimpost 속성 설정:
    • override에서 dimpost를 설정하여 텍스트와 치수값을 결합했습니다.
    • dimpost는 <>"와 같은 측정값 자리 표시자와 텍스트를 함께 사용합니다.
  2. override 활용:
    • dimpost 외에도 텍스트 높이(dimtxt), 소수점 자리수(dimdec), 간격(dimgap) 등을 override로 설정합니다.
  3. dim.render() 호출:
    • 치수선을 렌더링하여 DXF 파일 구조에 반영합니다.

호출 예시

ds(doc, 0, 0, 1000, 0, dis=50, direction="up", text="직선거리")

결과

위 코드는 "직선거리 1000"과 같은 텍스트를 포함한 치수선을 생성하며, AutoCAD에서도 올바르게 표시됩니다. 문제 발생 시 추가로 알려주세요! 😊

 

마무리

Python의 ezdxf 라이브러리를 활용하면 AutoCAD의 치수 작업을 자동화하고, 더욱 세밀하게 제어할 수 있습니다. "문구 + 치수값" 구조를 활용해 CAD 도면을 더 직관적으로 만들어 보세요! 추가 질문이 있다면 댓글로 남겨주세요 😊

 

반응형