Calculating the 3 closest locations
#1

Hi, so I have a problem with my function below. It's supposed to calculate the 3 nearest positions but it only returns the closest one on all of them. I've been trying various methods but I just can't seem to get it working :/
Any help would be appericated.
pawn Код:
stock ReturnClosestDestinations(playerid, &dest1, &dest2, &dest3)
{
    new Float:Pos[3], tmp1, tmp2, tmp3, Float:pdistance;
    GetPlayerPos(playerid, Pos[0], Pos[1], Pos[2]);
    foreach(Locations, i)
    {
        pdistance = DistanceToPoint(Pos[0], Pos[1], Pos[2], lInfo[i][PointX], lInfo[i][PointY], lInfo[i][PointZ]);
        printf("distance 1: %f", DistanceToPoint(Pos[0], Pos[1], Pos[2], lInfo[i][PointX], lInfo[i][PointY], lInfo[i][PointZ]));
        printf("distance to point 1: %f | distance to point 2: %f ", DistanceToPoint(Pos[0], Pos[1], Pos[2], lInfo[i][PointX], lInfo[i][PointY], lInfo[i][PointZ]), DistanceToPoint(Pos[0], Pos[1], Pos[2], lInfo[tmp1][PointX], lInfo[tmp1][PointY], lInfo[tmp1][PointZ]));
        if(pdistance <= DistanceToPoint(Pos[0], Pos[1], Pos[2], lInfo[tmp1][PointX], lInfo[tmp1][PointY], lInfo[tmp1][PointZ]))
        {
            dest1 = tmp1 = i;
            print("tmp 1");
        }
        if(pdistance <= DistanceToPoint(Pos[0], Pos[1], Pos[2], lInfo[tmp2][PointX], lInfo[tmp2][PointY], lInfo[tmp2][PointZ]) && i != dest1)
        {
            dest2 = tmp2 = i;
            print("tmp 2");
        }
        if(pdistance <= DistanceToPoint(Pos[0], Pos[1], Pos[2], lInfo[tmp3][PointX], lInfo[tmp3][PointY], lInfo[tmp3][PointZ]) && i != dest1 && i != dest2)
        {
            dest3 = tmp3 = i;
            print("tmp 3");
        }
    }
    return 1;
}
Thanks,
[03]Garsino.
Reply
#2

Try with 3 loops:

pawn Код:
stock ReturnClosestDestinations(playerid, &dest1, &dest2, &dest3)
{
    new Float:Pos[3], tmp1, tmp2, tmp3, Float:pdistance, Float:closest=9999.99;
    GetPlayerPos(playerid, Pos[0], Pos[1], Pos[2]);
    foreach(Locations, i)
    {
        pdistance = DistanceToPoint(Pos[0], Pos[1], Pos[2], lInfo[i][PointX], lInfo[i][PointY], lInfo[i][PointZ]);
        if(pdistance < closest)
        {
            dest1 = tmp1 = i;
            closest = pdistance;
        }
    }
    closest = 9999.99;
    foreach(Locations, i)
    {
        if(i == tmp1) continue;
        pdistance = DistanceToPoint(Pos[0], Pos[1], Pos[2], lInfo[i][PointX], lInfo[i][PointY], lInfo[i][PointZ]);
        if(pdistance < closest)
        {
            dest2 = tmp2 = i;
            closest = pdistance;
        }
    }
    closest = 9999.99;
    foreach(Locations, i)
    {
        if(i == tmp1 || i == tmp2) continue;
        pdistance = DistanceToPoint(Pos[0], Pos[1], Pos[2], lInfo[i][PointX], lInfo[i][PointY], lInfo[i][PointZ]);
        if(pdistance < closest)
        {
            dest3 = tmp3 = i;
            closest = pdistance;
        }
    }
    return 1;
}
Reply
#3

It works, but only if location ID 0 is not the closest one. I really want to get it working with ID 0 too :O
Reply
#4

bumpity bump. Need help with the ID 0 issue from MadeMan's code.
Reply
#5

Quote:
Originally Posted by [03]Garsino
Посмотреть сообщение
bumpity bump. Need help with the ID 0 issue from MadeMan's code.
^

It's been 4 days since my last bump, anyone knows? D:
Reply
#6

this is for gps system that rocks them all right?
did you add iter_add 0?
i don't know exactly how foreach works
Reply
#7

Use sorting functions which already exists around the forums to simplify your code, I believe ****** has written a version of quick sort in one of his libraries.

pawn Код:
stock ReturnClosestDestinations(playerid, &dest1, &dest2, &dest3)
{
    new
        fLocationDistances[MAX_LOCATIONS], // lets assume you have a MAX_LOCATIONS constant, change it to sizeof(lInfo) if not ..
        fPlyrX, fPlyrY, fPlyrZ;

    GetPlayerPos(playerid, fPlyrX, fPlyrY, fPlyrZ);


    foreach(Locations, i) {
        fLocationDistances[i] = DistanceToPoint(fPlyrX, fPlyrY, fPlyrZ, lInfo[i][PointX], lInfo[i][PointY], lInfo[i][PointZ]);
    }

    QSort(fLocationDistances, sizeof(fLocationDistances));

    /*
    fLocationDistances[0] // 1st closest ..
    fLocationDistances[1] // 2nd closest ..
    fLocationDistances[2] // 3rd closest ..
    fLocationDistances[n] // (n+1)th closest (you can change the required precision)
    */


    dest1 = fLocationDistances[0];
    dest2 = fLocationDistances[1];
    dest3 = fLocationDistances[2];
}
Here's ******' QuickSort implementation, since the link in his original Pastebin post has expired.

pawn Код:
#define QuickSort(%1,%2) \
        QSort((%1), 0, (%2) - 1)
       
stock QSort(numbers[], left, right)
{
    new
        pivot = numbers[left],
        l_hold = left,
        r_hold = right;
    while (left < right)
    {
        while ((numbers[right] >= pivot) && (left < right)) right--;
        if (left != right)
        {
            numbers[left] = numbers[right];
            left++;
        }
        while ((numbers[left] <= pivot) && (left < right)) left++;
        if (left != right)
        {
            numbers[right] = numbers[left];
            right--;
        }
    }
    numbers[left] = pivot;
    pivot = left;
    left = l_hold;
    right = r_hold;
    if (left < pivot) QSort(numbers, left, pivot - 1);
    if (right > pivot) QSort(numbers, pivot + 1, right);
}
Note: I haven't had a chance to test this, so it may sort the opposite way than I assumed. To fix this you will just need to change the final part of the code to:

pawn Код:
/*
    fLocationDistances[sizeof(fLocationDistances) - 1] // 1st closest ..
    fLocationDistances[sizeof(fLocationDistances) - 2] // 2nd closest ..
    fLocationDistances[sizeof(fLocationDistances) - 3] // 3rd closest ..
    fLocationDistances[sizeof(fLocationDistances) - n] // nth closest (you can change the required precision)
    */


    dest1 = fLocationDistances[sizeof(fLocationDistances) - 1];
    dest2 = fLocationDistances[sizeof(fLocationDistances) - 2];
    dest3 = fLocationDistances[sizeof(fLocationDistances) - 3];
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)