PDA

View Full Version : Provide GPS coordinates of all track reference points + GPS calculation in javascript



M. -VIPER- Morgan
16-09-2015, 08:38
First of all I have to say that it was hard work to find the reference points.
But we (a friend and I) needed it for our project to show live position data in google maps. I only had help by the member colets, he provides me some reference points which he found in the past. Thank you for that.

The data is embedded in javascript functions/objects.
If you want to use it you can simply call the function calc_coordinates (circuit_id,PosX,PosY)
PosX and PosY is in millimeter, because of the DS API. Caution: PosY here is Z in the Game/DS API. Y in the Game API has the altitude information.
Further the Game API provides the position data in meter, the DS API in millimeter.

The calc_coordinates function references to the reference points and finds the data via the circuit_id.
The function returns an associative array with latitude and longitude of the current car position.
var gps = calc_coordinates (-1612023328,-288200,232450); //example Laguna Seca
var lat = gps["Lat"]; // latitude at this point
var long = gps["Long"]; //longitude at this point

Some words on the calculation
Our calculation is based on the radius of the earth. There are some sources of error which results in not perfectly calculated points. There are some tracks with many meters discrepancy.
I worked with some correction values, but this also did not help completely. I fiddle around with this values, but it is a question of perfection ;-)
You can see the current state in the "Comment" field of the reference points - "live check" means finetuning, there are low discrepancies. But there are some tracks like Nordschleife, Silverstone or Road America where I have bigger discrepancies
Sources of error:
- radius of the earth - I used a radius of 6371 km, but our earth is no perfect ball. At the equator you have a higer radius and at the poles a lower one.
- altitude - our calculation completely ignores the altitude information - this can have an impact on tracks with high altitude differences.
- track maybe not 100% correct designed
I can reduce these errors with the correction values, but cannot completely solve it.

There is a jsfiddle (jsfiddle.net/3jr4ghgf/40/) with the calculation function, which I use to find the best correction values. There you can see how it works. In the lower frame you have to enter the refPoint data and in the upper frame the position data from the API in millimeters. After pressing "Run" you find the result on the right, which you can paste at gpsvisualizer.com.
The 12 Testpoints there are from my work of finding the reference point. I take a lot of screenshots ingame, noted the API position data and marked the positions on a satellite map.
You can see it here as an example for Catalunya: http://pcars.web2mm.com/storage/tools/trackmaps/Catalunya.pdf - Info: the browser has sometimes problems with showing the pdf correctly, better use Adobe Reader.


And now the most important:

REFERENCE POINTS - Info: fictional tracks have all a dummy ref point in Greenland


/// Reference Object
// CLASS of RefPoints
function Refpoint(circuit_id)
{

// console.log ("RefPoint - Parameter: " , circuit_id);
this.circuit_id = circuit_id;
this.Lat = undefined;
this.Long = undefined;
this.Rot = undefined;
this.cuircit_name = undefined;

var aRefPoints = new Array();

//static information

//Default
aRefPoints[9999999999] = new Array();
aRefPoints[9999999999] =
{
"refLat": 51.500681 // GPS coords of the zero point, where X=0 and Z=0
,"refLong": -0.071795
,"rotation": 0 // rotation correction angle in degree anticlockwise, negative value means clockwise
,"cor_r_Long": 0 // earth radius correction value for east/west calculation in millimeter
,"cor_r_Lat": 0 // earth radius correction value for north/south calculation in millimeter
,"cor_PosX_mul": 1 // correction multiplier for PosX on input data before calculation / the multipliers have a similar result as the cor_r_xxx values, but help better for tracks with a rotation error
,"cor_PosY_mul": 1 // correction multiplier for PosY on input data before calculation
,"Name": "Slightly Mad Studios Ltd" // real name of the circuit in DS API
,"Name2": "" // real name of the circuit in Game API, if it differs from DS API Name
,"Zoom": 19 // wanted zoom level for initial google map
,"MapInitLat": 51.500681 // google map initialization coords
,"MapInitLong": -0.071795
,"Comment": "Default"
};

//Default for fictional tracks
aRefPoints[8888888888] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 62.552546
,"refLong": -45.678026
,"Name": "Greenland"
,"Zoom": 15
,"MapInitLat": 41.036357
,"MapInitLong": -113.535295
,"Comment": "Default for fictional tracks"
});

//Hockenheim GP
aRefPoints[1695182971] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 49.329738
,"refLong": 8.574270
,"rotation": 0.573
,"cor_r_Long": 45000000
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Hockenheim GP"
,"Name2": "Hockenheim Grand Prix" //"mTrackLocation":"Hockenheim","mTrackVariation":"Grand Prix"
,"Zoom": 16
,"MapInitLat": 49.329718
,"MapInitLong": 8.574300
,"Comment": "finetuning"
});
//Hockenheim Short
aRefPoints[1768660198] = CopyObjectWithModifications(aRefPoints[1695182971], {"Name": "Hockenheim Short","Name2": ""});
//Hockenheim National
aRefPoints[-1977142985] = CopyObjectWithModifications(aRefPoints[1695182971], {"Name": "Hockenheim National","Name2": ""});

//Dubai Autodrome GP
aRefPoints[-661887517] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 25.046650
,"refLong": 55.231300
,"rotation": -0.401
,"cor_r_Long": 45000000
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Dubai Autodrome GP"
,"Name2": "Dubai Autodrome Grand Prix" //"mTrackLocation":"Dubai Autodrome","mTrackVariation":"Grand Prix"
,"Zoom": 17
,"MapInitLat": 25.050102
,"MapInitLong": 55.238634
,"Comment": "live check"
});

///Dubai Autodrome International
aRefPoints[-710712693] = CopyObjectWithModifications(aRefPoints[-661887517], {"Name": "Dubai Autodrome International","Name2": ""});
//Dubai Kartdrome
aRefPoints[-232513374] = CopyObjectWithModifications(aRefPoints[-661887517], {"Name": "Dubai Kartdrome","Name2": ""});
//Dubai Autodrome National
aRefPoints[-31727447] = CopyObjectWithModifications(aRefPoints[-661887517], {"Name": "Dubai Autodrome National","Name2": ""});
//Dubai Autodrome Club
aRefPoints[1735854797] = CopyObjectWithModifications(aRefPoints[-661887517], {"Name": "Dubai Autodrome Club","Name2": ""});

//Nuerburgring GP
aRefPoints[-945967394] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 50.332733
,"refLong": 6.943355
,"rotation": -0.9
,"cor_r_Long": 30000000
,"cor_r_Lat": -30000000
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Nürburgring GP"
,"Name2": "Nürburgring Grand Prix" //"mTrackLocation":"Nürburgring","mTrackVariation":"Grand Prix"
,"Zoom": 15
,"MapInitLat": 50.332154
,"MapInitLong": 6.940467
,"Comment": "live check"
});

//Nuerburgring Sprint Short
aRefPoints[-810715843] = CopyObjectWithModifications(aRefPoints[-945967394], {"Name": "Nürburgring Sprint Short","Name2": ""});
//Nuerburgring Sprint
aRefPoints[-709737101] = CopyObjectWithModifications(aRefPoints[-945967394], {"Name": "Nürburgring Sprint","Name2": ""});
//Nuerburgring Muellenbach
aRefPoints[-246966400] = CopyObjectWithModifications(aRefPoints[-945967394], {"Name": "Nürburgring Müllenbach","Name2": "Nürburgring MuellenBach"}); //"mTrackLocation":"Nürburgring","mTrackVariation":"MuellenBach"

//Nordschleife
aRefPoints[697498609] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 50.332733
,"refLong": 6.943385
,"rotation": -0.9
,"cor_r_Long": 10000000
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Nordschleife"
,"Name2": "Nordschleife Full" //"mTrackLocation":"Nordschleife","mTrackVariation":"Full"
,"Zoom": 13
,"MapInitLat": 50.359101
,"MapInitLong": 6.962529
,"Comment": "live check, big discrepancies on some parts of track"
});
//Nordschleife Stage 3
aRefPoints[1128950148] = CopyObjectWithModifications(aRefPoints[-945967394], {"Name": "Nordschleife Stage 3","Name2": ""});
//Nordschleife Stage 1
aRefPoints[1459212514] = CopyObjectWithModifications(aRefPoints[-945967394], {"Name": "Nordschleife Stage 1","Name2": ""});
//Nordschleife Stage 2
aRefPoints[-300387291] = CopyObjectWithModifications(aRefPoints[-945967394], {"Name": "Nordschleife Stage 2","Name2": ""});

//Sonoma Raceway
aRefPoints[-1454279631] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 38.162514
,"refLong": -122.457216
,"rotation": 142
,"cor_r_Long": 10000000
,"cor_r_Lat": -30000000
,"cor_PosX_mul": 1
,"cor_PosY_mul": 0.97
,"Name": "Sonoma Raceway GP"
,"Name2": "Sonoma Raceway Grand Prix" //"mTrackLocation":"Sonoma Raceway","mTrackVariation":"Grand Prix"
,"Zoom": 16
,"MapInitLat": 38.162770
,"MapInitLong": -122.457449
,"Comment": "live check"
});
//Sonoma Raceway National
aRefPoints[-995202729] = CopyObjectWithModifications(aRefPoints[-1454279631], {"Name": "Sonoma Raceway National","Name2": ""});
//Sonoma Sonoma Raceway Short
aRefPoints[1035110721] = CopyObjectWithModifications(aRefPoints[-1454279631], {"Name": "Sonoma Raceway Short","Name2": ""});

//Circuit des 24 Heures du Mans
aRefPoints[1740968730] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 47.939065
,"refLong": 0.218178
,"rotation": 1.6
,"cor_r_Long": 25000000
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Circuit des 24 Heures du Mans"
,"Name2": "Le Mans Circuit des 24 Heures du Mans" //"mTrackLocation":"Le Mans","mTrackVariation":"Circuit des 24 Heures du Mans"
,"Zoom": 13
,"MapInitLat": 47.936818
,"MapInitLong": 0.223960
,"Comment": "live check"
});
//Le Circuit Bugatti
aRefPoints[-1027934689] = CopyObjectWithModifications(aRefPoints[1740968730], {"Name": "Le Circuit Bugatti","Name2": "Le Mans Le Circuit Bugatti","Zoom": 15,"MapInitLat": 47.954335,"MapInitLong": 0.211027}); //"mTrackLocation":"Le Mans","mTrackVariation":"Le Circuit Bugatti"

//Ruapuna Park GP
aRefPoints[1277693448] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": -43.533275
,"refLong": 172.478130
,"rotation": -0.3
,"cor_r_Long": 0
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Ruapuna Park GP"
,"Name2": "Ruapuna Park Grand Prix" //"mTrackLocation":"Ruapuna Park","mTrackVariation":"Grand Prix"
,"Zoom": 15
,"MapInitLat": -43.531123
,"MapInitLong": 172.479408
,"Comment": "live check"
});
//Ruapuna Park A Circuit
aRefPoints[619694160] = CopyObjectWithModifications(aRefPoints[1277693448], {"Name": "Ruapuna Park A Circuit","Name2": "Ruapuna Park A_Circuit"}); //"mTrackLocation":"Ruapuna Park","mTrackVariation":"A_Circuit"
//Ruapuna Park Club
aRefPoints[1446378877] = CopyObjectWithModifications(aRefPoints[1277693448], {"Name": "Ruapuna Park Club","Name2": ""});
//Ruapuna Park Outer Loop
aRefPoints[1940584155] = CopyObjectWithModifications(aRefPoints[1277693448], {"Name": "Ruapuna Park Outer Loop","Name2": "Ruapuna Park Outer_Loop"}); //"mTrackLocation":"Ruapuna Park","mTrackVariation":"Outer_Loop"
//Ruapuna Park B Circuit
aRefPoints[-2046633090] = CopyObjectWithModifications(aRefPoints[1277693448], {"Name": "Ruapuna Park B Circuit","Name2": "Ruapuna Park B_Circuit"}); //"mTrackLocation":"Ruapuna Park","mTrackVariation":"B_Circuit"

//Cadwell GP
aRefPoints[1876749797] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 53.310651
,"refLong": -0.059440
,"rotation": 0
,"cor_r_Long": 0
,"cor_r_Lat": -30000000
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Cadwell GP"
,"Name2": "Cadwell Grand Prix" //"mTrackLocation":"Cadwell","mTrackVariation":"Grand Prix"
,"Zoom": 15
,"MapInitLat": 53.308465
,"MapInitLong": -0.063734
,"Comment": "live check"
});
//Cadwell Club Circuit
aRefPoints[328972919] = CopyObjectWithModifications(aRefPoints[1876749797], {"Name": "Cadwell Club Circuit","Name2": ""});
//Cadwell Woodland
aRefPoints[-1408189041] = CopyObjectWithModifications(aRefPoints[1876749797], {"Name": "Cadwell Woodland","Name2": ""});

//Oulton Park International
aRefPoints[545979690] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 53.179864
,"refLong": -2.613992
,"rotation": -0.3
,"cor_r_Long": 0
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Oulton Park International"
,"Zoom": 15
,"MapInitLat": 53.176808
,"MapInitLong": -2.616589
,"Comment": "live check"
});
//Oulton Park Fosters
aRefPoints[-2021024495] = CopyObjectWithModifications(aRefPoints[545979690], {"Name": "Oulton Park Fosters"});
//Oulton Park Island
aRefPoints[-1877699523] = CopyObjectWithModifications(aRefPoints[545979690], {"Name": "Oulton Park Island"});

//Snetterton 300
aRefPoints[1508903068] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 52.463952
,"refLong": 0.945230
,"rotation": 0.2
,"cor_r_Long": 0
,"cor_r_Lat": 20000000
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Snetterton 300"
,"Name2": "Snetterton 300 Circuit" //"mTrackLocation":"Snetterton","mTrackVariation":"300 Circuit"
,"Zoom": 15
,"MapInitLat": 52.465021
,"MapInitLong": 0.947079
,"Comment": "live check"
});
//Snetterton 200
aRefPoints[1058872832] = CopyObjectWithModifications(aRefPoints[1508903068], {"Name": "Snetterton 200","Name2": "Snetterton 200 Circuit"}); //"mTrackLocation":"Snetterton","mTrackVariation":"200 Circuit"
//Snetterton 100
aRefPoints[-867340010] = CopyObjectWithModifications(aRefPoints[1508903068], {"Name": "Snetterton 100","Name2": "Snetterton 100 Circuit"}); //"mTrackLocation":"Snetterton","mTrackVariation":"100 Circuit"

//Zhuhai International Circuit
aRefPoints[1836888499] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 22.367585
,"refLong": 113.559640
,"rotation": -29.9
,"cor_r_Long": -15000000
,"cor_r_Lat": -25000000
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Zhuhai International Circuit"
,"Zoom": 15
,"MapInitLat": 22.367988
,"MapInitLong": 113.556162
,"Comment": "live check"
});

//Silverstone GP
aRefPoints[1641471184] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 52.078807
,"refLong": -1.015293
,"rotation": -0.2
,"cor_r_Long": 20000000
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Silverstone GP"
,"Name2": "Silverstone Grand Prix" //"mTrackLocation":"Silverstone","mTrackVariation":"Grand Prix"
,"Zoom": 15
,"MapInitLat": 52.071727
,"MapInitLong": -1.015736
,"Comment": "track maybe not correct, check again"
});
//Silverstone International
aRefPoints[1101719627] = CopyObjectWithModifications(aRefPoints[1641471184], {"Name": "Silverstone International","Name2": ""});
//Silverstone Stowe
aRefPoints[1600840139] = CopyObjectWithModifications(aRefPoints[1641471184], {"Name": "Silverstone Stowe","Name2": ""});
//Silverstone National
aRefPoints[1952936927] = CopyObjectWithModifications(aRefPoints[1641471184], {"Name": "Silverstone National","Name2": ""});

//Brands Hatch GP
aRefPoints[1988984740] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 51.357240
,"refLong": 0.261592
,"rotation": 0
,"cor_r_Long": -10000000
,"cor_r_Lat": 20000000
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Brands Hatch GP"
,"Name2": "Brands Hatch Grand Prix" //"mTrackLocation":"Brands Hatch","mTrackVariation":"Grand Prix"
,"Zoom": 15
,"MapInitLat": 51.357186
,"MapInitLong": 0.262930
,"Comment": "live check, track maybe not correct, small discrepancies"
});
//Brands Hatch Indy
aRefPoints[1300627020] = CopyObjectWithModifications(aRefPoints[1988984740], {"Name": "Brands Hatch Indy","Name2": ""});

//Mazda Raceway Laguna Seca
aRefPoints[-1612023328] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 36.584300
,"refLong": -121.753357
,"rotation": 2
,"cor_r_Long": 0
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Mazda Raceway Laguna Seca"
,"Zoom": 15
,"MapInitLat": 36.584275
,"MapInitLong": -121.753345
,"Comment": "live check"
});

//Brno
aRefPoints[-907901266] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 49.203370
,"refLong": 16.444172
,"rotation": 156.6
,"cor_r_Long": 10000000
,"cor_r_Lat": -30000000
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Brno"
,"Zoom": 15
,"MapInitLat": 49.205370
,"MapInitLong": 16.452067
,"Comment": "live check"
});

//Road America
aRefPoints[-660300766] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 43.798290
,"refLong": -87.995239
,"rotation": 0
,"cor_r_Long": 30000000
,"cor_r_Lat": 10000000
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Road America"
,"Zoom": 15
,"MapInitLat": 43.798710
,"MapInitLong": -87.995182
,"Comment": "check again, big discrepancies"
});

//Zolder
aRefPoints[-360711057] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 50.992257
,"refLong": 5.258882
,"rotation": -148.2
,"cor_r_Long": 15000000
,"cor_r_Lat": 0
,"cor_PosX_mul": 0.955
,"cor_PosY_mul": 0.96
,"Name": "Zolder"
,"Name2": "Zolder Grand Prix" //"mTrackLocation":"Zolder","mTrackVariation":"Grand Prix"
,"Zoom": 15
,"MapInitLat": 50.990644
,"MapInitLong": 5.257656
,"Comment": "live check"
});

//Donington Park GP
aRefPoints[354022214] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 52.830575
,"refLong": -1.374732
,"rotation": 174
,"cor_r_Long": 10000000
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Donington Park GP"
,"Name2": "Donington Park Grand Prix" //"mTrackLocation":"Donington Park","mTrackVariation":"Grand Prix"
,"Zoom": 15
,"MapInitLat": 52.830756
,"MapInitLong": -1.375103
,"Comment": "live check"
});
//Donington Park National
aRefPoints[-1194019375] = CopyObjectWithModifications(aRefPoints[354022214], {"Name": "Donington Park National","Name2": ""});


//Oschersleben GP
aRefPoints[-1194185720] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 52.027834
,"refLong": 11.280251
,"rotation": 161.8
,"cor_r_Long": 0
,"cor_r_Lat": 0
,"cor_PosX_mul": 1.003
,"cor_PosY_mul": 1
,"Name": "Oschersleben GP"
,"Name2": "Oschersleben Grand Prix" //"mTrackLocation":"Oschersleben","mTrackVariation":"Grand Prix"
,"Zoom": 16
,"MapInitLat": 52.028843
,"MapInitLong": 11.276850
,"Comment": "live check"
});
//Oschersleben National
aRefPoints[816601966] = CopyObjectWithModifications(aRefPoints[-1194185720], {"Name": "Oschersleben National","Name2": ""});
//Oschersleben C Circuit
aRefPoints[-1359299594] = CopyObjectWithModifications(aRefPoints[-1194185720], {"Name": "Oschersleben C Circuit","Name2": ""});

//Azure Circuit
aRefPoints[832629329] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 43.737030
,"refLong": 7.427395
,"rotation": 126
,"cor_r_Long": 0
,"cor_r_Lat": 0
,"cor_PosX_mul": 0.983
,"cor_PosY_mul": 0.985
,"Name": "Azure Circuit"
,"Name2": "Azure Circuit Grand Prix" //"mTrackLocation":"Azure Circuit","mTrackVariation":"Grand Prix"
,"Zoom": 15
,"MapInitLat": 43.737186
,"MapInitLong": 7.425732
,"Comment": "live check"
});

//Bathurst
aRefPoints[921120824] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": -33.439873
,"refLong": 149.559704
,"rotation": -9
,"cor_r_Long": 15000000
,"cor_r_Lat": 15000000
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Bathurst"
,"Zoom": 14
,"MapInitLat": -33.448809
,"MapInitLong": 149.555024
,"Comment": "live check"
});

//Circuit de Spa-Francorchamps
aRefPoints[904625875] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 50.430342
,"refLong": 5.976448
,"rotation": -2.45
,"cor_r_Long": 30000000
,"cor_r_Lat": 40000000
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Circuit de Spa-Francorchamps"
,"Zoom": 15
,"MapInitLat": 50.437254
,"MapInitLong": 5.970570
,"Comment": "live check"
});
//Greenwood Karting Circuit - Kart track of Spa-Franchorchamps
aRefPoints[-1160443077] = CopyObjectWithModifications(aRefPoints[904625875], {"Name": "Greenwood Karting Circuit"});

//Circuit de Barcelona-Catalunya GP
aRefPoints[521933422] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 41.569355
,"refLong": 2.258060
,"rotation": 58.1
,"cor_r_Long": 0
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Circuit de Barcelona-Catalunya GP"
,"Name2": "Circuit de Barcelona-Catalunya Grand Prix" //"mTrackLocation":"Circuit de Barcelona-Catalunya","mTrackVariation":"Grand Prix"
,"Zoom": 15
,"MapInitLat": 41.569612
,"MapInitLong": 2.257745
,"Comment": "live check"
});
//Circuit de Barcelona-Catalunya Club
aRefPoints[-1042928898] = CopyObjectWithModifications(aRefPoints[521933422], {"Name": "Circuit de Barcelona-Catalunya Club","Name2": ""});
//Circuit de Barcelona-Catalunya National
aRefPoints[-998191994] = CopyObjectWithModifications(aRefPoints[521933422], {"Name": "Circuit de Barcelona-Catalunya National","Name2": ""});

//Imola
aRefPoints[920145926] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 44.340705
,"refLong": 11.717190
,"rotation": -1.9
,"cor_r_Long": -20000000
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Imola"
,"Name2": "Imola Grand Prix" //"mTrackLocation":"Imola","mTrackVariation":"Grand Prix"
,"Zoom": 15
,"MapInitLat": 44.341112
,"MapInitLong": 11.712506
,"Comment": "live check"
});

//Willow Springs International Raceway
aRefPoints[-103312908] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 34.871624
,"refLong": -118.263848
,"rotation": -32.8
,"cor_r_Long": 0
,"cor_r_Lat": 0
,"cor_PosX_mul": 0.97
,"cor_PosY_mul": 0.97
,"Name": "Willow Springs International Raceway"
,"Zoom": 15
,"MapInitLat": 34.872929
,"MapInitLong": -118.264394
,"Comment": "live check, small discrepancies"
});
//Willow Springs Horse Thief Mile
aRefPoints[-1849531562] = CopyObjectWithModifications(aRefPoints[-103312908],
{
"rotation": -33.3
,"cor_PosX_mul": 0.97
,"cor_PosY_mul": 0.985
,"Name": "Willow Springs Horse Thief Mile"
,"MapInitLat": 34.878537
,"MapInitLong": -118.264290
,"Comment": "live check"
});

//Watkins Glen GP
aRefPoints[-1785781495] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 42.329767
,"refLong": -76.920975
,"rotation": -178.4
,"cor_r_Long": 0
,"cor_r_Lat": 0
,"cor_PosX_mul": 1.062
,"cor_PosY_mul": 1.065
,"Name": "Watkins Glen GP"
,"Name2": "Watkins Glen International Grand Prix" //"mTrackLocation":"Watkins Glen International","mTrackVariation":"Grand Prix"
,"Zoom": 15
,"MapInitLat": 42.336564
,"MapInitLong": -76.924519
,"Comment": "live check"
});
//Watkins Glen Short
aRefPoints[1590386668] = CopyObjectWithModifications(aRefPoints[-1785781495], {"Name": "Watkins Glen Short","Name2": "Watkins Glen International Short Circuit"}); //"mTrackLocation":"Watkins Glen International","mTrackVariation":"Short Circuit"

//Autodromo Nazionale Monza GP
aRefPoints[-52972612] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 45.619146
,"refLong": 9.280608
,"rotation": 0
,"cor_r_Long": 25000000
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1
,"Name": "Autodromo Nazionale Monza GP"
,"Name2": "Autodromo Nazionale Monza Grand Prix" //"mTrackLocation":"Autodromo Nazionale Monza","mTrackVariation":"Grand Prix"
,"Zoom": 15
,"MapInitLat": 45.621690
,"MapInitLong": 9.286990
,"Comment": "live check"
});

//Autodromo Nazionale Monza Short
aRefPoints[368740158] = CopyObjectWithModifications(aRefPoints[-52972612], {"Name": "Autodromo Nazionale Monza Short","Name2": ""});

//// fictional tracks
//Azure Coast
aRefPoints[560711985] = CopyObjectWithModifications(aRefPoints[8888888888],
{
"Name": "Azure Coast"
,"Name2": "Azure Coast Eastbound"
,"Comment": "fictional track"
});
//Azure Coast Westbound
aRefPoints[-1936790504] = CopyObjectWithModifications(aRefPoints[560711985], {"Name": "Azure Coast Westbound","Name2": ""});
//Azure Coast Stage 1
aRefPoints[550129415] = CopyObjectWithModifications(aRefPoints[560711985], {"Name": "Azure Coast Stage 1","Name2": ""});
//Azure Coast Stage 2
aRefPoints[-780879576] = CopyObjectWithModifications(aRefPoints[560711985], {"Name": "Azure Coast Stage 2","Name2": ""});
//Azure Coast Stage 3
aRefPoints[-1737261125] = CopyObjectWithModifications(aRefPoints[560711985], {"Name": "Azure Coast Stage 3","Name2": ""});


//California Highway Full
aRefPoints[-1593944167] = CopyObjectWithModifications(aRefPoints[8888888888],
{
"Name": "California Highway Full"
,"Comment": "fictional track"
});
//California Highway Reverse
aRefPoints[928006536] = CopyObjectWithModifications(aRefPoints[-1593944167], {"Name": "California Highway Reverse"});
//California Highway Stage 1
aRefPoints[1676943041] = CopyObjectWithModifications(aRefPoints[-1593944167], {"Name": "California Highway Stage 1"});
//California Highway Stage 2
aRefPoints[940391868] = CopyObjectWithModifications(aRefPoints[-1593944167], {"Name": "California Highway Stage 2"});
//California Highway Stage 3
aRefPoints[-331502851] = CopyObjectWithModifications(aRefPoints[-1593944167], {"Name": "California Highway Stage 3"});

//Sakitto GP
aRefPoints[-1759743046] = CopyObjectWithModifications(aRefPoints[8888888888],
{
"Name": "Sakitto GP"
,"Name2": "Sakitto Grand Prix"
,"Comment": "fictional track"
});
//Sakitto International
aRefPoints[-1474170192] = CopyObjectWithModifications(aRefPoints[-1759743046], {"Name": "Sakitto International","Name2": ""});
//Sakitto Sakitto National
aRefPoints[-1260826266] = CopyObjectWithModifications(aRefPoints[-1759743046], {"Name": "Sakitto National","Name2": ""});
//Sakitto Sprint
aRefPoints[-879282119] = CopyObjectWithModifications(aRefPoints[-1759743046], {"Name": "Sakitto Sprint","Name2": ""});

//Mojave Cougar Ridge
aRefPoints[-688586697] = CopyObjectWithModifications(aRefPoints[8888888888],
{
"Name": "Mojave Cougar Ridge"
,"Comment": "fictional track"
});
//Mojave Boa Ascent
aRefPoints[850003838] = CopyObjectWithModifications(aRefPoints[-688586697], {"Name": "Mojave Boa Ascent"});
//Mojave Gila Crest
aRefPoints[2089801285] = CopyObjectWithModifications(aRefPoints[-688586697], {"Name": "Mojave Gila Crest"});
//Mojave Coyote Noose
aRefPoints[-2125682335] = CopyObjectWithModifications(aRefPoints[-688586697], {"Name": "Mojave Coyote Noose"});
//Mojave Sidewinder
aRefPoints[-1463443929] = CopyObjectWithModifications(aRefPoints[-688586697], {"Name": "Mojave Sidewinder"});
//Mojave Test Track - only in Game API available, because you cannot play it in Multiplayer, it has no TrackID -> works only in CREST Mode
aRefPoints[0] = CopyObjectWithModifications(aRefPoints[-688586697], {"Name": "Mojave Test Track"});

//Bannochbrae Road Circuit
aRefPoints[-602684269] = CopyObjectWithModifications(aRefPoints[8888888888],
{
"Name": "Bannochbrae Road Circuit"
,"Comment": "fictional track"
});

//// fictional Kart tracks
//Summerton
aRefPoints[-44748320] = CopyObjectWithModifications(aRefPoints[8888888888],
{
"Name": "Summerton"
,"Name2": "Summerton International" //"mTrackLocation":"Summerton","mTrackVariation":"International"
,"Comment": "Kart Track?"
});
//Summerton National
aRefPoints[1408845203] = CopyObjectWithModifications(aRefPoints[-44748320], {"Name": "Summerton National","Name2": ""});
//Summerton Sprint
aRefPoints[-1605913568] = CopyObjectWithModifications(aRefPoints[-44748320], {"Name": "Summerton Sprint","Name2": ""});

//Chesterfield
aRefPoints[-1735912413] = CopyObjectWithModifications(aRefPoints[8888888888],
{
"Name": "Chesterfield"
,"Name2": "Chesterfield Grand Prix" //"mTrackLocation":"Chesterfield","mTrackVariation":"Grand Prix"
,"Comment": "Kart Track"
});

//Glencairn
aRefPoints[-1066742780] = CopyObjectWithModifications(aRefPoints[8888888888],
{
"Name": "Glencairn"
,"Name2": "Glencairn Grand Prix" //"mTrackLocation":"Glencairn","mTrackVariation":"Grand Prix"
,"Comment": "Kart Track"
});
//Glencairn Reverse
aRefPoints[-1520844580] = CopyObjectWithModifications(aRefPoints[-1066742780], {"Name": "Glencairn Reverse","Name2": "Glencairn GP Reverese"}); //"mTrackLocation":"Glencairn","mTrackVariation":"GP Reverese"
//Glencairn East
aRefPoints[766599953] = CopyObjectWithModifications(aRefPoints[-1066742780], {"Name": "Glencairn East","Name2": ""});
//Glencairn East Reverse
aRefPoints[-446794969] = CopyObjectWithModifications(aRefPoints[-1066742780], {"Name": "Glencairn East Reverse","Name2": ""});
//Glencairn West
aRefPoints[-1408779593] = CopyObjectWithModifications(aRefPoints[-1066742780], {"Name": "Glencairn West","Name2": ""});
//Glencairn West Reverse
aRefPoints[-913625358] = CopyObjectWithModifications(aRefPoints[-1066742780], {"Name": "Glencairn West Reverse","Name2": ""});


//// Historic Tracks
//Rouen Les Essarts
aRefPoints[-1031249929] = CopyObjectWithModifications(aRefPoints[9999999999],
{
"refLat": 49.333052
,"refLong": 1.010787
,"rotation": 55.5
,"cor_r_Long": 0
,"cor_r_Lat": 0
,"cor_PosX_mul": 1
,"cor_PosY_mul": 1.04
,"Name": "Rouen Les Essarts"
,"Zoom": 14
,"MapInitLat": 49.333581
,"MapInitLong": 1.004589
,"Comment": "live check"
});
//Rouen Les Essarts Short
aRefPoints[-1515473908] = CopyObjectWithModifications(aRefPoints[-1031249929], {"Name": "Rouen Les Essarts Short"});

//Hockenheim Classic - copy of Hockenheim GP
aRefPoints[1552853772] = CopyObjectWithModifications(aRefPoints[1695182971], {"Name": "Hockenheim Classic","Name2": ""});

//Silverstone Classic - copy of Silverstone GP
aRefPoints[-1194290828] = CopyObjectWithModifications(aRefPoints[1641471184], {"Name": "Silverstone Classic","Name2": ""});



///////////////////////////////////////////////////////////////////////////
//console.log("Refpoints: " , aRefPoints);

if (circuit_id == undefined)
{
// no paramter given -> set to an default value to prevent empty return value
console.log ("Circuit_id NOT set, change to default!");
this.circuit_id = 9999999999;

}

//console.log ("+++ RefPoints: " , aRefPoints);
//console.log ("++ used CuircitID: " + this.circuit_id );

return aRefPoints;
/////////////////////// function of this object


}

function CopyObjectWithModifications(source, changes )
{
var dest = {};
dest = JSON.parse( JSON.stringify( source ) );

// console.log("CopyObject(): ", changes)
for (var key in changes)
{
//console.log("Object Dest: " , dest["Name"]);
//console.log("key: " + key + " value: " + changes[key]);
dest[key] = changes[key];
}

return JSON.parse( JSON.stringify( dest ) );
}




CALCULATION


function calc_coordinates (circuit_id,PosX,PosY){

var aRefPointTmp = new Refpoint(circuit_id);

// define variables
var rotation = degreeToRadians ( aRefPointTmp[circuit_id]["rotation"] ); //rotation angle in radian, because Math.cos() needs angle in radian
var x_new;
var y_new;

//correction multiplier
PosX = PosX * aRefPointTmp[circuit_id]["cor_PosX_mul"];
PosY = PosY * aRefPointTmp[circuit_id]["cor_PosY_mul"];

//console.log("CALC:", aRefPointTmp );
//console.log("Calc rotation: " + rotation);

//eliminate rotation error
if ( aRefPointTmp[circuit_id]["rotation"] != 0) {
//ATTENTION: Math.cos needs angle in radian
x_new = (Math.cos(rotation) * PosX) - (Math.sin(rotation) * PosY);
y_new = (Math.sin(rotation) * PosX) + (Math.cos(rotation) * PosY);
}else{
// no rotation
x_new = PosX;
y_new = PosY;
}

//console.log ("X_old: " + PosX + " X_New: " + x_new + "Y_old: " + PosY + " Y_New: " + y_new);

//calculation from game position data to an GPS angle (radius earth 6371.000.000 mm, because the data from the Game DS API is in millimeter):
//ATTENTION: Math.cos needs angle in radian
var radius2EarthAxis = 6371000000 * Math.cos( degreeToRadians(aRefPointTmp[circuit_id]["refLat"]) ) + aRefPointTmp[circuit_id]["cor_r_Long"];


/************************************************************
////Method 1: right-angled triangle
var angleX = Math.asin(x_new/radius2EarthAxis);
var angleY = Math.asin(y_new/6371000000);
//convert radian to degree
// console.log("angleX before calculation: " + angleX + " angleY: " + angleY );
angleX = radiansToDegrees(angleX);
angleY = radiansToDegrees(angleY);
**************************************************************/

//Method 2: set angle in relation, 360 degrees are 40030km circumference - better method
//var circumference_earth = 40030000000; //in millimeter
var circumference_earth = 2 * Math.PI * (6371000000 + aRefPointTmp[circuit_id]["cor_r_Lat"]);
var circumference_earth_Lat = 2 * Math.PI * radius2EarthAxis; //in millimeter


//console.log("Calc Coordinates. circumference_earth/circumference_earth_Lat: " + circumference_earth + " / " + circumference_earth_Lat );

var angleX = x_new / circumference_earth_Lat * 360;
var angleY = y_new / circumference_earth * 360;


//console.log("CuircitName: " + aRefPointTmp[circuit_id]["Name"]);
//console.log("radius2EarthAxis: " + radius2EarthAxis);
//console.log("angleX: " + angleX + " angleY: " + angleY );

// calculate final value
var car_coordinateLong = aRefPointTmp[circuit_id]["refLong"] + angleX;
var car_coordinateLat = aRefPointTmp[circuit_id]["refLat"] + angleY;

//console.log ("GPS RefLong: " + aRefPointTmp[circuit_id]["refLong"] + " RefLat: " + aRefPointTmp[circuit_id]["refLat"] );
//console.log ("GPS Long: " + car_coordinateLong + " Lat: " + car_coordinateLat + "++++++++++++End++++++");

// return a hash of gps coordinates
return {"Lat" : car_coordinateLat , "Long" : car_coordinateLong};
}

function degreeToRadians($degree)
{
return $degree * Math.PI / 180;
}

function radiansToDegrees($radian)
{
return $radian * 180/ Math.PI;
}




All links together

Test calculation function (jsfiddle.net/3jr4ghgf/40/)
Trackmap example for Catalunya (http://pcars.web2mm.com/storage/tools/trackmaps/Catalunya.pdf)
All trackmaps with marked reference point (http://pcars.web2mm.com/storage/tools/trackmaps/maps.zip) - the two red lines are the X and Z axis, the testpoint coordinates are all in millimeter, at the orange points I was not quite sure if they are on the correct position


What you can do with it

Here is a video of our WIP project:


https://www.youtube.com/watch?v=mIhFekqmO30

M. -VIPER- Morgan
17-09-2015, 05:16
Updated first post with all links at the end and added a link to all trackmaps.
I will further update the first post in the future with the state of our WIP project.

M. -VIPER- Morgan
24-09-2015, 05:03
Video added in first post.

cogent
05-10-2015, 19:06
Great work.

Schnizz58
05-10-2015, 19:33
That's really cool.

ex_
15-10-2015, 20:57
Hello, I work with mapping software in my profession, and what you describe about coorinate errors is something we encounter based on varying places around the globe. You'll need to choose a Geographic Coordinate System and associated Datum in order to correctly map points within one continent, versus another, for instance. Essentially, to summarize - the Earth is not a perfect spheriod, and has a different radius, depending on where you stand.

Because pCARS and most games have tracks located on different continents, this sort of idea is bound to encounter this issue in a noticeable way.

I may be able to provide some insight into this component if you so desire...

Here is an article on the topic:
http://resources.esri.com/help/9.3/arcgisengine/dotnet/89b720a5-7339-44b0-8b58-0f5bf2843393.htm

M. -VIPER- Morgan
03-02-2016, 13:59
Hello, I work with mapping software in my profession, and what you describe about coorinate errors is something we encounter based on varying places around the globe. You'll need to choose a Geographic Coordinate System and associated Datum in order to correctly map points within one continent, versus another, for instance. Essentially, to summarize - the Earth is not a perfect spheriod, and has a different radius, depending on where you stand.

Because pCARS and most games have tracks located on different continents, this sort of idea is bound to encounter this issue in a noticeable way.

I may be able to provide some insight into this component if you so desire...

Here is an article on the topic:
http://resources.esri.com/help/9.3/arcgisengine/dotnet/89b720a5-7339-44b0-8b58-0f5bf2843393.htm

The problem here is, we need a simple calculation, because the calculation runs multiple times per second in javascript in a browser. And the calculation is only one part which runs in this time.
There is the TCP socket, the satellite maps, etc...
And we already have a high CPU load of the browser process. Everything we add on complexity of the calculation raises the CPU load.
Further I think I will have problems to understand the complexity of correct calculated coordinates and next thing is, you have to implement it in javascript. Software development is not my daily business, more a hobby.

In result I don't want to change the calculation, but thanks for your offer.

I think for the small distances we have for race tracks the calculation errors are minimal, some meters calculation error is ok for me. There is also a chance that the track is not perfectly designed.

M. -VIPER- Morgan
03-02-2016, 14:11
Reference Points updated in first post.

The historic Rouen track is currently mapped as fictional track, but you can still identify it on the satellite map:
https://www.google.de/maps/@49.3313226,1.0042466,3449m/data=!3m1!1e3

I think I will add a real reference point for it.

M. -VIPER- Morgan
05-02-2016, 06:56
Rouen Reference Point updated in OP. Looks good so far with my test points:

226790