কাছাকাছি এলোমেলো অবস্থান তৈরি?


30

আমি আমার অবস্থান কাছাকাছি এলোমেলো অবস্থান তৈরি করার চেষ্টা করছি। আমি যা চাই তা হল আমার অবস্থানের চারপাশে 200 মিটার বৃত্তের ভিতরে এলোমেলো অক্ষাংশ / দ্রাঘিমাংশ জোড়া তৈরি করা।

এটিই সূত্রটি আমি নিয়ে এসেছি (স্ট্যাকওভারফ্লোতে লোকের সহায়তায়): (র্যান্ডম সংখ্যা -1 এবং 1 এর মধ্যে) * ব্যাসার্ধ + (পুরানো দ্রাঘিমাংশ) = পুরানো দ্রাঘিমাংশের ব্যাসার্ধের মধ্যে নতুন দ্রাঘিমাংশ

(-1 এবং 1 এর মধ্যে এলোমেলো সংখ্যা) * ব্যাসার্ধ + (পুরানো অক্ষাংশ) = পুরানো অক্ষাংশের ব্যাসার্ধের মধ্যে নতুন অক্ষাংশ

জিনিসটি হ'ল আমার বাস্তবায়নের সাথে অদ্ভুত কিছু ঘটছে কারণ সমস্ত এলোমেলো অবস্থানগুলি আমার অবস্থান কেন্দ্রের খুব কাছেই রয়েছে বলে মনে হয় যে সূত্রটি পুরো ব্যাসার্ধকে আবরণ করে না।

আমার সূত্রটি ভুল হতে পারে কি কোন ধারণা?

বর্তমান জাভা বাস্তবায়ন দেখানোর জন্য সম্পাদিত:

public static Location getLocation(Location location, int radius) {
    Random random = new Random();

    // Convert radius from meters to degrees
    double radiusInDegrees = radius / METERS_IN_DEGREES;

    double x0 = location.getLongitude() * 1E6;
    double y0 = location.getLatitude() * 1E6;
    double u = random.nextInt(1001) / 1000;
    double v = random.nextInt(1001) / 1000;
    double w = radiusInDegrees * Math.sqrt(u);
    double t = 2 * Math.PI * v;
    double x = w * Math.cos(t);
    double y = w * Math.sin(t);

    // Adjust the x-coordinate for the shrinking of the east-west distances
    double new_x = x / Math.cos(y0);

    // Set the adjusted location
    Location newLocation = new Location("Loc in radius");
    newLocation.setLongitude(new_x + x0);
    newLocation.setLatitude(y + y0);

    return newLocation;
}

আমি কী ভুল করছি তা নিশ্চিত নই, কারণ নতুন অবস্থানগুলি সমুদ্রের মাঝখানে তৈরি করা হয়েছে।

কোন ধারণা?


আপনি এই সূত্রটি কীভাবে বাস্তবায়ন করবেন? আপনি কি আপনার কোডের এই অংশটি উপস্থাপন করতে পারেন? সিউডোর্যান্ডম নম্বর জেনারেটরে আপনার সমস্যা হতে পারে ?
অ্যালেক্স মার্কভ

চূড়ান্ত প্রশ্ন হিসাবে যতক্ষণ যায়, এই জাতীয় প্রক্রিয়াগুলির মতো প্রক্রিয়াগুলি এ জাতীয় সমস্যার কারণ (i) দূরত্বগুলি ভুলভাবে অক্ষাংশ বা দ্রাঘিমাংশের ডিগ্রিতে রূপান্তরিত হয় এবং (ii) স্থানাঙ্ক ব্যবস্থার মেট্রিক বিকৃতির জন্য দায়বদ্ধ হয় না বা ভুলভাবে গণনা করা হয়। কোনও ভৌগলিক স্থানাঙ্ক ব্যবস্থার পরিবর্তে একটি প্রজেক্টেড সমন্বিত সিস্টেম ব্যবহার করা সাধারণত এই উভয় সমস্যারই মুখোমুখি হয়। এটি করার ফলে আপনার সূত্রের একটি মৌলিক সম্পত্তি প্রকাশিত হবে, যা কাঙ্ক্ষিত হতে পারে বা নাও পারে: এটি কোনও বৃত্তের মধ্যে নয়, কোনও অবস্থানের চারপাশে একটি আয়তক্ষেত্রের মধ্যে অবস্থানগুলি তৈরি করে ।
whuber

: ধন্যবাদ অ্যালেক্স, জাভা কোড Stackoverflow এ পোস্ট করা হয় stackoverflow.com/questions/10682743/...
pindleskin

সম্পাদিত কোডটি পুনরায় করুন: (i) random.nextInt(1001)/1000সময়ের প্রায় 1% 0.1% এর চেয়ে বেশি মান প্রদান করবে। আপনি random.nextDoubleবা ব্যবহার করছেন না কেন random.nextFloat? (২) গুন x0এবং y0দ্বারা 1E6বরং রহস্যময় হয়; দেখে মনে হচ্ছে না এটি সঠিক ফলাফল দেবে।
whuber

সত্য, আমি নেক্সটডুবল ব্যবহার করে পদ্ধতিটি সম্পাদনা করেছি এবং 1E6 এর থেকে মুক্তি পেয়েছি। এখন, সমস্ত এলোমেলোভাবে উত্পন্ন স্থানের আমার অবস্থানের একই স্থানাঙ্ক রয়েছে। সহায়তার জন্য ধন্যবাদ, মনে হচ্ছে আমি খুব শীঘ্রই এটিকে যে কোনও সময় সমাধান করতে যাচ্ছি
pindleskin

উত্তর:


46

এটি দুটি কারণে জটিল কারণ: প্রথমত, বর্গের পরিবর্তে একটি বৃত্তে পয়েন্টগুলি সীমাবদ্ধ করে; দ্বিতীয়ত, দূরত্ব গণনায় বিকৃতির জন্য অ্যাকাউন্টিং।

অনেকগুলি জিআইএস-এ এমন ক্ষমতা রয়েছে যা স্বয়ংক্রিয়ভাবে এবং স্বচ্ছভাবে উভয় জটিলতা পরিচালনা করে। তবে, এখানে ট্যাগগুলি পরামর্শ দেয় যে একটি অ্যালগরিদমের একটি জিআইএস-স্বতন্ত্র বিবরণ আকাঙ্ক্ষিত হতে পারে।

  1. পয়েন্ট উৎপন্ন করার জন্য অবিশেষে, এলোমেলোভাবে, এবং একটি বৃত্তের মধ্যে স্বাধীনভাবে ব্যাসার্ধ্যের R একটি অবস্থান (x0, y0) চারপাশে, দুটি স্বাধীন অভিন্ন র্যান্ডম মান উৎপাদিত করে শুরু U এবং V ব্যবধান [0, 1) হবে। (প্রায় প্রতিটি এলোমেলো নম্বর জেনারেটর আপনাকে এটি সরবরাহ করে provides) গণনা

    w = r * sqrt(u)
    t = 2 * Pi * v
    x = w * cos(t) 
    y = w * sin(t)

    পছন্দসই র্যান্ডম পয়েন্টটি অবস্থানটিতে রয়েছে (x + x0, y + y0)।

  2. ভৌগলিক (ল্যাট, লন) স্থানাঙ্কগুলি ব্যবহার করার সময়, x0 (দ্রাঘিমাংশ) এবং y0 (অক্ষাংশ) ডিগ্রিতে থাকবে তবে r সম্ভবত মিটারে (বা ফুট বা মাইল বা অন্য কোনও লিনিয়ার পরিমাপ) হবে। প্রথমত, ব্যাসার্ধ রূপান্তর ডিগ্রী মধ্যে যেন আপনি বিষুবরেখা কাছাকাছি অবস্থিত ছিল। এখানে প্রায় 111,300 মিটার একটি ডিগ্রি রয়েছে।

    দ্বিতীয়ত, পদক্ষেপ (1) হিসাবে x এবং y উত্পন্ন করার পরে , পূর্ব-পশ্চিম দূরত্ব সঙ্কুচিত করার জন্য এক্স-স্থানাঙ্কটি সামঞ্জস্য করুন:

    x' = x / cos(y0)

    পছন্দসই র্যান্ডম পয়েন্টটি অবস্থানটিতে রয়েছে (x '+ x0, y + y0)। এটি একটি আনুমানিক পদ্ধতি। ছোট রেডিয়ির জন্য (কয়েক শতাধিক কিলোমিটারেরও কম) পৃথিবীর উভয় মেরুতে প্রসারিত হয় না, এটি সাধারণত এত নির্ভুল হবে যে প্রতিটি কেন্দ্রের চারপাশে কয়েক হাজার এলোমেলো পয়েন্ট তৈরি করার পরেও আপনি কোনও ত্রুটি সনাক্ত করতে পারবেন না (x0, y0) ।


2
দুর্দান্ত ব্যাখ্যা হ'ল, এটি আমার জানা দরকার। এখন আমি এটি বাস্তবায়ন করতে যাচ্ছি। ধন্যবাদ
পিন্ডলসকিন

1
আমি সূত্রটির কিছু জাভা বাস্তবায়ন দেখানোর জন্য প্রশ্নটি সম্পাদনা করেছি
পিন্ডলসকিন

1
"একটি ডিগ্রীতে প্রায় 111,300 মিটার রয়েছে" কেবল দ্রষ্টব্য হিসাবে কমা হাজার বিভাজক হিসাবে ব্যবহৃত হয়। রেডিয়াসআইনডিগ্রিজ = ব্যাসার্ধ / 111300
আরমাল্কে

2
ল্যাট, দীর্ঘ স্থানাঙ্কের জন্য আপনাকে এক্স '= x / কোস (y0 * পাই / 180) করা উচিত নয়
হারুন স্টেইনব্যাক ২

2
মনকে @ হু হু করে ফুটিয়ে তুলেছে এবং তা বোঝা যায়। এটি অনুমান করার আরেকটি উপায় আমি অনুমান করি যে ২০ টি ব্যাসার্ধের জন্য 55 টি এলোমেলো রেডিয়াই তৈরি হচ্ছে তা কল্পনা করা Let's আসুন ধরা যাক প্রতিটি এলোমেলো রেডিয়াই 0 থেকে 20 এর সমান এবং তাই 0, 2, 4, ..., 20 সুতরাং, 2 এর রেডিয়াইয়ের 5 এর রেডিয়ো সহ 5 পয়েন্ট থাকবে। 2 এর রেডিয়াইয়ের সাথে 5 পয়েন্টগুলি (2 ব্যাসার্ধের একটি বৃত্তের চারপাশে) একটি রেডিয়ির সাথে 5 পয়েন্টের তুলনায় একে অপরের আরও কাছাকাছি দেখবে 20.
আজিজ জাভেদ

11

জাভাস্ক্রিপ্টের জন্য প্রয়োগ করা:

var r = 100/111300 // = 100 meters
  , y0 = original_lat
  , x0 = original_lng
  , u = Math.random()
  , v = Math.random()
  , w = r * Math.sqrt(u)
  , t = 2 * Math.PI * v
  , x = w * Math.cos(t)
  , y1 = w * Math.sin(t)
  , x1 = x / Math.cos(y0)

newY = y0 + y1
newX = x0 + x1

10

সঠিক বাস্তবায়নটি হ'ল:

public static void getLocation(double x0, double y0, int radius) {
    Random random = new Random();

    // Convert radius from meters to degrees
    double radiusInDegrees = radius / 111000f;

    double u = random.nextDouble();
    double v = random.nextDouble();
    double w = radiusInDegrees * Math.sqrt(u);
    double t = 2 * Math.PI * v;
    double x = w * Math.cos(t);
    double y = w * Math.sin(t);

    // Adjust the x-coordinate for the shrinking of the east-west distances
    double new_x = x / Math.cos(Math.toRadians(y0));

    double foundLongitude = new_x + x0;
    double foundLatitude = y + y0;
    System.out.println("Longitude: " + foundLongitude + "  Latitude: " + foundLatitude );
}

এটি আরও অ্যাক্সেসযোগ্য করার জন্য আমি বাহ্যিক লাইব্রেরির উপর নির্ভরতা সরিয়েছি।


এই স্ট্যাকওভারফ্লো প্রশ্নোত্তর হিসাবে ও-এর প্রস্তাবিত সম্পাদনা জাভা ম্যাথকোস () তে রেডিয়ানের ইনপুট আশা করে।
মাইকJRamsey56

3

গৃহীত উত্তর এবং ডেরিভেটিভস আমার পক্ষে কাজ করেনি। ফলাফলগুলি খুব সঠিক ছিল না।

জাভাস্ক্রিপ্টে সঠিক প্রয়োগ:

function pointAtDistance(inputCoords, distance) {
    const result = {}
    const coords = toRadians(inputCoords)
    const sinLat =  Math.sin(coords.latitude)
    const cosLat =  Math.cos(coords.latitude)

    /* go a fixed distance in a random direction*/
    const bearing = Math.random() * TWO_PI
    const theta = distance/EARTH_RADIUS
    const sinBearing = Math.sin(bearing)
    const cosBearing =  Math.cos(bearing)
    const sinTheta = Math.sin(theta)
    const cosTheta =    Math.cos(theta)

    result.latitude = Math.asin(sinLat*cosTheta+cosLat*sinTheta*cosBearing);
    result.longitude = coords.longitude + 
        Math.atan2( sinBearing*sinTheta*cosLat, cosTheta-sinLat*Math.sin(result.latitude )
    );
    /* normalize -PI -> +PI radians (-180 - 180 deg)*/
    result.longitude = ((result.longitude+THREE_PI)%TWO_PI)-Math.PI

    return toDegrees(result)
}

function pointInCircle(coord, distance) {
    const rnd =  Math.random()
    /*use square root of random number to avoid high density at the center*/
    const randomDist = Math.sqrt(rnd) * distance
    return pointAtDistance(coord, randomDist)
}

এখানে পূর্ণ বক্তব্য

গৃহীত উত্তরে - আমি দেখতে পেলাম যে পয়েন্টগুলি তার প্রস্থের দৈর্ঘ্যের 1.5 গুণ (পানামায়) এবং এর উচ্চতার 8 গুণ (সুইডেনের উত্তরে) দিয়ে একটি উপবৃত্তে বিতরণ করা হয়েছে। যদি আমি @ হুইবারের উত্তর থেকে এক্স কোর্ডার সামঞ্জস্যটি সরিয়ে ফেলি তবে উপবৃত্তটি অন্য উপায়ে বিকৃত করা হয়, এর প্রস্থের চেয়ে 8 গুণ বেশি।

আমার উত্তরের কোডটি এখান থেকে অ্যালগরিদমের ভিত্তিতে ছিল

নীচে আপনি দুটি jsfiddles দেখতে পারেন যা প্রসারিত উপবৃত্তের সাথে সমস্যাটি দেখায়

সঠিক অ্যালগরিদম

বিকৃত অ্যালগরিদম


আপনার যে সমস্যার সম্মুখীন হয়েছে সেগুলির বর্ণনা সম্পর্কে আপনার প্রয়োগটি ভুল ছিল।
whuber

আপনি ভাল সঠিক হতে পারে। আপনি যে জেএসফিডলগুলি তৈরি করেছেন তা একবার খেয়াল করবেন এবং আমাকে কোথায় ভুল হয়েছে তা বলবেন?
জুলিয়ান মান

আমি উপরের ATOK এর জাভা উত্তর সঙ্গে তুলনা, এবং distored আলগোরিদিম আপনার jsfiddle এই পরিবর্তনটি করে whuberPointAtDistance(): x1 = (w * Math.cos(t)) / Math.cos(y0 * (Math.PI / 180))
ম্যাট

1
আমার সংশোধন হওয়া সত্ত্বেও জুলিয়ান এর ইস্ট সহ আমার আরও অনেক সঠিক ফলাফল ছিল accurate আমার সংশোধনীগুলি হোয়াইট পয়েন্টএটিডাস্টেন্স () এ যুক্ত করে এবং এটিকে ত্রুটি প্রতিবেদনের সাহায্যে চালানো, এটি তিনটি পরিস্থিতিতেই বিকল্পের তুলনায় 0.05% ত্রুটি দেখিয়েছিল (বিকল্পের তুলনায় উল্লেখযোগ্যভাবে বেশি)
ম্যাট

1

পাইথনে

# Testing simlation of generating random points 
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA

def create_random_point(x0,y0,distance):
    """
            Utility method for simulation of the points
    """   
    r = distance/ 111300
    u = np.random.uniform(0,1)
    v = np.random.uniform(0,1)
    w = r * np.sqrt(u)
    t = 2 * np.pi * v
    x = w * np.cos(t)
    x1 = x / np.cos(y0)
    y = w * np.sin(t)
    return (x0+x1, y0 +y)

fig = plt.figure()
ax = host_subplot(111, axes_class=AA.Axes)

#ax.set_ylim(76,78)
#ax.set_xlim(13,13.1)
ax.set_autoscale_on(True)

latitude1,longitude1 = 13.04738626,77.61946793  
ax.plot(latitude1,longitude1,'ro')

for i in range(1,20):
    x,y = create_random_point(latitude1,longitude1 ,500 )
    ax.plot(x,y,'bo')
    dist = haversine(x,y,latitude1,longitude1)
    print "Distance between points is " ,dist    # a value approxiamtely less than 500 meters   


plt.show()

আউটপুট

পয়েন্টের মধ্যে দূরত্ব 0.288044147914 পয়েন্টের মধ্যে দূরত্ব 0.409557451806 পয়েন্টের মধ্যে দূরত্ব 0.368260305716 পয়েন্টের মধ্যে দূরত্ব 0.453773334731 পয়েন্টের মধ্যে দূরত্ব 0.460608754561 পয়েন্টের মধ্যে দূরত্ব 0.49718825456 এর মধ্যে দূরত্ব 0.4971882556458156188158158158156158156158158156156158156156158156158158156158158151151 পয়েন্টের মধ্যে দূরত্ব 0.503691568896 পয়েন্টের মধ্যে দূরত্ব 0.175153349209 পয়েন্টের মধ্যে দূরত্ব 0.195149463735 পয়েন্টের মধ্যে দূরত্ব 0.424094009858 পয়েন্টের মধ্যে দূরত্ব 0.49807741494 পয়েন্টের মধ্যে দূরত্ব 0.498612171417 এর মধ্যে দূরত্ব 0.498612171417 দূরত্ব হয়

এখানে চিত্র বর্ণনা লিখুন


0

আপনি এখানে আপনার গণনার ফলাফল চেক করতে পারেন । "গন্তব্যস্থল প্রদত্ত দূরত্ব এবং শুরুর দিক থেকে বহন করা" নামক বিভাগটিতে স্ক্রোল করুন। এটি বাস্তবায়নের জন্য নীচে একটি সাধারণ জাভাস্ক্রিপ্ট সূত্র রয়েছে। আপনার এখনও রেডিয়ানে একটি এলোমেলো ভার্জিং \ \ থেটা gene উত্পন্ন করতে হবে (উত্তর থেকে ঘড়ির কাঁটার দিকটি পরিমাপ করা হয়েছে), যদিও এটি বেশ সোজা হয়ে যাওয়া উচিত। এই সূত্রগুলি একটি গোলাকার পৃথিবী ধরে নেয় (যদিও এটি উপবৃত্তাকার), এটি যথেষ্ট ভাল কারণ এটি 0.3% পর্যন্ত ত্রুটি তৈরি করে।


0

সুইফ্টের জন্য বাস্তবায়ন

জিওনকোডার থেকে ল্যাট এবং এলএনজি পাওয়া এবং এটি এই ফাংশনে প্রেরণ করা

func generateRandomLocation(lat: CLLocationDegrees, lng: CLLocationDegrees){
    let radius : Double = 100000 // this is in meters so 100 KM
    let radiusInDegrees: Double = radius / 111000
    let u : Double = Double(arc4random_uniform(100)) / 100.0
    let v : Double = Double(arc4random_uniform(100)) / 100.0
    let w : Double = radiusInDegrees * u.squareRoot()
    let t : Double = 2 * Double.pi * v
    let x : Double = w * cos(t)
    let y : Double = w * sin(t)

    // Adjust the x-coordinate for the shrinking of the east-west distances
    //in cos converting degree to radian
    let new_x : Double = x / cos(lat * .pi / 180 )

    processedLat = new_x + lat
    processedLng = y + lng

    print("The Lat are :- ")
    print(processedLat)
    print("The Lng are :- ")
    print(processedLng)
}

উপরের আমার উদাহরণে আমি দেশের নাম জিওনকোডিংয়ের সাথে অক্ষাংশ এবং দ্রাঘিমাংশ পেয়েছি, প্রতিবারের মতো, দেশের নামটি একইভাবে অক্ষাংশ এবং দ্রাঘিমাংশ দেয়, এটিও দেশের মধ্যভাগে, তাই আমার এলোমেলো প্রয়োজন needed


-1

প্রাইভেট অকার্যকর ড্র পললাইন (ডাবল ল্যাট, ডাবল এলএনজি) {

         double Pi=Math.PI;

         double lt=lat;
         double ln=lng;

        //Earth’s radius, sphere
         double R=6378137;

         double dn = 50;
         double de = 50;

         //Coordinate offsets in radians
         double dLat = dn/R;
         double dLon = de/(R*Math.cos(Pi*lat/180));

        //OffsetPosition, decimal degrees
        double lat2 = lt + dLat * 180/Pi;
        double lon2 = ln + dLon * 180/Pi ;



            //12.987859, 80.231038
            //12.987954, 80.231252

        double lat3 = lt - dLat * 180/Pi;
        double lon3 = ln - dLon * 180/Pi ;

            LatLng origin=new LatLng(lt, lon3);

            LatLng dest=new LatLng(lt, lon2);




          Polyline line = googleMap.addPolyline(new PolylineOptions()
         .add(origin, dest)
         .width(6)
         .color(Color.RED));

5
এটি কীভাবে ওপিগুলির সমস্যাগুলি সমাধান করে এবং আপনার কোডটি ব্রিফলি ব্যাখ্যা করবে সে সম্পর্কে আপনি কিছুটা প্রসারিত করতে পারেন?
মার্টিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.