मैं आर्कपी का उपयोग करके अपने आकार में हर बहुभुज के लिए एक उन्मुख बफर बनाना चाहता हूं। उन्मुख होने से मेरा मतलब है कि मेरे पास दो कोण हैं a1 और a2 जो बफर की दिशा में बाधा डालते हैं। यह नीचे दिए गए ग्राफ में दर्शाया गया है:
कोई विचार?
मैं आर्कपी का उपयोग करके अपने आकार में हर बहुभुज के लिए एक उन्मुख बफर बनाना चाहता हूं। उन्मुख होने से मेरा मतलब है कि मेरे पास दो कोण हैं a1 और a2 जो बफर की दिशा में बाधा डालते हैं। यह नीचे दिए गए ग्राफ में दर्शाया गया है:
कोई विचार?
जवाबों:
यह उत्तर प्रश्न को एक बड़े संदर्भ में रखता है, एक कुशल एल्गोरिदम का वर्णन करता है जो सुविधाओं के आकार-प्रकार के प्रतिनिधित्व पर लागू होता है (जैसे कि "वैक्टर" या "अंक के" लिनेस्टर), इसके आवेदन के कुछ उदाहरण दिखाता है, और उपयोग करने या पोर्ट करने के लिए वर्किंग कोड देता है। एक जीआईएस वातावरण।
यह एक रूपात्मक फैलाव का एक उदाहरण है । पूर्ण सामान्यता में, एक फैलाव एक क्षेत्र के बिंदुओं को उनके पड़ोस में "फैलाता है"; बिंदुओं का संग्रह जहां वे हवा करते हैं वह "फैलाव" है। जीआईएस में आवेदन कई हैं: आग के प्रसार, सभ्यताओं के आंदोलन, पौधों के प्रसार, और बहुत कुछ मॉडलिंग।
गणितीय रूप से, और बहुत महान (लेकिन उपयोगी) सामान्यता में, एक फैलाव रिअमानियन मैनिफोल्ड में कई बिंदुओं का एक सेट फैलाता है (जैसे कि एक विमान, गोला, या दीर्घवृत्त)। स्प्रेडिंग को इन बिंदुओं पर स्पर्शरेखा बंडल के सबसेट द्वारा निर्धारित किया जाता है। इसका मतलब है कि प्रत्येक बिंदु पर वैक्टर (दिशाओं और दूरी) का एक सेट दिया जाता है (मैं इसे "पड़ोस" कहता हूं); इनमें से प्रत्येक वैक्टर अपने बेस पॉइंट पर शुरू होने वाले एक जियोडेसिक पथ का वर्णन करता है। आधार बिंदु इन सभी रास्तों के छोर तक "फैला हुआ" है। ("फैलाव" की बहुत अधिक सीमित परिभाषा के लिए, जिसे पारंपरिक रूप से छवि प्रसंस्करण में नियोजित किया गया है, विकिपीडिया लेख देखें । प्रसार समारोह को घातीय मानचित्र के रूप में जाना जाता है। अंतर ज्यामिति में।)
किसी विशेषता का "बफरिंग" इस तरह के फैलाव के सबसे सरल उदाहरणों में से एक है: फीचर के प्रत्येक बिंदु के आसपास निरंतर त्रिज्या (बफर त्रिज्या) की एक डिस्क (कम से कम वैचारिक रूप से) बनाई जाती है। इन डिस्क का संघ बफर है।
यह सवाल थोड़ा और अधिक जटिल फैलाव की गणना के लिए पूछता है जहां प्रसार को कोणों की एक दी गई सीमा (जो कि एक परिपत्र क्षेत्र के भीतर है) के भीतर ही होने की अनुमति है। यह केवल उन विशेषताओं के लिए समझ में आता है जो बिना किसी सराहनीय घुमावदार सतह को घेरते हैं (जैसे कि गोले या दीर्घवृत्त पर छोटी विशेषताएं या विमान में कोई भी सुविधाएँ)। जब हम प्लेन में काम कर रहे होते हैं तो सभी सेक्टरों को एक ही दिशा में उन्मुख करना भी सार्थक होता है। (अगर हम हवा से आग के प्रसार को मॉडलिंग कर रहे थे, हालांकि, हम चाहते हैं कि सेक्टर हवा के साथ उन्मुख हों और उनके आकार हवा की गति के साथ-साथ भिन्न भी हो सकते हैं: यह मैंने फैलाव की सामान्य परिभाषा के लिए एक प्रेरणा है। ) (एक दीर्घवृत्त जैसी घुमावदार सतहों पर सभी क्षेत्रों को "समान" दिशा में उन्मुख करना सामान्य रूप से असंभव है।)
निम्नलिखित परिस्थितियों में फैलाव की गणना करना अपेक्षाकृत आसान है:
विमान में सुविधा है (यानी हम सुविधा के नक्शे को पतला कर रहे हैं और उम्मीद है कि नक्शा काफी सटीक है)।
फैलाव स्थिर होगा : सुविधा के प्रत्येक बिंदु पर प्रसार समान अभिविन्यास के पड़ोस के भीतर होगा।
यह आम पड़ोस उत्तल है। उत्तलता गणना को सरल और गति प्रदान करती है।
यह प्रश्न ऐसी विशिष्ट परिस्थितियों में फिट बैठता है: यह परिपत्र क्षेत्रों द्वारा मूल बहुभुजों के फैलाव की मांग करता है जिनकी उत्पत्ति (डिस्क के केंद्र जहां से वे आए थे) आधार बिंदुओं पर स्थित हैं। बशर्ते कि उन क्षेत्रों में 180 डिग्री से अधिक की अवधि न हो, वे उत्तल होंगे। (बड़े क्षेत्रों को हमेशा आधे में दो उत्तल क्षेत्रों में विभाजित किया जा सकता है; दो छोटे फैलाव का मिलन वांछित परिणाम देगा।)
क्योंकि हम यूक्लिडियन गणना कर रहे हैं - विमान में फैलने का काम - हम केवल उस बिंदु तक फैलाव पड़ोस का अनुवाद करके एक बिंदु को पतला कर सकते हैं । (ऐसा करने में सक्षम होने के लिए, पड़ोस को एक मूल की आवश्यकता हैजो आधार बिंदु के अनुरूप होगा। उदाहरण के लिए, इस प्रश्न में क्षेत्रों की उत्पत्ति उस चक्र का केंद्र है, जहां से वे बने हैं। यह उत्पत्ति क्षेत्र की सीमा पर झूठ बोलने के लिए होती है। मानक जीआईएस बफरिंग ऑपरेशन में पड़ोस अपने केंद्र में मूल के साथ एक चक्र है; अब मूल चक्र के आंतरिक भाग में स्थित है। एक उत्पत्ति का चयन करना कम्प्यूटेशनल रूप से कोई बड़ी बात नहीं है, क्योंकि उत्पत्ति के परिवर्तन से केवल पूरे फैलाव को बदल दिया जाता है, लेकिन यह प्राकृतिक घटनाओं की मॉडलिंग के संदर्भ में एक बड़ी बात हो सकती है। sector
कोड में समारोह नीचे दर्शाता है कि एक मूल निर्दिष्ट किया जा सकता है।)
एक पंक्ति खंड को पतला करना मुश्किल हो सकता है, लेकिन उत्तल पड़ोस के लिए हम दो एंडपॉइंट के फैलाव के संघटन के साथ-साथ सावधानीपूर्वक चुने गए समानांतर चतुर्भुज के रूप में फैलाव बना सकते हैं। (अंतरिक्ष के हित में मैं इस तरह से गणितीय दावे को साबित करने के लिए विराम नहीं दूंगा, लेकिन पाठकों को अपने स्वयं के प्रमाणों का प्रयास करने के लिए प्रोत्साहित करता हूं क्योंकि यह एक व्यावहारिक अभ्यास है।) यहां तीन क्षेत्रों (गुलाबी रंग में दिखाया गया) का उपयोग करते हुए एक चित्रण किया गया है। उनके पास यूनिट रेडी है और उनके कोणों को शीर्षकों में दिया गया है। लाइन सेगमेंट की लंबाई 2 है, क्षैतिज है, और काले रंग में दिखाया गया है:
समांतर चतुर्भुज गुलाबी बिंदुओं का पता लगाकर पाए जाते हैं जो कि ऊर्ध्वाधर दिशा में खंड से यथासंभव दूर हैं । यह दो निचले बिंदुओं और दो ऊपरी बिंदुओं को लाइनों के साथ देता है जो कि खंड के समानांतर हैं। हमें बस चार बिंदुओं को समांतर चतुर्भुज (नीले रंग में दिखाया गया है) में शामिल होना है। ध्यान दें, दाईं ओर, यह तब भी कैसे समझ में आता है जब सेक्टर केवल एक लाइन सेगमेंट (और एक सच्चा बहुभुज) नहीं है: वहाँ, खंड पर हर बिंदु को दिशा में 171 डिग्री पूर्व में उत्तर की ओर दूरी के लिए अनुवाद किया गया है 0 से 1. इन समापन बिंदुओं का सेट दिखाया गया समांतर चतुर्भुज है। इस गणना का विवरण नीचे दिए गए कोड में buffer
निर्धारित फ़ंक्शन में दिखाई देता है dilate.edges
।
एक पॉलीलाइन को पतला करने के लिए , हम इसे बनाने वाले बिंदुओं और खंडों के फैलाव का संघ बनाते हैं। dilate.edges
इस लूप के प्रदर्शन की अंतिम दो पंक्तियाँ ।
बहुभुज को पतला करने के लिए बहुभुज के आंतरिक भाग के साथ-साथ इसकी सीमा के फैलाव की आवश्यकता होती है। (यह कथन फैलाव पड़ोस के बारे में कुछ धारणाएं बनाता है। एक यह है कि सभी पड़ोसों में बिंदु (0,0) शामिल है, जो बहुभुज की गारंटी देता है, इसके फैलाव के भीतर शामिल है। चर पड़ोस के मामले में यह भी माना जाता है कि किसी भी इंटीरियर का फैलाव। बहुभुज का बिंदु सीमा के फैलाव से आगे नहीं बढ़ेगा। यह निरंतर पड़ोस के लिए मामला है।)
आइए कुछ उदाहरणों पर गौर करें कि यह कैसे काम करता है, पहले एक नॉनगन (विस्तार प्रकट करने के लिए चुना गया) और फिर एक सर्कल के साथ (प्रश्न में चित्रण से मेल खाने के लिए चुना गया)। उदाहरण वही तीन पड़ोस का उपयोग करना जारी रखेंगे, लेकिन 1/3 के दायरे तक सिकुड़ते रहेंगे।
इस आंकड़े में बहुभुज का आंतरिक भाग ग्रे है, बिंदु फैलाव (क्षेत्र) गुलाबी है, और किनारे फैलाव (समांतर चतुर्भुज) नीले हैं।
"सर्कल" वास्तव में सिर्फ एक 60-गॉन है, लेकिन यह अच्छी तरह से एक सर्कल का अनुमान लगाता है।
जब आधार सुविधा को एन बिंदुओं द्वारा और एम बिंदुओं द्वारा फैलाव पड़ोस का प्रतिनिधित्व किया जाता है, तो इस एल्गोरिथ्म में ओ (एन एम) प्रयास की आवश्यकता होती है । संघ में कोने और किनारों की गंदगी को सरल करके इसका पालन किया जाना चाहिए, जिसमें ओ (एन एम लॉग (एन एम)) प्रयास की आवश्यकता हो सकती है: जो कि जीआईएस को करने के लिए कहने के लिए कुछ है; हमें वह प्रोग्राम नहीं करना चाहिए।
उत्तल आधार सुविधाओं के लिए कम्प्यूटेशनल प्रयास को ओ (एम + एन) में सुधार किया जा सकता है (क्योंकि आप मूल दो आकृतियों की सीमाओं का वर्णन करने वाले कोने की सूचियों को उचित रूप से विलय करके नई सीमा के चारों ओर यात्रा कैसे कर सकते हैं)। यह किसी भी बाद की सफाई की आवश्यकता नहीं होगी।
जब बेस पड़ोस में धीरे-धीरे परिवर्तन पड़ोस और / या अभिविन्यास बदल जाता है, तो आधार के फैलाव को इसके समापन बिंदुओं के संघनन के उत्तल पतवार से बारीकी से लगाया जा सकता है। यदि दो फैलाव पड़ोस में एम 1 और एम 2 बिंदु हैं, तो यह शमोस और प्रिपेटा, कम्प्यूटेशनल ज्यामिति में वर्णित एल्गोरिदम का उपयोग करके ओ (एम 1 + एम 2) प्रयास के साथ पाया जा सकता है । इसलिए, K = M1 + M2 + ... + M (N) N फैलाव पड़ोस में कुल संख्याओं का होना, हम O (K * log (K)) समय में फैलाव की गणना कर सकते हैं।
अगर हम चाहते हैं कि एक सामान्य बफर है तो हम इस तरह के सामान्यीकरण से क्यों निपटना चाहेंगे? पृथ्वी पर बड़ी विशेषताओं के लिए, एक फैलाव पड़ोस (जैसे डिस्क) जिसका वास्तविकता में निरंतर आकार होता है, उस मानचित्र पर भिन्न आकार हो सकता है जहां ये गणना की जाती है। इस प्रकार हम गणना करने का एक तरीका प्राप्त करते हैं जो यूक्लिडोस ज्यामिति के सभी लाभों का आनंद लेते हुए दीर्घवृत्त के लिए सटीक होता है।
इस R
प्रोटोटाइप के साथ उदाहरण पेश किए गए , जो आसानी से आपकी पसंदीदा भाषा (पायथन, सी ++, आदि) में पोर्ट किए जा सकते हैं। संरचना में यह इस उत्तर में बताए गए विश्लेषण को समानता देता है और इसलिए इसे अलग से स्पष्टीकरण की आवश्यकता नहीं है। टिप्पणियाँ कुछ विवरणों को स्पष्ट करती हैं।
(यह ध्यान रखना दिलचस्प हो सकता है कि त्रिकोणमितीय गणना का उपयोग केवल उदाहरण सुविधाओं को बनाने के लिए किया जाता है - जो नियमित रूप से बहुभुज और क्षेत्र होते हैं। प्रसार गणना के किसी भी भाग को किसी भी त्रिकोणमिति की आवश्यकता नहीं होती है।)
#
# Dilate the vertices of a polygon/polyline by a shape.
#
dilate.points <- function(p, q) {
# Translate a copy of `q` to each vertex of `p`, resulting in a list of polygons.
pieces <- apply(p, 1, function(x) list(t(t(q)+x)))
lapply(pieces, function(z) z[[1]]) # Convert to a list of matrices
}
#
# Dilate the edges of a polygon/polyline `p` by a shape `q`.
# `p` must have at least two rows.
#
dilate.edges <- function(p, q) {
i <- matrix(c(0,-1,1,0), 2, 2) # 90 degree rotation
e <- apply(rbind(p, p[1,]), 2, diff) # Direction vectors of the edges
# Dilate a single edge from `x` to `x+v` into a parallelogram
# bounded by parts of the dilation shape that are at extreme distances
# from the edge.
buffer <- function(x, v) {
y <- q %*% i %*% v # Signed distances orthogonal to the edge
k <- which.min(y) # Find smallest distance, then the largest *after* it
l <- (which.max(c(y[-(1:k)], y[1:k])) + k-1) %% length(y)[1] + 1
list(rbind(x+q[k,], x+v+q[k,], x+v+q[l,], x+q[l,])) # A parallelogram
}
# Apply `buffer` to every edge.
quads <- apply(cbind(p, e), 1, function(x) buffer(x[1:2], x[3:4]))
lapply(quads, function(z) z[[1]]) # Convert to a list of matrices
}
#----------------------- (This ends the dilation code.) --------------------------#
#
# Display a polygon and its point and edge dilations.
# NB: In practice we would submit the polygon, its point dilations, and edge
# dilations to the GIS to create and simplify their union, producing a single
# polygon. We keep the three parts separate here in order to illustrate how
# that polygon is constructed.
#
display <- function(p, d.points, d.edges, ...) {
# Create a plotting region covering the extent of the dilated figure.
x <- c(p[,1], unlist(lapply(c(d.points, d.edges), function(x) x[,1])))
y <- c(p[,2], unlist(lapply(c(d.points, d.edges), function(x) x[,2])))
plot(c(min(x),max(x)), c(min(y),max(y)), type="n", asp=1, xlab="x", ylab="y", ...)
# The polygon itself.
polygon(p, density=-1, col="#00000040")
# The dilated points and edges.
plot.list <- function(l, c) lapply(l, function(p)
polygon(p, density=-1, col=c, border="#00000040"))
plot.list(d.points, "#ff000020")
plot.list(d.edges, "#0000ff20")
invisible(NULL) # Doesn't return anything
}
#
# Create a sector of a circle.
# `n` is the number of vertices to use for approximating its outer arc.
#
sector <- function(radius, arg1, arg2, n=1, origin=c(0,0)) {
t(cbind(origin, radius*sapply(seq(arg1, arg2, length.out=n),
function(a) c(cos(a), sin(a)))))
}
#
# Create a polygon represented as an array of rows.
#
n.vertices <- 60 # Inscribes an `n.vertices`-gon in the unit circle.
angles <- seq(2*pi, 0, length.out=n.vertices+1)
angles <- angles[-(n.vertices+1)]
polygon.the <- cbind(cos(angles), sin(angles))
if (n.vertices==1) polygon.the <- rbind(polygon.the, polygon.the)
#
# Dilate the polygon in various ways to illustrate.
#
system.time({
radius <- 1/3
par(mfrow=c(1,3))
q <- sector(radius, pi/12, 2*pi/3, n=120)
d.points <- dilate.points(polygon.the, q)
d.edges <- dilate.edges(polygon.the, q)
display(polygon.the, d.points, d.edges, main="-30 to 75 degrees")
q <- sector(radius, pi/3, 4*pi/3, n=180)
d.points <- dilate.points(polygon.the, q)
d.edges <- dilate.edges(polygon.the, q)
display(polygon.the, d.points, d.edges, main="-150 to 30 degrees")
q <- sector(radius, -9/20*pi, -9/20*pi)
d.points <- dilate.points(polygon.the, q)
d.edges <- dilate.edges(polygon.the, q)
display(polygon.the, d.points, d.edges, main="171 degrees")
})
इस उदाहरण के लिए कम्प्यूटिंग समय (अंतिम आंकड़े से), एन = 60 और एम = 121 (बाएं), एम = 181 (मध्य), और एम = 2 (दाएं) के साथ, एक चौथाई दूसरा था। हालाँकि, इसमें से अधिकांश डिस्प्ले के लिए था। आमतौर पर, यह R
कोड N M = 1.5 मिलियन प्रति सेकंड (केवल 0.002 सेकंड या इतने पर दिखाए गए सभी उदाहरण गणना करने के लिए) संभाल लेगा । फिर भी, उत्पाद एम एन की उपस्थिति का अर्थ है एक विस्तृत पड़ोस के माध्यम से कई आंकड़े या जटिल आंकड़े का फैलाव काफी समय लग सकता है, इसलिए सावधान रहें! एक बड़ी समस्या से निपटने से पहले छोटी समस्याओं के लिए बेंचमार्क। ऐसी परिस्थितियों में कोई भी एक रेखापुंज आधारित समाधान को देख सकता है (जो लागू करने के लिए बहुत आसान है, अनिवार्य रूप से सिर्फ एक पड़ोस गणना की आवश्यकता है।)
यह बहुत व्यापक है, लेकिन आप यह कर सकते हैं: