SpatialLines वस्तुओं की समानता को कैसे मापें


9

मैंने SpatialLinesR: में दो ऑब्जेक्ट बनाए आकृति

इन वस्तुओं को इस तरह बनाया गया था:

library(sp)
xy <- cbind(x,y)
xy.sp = sp::SpatialPoints(xy)
spl1 <- sp::SpatialLines(list(Lines(Line(xy.sp), ID="a")))

अब मैं किसी तरह यह निष्कर्ष निकालना चाहता हूं कि यह वही रेखा है जो घुमाई और फूटी है, और यह कि उनके बीच का अंतर 0 के बराबर है (अर्थात आकार बराबर है)।

ऐसा करने के लिए, कोई maptoolsपैकेज का उपयोग कर सकता है और लाइन # 1 को घुमा सकता है , जैसे:

spl180 <- maptools::elide(spl1, rotate=180)

प्रत्येक घुमाई गई रेखा को तब rgeosपैकेज # 2 का उपयोग करके जाँच की जानी चाहिए , जैसे:

hdist <- rgeos::gDistance(spl180, spl2, byid=FALSE, hausdorff=TRUE)

हालाँकि, यह SpatialLinesवस्तुओं से मेल खाने के लिए इतना कम्प्यूटेशनल तरीका है , खासकर अगर वस्तुओं की संख्या 1000 के आसपास हो।

क्या इस काम को करने का कोई चतुर तरीका है?

PS इसके अलावा, ऊपर वर्णित दृष्टिकोण सभी संभावित घुमावों और फ़्लिप की गारंटी नहीं देता है।

P.S2। यदि लाइन # 1 को लाइन # 2 के संबंध में ज़ूम आउट किया जाता है, तो लाइन # 1 और # 2 के बीच का अंतर अभी भी 0 के बराबर होना चाहिए।

अपडेट करें:

यहां छवि विवरण दर्ज करें

जवाबों:


9

कोई भी सही मायने में सामान्य-उद्देश्य प्रभावी पद्धति आकृतियों के अभ्यावेदन को मानकीकृत करेगी ताकि वे आंतरिक प्रतिनिधित्व में रोटेशन, अनुवाद, प्रतिबिंब, या तुच्छ परिवर्तन पर नहीं बदलेंगे।

इसका एक तरीका यह है कि प्रत्येक जुड़े हुए आकार को एक छोर से शुरू करते हुए, किनारे की लंबाई और (हस्ताक्षरित) कोणों के एक वैकल्पिक अनुक्रम के रूप में सूचीबद्ध किया जाए। (कोई शून्य-लंबाई वाले किनारे या सीधे कोण होने के अर्थ में आकार "साफ" होना चाहिए।) इस अदर्शन को प्रतिबिंब के तहत बनाने के लिए, सभी कोणों को नकारात्मक करें यदि पहला गैर-शून्य एक नकारात्मक है।

(के किसी भी कनेक्ट किए पॉलीलाइन क्योंकि n कोने होगा एन -1 किनारों से अलग कर दिया एन -2 कोण, मैं इसे में सुविधाजनक पाया है Rकोड के नीचे दो सरणियों, किनारे लंबाई के लिए एक से मिलकर एक डेटा संरचना का उपयोग करने $lengthsऔर अन्य के लिए कोण, $anglesएक पंक्ति खंड में कोई कोण नहीं होगा, इसलिए ऐसी डेटा संरचना में शून्य-लंबाई सरणियों को संभालना महत्वपूर्ण है।)

इस तरह के प्रतिनिधित्व को शाब्दिक रूप से आदेश दिया जा सकता है। मानकीकरण प्रक्रिया के दौरान संचित फ्लोटिंग-पॉइंट त्रुटियों के लिए कुछ भत्ता बनाया जाना चाहिए। एक सुरुचिपूर्ण प्रक्रिया मूल निर्देशांक के कार्य के रूप में उन त्रुटियों का अनुमान लगाती है। नीचे दिए गए समाधान में, एक सरल विधि का उपयोग किया जाता है जिसमें दो लंबाई को समान माना जाता है जब वे एक रिश्तेदार आधार पर बहुत कम राशि से भिन्न होते हैं। कोण निरपेक्ष आधार पर केवल बहुत कम राशि से भिन्न हो सकते हैं।

अंतर्निहित अभिविन्यास के उत्क्रमण के तहत उन्हें अपरिवर्तनीय बनाने के लिए, पॉलिऑनोग्राफिक रूप से सबसे शुरुआती प्रतिनिधित्व को पॉलीलाइन और उसके उत्क्रमण के बीच चुनें।

बहु-भाग पॉलीइलाइन को संभालने के लिए, उनके घटकों को लेक्सिकोग्राफ़िक क्रम में व्यवस्थित करें।

यूक्लिडियन परिवर्तनों के तहत समतुल्यता वर्गों को खोजने के लिए ,

  • आकृतियों के मानकीकृत अभ्यावेदन बनाएँ।

  • मानकीकृत अभ्यावेदन का एक लेक्सोग्राफिक प्रकार करें।

  • समान अभ्यावेदन के अनुक्रमों की पहचान करने के लिए क्रमबद्ध क्रम से गुजरें।

अभिकलन समय O (n * log (n) * N) के समानुपाती होता है जहाँ n सुविधाओं की संख्या होती है और N किसी भी विशेषता में सबसे बड़ी संख्या है। यह कुशल है।

संभवतः यह पारित करने के लायक है कि उस केंद्र के बारे में पॉलीलाइन लंबाई, केंद्र और क्षणों जैसे आसानी से गणना किए गए अपरिवर्तनीय ज्यामितीय गुणों के आधार पर एक प्रारंभिक समूह , अक्सर पूरी प्रक्रिया को कारगर बनाने के लिए लागू किया जा सकता है। प्रत्येक को ऐसे प्रत्येक प्रारंभिक समूह के भीतर बधाई सुविधाओं के उपसमूहों को खोजने की आवश्यकता है। यहां दी गई पूरी विधि को आकृतियों के लिए आवश्यक होगा जो अन्यथा इतनी उल्लेखनीय रूप से समान होगी कि ऐसे सरल आक्रमणकारी अभी भी उन्हें अलग नहीं करेंगे। उदाहरण के लिए, रेखापुंज डेटा से निर्मित सरल विशेषताओं में ऐसी विशेषताएं हो सकती हैं। हालाँकि, यहाँ दिए गए समाधान वैसे भी इतने कुशल हैं, कि यदि कोई इसे लागू करने के प्रयास में जाने वाला है, तो यह अपने आप ही ठीक काम कर सकता है।


उदाहरण

बाएं हाथ का आंकड़ा पांच पॉलीलाइन प्लस 15 से अधिक दिखाता है जो कि यादृच्छिक अनुवाद, रोटेशन, प्रतिबिंब और आंतरिक अभिविन्यास (जो दिखाई नहीं देता है) के उत्क्रमण के माध्यम से प्राप्त किया गया था। दाएं हाथ के आंकड़े उन्हें उनके यूक्लिडियन तुल्यता वर्ग के अनुसार रंग देते हैं: एक सामान्य रंग के सभी आंकड़े बधाई हैं; अलग-अलग रंग बधाई नहीं हैं।

आकृति

Rकोड इस प्रकार है। जब इनपुट्स को 500 आकृतियों, 500 अतिरिक्त (सर्वांगसम) आकृतियों में अद्यतन किया गया, तो प्रति आकृति 100 चक्कर के साथ, इस मशीन पर निष्पादन का समय 3 सेकंड था।

यह कोड अधूरा है: क्योंकि Rइसमें मूल लेक्सोग्राफिक सॉर्ट नहीं है, और मुझे खरोंच से एक कोडिंग की तरह महसूस नहीं हुआ था, मैं बस प्रत्येक मानकीकृत आकार के पहले समन्वय पर छँटाई करता हूं। यहां बनाई गई यादृच्छिक आकृतियों के लिए यह ठीक होगा, लेकिन उत्पादन कार्य के लिए एक पूर्ण लेक्सिकोग्राफिक प्रकार लागू किया जाना चाहिए। इस परिवर्तन से कार्य order.shapeप्रभावित होगा। इसका इनपुट मानकीकृत आकार की एक सूची है sऔर इसका आउटपुट अनुक्रमित अनुक्रम है sजो इसमें क्रमबद्ध होगा।

#
# Create random shapes.
#
n.shapes <- 5      # Unique shapes, up to congruence
n.shapes.new <- 15 # Additional congruent shapes to generate
p.mean <- 5        # Expected number of vertices per shape
set.seed(17)       # Create a reproducible starting point
shape.random <- function(n) matrix(rnorm(2*n), nrow=2, ncol=n)
shapes <- lapply(2+rpois(n.shapes, p.mean-2), shape.random)
#
# Randomly move them around.
#
move.random <- function(xy) {
  a <- runif(1, 0, 2*pi)
  reflection <- sign(runif(1, -1, 1))
  translation <- runif(2, -8, 8)
  m <- matrix(c(cos(a), sin(a), -sin(a), cos(a)), 2, 2) %*%
    matrix(c(reflection, 0, 0, 1), 2, 2)
  m <- m %*% xy + translation
  if (runif(1, -1, 0) < 0) m <- m[ ,dim(m)[2]:1]
  return (m)
}
i <- sample(length(shapes), n.shapes.new, replace=TRUE)
shapes <- c(shapes, lapply(i, function(j) move.random(shapes[[j]])))
#
# Plot the shapes.
#
range.shapes <- c(min(sapply(shapes, min)), max(sapply(shapes, max)))
palette(gray.colors(length(shapes)))
par(mfrow=c(1,2))
plot(range.shapes, range.shapes, type="n",asp=1, bty="n", xlab="", ylab="")
invisible(lapply(1:length(shapes), function(i) lines(t(shapes[[i]]), col=i, lwd=2)))
#
# Standardize the shape description.
#
standardize <- function(xy) {
  n <- dim(xy)[2]
  vectors <- xy[ ,-1, drop=FALSE] - xy[ ,-n, drop=FALSE]
  lengths <- sqrt(colSums(vectors^2))
  if (which.min(lengths - rev(lengths))*2 < n) {
    lengths <- rev(lengths)
    vectors <- vectors[, (n-1):1]
  }
  if (n > 2) {
    vectors <- vectors / rbind(lengths, lengths)
    perps <- rbind(-vectors[2, ], vectors[1, ])
    angles <- sapply(1:(n-2), function(i) {
      cosine <- sum(vectors[, i+1] * vectors[, i])
      sine <- sum(perps[, i+1] * vectors[, i])
      atan2(sine, cosine)
    })
    i <- min(which(angles != 0))
    angles <- sign(angles[i]) * angles
  } else angles <- numeric(0)
  list(lengths=lengths, angles=angles)
}
shapes.std <- lapply(shapes, standardize)
#
# Sort lexicographically.  (Not implemented: see the text.)
#
order.shape <- function(s) {
  order(sapply(s, function(s) s$lengths[1]))
}
i <- order.shape(shapes.std)
#
# Group.
#
equal.shape <- function(s.0, s.1) {
  same.length <- function(a,b) abs(a-b) <= (a+b) * 1e-8
  same.angle <- function(a,b) min(abs(a-b), abs(a-b)-2*pi) < 1e-11
  r <- function(u) {
    a <- u$angles
    if (length(a) > 0) {
      a <- rev(u$angles)
      i <- min(which(a != 0))
      a <- sign(a[i]) * a
    }
    list(lengths=rev(u$lengths), angles=a)
  }
  e <- function(u, v) {
    if (length(u$lengths) != length(v$lengths)) return (FALSE)
    all(mapply(same.length, u$lengths, v$lengths)) &&
      all(mapply(same.angle, u$angles, v$angles))
    }
  e(s.0, s.1) || e(r(s.0), s.1)
}
g <- rep(1, length(shapes.std))
for (j in 2:length(i)) {
  i.0 <- i[j-1]
  i.1 <- i[j]
  if (equal.shape(shapes.std[[i.0]], shapes.std[[i.1]])) 
    g[j] <- g[j-1] else g[j] <- g[j-1]+1
}
palette(rainbow(max(g)))
plot(range.shapes, range.shapes, type="n",asp=1, bty="n", xlab="", ylab="")
invisible(lapply(1:length(i), function(j) lines(t(shapes[[i[j]]]), col=g[j], lwd=2)))

जब कोई परिवर्तन के समूह में मनमाना फैलाव (या "आइसोटेटीज़") शामिल करता है, तो समतुल्यता वर्ग समरूप ज्यामिति के अनुरूपता वर्ग होते हैं । इस जटिलता को आसानी से नियंत्रित किया जाता है: उदाहरण के लिए, कुल इकाई लंबाई के लिए सभी पॉलीइन्स को मानकीकृत करें।
whuber

बहुत बहुत धन्यवाद। बस एक सवाल: क्या आकार को स्पैटियललाइन या स्पैटियल पॉलीगॉन के रूप में दर्शाया जाना चाहिए?
क्लाउस क्लॉस

बहुभुज एक और जटिलता पैदा करते हैं: उनकी सीमाओं का कोई निश्चित समापन बिंदु नहीं है। इसे संभालने के कई तरीके हैं, जैसे कि (कहने) को शुरू करने के लिए प्रतिनिधित्व को मानकीकृत करना। वह शीर्ष जो पहले xy lexicographic क्रम में क्रमबद्ध होता है और बहुभुज के चारों ओर एक वामावर्त दिशा में आगे बढ़ता है। (एक topologically "स्वच्छ" जुड़ा बहुभुज में केवल एक ही ऐसा शीर्ष होगा।) क्या एक आकृति को बहुभुज माना जाता है या पॉलीलाइन इस बात पर निर्भर करता है कि यह किस तरह की विशेषता का प्रतिनिधित्व करता है: अंकों की किसी भी बंद सूची को कहने का कोई आंतरिक तरीका नहीं है। एक पॉलीलाइन या बहुभुज होने का इरादा है।
whuber

एक साधारण प्रश्न के लिए क्षमा करें, लेकिन मुझे इसे आपके उदाहरण को समझने के लिए कहना चाहिए। आपकी ऑब्जेक्ट आकृतियाँ.स्टेड में $ लंबाई और $ कोण दोनों हैं। यदि, हालांकि, मैं इस कोड को अपने xy डेटा (उदाहरण [1, 3093.5 -2987.8 [2, 3072.7 -2991.0 आदि) पर चलाता हूं, तो यह कोणों का अनुमान नहीं लगाता है, न ही आकृतियों को आकर्षित करता है। अगर मैं प्लॉट (आकार [[1]]) चलाता हूं, तो मैं स्पष्ट रूप से अपनी पॉलीलाइन देख सकता हूं। तो, मुझे अपने डेटा पर अपने कोड का परीक्षण करने में सक्षम होने के लिए आर में पॉलीलाइन कैसे बचाना चाहिए?
क्लाउसोस क्लाउसोस

मैंने उसी डेटा संरचना के साथ शुरुआत की जो आपने किया था: (x, y) निर्देशांक की एक सरणी। मेरी सरणियों ने उन निर्देशांक को स्तंभों में डाल दिया (जैसे कि आपने rbind(x,y)इसके बजाय उपयोग किया था cbind(x,y))। आपको बस इतना ही चाहिए: spपुस्तकालय का उपयोग नहीं किया जाता है। आप क्या विस्तार से किया जाता है का पालन करना चाहते हैं, मैं सुझाव है कि आप के साथ, कहते हैं, बाहर शुरू n.shapes <- 2, n.shapes.new <- 3और p.mean <- 1। फिर shapes, shapes.stdआदि सभी आसानी से निरीक्षण किए जाने के लिए पर्याप्त छोटे हैं। सुरुचिपूर्ण - और "सही" तरीका - इन सब से निपटने के लिए मानकीकृत सुविधा अभ्यावेदन का एक वर्ग बनाना होगा ।
whuber

1

आप मनमाना रोटेशन और फैलाव के साथ बहुत कुछ पूछ रहे हैं! यह निश्चित नहीं है कि हौसडॉर्फ दूरी कितनी उपयोगी होगी, लेकिन इसकी जांच करें। मेरा दृष्टिकोण सस्ते डेटा के माध्यम से जांच करने के मामलों की संख्या को कम करना होगा। उदाहरण के लिए, आप महंगी तुलनाओं को छोड़ सकते हैं यदि दो अलंकारों की लंबाई पूर्णांक अनुपात नहीं है ( पूर्णांक / स्नातक स्केलिंग मानकर )। यदि बाउंडिंग बॉक्स क्षेत्र या उनके उत्तल पतवार क्षेत्र एक अच्छे अनुपात में हैं, तो आप इसी तरह देख सकते हैं। मुझे यकीन है कि वहाँ बहुत सारे सस्ते चेक हैं जो आप सेंट्रो के खिलाफ कर सकते हैं, जैसे शुरू / अंत से दूरी या कोण।

तभी, यदि आप स्केलिंग का पता लगाते हैं, तो इसे पूर्ववत करें और वास्तव में महंगी जांच करें।

स्पष्टता: मैं उन पैकेजों को नहीं जानता जो आप उपयोग कर रहे हैं। पूर्णांक अनुपात से मेरा मतलब है कि आपको दोनों दूरियों को विभाजित करना चाहिए, जांचें कि क्या परिणाम एक पूर्णांक है, यदि नहीं, तो उस मूल्य को उल्टा करें (क्या आप गलत आदेश उठाया जा सकता है) और पुन: जांच करें। यदि आपको पूर्णांक या पर्याप्त पास मिलता है, तो आप यह अनुमान लगा सकते हैं कि शायद स्केलिंग चल रही थी। या यह सिर्फ दो अलग-अलग आकार हो सकता है।

बाउंडिंग बॉक्स के लिए, आपको संभवतः आयत के विपरीत अंक मिले हैं जो इसका प्रतिनिधित्व करते हैं, इसलिए उनमें से क्षेत्र को प्राप्त करना सरल अंकगणित है। अनुपात की तुलना के पीछे सिद्धांत समान है, बस परिणाम चुकता होगा। उत्तल पतवार के साथ परेशान मत करो अगर आप उन्हें उस आर पैकेज से अच्छी तरह से बाहर नहीं निकाल सकते हैं, तो यह सिर्फ एक विचार था (संभवतः वैसे भी सस्ता नहीं है)।


बहुत बहुत धन्यवाद। क्या आप बता सकते हैं कि कैसे पता लगाया जाए कि दो अलंकारों की लंबाई पूर्णांक अनुपात नहीं है? इसके अलावा, मैं बहुत सराहना करता हूं यदि आप चेकिंग का उदाहरण दे सकते हैं "यदि बाउंडिंग बॉक्स क्षेत्र या उत्तल पतवार क्षेत्र एक अच्छे अनुपात में हैं"
क्लाउस क्लॉज़ोस

उदाहरण के लिए, यदि मैं स्थानिक डेटा से स्थानिक बाउंडिंग बॉक्स निकालता हूं, तो मुझे केवल दो अंक मिलते हैं: spl <- sp :: SpatialLines (सूची (लाइनें (xy.sp), ID = i))) b <- bbox ( spl)
क्लाउस क्लाउसोस

मुख्य पोस्ट बढ़ाया।
lynxlynxlynx

"यदि आपको एक पूर्णांक या पर्याप्त पास मिलता है, तो आप यह अनुमान लगा सकते हैं कि शायद स्केलिंग चल रही थी।" क्या कोई उपयोगकर्ता 1.4 या इतने के पैमाने को लागू नहीं कर सकता है?
जर्मेन कैरिलो

ज़रूर, लेकिन मेरी धारणा स्पष्ट की गई थी, खासकर बाद के संपादन के साथ। मैं वेबमैप शैली को ज़ूम करने की कल्पना कर रहा था, जहां एक अच्छी तरह से सीमित है।
lynxlynxlynx

1

इन पॉलीइन्स की तुलना करने का एक अच्छा तरीका प्रत्येक कोने में (दूरी, टर्न एंगल्स) के अनुक्रम के रूप में एक प्रतिनिधित्व पर भरोसा P1, P2, ..., PNकरना होगा: बिंदुओं से बनी एक पंक्ति के लिए , ऐसा क्रम होगा:

(दूरी (P1P2), कोण (P1, P2, P3), दूरी (P2P3), ..., कोण (P (N-2), P (N-1), PN), दूरी (P-N-1) ) पीएन))।

आपकी आवश्यकताओं के अनुसार, दो पंक्तियाँ समान हैं यदि और केवल यदि उनके संगत अनुक्रम समान हैं (तो मोडुलो आदेश और कोण दिशा)। संख्या क्रमों की तुलना तुच्छ है।

प्रत्येक पॉलीलाइन अनुक्रम की गणना केवल एक बार और, जैसा कि lynxlynxlynx द्वारा सुझाया गया है, केवल एक ही तुच्छ विशेषताओं (लंबाई, कोने की संख्या ...) वाले पॉलीलाइन के लिए अनुक्रम समानता का परीक्षण करना, गणना वास्तव में तेज़ होनी चाहिए!


यह सही विचार है। इसके लिए वास्तव में काम करने के लिए, हालांकि, कई विवरणों को संबोधित करने की आवश्यकता है, जैसे प्रतिबिंबों, आंतरिक अभिविन्यास, कई जुड़े घटकों की संभावना और फ्लोटिंग पॉइंट राउंडऑफ़ त्रुटि। मेरे द्वारा प्रदान किए गए समाधान में उनकी चर्चा की गई है।
whuber

हां, मैंने केवल मुख्य विचार का वर्णन किया है। आपका उत्तर उल्लेखनीय रूप से अधिक पूर्ण है (जैसे अक्सर :-)
जुलिएन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.