c# - यह बताने के लिए कि क्या एक बिंदु रेखा के दाएं या बाएं तरफ है




math geometry convex-hull (10)

आप निर्धारक के हस्ताक्षर को देखते हैं

| x2-x1  x3-x1 |
| y2-y1  y3-y1 |

यह एक तरफ के बिंदुओं के लिए सकारात्मक होगा, और दूसरे पर नकारात्मक होगा (और लाइन पर बिंदुओं के लिए शून्य)।

मेरे पास अंक का एक सेट है। मैं उन्हें 2 अलग-अलग सेटों में अलग करना चाहता हूं। ऐसा करने के लिए, मैं दो बिंदु ( और बी ) चुनता हूं और उनके बीच एक काल्पनिक रेखा खींचता हूं। अब मैं उन सभी बिंदुओं को रखना चाहता हूं जो इस लाइन से एक सेट में छोड़े गए हैं और जो कि इस सेट से दूसरे सेट में हैं।

मैं किसी दिए गए बिंदु z के लिए कैसे बता सकता हूं कि यह बाएं या दाएं सेट में है या नहीं? मैंने एजीबी के बीच कोण की गणना करने की कोशिश की - 180 से छोटे कोण दायीं तरफ 180 से अधिक हैं, लेकिन बाईं ओर 180 से अधिक हैं - लेकिन आर्ककोस की परिभाषा के कारण, गणना किए गए कोण हमेशा 180 डिग्री से छोटे होते हैं। 180 डिग्री से अधिक कोणों (या दाएं या बाएं किनारे को चुनने के लिए कोई अन्य सूत्र) की गणना करने के लिए कोई सूत्र है?


वैक्टर (AB,AM) के निर्धारक के संकेत का प्रयोग करें, जहां M(X,Y) क्वेरी पॉइंट है:

position = sign((Bx - Ax) * (Y - Ay) - (By - Ay) * (X - Ax))

यह लाइन पर 0 , और एक तरफ +1 , दूसरी तरफ -1


अंक मानते हैं (एक्स, आय) (बीएक्स, बाय) और (सीएक्स, सीई), आपको गणना करने की आवश्यकता है:

(बीएक्स - एक्स) * (साइ - अय) - (द्वारा - अय) * (सीएक्स - एक्स)

यह अंक बराबर होगा यदि बिंदु सी बिंदु ए और बी द्वारा बनाई गई रेखा पर है, और पक्ष के आधार पर एक अलग चिह्न होगा। यह कौन सा पक्ष आपके (एक्स, वाई) निर्देशांक के अभिविन्यास पर निर्भर करता है, लेकिन आप इस सूत्र में ए, बी और सी के लिए परीक्षण मूल्यों को प्लग कर सकते हैं यह निर्धारित करने के लिए कि ऋणात्मक मान बाएं या दाएं हैं या नहीं।


रूबी में @ एवीबी का जवाब

det = Matrix[
  [(x2 - x1), (x3 - x1)],
  [(y2 - y1), (y3 - y1)]
].determinant

यदि उपरोक्त सकारात्मक है, तो नीचे नकारात्मक है। यदि 0, यह लाइन पर है।


लाइन एबी के समीकरण का उपयोग करके, उसी y-coordinate पर लाइन पर x-coordinate को सॉर्ट करने के बिंदु के रूप में प्राप्त करें।

  • यदि बिंदु का x> रेखा का एक्स, बिंदु रेखा के दाईं ओर है।
  • यदि बिंदु का x <line x है, तो बिंदु रेखा के बाईं ओर है।
  • यदि बिंदु x == लाइन का एक्स है, तो बिंदु रेखा पर है।

सबसे पहले जांच करें कि क्या आपके पास लंबवत रेखा है:

if (x2-x1) == 0
  if x3 < x2
     it's on the left
  if x3 > x2
     it's on the right
  else
     it's on the line

फिर, ढलान की गणना करें: m = (y2-y1)/(x2-x1)

फिर, बिंदु ढलान फ़ॉर्म का उपयोग कर लाइन का समीकरण बनाएं: y - y1 = m*(x-x1) + y1 । मेरी व्याख्या के लिए, इसे ढलान-अवरोध फ़ॉर्म (आपके एल्गोरिदम में आवश्यक नहीं) को सरल y = mx+b : y = mx+b

अब x और y लिए प्लग (x3, y3) । यहां कुछ छद्म कोड है जो बताता है कि क्या होना चाहिए:

if m > 0
  if y3 > m*x3 + b
    it's on the left
  else if y3 < m*x3 + b
    it's on the right
  else
    it's on the line
else if m < 0
  if y3 < m*x3 + b
    it's on the left
  if y3 > m*x3+b
    it's on the right
  else
    it's on the line
else
  horizontal line; up to you what you do

मूल रूप से, मुझे लगता है कि एक समाधान है जो किसी भी दिए गए बहुभुज के लिए बहुत आसान और सीधे आगे है, कहता है कि चार कोष्ठक (पी 1, पी 2, पी 3, पी 4) शामिल हैं, बहुभुज में दो चरम विपरीत विपरीत को ढूंढें, दूसरे में शब्दों के लिए, उदाहरण के लिए सबसे ऊपर बाएं कशेरुक (चलो पी 1 कहें) और विपरीत वर्टेक्स जो सबसे नीचे दाईं ओर स्थित है (कहें)। इसलिए, आपके परीक्षण बिंदु सी (एक्स, वाई) दिया गया है, अब आपको सी और पी 1 और सी और पी 4 के बीच दोहरी जांच करनी है:

यदि सीएक्स> पी 1 एक्स और साइ> पी 1y ==> का अर्थ है कि सी कम है और पी 1 के दाईं ओर है तो सीएक्स <पी 2 एक्स और साइ <p2y ==> का अर्थ है कि सी ऊपरी है और पी 4 के बायीं तरफ है

निष्कर्ष, सी आयताकार के अंदर है।

धन्यवाद :)


वेक्टर (y1 - y2, x2 - x1) लाइन के लिए लंबवत है, और हमेशा सही इंगित करता है (या हमेशा बाएं ओर इशारा करते हुए, यदि आप विमान अभिविन्यास मेरा से अलग हैं)।

इसके बाद आप उस वेक्टर के डॉट उत्पाद की गणना कर सकते हैं और (x3 - x1, y3 - y1) यह निर्धारित करने के लिए कि बिंदु लंबवत वेक्टर (डॉट उत्पाद> 0 ) या नहीं के रूप में रेखा के एक ही तरफ स्थित है या नहीं।


Clojure में लिखे गए क्रॉस उत्पाद तर्क का उपयोग करके एक संस्करण यहां दिया गया है।

(defn is-left? [line point]
  (let [[[x1 y1] [x2 y2]] (sort line)
        [x-pt y-pt] point]
    (> (* (- x2 x1) (- y-pt y1)) (* (- y2 y1) (- x-pt x1)))))

उदाहरण का उपयोग:

(is-left? [[-3 -1] [3 1]] [0 10])
true

जो कहना है कि बिंदु (0, 10) लाइन (3, -1) और (3, 1) द्वारा निर्धारित रेखा के बाईं ओर है।

नोट: यह कार्यान्वयन एक समस्या हल करता है कि अन्य में से कोई भी (अब तक) करता है! लाइन निर्धारित करने वाले अंक देने पर मामलों का आदेश दें । हां, यह एक निश्चित रूप से एक "निर्देशित रेखा" है। तो उपर्युक्त कोड के साथ, यह आविष्कार भी true का परिणाम उत्पन्न करता true :

(is-left? [[3 1] [-3 -1]] [0 10])
true

यह कोड के इस स्निपेट की वजह से है:

(sort line)

अंत में, अन्य क्रॉस उत्पाद आधारित समाधानों के साथ, यह समाधान एक बुलियन लौटाता है, और कॉललाइनरिटी के लिए तीसरा परिणाम नहीं देता है। लेकिन यह एक परिणाम देगा जो समझ में आता है, उदाहरण के लिए:

(is-left? [[1 1] [3 1]] [10 1])
false

ऑब्जेक्ट JsonConverter को संभालने के लिए कस्टम JsonConverter बनाकर आप इसे आसानी से कर सकते हैं। मान लें कि आपके वर्गों ने इस तरह कुछ परिभाषित किया है:

public abstract class GalleryItem
{
    public string id { get; set; }
    public string title { get; set; }
    public string link { get; set; }
    public bool is_album { get; set; }
}

public class GalleryImage : GalleryItem
{
    // ...
}

public class GalleryAlbum : GalleryItem
{
    public int images_count { get; set; }
    public List<GalleryImage> images { get; set; }
}

आप इस तरह कनवर्टर बना देंगे:

public class GalleryItemConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(GalleryItem).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, 
        Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject item = JObject.Load(reader);
        if (item["is_album"].Value<bool>())
        {
            return item.ToObject<GalleryAlbum>();
        }
        else
        {
            return item.ToObject<GalleryImage>();
        }
    }

    public override void WriteJson(JsonWriter writer, 
        object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

कार्रवाई में कनवर्टर दिखाते हुए एक उदाहरण प्रोग्राम यहां दिया गया है:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        [
            {
                ""id"": ""OUHDm"",
                ""title"": ""My most recent drawing. Spent over 100 hours."",
                ""link"": ""http://i.imgur.com/OUHDm.jpg"",
                ""is_album"": false
            },
            {
                ""id"": ""lDRB2"",
                ""title"": ""Imgur Office"",
                ""link"": ""http://alanbox.imgur.com/a/lDRB2"",
                ""is_album"": true,
                ""images_count"": 3,
                ""images"": [
                    {
                        ""id"": ""24nLu"",
                        ""link"": ""http://i.imgur.com/24nLu.jpg""
                    },
                    {
                        ""id"": ""Ziz25"",
                        ""link"": ""http://i.imgur.com/Ziz25.jpg""
                    },
                    {
                        ""id"": ""9tzW6"",
                        ""link"": ""http://i.imgur.com/9tzW6.jpg""
                    }
                ]
            }
        ]";

        List<GalleryItem> items = 
            JsonConvert.DeserializeObject<List<GalleryItem>>(json,
                new GalleryItemConverter());

        foreach (GalleryItem item in items)
        {
            Console.WriteLine("id: " + item.id);
            Console.WriteLine("title: " + item.title);
            Console.WriteLine("link: " + item.link);
            if (item.is_album)
            {
                GalleryAlbum album = (GalleryAlbum)item;
                Console.WriteLine("album images (" + album.images_count + "):");
                foreach (GalleryImage image in album.images)
                {
                    Console.WriteLine("    id: " + image.id);
                    Console.WriteLine("    link: " + image.link);
                }
            }
            Console.WriteLine();
        }
    }
}

और यहां उपरोक्त कार्यक्रम का आउटपुट है:

id: OUHDm
title: My most recent drawing. Spent over 100 hours.
link: http://i.imgur.com/OUHDm.jpg

id: lDRB2
title: Imgur Office
link: http://alanbox.imgur.com/a/lDRB2
album images (3):
    id: 24nLu
    link: http://i.imgur.com/24nLu.jpg
    id: Ziz25
    link: http://i.imgur.com/Ziz25.jpg
    id: 9tzW6
    link: http://i.imgur.com/9tzW6.jpg




c# math geometry convex-hull