0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Fix for extract_geometry_from_intersection function handling SymPy polygon intersections「SymPyの多角形交差(intersection)における extract_geometry_from_intersection 関数の修正とエラー対策」をAI先生に教えてもらいました。

0
Last updated at Posted at 2026-10-08

https://qiita.com/mrrclb48z/items/f15a4283ab76544ac44a
前行の続きです。

(タイトルもGemini先生より)
・後半に作図あり。
・以前教えてもらった 
def extract_geometry_from_intersection(intersection_result):
が、戻り値にsegment がでました。

(本日の)Gemini先生へ

# intersection 間違っています。
# from sympy import *
# def extract_geometry_from_intersection(intersection_result):
#     """
#     SymPyの intersection() 結果(Polygon, Triangle, Point, Segment の組み合わせ)
#     から、交差領域の図形(Polygon / Triangle)を汎用的に抽出・再構築する関数。
    
#     Returns:
#         tuple: (geometry_object, area)
#                交差部分がない場合は (None, 0) を返す
#     """
#     # 1. 渡された値が単一オブジェクトの場合、リストに正規化
#     if not isinstance(intersection_result, (list, tuple, FiniteSet)):
#         items = [intersection_result]
#     else:
#         items = list(intersection_result)

#     if not items:
#         return None, S.Zero

#     # 2. すでに Polygon / Triangle が直接含まれている場合
#     polygons = [obj for obj in items if isinstance(obj, Polygon)]
#     if polygons:
#         poly = polygons[0]
#         return poly, poly.area

#     # 3. Point群とSegment群から面(Polygon/Triangle)を再構築する場合
#     points = [obj for obj in items if isinstance(obj, Point)]
#     segments = [obj for obj in items if isinstance(obj, Segment)]

#     # Segmentの全端点と孤立したPointを抽出して重複を除去
#     all_vertices = []
#     for seg in segments:
#         all_vertices.extend([seg.p1, seg.p2])
#     all_vertices.extend(points)

#     # 座標の重複を排除(順序を維持)
#     unique_vertices = []
#     for pt in all_vertices:
#         if pt not in unique_vertices:
#             unique_vertices.append(pt)

#     # 頂点が3つ以上あれば多角形(3つの場合はTriangle、それ以上はPolygon)を作成
#     if len(unique_vertices) == 3:
#         tri = Triangle(*unique_vertices)
#         return tri, tri.area
#     elif len(unique_vertices) > 3:
#         poly = Polygon(*unique_vertices)
#         return poly, poly.area

#     # 面を構成しない場合(線や点のみ、または空)
#     return None, S.Zero
# AD,DB,BE,EC=4,8,6,3
# A,D,B,E,C  =map(Point,[(0,AD+DB),(0,DB),(0,0),(BE,0),(BE+EC,0) ])
# trABE      =Triangle(A,B,E)
# trBCD      =Triangle(B,C,D)
# intersection_result=trABE.intersection(trBCD)
# print("#",intersection_result)
# # [Point2D(18/5, 24/5), Segment2D(Point2D(0, 0), Point2D(6, 0)), Segment2D(Point2D(0, 8), Point2D(0, 0))]

・英文の回答でした。(省略)

Corrected Code

# Function to extract geometry and calculate area from SymPy intersection results
from sympy import *

def extract_geometry_from_intersection(intersection_result):
    """
    Extracts the intersecting 2D geometry (Polygon/Triangle) and its area
    from a SymPy intersection() result.
    """
    if not intersection_result:
        return None, S.Zero

    # Unpack FiniteSet or Union into a list of geometric objects
    if isinstance(intersection_result, (FiniteSet, Union)):
        items = list(intersection_result.args)
    elif isinstance(intersection_result, (list, tuple)):
        items = list(intersection_result)
    else:
        items = [intersection_result]

    # 1. Look directly for 2D area-bearing Polygons / Triangles
    polygons = [obj for obj in items if isinstance(obj, Polygon)]
    if polygons:
        # If multiple sub-polygons exist, take the union / primary area
        total_area = sum(p.area for p in polygons)
        return (polygons[0] if len(polygons) == 1 else polygons), total_area

    # 2. Reconstruct polygon from segments if necessary (convex hull ensures valid boundary ordering)
    segments = [obj for obj in items if isinstance(obj, Segment)]
    points = [obj for obj in items if isinstance(obj, Point)]

    all_points = []
    for seg in segments:
        all_points.extend([seg.p1, seg.p2])
    all_points.extend(points)

    # Filter unique points
    unique_points = []
    for pt in all_points:
        if pt not in unique_points:
            unique_points.append(pt)

    if len(unique_points) >= 3:
        # convex_hull arranges points in proper boundary order
        hull = convex_hull(*unique_points)
        if isinstance(hull, Polygon) and hull.area > 0:
            return hull, hull.area

    return None, S.Zero


# Example run with your defined triangles
AD, DB, BE, EC = 4, 8, 6, 3
A, D, B, E, C = map(Point, [(0, AD + DB), (0, DB), (0, 0), (BE, 0), (BE + EC, 0)])

trABE = Triangle(A, B, E)
trBCD = Triangle(B, C, D)

intersection_result = trABE.intersection(trBCD)
geom, area = extract_geometry_from_intersection(intersection_result)

print("Intersection raw output:", intersection_result)
print("Extracted Geometry:    ", geom)
print("Intersection Area:     ", area)

計算結果

Intersection raw output: [Point2D(18/5, 24/5), Segment2D(Point2D(0, 0), Point2D(6, 0)), Segment2D(Point2D(0, 8), Point2D(0, 0))]
Extracted Geometry:     Polygon(Point2D(0, 0), Point2D(6, 0), Point2D(18/5, 24/5), Point2D(0, 8))
Intersection Area:      144/5

(続けて)Gemini先生へ。作図。

上記ののPNG図のみ出力して下さい。

・matplotlibで作図しました。

image.png

AI先生へ動画。

・どなたかチャレンジしてもらうと助かります。

以下の動画を作って。
(ソースコードの表示を省略)

いつもと違うおすすめです。

Qiita内

sympy のdoc

・いらないカモ。前ページとおまとめで。

ver0.1

ver0.2

ver0.3

・equation(x='x', y='y') < Line
https://docs.sympy.org/latest/modules/geometry/lines.html#sympy.geometry.line.Line2D.equation

ver1.1

ver2.1

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?