Işın “Ray” Yaratma Algoriması: AutoCAD’de Bir Sürekli Çizginin “Polyline” İçindeki Noktayı VBA ile Belirleme

Geçenlerde bir autoCADbeyni.com üyesi bana VBA kullanarak bir sürekli çizgi “polyline” içerisinde bulunan bir noktanın nasıl belirlenebileceğini sordu. Bunu yapabilmek için, bazıları diğerlerinden daha karmaşık fakat her biri kendi avantajlarına sahip birkaç yol vardır. Bununla birlikte, AutoCAD ortamı içerisinde biraz daha basit olan İle Kesişen “Intersect With” metodu gibi AutoCAD ‘in yerleşik özelliklerini kullanabildiğimiz tek bir yol vardır.

Bir sürekli çizgi “polyline” içerisindeki noktalardan birini bulma kavramı şudur – şayet herhangi bir noktadan başlayan ve herhangi bir yönde sonsuza giden bir çizgi çizdiysek, çizginin sürekli çizgi “polyline” ile yapacağı kesişimlerin sayısı bir tek sayı olmalıdır. Bunu iyi düşünün –şayet sürekli çizgi “polyline” bir dikdörtgen ise, sonsuza giden çizgi sürekli çizgiyi “polyline” tek bir kez keser. çizginin sürekli çizgiyi “polyline” birçok kez kestiği düzensiz şekiller için, çizgi ilk olarak şekilden dışarı çıkmak zorundadır – şeklin içine yeniden girişe karşılık gelen bir çıkış olmak zorundadır – yani şayet nokta sürekli çizginin “polyline” içindeyse, o noktadan çıkan ve sonsuza giden herhangi bir çizgi sınırı bir tek sayı adedinde kesmek zorundadır.

Evet,  artık bu bilgiyle kuşandığımıza göre, şimdi buna AutoCAD’de ulaşmak için, bir yol bulmamız gerekmektedir. Bunu yapmanın en kolay yolu herhangi bir yönde bir ışın yaratmak ve sınır ile kaç tane kesişim olduğunu bulmaktır. İşte aşağıdaki kod da tam olarak bunu yapmaktadır:

Option Explicit
 Sub main()
    Dim selPolyline As AcadLWPolyline
    Dim selPoint As AcadPoint
    Dim pnt As Variant
    Randomize 'Initialise random number generator
    ThisDrawing.Utility.GetEntity selPolyline, pnt, "Sürekli Çizgiyi tıklayarak seçin:"
    ThisDrawing.Utility.GetEntity selPoint, pnt, "Noktayı tıklayarak seçin:"
    If isPointInPolyline(selPolyline, selPoint) Then
        ThisDrawing.Utility.Prompt "Seçtiğiniz Nokta sürekli çizginin içindedir. (!!!)"
        
    Else
        ThisDrawing.Utility.Prompt " Seçtiğiniz Nokta sürekli çizginin dışındadır. (X)"
    End If
End Sub
 
Function isPointInPolyline(pl As AcadLWPolyline, pnt As AcadPoint) As Boolean
    Dim p1 As Variant
    Dim p2 As Variant
    Dim ray As AcadRay
    Dim arr As Variant
    Dim upperbound As Long
    Dim IntersectionCount As Long
    p1 = pnt.Coordinates
    p2 = p1
    ' 07/09/2013 tarihinde güvenilirliği arttırmak için düzenlenmiştir.
    ' ilk sürümde sadece yatay olarak yaratılabilen ışın “ray”, herhangi bir yönde yaratılabilen bir ışın “ray” olarak değiştirilmiştir.
    p2(0) = p2(0) + 1 - Rnd * 2 'Işındaki ikincil noktanın x koordinatını rastgele miktarda öteleme.
    p2(1) = p2(1) + 1 - Rnd * 2 ' Işındaki ikincil noktanın y koordinatını rastgele miktarda öteleme.
    ' düzenlemenin sonu.
    Set ray = thisSpace.AddRay(p1, p2)
    arr = ray.IntersectWith(pl, acExtendNone)
    upperbound = UBound(arr)
    If upperbound = -1 Then
    ' Kesişim yok - nokta sürekli çizginin “polyline” içinde olmak zorunda değildir.
    ' Yüksekliğin olmadığı (Z=0) kabul edilmiştir.
        isPointInPolyline = False
    Else
        IntersectionCount = (upperbound + 1) / 3
        ' hiç eleman olmadığı için dizideki eleman sayısı (upperbound + 1) e eşittir.
        'her bir kesişim X,Y ve Z olarak 3 koordinata sahip olduğu için, bulunan kesişim sayısını (yani IntersectionCount değişkeni değerini) bulmak için, 3 e bölüyoruz.
        
        If IntersectionCount Mod 2 = 0 Then
        'Sürekli çizginin “polyline” içinde olmayan tek sayıda kesişim vardır.
        isPointInPolyline = False
        Else
        'Sürekli çizginin “polyline” içinde olmak zorunda olan tek sayıda kesişim vardır.
        isPointInPolyline = True
        End If
        
    End If
    ray.Delete
End Function
 
Function thisSpace() As AcadBlock
    If ThisDrawing.ActiveSpace = acModelSpace Then
        Set thisSpace = ThisDrawing.ModelSpace
    Else
        Set thisSpace = ThisDrawing.PaperSpace
    End If

End Function