備忘録 課題 円弧を使う時の座標出力

 

G01とG02/G03を区別するコード








VBA


Option Explicit


Sub ボタン1_Click()


    Dim ws As Worksheet

    Set ws = ActiveSheet


    Dim XBASE As Double

    If Trim$(ws.Range("B1").Value) = "" Then

        MsgBox "B1(基準直径)が空です。例:510 を入れてください。"

        Exit Sub

    End If

    XBASE = CDbl(ws.Range("B1").Value)   ' 基準直径(例 510)


    Dim xzPath As String

    xzPath = "C:\jww\xz.txt"             ' JWWの座標ファイル(事前に作っておく)


    Dim csvPath As String

    csvPath = "C:\jww\result.csv"        ' Python出力


    Dim pyPath As String

    pyPath = "C:\jww\convert.py"         ' Pythonスクリプト


    '========================

    ' 出力欄クリア(残骸防止)

    '========================

    ws.Range("D1:H2000").Clear

    ws.Range("D1").Value = "X0"

    ws.Range("E1").Value = "Z0"

    ws.Range("F1").Value = "X(dia)"

    ws.Range("G1").Value = "Z"

    ws.Range("H1").Value = "R"


    '========================

    ' xz.txt があるか確認(消さない)

    '========================

    If Dir(xzPath) = "" Then

        MsgBox "xz.txt が見つかりません。先にJw_cadで " & xzPath & " を作成してください。"

        Exit Sub

    End If


    '========================

    ' result.csv は毎回消す(読み違い防止)

    '========================

    If Not DeleteFileIfExists(csvPath) Then Exit Sub


    '========================

    ' Python実行(完了まで待つ)

    '========================

    If Dir(pyPath) = "" Then

        MsgBox "convert.py が見つかりません:" & vbCrLf & pyPath

        Exit Sub

    End If


    Dim cmd As String

    cmd = "cmd /c python """ & pyPath & """"


    Dim wsh As Object

    Set wsh = CreateObject("WScript.Shell")

    wsh.Run cmd, 0, True


    '========================

    ' result.csv 確認

    '========================

    If Dir(csvPath) = "" Then

        MsgBox "result.csv が作成されていません。convert.py を確認してください。"

        Exit Sub

    End If


    '========================

    ' CSV読み込み(x0,z0,r)

    '   ※3列目が空でも落ちない

    '========================

    Dim lineText As String, arr

    Dim r As Long: r = 2


    Open csvPath For Input As #1

    Do Until EOF(1)


        Line Input #1, lineText

        lineText = Trim$(lineText)

        If Len(lineText) = 0 Then GoTo ContinueLoop


        arr = Split(lineText, ",")

        If UBound(arr) < 1 Then GoTo ContinueLoop   ' x0,z0 必須


        Dim x0 As Double, z0 As Double

        If Not IsNumeric(arr(0)) Or Not IsNumeric(arr(1)) Then GoTo ContinueLoop


        x0 = CDbl(arr(0))

        z0 = CDbl(arr(1))


        ' (0,0)除外(あなたのルール)

        If (x0 = 0# And z0 = 0#) Then GoTo ContinueLoop


        Dim rr As String

        rr = ""

        If UBound(arr) >= 2 Then

            rr = Trim$(arr(2))           ' 空でもOK

        End If


        ' 書き込み

        ws.Cells(r, "D").Value = x0

        ws.Cells(r, "E").Value = z0

        ws.Cells(r, "F").Value = XBASE + (2# * x0)

        ws.Cells(r, "G").Value = z0

        ws.Cells(r, "H").Value = rr


        ' Rがある行だけ色付け(見分け用)

        If Len(rr) > 0 Then

            ws.Range(ws.Cells(r, "D"), ws.Cells(r, "H")).Interior.Color = RGB(255, 255, 153) '薄黄色

            ws.Cells(r, "H").Font.Bold = True

        End If


        r = r + 1


ContinueLoop:

    Loop

    Close #1


    ' 表示形式

    If r > 2 Then

        ws.Range("D2:H" & r - 1).NumberFormat = "0.0000"

    End If


    '========================

    ' 重要:処理後に xz.txt を退避(累積防止)

    '========================

    Call ArchiveXzFile(xzPath)


    MsgBox "座標変換完了(RはH列、xz.txt は退避しました)"


End Sub



'------------------------------------------------------------

' ファイル削除。削除できなければ理由を出してFalse

'------------------------------------------------------------

Private Function DeleteFileIfExists(ByVal path As String) As Boolean

    On Error GoTo EH


    If Dir(path) <> "" Then

        Kill path

        If Dir(path) <> "" Then

            MsgBox "ファイルを削除できません:" & vbCrLf & path & vbCrLf & _

                   "Excelで開いている/同期ロック等の可能性があります。閉じてから再実行してください。"

            DeleteFileIfExists = False

            Exit Function

        End If

    End If


    DeleteFileIfExists = True

    Exit Function


EH:

    MsgBox "ファイル削除でエラー:" & vbCrLf & path & vbCrLf & _

           "エラー内容: " & Err.Description

    DeleteFileIfExists = False

End Function



'------------------------------------------------------------

' xz.txt をタイムスタンプ付きで退避(累積を防ぐ)

'------------------------------------------------------------

Private Sub ArchiveXzFile(ByVal xzPath As String)

    On Error GoTo EH


    If Dir(xzPath) = "" Then Exit Sub


    Dim folder As String

    folder = Left$(xzPath, InStrRev(xzPath, "\"))


    Dim ts As String

    ts = Format$(Now, "yyyymmdd_HHMMSS")


    Dim dst As String

    dst = folder & "xz_" & ts & ".txt"


    Name xzPath As dst

    Exit Sub


EH:

    ' 退避できなくても変換自体は完了しているので止めない

End Sub





PYTHON



import math


INFILE  = r"C:\jww\xz.txt"

OUTFILE = r"C:\jww\result.csv"

ROUND_N = 4

TOL = 0.02  # mm


def r4(x): return round(float(x), ROUND_N)


# --- 読み取り ---

segments = []

arcs = []  # (cx,cz,R,a1,a2)


with open(INFILE, "r", encoding="utf-8", errors="ignore") as f:

    for line in f:

        s = line.strip()

        if not s:

            continue

        parts = s.split()


        # 円弧: ci cx cy R a1 a2 ...

        if parts[0].lower() == "ci" and len(parts) >= 6:

            try:

                cx = float(parts[1]); cz = float(parts[2]); R = float(parts[3])

                a1 = float(parts[4]); a2 = float(parts[5])

            except ValueError:

                continue

            arcs.append((cx,cz,R,a1,a2))

            continue


        # 線分: x1 z1 x2 z2

        if len(parts) == 4:

            try:

                x1,z1,x2,z2 = map(float, parts)

            except ValueError:

                continue

            segments.append(((x1,z1),(x2,z2)))


# --- 8点用の点集合(線分端点) ---

pts = set()

for p1,p2 in segments:

    pts.add((r4(p1[0]), r4(p1[1])))

    pts.add((r4(p2[0]), r4(p2[1])))


points = list(pts)

if not points:

    open(OUTFILE, "w", encoding="utf-8").close()

    raise SystemExit("no points")


# --- ルール:輪郭点のXmax/Zmaxを0 ---

xmax = max(p[0] for p in points)

zmax = max(p[1] for p in points)


def conv_xy(x,z):

    return (r4(x - xmax), r4(z - zmax))


def near(p,q):

    return abs(p[0]-q[0]) <= TOL and abs(p[1]-q[1]) <= TOL


# --- 8点を作る((0,0)除外・Z降順)---

converted = []

for x,z in points:

    x0,z0 = conv_xy(x,z)

    if x0 == 0.0 and z0 == 0.0:

        continue

    converted.append([x0,z0,""])


converted.sort(key=lambda p: p[1], reverse=True)


# --- 各円弧について「下側端点だけ」Rを付ける ---

arc_targets = []  # (x0,z0,R)  ←下側端点のみ

for (cx,cz,R,a1,a2) in arcs:

    t1 = math.radians(a1); t2 = math.radians(a2)

    p1 = (cx + R*math.cos(t1), cz + R*math.sin(t1))

    p2 = (cx + R*math.cos(t2), cz + R*math.sin(t2))

    p1c = conv_xy(p1[0], p1[1])

    p2c = conv_xy(p2[0], p2[1])


    # ★下側(Zが小さい=よりマイナス側)を採用

    target = p1c if p1c[1] < p2c[1] else p2c

    arc_targets.append((target[0], target[1], r4(R)))


# --- 8点の中で一致する行にだけRを入れる ---

for tx, tz, RR in arc_targets:

    for row in converted:

        if near((row[0],row[1]), (tx,tz)):

            row[2] = f"{RR:.4f}"

            break


# --- CSV出力 x0,z0,r ---

with open(OUTFILE, "w", encoding="utf-8") as f:

    for x0,z0,rr in converted:

        f.write(f"{x0:.4f},{z0:.4f},{rr}\n")


print("reading:", INFILE)

print("written:", OUTFILE, "rows:", len(converted))

print("arc R targets (lower endpoints):", len(arc_targets))

for t in arc_targets:

    print("  target:", f"{t[0]:.4f}", f"{t[1]:.4f}", "R=", f"{t[2]:.4f}")



人気の投稿