
पिछले लेख में, मैंने इस बारे में बात की थी कि वेब-डायलर को जल्दी से कैसे बनाया जाए। लेकिन क्या होगा अगर आप एक अधिक महत्वाकांक्षी कार्य निर्धारित करते हैं - एक कार्ड के साथ, विज्ञापनों के बिना और लाठी के साथ अपने स्वयं के आवेदन को इकट्ठा करने के लिए? और अगर सिर्फ कुछ दिनों में?
चलो यह करते हैं! मैं बिल्ली माँगता हूँ।
सबसे पहले, आइए जानें कि हमें क्या करना है। आउटपुट पर, हम संदर्भ डेटा और एक मानचित्र के साथ एक आवेदन प्राप्त करना चाहते हैं। और ऑफ़लाइन काम करने के लिए। एक डेवलपर के रूप में, मुझे मुख्य रूप से सिर्फ नक्शे में दिलचस्पी है, क्योंकि हम पहले से ही संदर्भ डेटा दिखाना जानते हैं। और ऑफ़लाइन इस मामले में एक बहुत मजबूत सीमा है, क्योंकि ऑफ़लाइन समर्थन के साथ कई अच्छे पुस्तकालय नहीं हैं। इसलिए, लेख में हम नक्शे पर ध्यान केंद्रित करेंगे, लेकिन आइए पारित होने में मार्गदर्शिका के बारे में बात करते हैं।
एक मानचित्र इंजन चुनें
पहली बात यह है कि आवेदन के लिए डेटा प्राप्त करें। बाजार पर कई स्रोत हैं, मुफ्त और बहुत नहीं। एक शुरुआत के लिए, OpenStreetMap मानचित्र डेटा के एक खुले स्रोत के रूप में हमारे लिए काफी उपयुक्त है। वहां आप हमारी निर्देशिका के लिए निश्चित संख्या में POI ले सकते हैं।
अगला कदम कार्ड इंजन चुनना है। इंटरनेट पर, उनमें से बहुत कम हैं, यहां तक कि कम मुफ्त वाले भी हैं, और सामान्य रूप से ऑफ़लाइन समर्थन के साथ, केवल कुछ ही हैं। मैं एक बहुत अच्छा विकल्प का उपयोग करने का सुझाव देता हूं - mapforge / vtm । यह एक वेक्टर OpenGL इंजन है, जो बहुत तेज़ है, ऑफ़लाइन, Android, iOS, विभिन्न डेटा स्रोतों, कस्टम स्टाइल, ओवरले, मार्कर, 3D और यहां तक कि 3D मॉडल का समर्थन करता है! बहुत, बहुत अच्छा।
त्वरित शुरुआत के लिए रिपॉजिटरी के बहुत सारे उदाहरण हैं, तैयार किए गए नक्शे हैं, एक प्लग-इन है जो आपको ओएसएम प्रारूप में डेटा से अपने स्वयं के मानचित्र को इकट्ठा करने की अनुमति देता है। तो, चलिए शुरू करते हैं!
MapView mapView = findViewById(R.id.map_view); this.map = mapView.map(); File baseMapFile = getMapFile("cyprus.map"); MapFileTileSource tileSource = new MapFileTileSource(); tileSource.setMapFile(baseMapFile.getAbsolutePath()); VectorTileLayer layer = this.map.setBaseMap(tileSource); MapInfo info = tileSource.getMapInfo(); if (info != null) { MapPosition pos = new MapPosition(); pos.setByBoundingBox(info.boundingBox, Tile.SIZE * 4, Tile.SIZE * 4); this.map.setMapPosition(pos); } this.map.setTheme(VtmThemes.DEFAULT); this.map.layers().add(new BuildingLayer(this.map, layer)); this.map.layers().add(new LabelLayer(this.map, layer));
MapFileTileSource डेटा स्रोत बनाएं, मैप फ़ाइल का स्थान निर्दिष्ट करें। इसके अलावा, हम खुद को उस बाउंडिंग बॉक्स के केंद्र में रखते हैं जो हमें रुचिकर बनाता है, ताकि आवेदन शुरू होने पर चयनित स्थान के बाहर कहीं न हो। डिफ़ॉल्ट विषय स्थापित करें। घरों की एक परत और हस्ताक्षर की एक परत जोड़ें। वह सब है। हम लॉन्च करते हैं - चमत्कार!
यह तेज और आसान लगता है और नहीं हो सकता है।
हम जियोकोडिंग करते हैं
अगला महत्वपूर्ण कदम जियोकोडिंग को लागू करना है। कार्ड पहले से ही अच्छा है, लेकिन अन्तरक्रियाशीलता की आवश्यकता है। हम मानचित्र में टैप करना चाहते हैं और हमारे द्वारा हिट की गई वस्तु पर जानकारी देखना चाहते हैं। और कुछ कठिनाई है। हमारे पुस्तकालय में पूर्ण रूप से जियोकोडिंग नहीं है। यह शायद इसका सबसे बड़ा माइनस है। यदि कुछ भी आविष्कार नहीं किया गया है, तो हम मौजूदा कार्यक्षमता का लाभ उठा सकते हैं।
यह अपेक्षाकृत क्रियात्मक निकला। आपको एक टाइल खोजने की ज़रूरत है, तरीके प्राप्त करें (ओएसएम शब्दावली में, यह एक रैखिक वस्तु है), और आप उनमें से कुछ विशेषताओं को निकाल सकते हैं। तरीकों के अलावा, पीओआई प्राप्त करना संभव है, लेकिन यह सब कुछ है। आपको बाकी सारे तर्क खुद ही हवा देने होंगे: क्लिक हिट, फ़िल्टर को ज़ूम स्तर से फ़िल्टर करने वाले ऑब्जेक्ट के पूरे सेट से "सही" चुनें। और एक बात। वास्तव में, हम मूल ज्यामिति के बारे में जानकारी खो देते हैं और खोज के जवाब में लाइनों का एक सेट प्राप्त करते हैं। यदि आप भी भू-संपादक बनाना चाहते हैं, तो यह स्पष्ट रूप से पर्याप्त नहीं होगा।
लेकिन दृष्टिकोण का प्रदर्शन करने के लिए, सब कुछ हमारे अनुरूप है।
उन्नत जियोकोडिंग
सामान्यतया, एक अधिक उन्नत विकल्प है। इसके लिए हमें अपना आधार चाहिए। विशेष रूप से, आप SQLite का उपयोग कर सकते हैं। सच है, मानक SQLite हमारे लिए पर्याप्त नहीं होगा, और हमें भू-खोज के लिए RTree प्लगइन को जोड़कर अपना स्वयं का निर्माण करना होगा। यह कैसे करना है, मैंने पहले ही लेख में कहा था, अनुभाग "एक अच्छी खोज करें।"
इस मामले में, हमें डेटा पर पूर्ण नियंत्रण प्राप्त होता है, हम वह सब कुछ बचा सकते हैं जो आवश्यक है, और सही प्रारूप में। हम फुल टेक्स्ट सर्च को फास्ट कर सकते हैं और अपनी जियो ऑब्जेक्ट्स और कंपनियों के नाम, पते और अन्य विशेषताओं के आधार पर खोज सकते हैं।
दिशा है:
- हम टेबल बनाते हैं:
- हम सब कुछ डेटा से भरते हैं।
- जब आप मानचित्र में टैप करते हैं, तो हमें जियोप्वाइंट मिलता है और अनुरोध निष्पादित होता है:
SELECT id FROM geo_index WHERE minX>=-81.08 AND maxX<=-80.58 AND minY>=35.00 AND maxY<=35.44
- अंतिम चरण: फ़िल्टर करें और उचित ऑब्जेक्ट का चयन करें।
कार्यान्वयन विकल्पों में से एक को रिपॉजिटरी में देखा जा सकता है ।
नतीजतन, हम पहले से ही जानते हैं कि नक्शे को कैसे दिखाना है और क्लिक को कैसे संभालना है। बुरा नहीं है।
महत्वपूर्ण छोटी चीजें जोड़ें।
आइए कुछ महत्वपूर्ण विशेषताओं को जोड़ते हैं।
चलिए वर्तमान स्थान से शुरू करते हैं। Mapforge / vtm में इसके लिए बस एक विशेष है। स्थान परत। उपयोग अत्यंत सरल है।
LocationLayer locationLayer = new LocationLayer(this.map); locationLayer.setEnabled(true);
केवल एक खामी है - यह स्क्रीन की सीमा पर "ब्लू डॉट" का निरंतर तरंग है जब वर्तमान स्थान मानचित्र के बाहर होता है। सबसे अधिक संभावना है, उपयोग की प्रक्रिया में, आप शायद ही कभी ऐसी स्थिति में खुद को पाएंगे, लेकिन यह लगातार पुन: प्रतिपादन का कारण बनता है, तदनुसार, यह प्रोसेसर को थोड़ा लोड करता है। इससे छुटकारा पाने के लिए थोड़ा और मुश्किल है, आपको छाया में आने और इसे ठीक करने की आवश्यकता है। लेकिन यह पहले से ही पूर्णतावादियों के लिए है। कैसे करें - आप यहां देख सकते हैं।
तो, स्थिति यह है नेविगेशन बटन को वर्तमान स्थिति में जोड़ने का समय है, जैसा कि सभी स्वाभिमानी मैपिंग अनुप्रयोगों में है।
View vLocation = findViewById(R.id.am_location); vLocation.setOnClickListener(v -> this.map.animator().animateTo(initialGeoPoint));
हमें ज़ूम बटन की भी आवश्यकता है।
View vZoomIn = findViewById(R.id.am_zoom_in); vZoomIn.setOnClickListener(v -> this.map.animator().animateZoom(500, 2, 0, 0)); View vZoomOut = findViewById(R.id.am_zoom_out); vZoomOut.setOnClickListener(v -> this.map.animator().animateZoom(500, 0.5, 0, 0));
और केक पर चेरी एक कम्पास है।
View vCompass = findViewById(R.id.am_compass); vCompass.setVisibility(View.GONE); vCompass.setOnClickListener(v -> { MapPosition mapPosition = this.map.getMapPosition(); mapPosition.setBearing(0); this.map.animator().animateTo(500, mapPosition); vCompass.animate().setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { vCompass.setVisibility(View.GONE); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }).setDuration(500).rotation(0).start(); }); this.map.events.bind((e, mapPosition) -> { if (e == Map.ROTATE_EVENT) { vCompass.setRotation(mapPosition.getBearing()); vCompass.setVisibility(View.VISIBLE); } });
दुनिया पर कब्जा
दोस्तों, हम फिनिश लाइन पर हैं। यह अंतिम स्पर्श को जोड़ने के लिए बनी हुई है। हम दुनिया पर कब्जा करने की योजना बना रहे हैं, जिसका मतलब है कि हमें किसी तरह से इसे अपने आवेदन में समेटना होगा।
और चीजें ऐसी हैं कि हमारे इंजन के साथ यह जितना लगता है उससे कहीं ज्यादा आसान है।
हमें इसके लिए एक MultyMapTileSource जोड़कर मानचित्र लोड करने की विधि को थोड़ा संशोधित करने की आवश्यकता है। यह अनिवार्य रूप से किसी भी अन्य टाइल स्रोतों के लिए एक आवरण है, जो आपको मानचित्र पर एक बार में जोड़े जाने वाले सभी चीजों को प्रदर्शित करने की अनुमति देता है। बस एक हत्यारा सुविधा। नतीजतन, यह हमारे लिए न्यूनतम विस्तार के साथ एक विश्व मानचित्र तैयार करने के लिए बना हुआ है, इसे पहले हमारे आवरण में जोड़ें, और बाकी को शीर्ष पर खींचें। इसके अलावा, हम तुरंत उन सभी कार्डों को जोड़ सकते हैं जो हमारे पास एप्लिकेशन के नक्शे के साथ कैटलॉग में हैं! भव्य, सिर्फ भव्य। और यह मत भूलो कि यह ऑफ़लाइन है :)
शायद हम रिलीज के लिए तैयार हैं। हम बिल्ड इकट्ठा करते हैं, इसे बाजार में डालते हैं और अच्छी तरह से योग्य सितारे प्राप्त करते हैं :)
शहद के एक विशाल बैरल में टार के चम्मच के एक जोड़े
ओपन सोर्स इंजन सक्रिय रूप से विकसित हो रहा है, लेकिन उनकी टीम, स्पष्ट रूप से, बल्कि मामूली है। द्वारा और बड़े, यह devemux86 नाम से एक व्यक्ति है। और समय-समय पर कुछ और लोग।
कभी-कभी रेंडरिंग में कलाकृतियां होती हैं, कुछ निमिष और चिकोटी। लेकिन मुझे कभी भी कोई गंभीर समस्या और सभी अधिक दुर्घटनाओं का सामना नहीं करना पड़ा, जो आनन्दित नहीं कर सकते।
वहाँ एक और अति सूक्ष्म अंतर है जो सुखद नहीं हो सकता है। यह फ़िललेट्स और सर्कल का एक ड्राइंग है। स्क्रीनशॉट में यह कैसे दिखता है, इसका एक उदाहरण:
यदि प्रारंभिक ज्यामिति में बहुत सारे बिंदु हैं (गोलाई चिकनी है), तो मानचित्र पर आप कई छोटे उभारों और अवधियों के साथ एक "कोणीय" सर्कल देख सकते हैं। जाहिर है, यह प्रदर्शन और मानचित्र-फ़ाइल के आकार के लिए किया जाता है, लेकिन यह बहुत अच्छा नहीं लगता है।
आज के लिए शायद यही सबकुछ है। आप तय करें कि आप उनके साथ रह सकते हैं या नहीं। इस बीच, हम 1.5 से अधिक वर्षों से इस पुस्तकालय का उपयोग कर रहे हैं, उड़ान उत्कृष्ट है, कम से कम एंड्रॉइड पर।
परिणाम
इस लेख में, मैंने दिखाया है कि इस तरह की गैर-तुच्छ समस्या भी अपेक्षाकृत जल्दी हल हो सकती है। आपको एक तैयार कंकाल मिला, जिसके साथ आप किसी भी परियोजना को प्रोटोटाइप कर सकते हैं जिसमें न्यूनतम समय में ऑफ़लाइन मानचित्र का उपयोग शामिल है।
यदि रुचि है, तो अगले लेख में मैं दिखाऊंगा कि कैसे फर्श को ला 2 जीआईएस बनाया जाए। और यह वास्तव में लगता है की तुलना में बहुत आसान है :)