其他分享
首页 > 其他分享> > 权属面积批量修改0.1

权属面积批量修改0.1

作者:互联网

import win32com.client
import pythoncom
import tkinter as tk
from tkinter import messagebox
import numpy
import math
'''打开选择文件夹对话框'''
window = tk.Tk()
window.title("权属面积批量修改0.1")
window.geometry('380x30+800+200')  # 290 160为窗口大小,+1000 +10 定义窗口弹出时的默认展示位置

window.resizable(0, 0)
window['background'] = 'DimGray'


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 compute_polygon_area(points):
    point_num = len(points)
    if (point_num < 3): return 0.0
    s = points[0][1] * (points[point_num - 1][0] - points[1][0])
    # for i in range(point_num): # (int i = 1 i < point_num ++i):
    for i in range(1, point_num):  # 有小伙伴发现一个bug,这里做了修改,但是没有测试,需要使用的亲请测试下,以免结果不正确。
        s += points[i][1] * (points[i - 1][0] - points[(i + 1) % point_num][0])
    return numpy.around(abs(s / 2.0), 4)


'''
计算方位角
'''


def cross_point(line1, line2):  # 计算交点函数
    x1 = line1[0]  # 取四点坐标
    y1 = line1[1]
    x2 = line1[2]
    y2 = line1[3]

    x3 = line2[0]
    y3 = line2[1]
    x4 = line2[2]
    y4 = line2[3]

    k1 = (y2 - y1) * 1.0 / (x2 - x1)  # 计算k1,由于点均为整数,需要进行浮点数转化
    b1 = y1 * 1.0 - x1 * k1 * 1.0  # 整型转浮点型是关键
    if (x4 - x3) == 0:  # L2直线斜率不存在操作
        k2 = None
        b2 = 0
    else:
        k2 = (y4 - y3) * 1.0 / (x4 - x3)  # 斜率存在操作
        b2 = y3 * 1.0 - x3 * k2 * 1.0
    if k2 == None:
        x = x3
    else:
        x = (b2 - b1) * 1.0 / (k1 - k2)
    y = k1 * x * 1.0 + b1 * 1.0
    return [x, y]


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")
    slt = doc.SelectionSets.Add("SS1")
    slt.SelectOnScreen()
    mmm = float(text1_var.get())

    for x in slt:
        if x.ObjectName == "AcDbPolyline":
            original_area = 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)
            XY1 = Polyline_coordinates[0]
            XY2 = Polyline_coordinates[1]
            XY3 = Polyline_coordinates[2]
            XY4 = Polyline_coordinates[3]
            angle = azimuth(XY4[0], XY4[1], XY1[0], XY1[1])  # 角度

            angle2 = azimuth(XY3[0], XY3[1], XY2[0], XY2[1])  # 角度
            angle3 = azimuth(XY4[0], XY4[1], XY3[0], XY3[1])  # 角度

            angle4 = math.radians(180) + (angle3 - angle) - math.radians(90)
            area = mmm - original_area  # 面积差值

            d1 = math.sqrt((XY3[0] - XY4[0]) ** 2 + (XY3[1] - XY4[1]) ** 2)  # 1,2 点距离

            d5 = math.sqrt((XY2[0] - XY1[0]) ** 2 + (XY2[1] - XY1[1]) ** 2)  # 1,2 点距离

            d2 = (area * 2) / (d1 + d5)  # 延长距离

            d3 = d2 / math.cos(angle4)

            xMargin1 = XY4[0] - math.cos(angle) * d3
            yMargin1 = XY4[1] - math.sin(angle) * d3

            xMargin2 = xMargin1 + math.cos(angle3) * d1
            yMargin2 = yMargin1 + math.sin(angle3) * d1
            line1 = [xMargin1, yMargin1, xMargin2, yMargin2]
            line2 = XY2 + XY3

            dSanDian = cross_point(line1, line2)
            Polyline_coordinates[3] = [xMargin1, yMargin1]
            Polyline_coordinates[2] = [dSanDian[0], dSanDian[1]]

            ff = compute_polygon_area(Polyline_coordinates) - mmm

            if ff > 0.0:
                while True:
                    d3 = d3 - 0.000001
                    xMargin3 = XY4[0] - math.cos(angle) * (d3)
                    yMargin3 = XY4[1] - math.sin(angle) * (d3)

                    xMargin4 = xMargin3 + math.cos(angle3) * d1
                    yMargin4 = yMargin3 + math.sin(angle3) * d1

                    line1 = [xMargin3, yMargin3, xMargin4, yMargin4]
                    line2 = XY2 + XY3
                    dSanDian = cross_point(line1, line2)

                    Polyline_coordinates[3] = [xMargin3, yMargin3]
                    Polyline_coordinates[2] = [dSanDian[0], dSanDian[1]]

                    sd = compute_polygon_area(Polyline_coordinates)

                    if (mmm - 0.00004) <= sd <= (mmm + 0.00004):
                        break
            elif ff < 0.0:
                while True:
                    d3 = d3 + 0.000001
                    xMargin3 = XY4[0] - math.cos(angle) * d3
                    yMargin3 = XY4[1] - math.sin(angle) * d3

                    xMargin4 = xMargin3 + math.cos(angle3) * d1
                    yMargin4 = yMargin3 + math.sin(angle3) * d1

                    line1 = [xMargin3, yMargin3, xMargin4, yMargin4]
                    line2 = XY2 + XY3
                    dSanDian = cross_point(line1, line2)

                    Polyline_coordinates[3] = [xMargin3, yMargin3]
                    Polyline_coordinates[2] = [dSanDian[0], dSanDian[1]]

                    v = compute_polygon_area(Polyline_coordinates)

                    if (mmm - 0.00004) <= v <= (mmm + 0.00004):
                        break
            else:
                pass

            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
    messagebox.showinfo("tip","完成。")


lable1 = tk.Label(window, text="[面积替换:平方米]", width=15).grid(row=0, column=0)
text1_var = tk.StringVar()  # 获取text_1输入的值
text1_var.set(r'400')
text1 = tk.Entry(window, textvariable=text1_var, bd=5).grid(row=0, column=1)
tk.Button(window, text="开始", width=15, height=1, command=Select_element, bg="Silver").grid(row=0, column=2)
window.mainloop()

标签:angle,批量,point,0.1,list,coordinates,Polyline,权属,math
来源: https://blog.csdn.net/weixin_42479058/article/details/118256428