2011-01-31 4 views
5

मुझे एक आकार में आत्म-चौराहे से छुटकारा पाने की आवश्यकता है। आकार बिंदुओं की एक सरणी से बनाया गया है, इसलिए उस आकार के सभी खंड रेखाएं हैं। (केवल लाइनों, नहीं घटता और आर्क्स)एल्गोरिदम स्वयं-छेड़छाड़ किए गए पथ 2 डी को अलग-अलग आत्म-अंतर वाले पथों में विभाजित करने के लिए नहीं?

इससे पहले, मैं से कि अंक, इसमें से एक क्षेत्र का निर्माण, और फिर मैं कई Path2Ds, जो किसी भी तरह पिछले की उपपथ थे बनाई गई अपनी PathIterator का उपयोग कर Path2D बनाने की कोशिश की पथ, और इसलिए आत्म-घुसपैठ चले गए थे। लेकिन यह कुछ पथों के लिए काम नहीं कर रहा है - आत्म-चौराहे अभी भी वहां रहती है।

तो क्या आप मुझे किसी ऐसे स्थान पर इंगित कर सकते हैं जहां मुझे समान काम करने के लिए अच्छा एल्गोरिदम मिल सकता है?

संपादित करें: मुझे कहीं भी कुछ भी उपयोगी नहीं मिला है, इसलिए मैंने अपना स्वयं का एल्गोरिदम लिखा है। जवाब देखें।

+0

एक एकल घन बेज़ीर आत्म-अंतर कर सकता है, इसलिए सामान्य मामले में आपको बेज़ीर को दो में विभाजित करने की आवश्यकता होगी। "बेज़ीयर वक्र उपखंड" या "डी कास्टेलजौ के एल्गोरिदम" की अच्छी व्याख्या की तलाश करें। –

+0

@ पीटर टेलर - नहीं, जैसा कि मैंने कहा, कोई बेजियर वक्र नहीं हैं। केवल लाइनें – Rogach

+0

मैंने इसे 'एरिया' का उपयोग करके सफलतापूर्वक किया है और आपने जो समस्या का वर्णन किया है उसे कभी नहीं देखा है। क्या आप ऐसे पथ का उदाहरण पोस्ट कर सकते हैं जिसके परिणामस्वरूप 'एरिया' में आत्म-चौराहे हो? – finnw

उत्तर

1

तो Area आप के लिए काम नहीं कर रहा है, तो आप अपने Shape त्रिकोण, या (GL_LINE_LOOP विकल्प का उपयोग) के एक सेट में सिर्फ सीमा किनारों विघटित करने के लिए एक GLUtessellator उपयोग करने का प्रयास कर सकता है।

+0

वैसे, क्या आप क्षेत्र का उपयोग करके विभाजन के लिए अपना कोड पोस्ट कर सकते हैं? शायद मैं अपने कार्यक्रम में कुछ गलत कर रहा हूँ। – Rogach

+0

@Rogach, मेरे पास अभी नमूना खोजने का समय नहीं है, लेकिन मैंने आपके कोड को संक्षेप में देखा और मैंने एक संभावित बग देखा: आप 'SEG_CLOSE' को अनदेखा करते हैं। जब आप उस ध्वज को प्राप्त करते हैं तो आपको वर्तमान लूप को बंद करना चाहिए (यदि आवश्यक हो तो अंत में पहली बिंदु की एक प्रति जोड़ना चाहिए।) यह समस्या नहीं हो सकती है, हालांकि 'SEG_CLOSE' हमेशा' SEG_MOVETO' के बाद या उसके अंत तक होती है यात्रा। – finnw

+0

हां, यह एक समस्या हो सकती है। लेकिन उस पथ के लिए, "करीबी" हमेशा "चाल" के बाद किया जाता था। वैसे भी, मुझे लगता है कि मेरे पास एल्गोरिदम को विभाजित करने के लिए अच्छा विचार है। जब मैं करूँगा तो मैं इसे इस प्रश्न में पोस्ट करूंगा। – Rogach

1

इसलिए, चूंकि मैं वेब पर ऐसा कुछ नहीं ढूंढ पाया, इसलिए मैंने अपना स्वयं का एल्गोरिदम लिखा।

यह बेहद अप्रभावी हो सकता है, लेकिन यह मेरे लिए पर्याप्त तेज़ काम करता है।

यहाँ यह जाता है:

/** 
* Takes a polygon, defined by a list of lines, and splits it into several 
* paths on points of intersection. If non-self-intersected path is passed in, 
* the same path is returned. 
* @param path 
* @return 
*/ 
public static List<List<Line2D>> splitPath(List<Line2D> lines) { 
    List<List<Line2D>> splitted = new ArrayList<List<Line2D>>(); 
    // find intersections. 
    loop1: 
    for (Line2D l1 : lines) { 
     for (Line2D l2 : lines) { 
      if (l1 == l2) continue; 
      Point2D intr; 
      if ((intr = linesIntersect(l1, l2)) != null) { 
       // creating two splitted subpaths 
       int i1 = lines.indexOf(l1); 
       int i2 = lines.indexOf(l2); 

       List<Line2D> subpath1 = new ArrayList<Line2D>(); 
       subpath1.addAll(lines.subList(0, i1)); 
       subpath1.add(new Line2D.Double(l1.getP1(), intr)); 
       subpath1.add(new Line2D.Double(intr, l2.getP2())); 
       subpath1.addAll(lines.subList(i2 + 1, lines.size())); 
       splitted.addAll(splitPath(subpath1)); 

       List<Line2D> subpath2 = new ArrayList<Line2D>(); 
       subpath2.add(new Line2D.Double(intr, l1.getP2())); 
       subpath2.addAll(lines.subList(i1 + 1, i2)); 
       subpath2.add(new Line2D.Double(l2.getP1(), intr)); 
       splitted.addAll(splitPath(subpath2)); 
       break loop1; 
      } 
     } 
    } 
    if (splitted.size() > 0) { 
     return splitted; 
    } else { 
     return Collections.singletonList(lines); 
    } 
} 

/** 
* Returns point of intersection of this line segments. 
* @param l1 
* @param l2 
* @return 
*/ 
public static Point2D linesIntersect(Line2D l1, Line2D l2) { 
    if (l1.getP1().equals(l2.getP2()) || l1.getP2().equals(l2.getP1())) return null; 
    Point2D inter = lineIntersection(l1, l2); 
    if (inter == null) return null; 
    double infS = HEADER.infS; 
    double x = inter.getX(); 
    if (((l1.getX1() > l1.getX2()) ? (x + infS > l1.getX2() && x - infS < l1.getX1()) : (x - infS < l1.getX2() && x + infS > l1.getX1())) && 
      ((l2.getX1() > l2.getX2()) ? (x + infS > l2.getX2() && x - infS < l2.getX1()) : (x - infS < l2.getX2() && x + infS > l2.getX1()))) { 
     return inter; 
    } else { 
     return null; 
    } 
} 

/** 
* Returns point of lines intersection, or null if they are parallel. 
* @param l1 
* @param l2 
* @return 
*/ 
public static Point2D lineIntersection(Line2D l1, Line2D l2) { 
    double a1 = l1.getY2() - l1.getY1(); 
    double b1 = l1.getX1() - l1.getX2(); 
    double c1 = a1*l1.getX1() + b1*l1.getY1(); 
    double a2 = l2.getY2() - l2.getY1(); 
    double b2 = l2.getX1() - l2.getX2(); 
    double c2 = a2*l2.getX1() + b2*l2.getY1(); 
    double det = a1*b2 - a2*b1; 
    if (det != 0) { 
     double x = (b2*c1 - b1*c2)/det; 
     double y = (a1*c2 - a2*c1)/det; 
     return new Point2D.Double(x, y); 
    } else { 
     // lines are parallel 
     return null; 
    } 
} 
+1

मैं इस मुद्दे को भी देख रहा हूं - मुझे संदेह है कि आप एल्गोरिदम माध्यमिक चौराहे को संभाल नहीं लेते हैं (यदि उपपैथ 1 और उपपैथ 2 – tofarr

+0

के बीच एक छेड़छाड़ है, तो मुझे याद आया। मैं एक बेहतर एल्गोरिदम के बारे में सोचूंगा। ध्यान देने के लिए धन्यवाद! – Rogach

1

मैं अपने प्रश्न/उत्तर मामले में मैं कुछ इसी तरह अपने आप को लागू करने के लिए किया था बुकमार्क किए गए, लेकिन फिर मैं GEOS परियोजना जो इस को प्राप्त करने का एक आसान तरीका है पाया। मैं पाइथन/डीजेगो से जीईओएस को बुला रहा हूं, लेकिन पूरी बात JTS (Java Topology Suite) पर आधारित है, इसलिए मैं वहां से शुरू करूंगा और निम्नलिखित पायथन को psuedo-code के रूप में मानूंगा।

असल में, यूनिअन आपरेशन बस जुड़े भागों में एक पंक्ति विभाजित करेगा कि क्या यह बस जुड़ा हुआ नहीं है (here समझाया गया है), इसलिए लाइन UNIONing साथ यह पहली बात है करता है कि हम क्या जरूरत है:

line = LineString(list_of_lines_x_y_coordinates) 
# union with first point splits into MultiLineString containing segments 
segments = line.union(line[0]) 
संबंधित मुद्दे