2012-10-11 21 views
20

मैं एक आवेदन जहाँ मैं पास के स्थान प्राप्त करने की आवश्यकता पर काम कर रहा हूँ के साथ निकटतम स्थान का पता लगाएं, अपने वेब सेवा 2 मानकों (दशमलव देशांतर, दशमलव अक्षांश)देशांतर और अक्षांश

प्राप्त होगा मैं एक मेज जहां स्थान हैं, अक्षांश और अक्षांश क्षेत्रों के साथ डेटाबेस में सहेजे गए हैं,

मैं निकटतम स्थानों को पुनर्प्राप्त करना चाहता हूं।

क्या कोई मदद कर सकता है?

var locations = from l in locations 

    select l 

यहाँ इस बारे में अधिक जानकारी:

यहाँ मेरी कोड है मैं एक 2 क्षेत्र (दशमलव (18, 2) नल) 1 अक्षांश, 2 देशांतर एक डेटाबेस तालिका के अंदर, है

और मैं एक विधि

public List<Locations> GetLocation(decimal? Long, decimal? lat) 
{ 
var Loc = from l in Locations 
    //// now here is how to get nearest location ? how to query? 
    //// i have also tried Math.Abs(l.Lat - lat) its giving error about nullable decimal always hence i have seted decimal to nullable or converted to nullable 
//// also i have tried where (l.lat - Lat) * (l.lon - Long) this is also giving error about can not convert decimal to bool 
return Loc.ToList(); 
} 
+0

कोड? बहुत संक्षिप्त ... आपने सोफर की कोशिश की है? – lboshuizen

उत्तर

4

यहाँ, @Fung द्वारा टिप्पणी पर विस्तार करने के लिए यदि आप संस्थाओं के लिए इकाई की रूपरेखा/LINQ का उपयोग कर रहे हैं, अगर आप एक LINQ क्वेरी में GeoCoordinate.GetDistanceTo विधि का उपयोग करने का प्रयास करें समाधान

var constValue = 57.2957795130823D 

var constValue2 = 3958.75586574D; 

var searchWithin = 20; 

double latitude = ConversionHelper.SafeConvertToDoubleCultureInd(Latitude, 0), 
        longitude = ConversionHelper.SafeConvertToDoubleCultureInd(Longitude, 0); 
var loc = (from l in DB.locations 
let temp = Math.Sin(Convert.ToDouble(l.Latitude)/constValue) * Math.Sin(Convert.ToDouble(latitude)/constValue) + 
           Math.Cos(Convert.ToDouble(l.Latitude)/constValue) * 
           Math.Cos(Convert.ToDouble(latitude)/constValue) * 
           Math.Cos((Convert.ToDouble(longitude)/constValue) - (Convert.ToDouble(l.Longitude)/constValue)) 
          let calMiles = (constValue2 * Math.Acos(temp > 1 ? 1 : (temp < -1 ? -1 : temp))) 
          where (l.Latitude > 0 && l.Longitude > 0) 
          orderby calMiles 

select new location 
    { 
    Name = l.name 
    }); 
    return loc .ToList(); 
+0

रास्ता बहुत अधिक कोड – cyclical

+1

निरंतर मूल्य क्या हैं? –

+0

वर्तमान संदर्भ में 'रूपांतरणहेल्पर' नाम मौजूद नहीं है। ,कैसे हल करें? –

2

आप किसी मान्य श्रेणी है जिसमें से बाहर "हिट", है वास्तव में प्रासंगिक नहीं है? यदि ऐसा है, तो

from l in locations where ((l.lat - point.lat) * (l.lat - point.lat)) + ((l.lng - point.lng) * (l.lng - point.lng)) < (range * range) select l 

फिर उन परिणामों के लूप के भीतर सबसे छोटे वर्ग दूरी के साथ हिट ढूंढें।

+0

मुझे नहीं लगता कि यूक्लिडियन दूरी तुलना देशांतर/अक्षांश पर लागू होती है। – Fung

+0

छोटी श्रेणियों (<3 लैट/एलएनजी कॉर्ड में) के लिए, ठीक होना चाहिए ... –

+0

लैट और लम्बे वर्ग नहीं हैं, भूमध्य रेखा के पास हो सकता है, लेकिन कहीं और नहीं ... – sasjaq

44

आप पहले डेटाबेस में स्थान डेटा को System.Device.Location.GeoCoordinate पर परिवर्तित कर सकते हैं, फिर निकटतम को खोजने के लिए LINQ का उपयोग करें।

var coord = new GeoCoordinate(latitude, longitude); 
var nearest = locations.Select(x => new GeoCoordinate(x.Latitude, x.Longitude)) 
         .OrderBy(x => x.GetDistanceTo(coord)) 
         .First(); 
+2

+1 अच्छा लगता है! मुझे 'System.Device' के संदर्भ में जोड़ना पड़ा, लेकिन बहुत अच्छा काम करता है! अच्छा कोड धन्यवाद! –

+0

शानदार उत्तर, यह। +1। –

+1

क्या स्थानों को स्मृति में होना चाहिए? दूसरे शब्दों में: क्या यह शुद्ध लिंक-टू-एंटिटीज (एसक्यूएल में अनुवादित) में ऐसा करना संभव है? – sports

2

है, आप संदेश के साथ एक क्रम NotSupportedException मिल जाएगा:

संस्थाओं को LINQ विधि 'डबल GetDistanceTo (System.Device.Location.GeoCoordinate)' विधि को नहीं पहचानता है, और इस विधि एक दुकान अभिव्यक्ति में अनुवाद नहीं किया जा सकता है।

इकाई फ्रेमवर्क संस्करण 5 या 6 के साथ, एक विकल्प System.Data.Spatial.DbGeography कक्षा का उपयोग करना है। उदाहरण के लिए:

DbGeography searchLocation = DbGeography.FromText(String.Format("POINT({0} {1})", longitude, latitude)); 

var nearbyLocations = 
    (from location in _context.Locations 
    where // (Additional filtering criteria here...) 
    select new 
    { 
     LocationID = location.ID, 
     Address1 = location.Address1, 
     City = location.City, 
     State = location.State, 
     Zip = location.Zip, 
     Latitude = location.Latitude, 
     Longitude = location.Longitude, 
     Distance = searchLocation.Distance(
      DbGeography.FromText("POINT(" + location.Longitude + " " + location.Latitude + ")")) 
    }) 
    .OrderBy(location => location.Distance) 
    .ToList(); 

_context इस उदाहरण में आपके पूर्व में instantiated DbContext उदाहरण है।

हालांकि वर्तमान में यह undocumented in MSDN है, DbGeography.Distance विधि द्वारा लौटाई गई इकाइयां मीटर दिखाई देती हैं। देखें: System.Data.Spatial DbGeography.Distance units?

1
var objAllListing = (from listing in _listingWithLanguageRepository.GetAll().Where(z => z.IsActive == true) 
            let distance = 12742 * SqlFunctions.Asin(SqlFunctions.SquareRoot(SqlFunctions.Sin(((SqlFunctions.Pi()/180) * (listing.Listings.Latitude - sourceLatitude))/2) * SqlFunctions.Sin(((SqlFunctions.Pi()/180) * (listing.Listings.Latitude - sourceLatitude))/2) + 
                 SqlFunctions.Cos((SqlFunctions.Pi()/180) * sourceLatitude) * SqlFunctions.Cos((SqlFunctions.Pi()/180) * (listing.Listings.Latitude)) * 
                 SqlFunctions.Sin(((SqlFunctions.Pi()/180) * (listing.Listings.Longitude - sourceLongitude))/2) * SqlFunctions.Sin(((SqlFunctions.Pi()/180) * (listing.Listings.Longitude - sourceLongitude))/2))) 
            where distance <= input.Distance 

            select new ListingFinalResult { ListingDetail = listing, Distance = distance }).ToList();//.Take(5).OrderBy(x => x.distance).ToList(); 
संबंधित मुद्दे