दस्तावेज़ / मैप व्यू / कैमरा

कैमरा ― एब्सट्रैक्शन का सबसे मुश्किल हिस्सा

MapConductor में सबसे मुश्किल और सबसे मूल्यवान काम कैमरे को एकीकृत करना है। position, zoom, bearing, tilt, visibleRegion से बने एक कैमरा मॉडल को, 10 से अधिक प्रकार के मैप इंजन में एक ही अर्थ के साथ संरेखित किया गया है। अगर आप वही MapCameraPosition पास करें, तो किसी भी प्रदाता पर वही दृश्य दिखाई देगा।

POSITION
lat / lng
ZOOM
0 – 22
BEARING
0 – 360°
TILT
−60 – 60°

01 · एकीकरण का क्या मतलब है

मैप इंजन के पास अपना अलग कैमरा मॉडल होता है। कुछ ज़ूम के हिसाब से, कुछ कैमरा ऊंचाई के हिसाब से, कुछ ज़मीन पर फोकस पॉइंट के चारों ओर घूमते हैं, और कुछ व्यूपॉइंट को ही बदलते हैं। अगर आप नेटिव SDK का सीधे इस्तेमाल करते हैं, तो प्रदाता बदलते ही "एक ही संख्या के बावजूद अलग दृश्य" हो जाएगा और आपको स्क्रीन के लॉजिक तक को बदलना पड़ेगा।

MapConductor इस अंतर को एडेप्टर लेयर में सीमित रखता है और ऐप से सिर्फ एक कैमरा मॉडल दिखाता है। नतीजतन, कैमरा पोज़िशन एक ऐसा मान बन जाता है जिसे आप प्रदाताओं के बीच ले जा सकते हैं। सैंपल ऐप के Camera Sync पेज पर, आप एक कैमरा पोज़िशन को सभी प्रदाताओं में भेजकर यह वास्तव में देख सकते हैं कि वे सभी एक ही स्थान, एक ही स्केल और एक ही झुकाव पर कैसे दिखाई देते हैं।

DIFFERENCE 01

जूम या ऊंचाई

2D टाइल सिस्टम ज़ूम लेवल, और 3D सिस्टम कैमरा ऊँचाई या दृश्य दूरी का उपयोग करके पैमाने को व्यक्त करते हैं। इकाइयाँ और मानक भी अलग-अलग हैं।

DIFFERENCE 02

दृष्टि बिंदु या निरीक्षण बिंदु

पृथ्वी पर एक बिंदु के चारों ओर घूमने (ऑर्बिट) वाला मॉडल और कैमरे की स्थिति और दिशा से वर्णित मॉडल एक साथ मिले हुए हैं।

DIFFERENCE 03

झुकाव की सीमा

अधिकतम झुकाव कोण और यह कि क्या ऊपर की ओर झुकाया जा सकता है, यह इंजन के आधार पर भिन्न होता है। नकारात्मक झुकाव वाला कोई भी नहीं है।

चित्र · एक moveCameraTo हर इंजन पर एक ही दृश्य कैसे बनता है
val camera = MapCameraPosition(
    position = geoPoint,
    zoom = 18.0,
    tilt = 70.0,
)
moveCameraTo(camera)
MapConductor
एकीकृत कैमरा मॉडल
position / zoom · bearing / tilt
हर कंपनी का
मैप SDK अडैप्टर
हर कंपनी का
मैप SDK अडैप्टर
अडैप्टर इसे हर नेटिव कैमरा रूप में बदलते हैं। ज़ूम-आधारित, ऊँचाई-आधारित और ऊपर की ओर pitch न होने के अंतर यहीं सोख लिए जाते हैं।
ज़ूम-आधारित इंजन (Google Maps · Mapbox · MapLibre …)
ऊँचाई-आधारित इंजन (ArcGIS · Cesium · MapKit …)
एक ही प्रवेश बिंदु; बाहर निकलते समय अलग-अलग नेटिव अभिव्यक्तियाँ — पर स्क्रीन पर वही जगह, वही पैमाना और वही झुकाव।
सैंपल वीडियो · Camera Sync (एक कैमरा पोज़िशन को सभी प्रदाताओं में सिंक करना)

02 · एकीकृत कैमरा मॉडल

कैमरा को MapCameraPosition से दर्शाया जाता है। प्रदाता-विशिष्ट कोई टाइप नहीं है, बस यह वैल्यू बनाएं और इसे moveCameraTo में पास करें।

प्रॉपर्टी
विवरण
position
ज़मीन पर कैमरा जो केंद्र देख रहा है उसकी कोऑर्डिनेट।
zoom
स्केल। Google Maps के ज़ूम लेवल के आधार पर सभी प्रदाताओं में नॉर्मलाइज़ किया गया है।
bearing
बेयरिंग (वास्तविक उत्तर से घूमने का कोण)।
tilt
झुकाव। 0 सीधे ऊपर से, पॉज़िटिव आगे की ओर झुका हुआ तिरछा व्यू, और नेगेटिव क्षितिज से ऊपर देखने वाला एलिवेशन व्यू।
paddings
UI में छिपा हुआ क्षेत्र। सेंटर या फिट गणना इसे घटाकर की जाती है।
visibleRegion
स्क्रीन पर वास्तव में दिखाई देने वाला ज़मीनी क्षेत्र। इसमें एक आयताकार bounds और चारों कोनों की कोऑर्डिनेट होती हैं।

copy() से आप केवल कुछ हिस्सों को बदल सकते हैं, और तुलना ज़ूम 0.01 और झुकाव 0.01 की अनुमति त्रुटि के साथ की जाती है। ताकि प्रदाता से लौटने वाले मानों में हल्के उतार-चढ़ाव के कारण "चला गया" की गलत पहचान न हो।

प्लेटफ़ॉर्म

03 · ज़ूम लेवल=ऊंचाई का एकीकरण

ज़ूम को आंतरिक रूप से "कैमरा की ऊंचाई" के समान माना जाता है। 2D टाइल-आधारित ज़ूम और 3D आधारित ऊंचाई/दृश्य दूरी को परस्पर बदलने वाला कनवर्टर `core` में है, और किसी भी प्रदाता के मान को पहले एक सामान्य ज़ूम (Google Maps मानक) में बदला जाता है, फिर उसे प्रकाशित किया जाता है।

यह मानक सिर्फ सैद्धांतिक आधार पर तय नहीं किया गया है। सैंपल ऐप के कैलिब्रेशन टूल में, समान ज़ूम निर्दिष्ट करने पर वास्तव में दिखाई देने वाली सीमा का प्रत्येक इंजन द्वारा माप किया जाता है, और क्षेत्रफल मेल खाने के लिए मानक ऊंचाई को कैलिब्रेट किया जाता है। इसलिए, `zoom 14` किसी भी प्रदाता के लिए समान चौड़ाई है।

चित्र · ज़ूम स्तर और उनका पैमाना (मोटे तौर पर स्क्रीन की चौड़ाई में कितने km आते हैं)
0
≈ 40,000 km
पूरा गोला
पूरी दुनिया एक ही दृश्य में — सिर्फ़ महाद्वीपों की रूपरेखा।
3
≈ 5,000 km
महाद्वीप
महाद्वीप और महासागर; सीमाओं का अभी कोई अर्थ नहीं।
6
≈ 600 km
देश
पूरा देश और उसके शहर कहाँ हैं।
10
≈ 40 km
महानगर क्षेत्र
बसे हुए इलाके और मुख्य सड़कें — आम शुरुआती दृश्य।
14
≈ 2.5 km
इलाका
गलियों का जाल पढ़ा जा सकता है; स्टोर के पिन दिखाने के लिए ठीक।
17
≈ 300 m
ब्लॉक
चौराहे और इमारतों की रूपरेखा — पैदल नेविगेशन।
20
≈ 40 m
इमारत
प्रवेश द्वार और ठीक-ठीक स्थान।
हर कदम पैमाना दोगुना करता है। आँकड़े भूमध्य रेखा पर, 256 px स्क्रीन चौड़ाई के लिए हैं; ज़मीन पर असली दूरी अक्षांश के साथ बदलती है।
LATITUDE

एक ही ज़ूम को अक्षांश के अनुसार अलग ऊँचाई चाहिए

Web Mercator ध्रुवों की ओर मैप को बड़ा कर देता है, इसलिए एक ही ज़ूम स्तर के लिए कैमरे की ऊँचाई भूमध्य रेखा और ऊँचे अक्षांशों के बीच कई गुना बदल जाती है। ज़ूम ⇄ ऊँचाई का रूपांतरण इसका हिसाब रखता है।

ZOOM 10 · भूमध्य रेखा के पास
≈ 5,200 m
ZOOM 10 · लगभग 70°N
≈ 1,700 m
NATIVE
नेटिव मानों को इसी पैमाने पर लाना
±0.0
Google Maps · Mapbox 2D — इसे संदर्भ माना गया है। एकीकृत ज़ूम पैमाना इसी परिवार का अनुसरण करता है।
+1.0
MapLibre · MapTiler · TomTom — नेटिव ज़ूम एक कदम नीचे रहता है, इसलिए +1.0 का ऑफ़सेट लगाया जाता है।
m
MapKit · ArcGIS · Cesium · Google 3D — अक्षांश और झुकाव का हिसाब रखते हुए ज़ूम और ऊँचाई/रेंज के बीच बदला जाता है।
ZOOM RANGE
0.0 – 22.0
ZOOM FACTOR
2.0
ZOOM 0 ALTITUDE
171,319,879 m
MAPLIBRE OFFSET
+1.0

प्रत्येक दोगुने पर एक स्तर का संबंध और केवल मानक `zoom 0` की ऊंचाई स्थिरांक है। उच्च अक्षांश पर समान ज़ूम के लिए भूमि पर दूरी कम हो जाती है, यह बिंदु भी रूपांतरण में शामिल है, इसलिए टोक्यो और होनोलूलू में स्केल में कोई अंतर नहीं होता है।

04 · `tilt < 0` का नकली समर्थन

`tilt` −60 से 60 डिग्री का मान लेता है। धनात्मक मान एक परिचित तिरछा नीचे देखने का दृश्य है, लेकिन ऋणात्मक मान क्षितिज से ऊपर देखने का एक ऊंचा दृश्य है। मैप इंजन में इसे सीधे दर्शाने में सक्षम कुछ भी नहीं है। किसी भी SDK में `pitch` केवल 0 या उससे अधिक स्वीकार किया जाता है।

इसलिए `MapConductor` कैमरे की आंख की स्थिति और दिशा को बनाए रखते हुए, इंजन को एक धनात्मक झुकाव के रूप में देने के रूप में बदल देता है। ऐप से देखने पर ऋणात्मक `tilt` का उपयोग वैसे ही किया जा सकता है, और प्राप्त की गई कैमरा स्थिति भी ऋणात्मक `tilt` के रूप में वापस आती है।

tilt = 0

सीधे ऊपर से देखा गया समतल दृश्य। ज़मीन पर एक आयत स्क्रीन पर एक आयत बन जाता है।

tilt > 0

आगे की ओर झुका हुआ तिरछा दृश्य। ज़मीन पर यह एक समलम्ब बन जाता है जिसमें निकट की ओर संकरा और दूर की ओर चौड़ा हिस्सा होता है।

tilt < 0

क्षितिज से ऊपर देखने वाला उन्नत दृश्य। आकाश की ओर वाला दृश्य जो मूल रूप से मौजूद नहीं है।

एमुलेशन कैसे काम करता है
01
आँख की जगह और ऊँचाई वहीं रहती है; सिर्फ़ ज़मीन का लक्ष्य bearing की दिशा में आगे खिसकता है — उतना, जितना ऊँचाई और झुकाव के कोण से निकलता है।
02
फिर इंजन को abs(tilt) नीचे की ओर के pitch के रूप में दिया जाता है। आँख और उसकी दिशा मेल खाती है, इसलिए तस्वीर ऊपर की ओर के दृश्य जैसी ही बनती है। MapLibre परिवार के इंजनों में खिसकाव और ज़ूम पर तय सुधार-गुणक लगाए जाते हैं, ताकि फ़्रेमिंग भी मेल खाए।
03
कैमरा वापस पढ़ने पर यही गणित उलटा चलता है: आगे का खिसकाव और ज़ूम ऑफ़सेट हटाकर तार्किक ऋणात्मक tilt और मूल केंद्र लौटाया जाता है। आना-जाना स्थिर रहता है।
ऋणात्मक tilt का समर्थन
Android · सभी प्रोवाइडर
OK
iOS · सभी प्रोवाइडर
OK
React · Google Maps 2D को छोड़कर सभी
OK
React · Google Maps 2D
N/A

एकमात्र अपवाद React पर Google Maps 2D है — रास्टर JavaScript API वाला मैप। उसका tilt ब्राउज़र और टाइल की स्थिति पर निर्भर करता है, इसलिए एमुलेशन जिस ऊँचाई और दिशा पर टिका है, उन्हें नियंत्रित नहीं किया जा सकता। Google Maps 3D (Map3DElement) ऋणात्मक tilt का समर्थन करता है।

TiltMapPageViewModel.kt
// −60 से 60 वाला स्लाइडर सीधे दे दें; ऋणात्मक मान पर भी वही कॉल
currentPosition = currentPosition.copy(tilt = tilt)
mapViewState.value?.moveCameraTo(currentPosition)
सैंपल वीडियो · Tilt (−60〜60 को लगातार चलाना)

05 · VisibleRegion ― वास्तव में दिखाई देने वाली सीमा

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

`near` स्क्रीन का निचला किनारा है, यानी कैमरे के करीब वाला भाग, और `far` ऊपरी किनारा है जो दूर की ओर है। `left` / `right` स्क्रीन के आधार पर हैं, इसलिए `bearing` से मैप को घुमाने पर अर्थ नहीं बदलता है। इन 4 बिंदुओं के होने के लिए, झुके हुए मैप में भी डेटा प्राप्ति की सीमा और स्रोत नोट के निर्धारण को सही ढंग से किया जा सकता है।

farLeft
farRight
nearLeft
nearRight
स्क्रीन का आयत → ज़मीन पर समलंब
दूर वाला किनारा चौड़ा, पास वाला सँकरा। Bounds इसी समलंब के चारों ओर का बक्सा है।
bounds
समलंब के चारों ओर का दक्षिण-पश्चिम / उत्तर-पूर्व बक्सा — मोटी जाँच और पहले से मौजूद API के लिए।
nearLeft / nearRight
स्क्रीन के निचले कोनों के ज़मीनी निर्देशांक — पास वाली ओर।
farLeft / farRight
स्क्रीन के ऊपरी कोनों के ज़मीनी निर्देशांक — दूर वाली ओर, जो झुकाने पर और चौड़ी होती जाती है।
कहाँ काम आता है
दिखने वाले क्षेत्र का डेटा लाने, fitBounds, और टाइल एट्रिब्यूशन के नियम बदलने में।
VisibleRegionViewModel.kt
mapViewState.cameraPosition.visibleRegion?.let { region ->
    val sw = region.bounds.southWest
    val ne = region.bounds.northEast
    // झुकी हुई स्क्रीन के चारों कोने — समलंब की तरह इस्तेमाल हो सकते हैं
    val corners = listOf(region.nearLeft, region.nearRight, region.farLeft, region.farRight)
}

संबंधित पेज