天天看點

python 連接配接CAD 修改圖斑點順序到西北角

1.通過點到矩形外框西北角的距離,以及方位角的大小來判斷西北角的位置。不是很理想。
2.通過面積判斷結果是否正确,7000個點測試時,圖斑生成正常。
希望程式對測繪工作有些幫助。
           
import win32com.client
import pythoncom
import tkinter as tk
from tkinter import messagebox
import numpy
import math


def vtpnt(x, y, z=0):
    """坐标點轉化為浮點數"""
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x, y, z))


def vtobj(obj):
    """轉化為對象數組"""
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DISPATCH, obj)


def vtFloat(list):
    """清單轉化為浮點數"""
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, list)


def vtInt(list):
    """清單轉化為整數"""
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_I2, list)


def vtVariant(list):
    """清單轉化為變體"""
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_VARIANT, list)


def list_format_conversion(old_list, leixing=False, step=2, deduction=None):
    if leixing is False:
        leixing = list
    else:
        leixing = tuple
    new_list = []
    for counte in range(0, len(old_list), step):
        new_list.append(leixing(old_list[counte:counte + step])[:deduction])
    return new_list


'''
進位,傳回str
'''


def rrd(point, f):
    if f == 0:
        point = str(int(point))
    elif f > 0:
        SP = str(numpy.around(point, f))
        sy = SP.split(".")
        n = len(sy[1])
        if n < f:
            sj = f - n
            point = sy[0] + "." + sy[1] + "0" * sj
        else:
            point = SP
    elif f < 0:
        tk.messagebox.showinfo('提示', "取位不可為負")
    return point


'''
計算順時針或逆時針
green方法判斷面積正負
'''


def polyline_order(P):
    n = len(P)
    P.append(P[0])
    S = 0
    for i in range(0, n):
        S = S + (P[i][0] + P[i + 1][0]) * (P[i + 1][1] - P[i][1])
    if S > 0:
        return False  # 逆時針
    else:
        return True  # 順時針


'''
計算方位角
'''


def azimuth(x1, y1, x2, y2):
    angle = 0
    dx = x2 - x1
    dy = y2 - y1
    if dx == 0 and dy > 0:  # 判斷象限
        angle = 0
    if dx == 0 and dy < 0:
        angle = 180
    if dy == 0 and dx > 0:
        angle = 90
    if dy == 0 and dx < 0:
        angle = 270
    if dx > 0 and dy > 0:
        angle = math.atan(dx / dy) * 180 / math.pi
    elif dx < 0 and dy > 0:
        angle = 360 + math.atan(dx / dy) * 180 / math.pi
    elif dx < 0 and dy < 0:
        angle = 180 + math.atan(dx / dy) * 180 / math.pi
    elif dx > 0 and dy < 0:
        angle = 180 + math.atan(dx / dy) * 180 / math.pi
    angle = 90 - angle
    angle = math.radians(angle)
    return angle  # j


'''
計算西北角
'''


def distance(point, poly):
    d = {}
    min_d = []
    azimuth_2 = {}
    for Endpoint in poly:
        distance_list = math.sqrt((Endpoint[0] - point[0]) ** 2 + (Endpoint[1] - point[1]) ** 2)
        d.update({tuple(Endpoint): distance_list})
    for key, val in d.items():
        if val == min(d.values()):
            min_d.append(key)
    if len(min_d) > 1:
        for x, y in min_d:
            angle = azimuth(x, y, point[0], point[1])
            azimuth_2.update({(x, y): angle})
        min_point = max(azimuth_2, key=azimuth_2.get)
        return min_point
    elif len(min_d) == 1:
        min_point = min_d[0]
        return min_point


'''
重畫西北角
'''


def Select_element():
    global acad, doc, mp, original_area
    acad = win32com.client.Dispatch("AutoCAD.Application")
    doc = acad.ActiveDocument
    doc.Utility.Prompt("\n醉後不知天在水\n滿船清夢壓星河\n")
    mp = doc.ModelSpace  # 模型空間
    tk.messagebox.showinfo('提示', "請在螢幕拾取圖元,以Enter鍵結束")
    try:
        doc.SelectionSets.Item("SS1").Delete()
    except:
        tk.messagebox.showinfo('警告', "Delete selection failed")
    original_area = []

    slt = doc.SelectionSets.Add("SS1")
    slt.SelectOnScreen()
    for x in slt:
        if x.ObjectName == "AcDbPolyline":
            original_area.append(x.Area)  # 面積
            old_coord = list_format_conversion(x.Coordinates, leixing=True)
            new_coord = tuple({}.fromkeys(old_coord).keys())  # 剔除重複點
            list4 = []
            for ier in old_coord:
                if ier not in list4:
                    list4.append(ier)
                else:
                    center, radius = vtpnt(ier[0], ier[1], 0), 2

                    cenobj = acad.ActiveDocument.Layers.Add("01重複點")
                    acad.ActiveDocument.ActiveLayer = cenobj
                    ClrNum = 2
                    cenobj.color = ClrNum
                    mp.AddCircle(center, radius)

            Polyline_coordinates = [list(x) for x in new_coord]  # 改變坐标格式【【1,2】,【4,3】,【6,7】】

            if not polyline_order(Polyline_coordinates):  # 若逆時針,反轉清單
                Polyline_coordinates.reverse()

            poly_x = [x[0] for x in Polyline_coordinates]
            poly_y = [y[1] for y in Polyline_coordinates]
            max_y = max(poly_y)
            min_x = min(poly_x)

            northwest_point = [min_x, max_y]  # 矩形框西北角
            northwest_point_end_point_distance = distance(northwest_point, Polyline_coordinates)  # 圖斑最靠近圖框西北角的坐标
            count = Polyline_coordinates.index(list(northwest_point_end_point_distance))  # 查找在清單中的位置

            Polyline_coordinates = Polyline_coordinates[:-1]
            for _ in range(0, count):
                delete = Polyline_coordinates.pop(0)
                Polyline_coordinates.append(delete)

            Polyline_coordinates = numpy.array([m for n in Polyline_coordinates for m in n], dtype=numpy.float)

            points = vtFloat(Polyline_coordinates)
            # 設定圖層
            layerobj = acad.ActiveDocument.Layers.Add("02重置圖斑")
            acad.ActiveDocument.ActiveLayer = layerobj
            # 多段線顔色
            ClrNum = 1
            layerobj.color = ClrNum
            polylineobj = mp.AddLightweightPolyline(points)
            polylineobj.Closed = True


def judge():
    modify_area = []
    try:
        doc.SelectionSets.Item("SS1").Delete()
    except:
        tk.messagebox.showinfo('警告', "Delete selection failed")
    slt = doc.SelectionSets.Add("SS1")
    slt.SelectOnScreen()
    for x in slt:
        if x.ObjectName == "AcDbPolyline":
            if x.Layer == "02重置圖斑":
                modify_area.append(x.Area)
    A = sum(original_area)
    B = sum(modify_area)
    C = abs(A - B)
    if C <= 0.000001:
        tk.messagebox.showinfo('提示', "成功!")
    else:
        tk.messagebox.showinfo('提示', "誤差超限!")


Select_element()
judge()