diff --git a/.dockerignore b/.dockerignore index 135b1bc..39abb5c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,3 @@ *.md auxiliary/ -js-inactive/ Dockerfile diff --git a/Dockerfile b/Dockerfile index c396ff1..9c68fe2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ FROM alpine:latest as build WORKDIR /build RUN apk add unzip wget && \ - wget https://arma.openlink.bot/assets/map.zip && \ + wget https://github.com/Dreamfarer/ARMA-3-ARTILLERY-CALCULATOR-ARES/releases/download/tiles-altis-v1.0.0/tiles-altis.zip && \ unzip map.zip && \ rm map.zip diff --git a/README.md b/README.md index 18976f4..ac08dea 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ I have created an [API](https://api.openlink.bot/ares.php?x=10000&y=10000) to ge Let's go for an example: If you would like to know the altitude at 10'000, 10'000 on Altis, make a call to the API like this: https://api.openlink.bot/ares.php?x=10000&y=10000 #### Download Map Data -Unfortunately, the map tiles exceed the GitHub upload limit. You can get them [HERE](https://arma.openlink.bot/assets/map.zip). Unzip `map.zip` and drag-and-drop the map folder into the root project folder +Unfortunately, the map tiles exceed the GitHub upload limit. You can get them [HERE](https://github.com/Dreamfarer/ARMA-3-ARTILLERY-CALCULATOR-ARES/releases/download/tiles-altis-v1.0.0/tiles-altis.zip). Unzip `map.zip` and drag-and-drop the map folder into the root project folder ## The Magic Behind It The following documentation is split in two sections. The first section deals with the flight path of artillery shells shot by self-propelled artillery like the 2S9 Sochor and M4 Scorcher. Fortunately, in Arma 3, artillery shells are the only projectiles [not](https://community.bistudio.com/wiki/CfgAmmo_Config_Reference#airFriction) affected by external force such as wind or air friction.\ diff --git a/auxiliary/Initiate.py b/auxiliary/Initiate.py deleted file mode 100644 index 45c2c50..0000000 --- a/auxiliary/Initiate.py +++ /dev/null @@ -1,15 +0,0 @@ -import mysql.connector - -#MYSQL -mydb = mysql.connector.connect( - host="", - user="", - password=", - database="" -) - -mycursor = mydb.cursor() - -mycursor.execute("CREATE TABLE heightmap (id INT AUTO_INCREMENT PRIMARY KEY, altitude INT)") - -s = input('Job done, yee') diff --git a/auxiliary/Iterate.py b/auxiliary/Iterate.py deleted file mode 100644 index 2fe3538..0000000 --- a/auxiliary/Iterate.py +++ /dev/null @@ -1,37 +0,0 @@ -file = open('HeightMap.B3D', 'r') - -array = [] - -arrayCounter = 0 -startCollecting = 0 - -temp = "" - -#37761024 -while arrayCounter < 37761025: - - char = file.read(1) - - if char == ')': - startCollecting = 0 - - - if startCollecting == 1: - if char == ',': - - array.append(float(temp)) - temp = "" - arrayCounter += 1 - - else: - temp += char - - if char == '(': - startCollecting = 1 - - -file.close() - -print(array[19813060]) - -s = input('--> ') diff --git a/auxiliary/Rename imagick files to suit Leaflet tiles.rb b/auxiliary/Rename imagick files to suit Leaflet tiles.rb deleted file mode 100644 index 5e36dab..0000000 --- a/auxiliary/Rename imagick files to suit Leaflet tiles.rb +++ /dev/null @@ -1,31 +0,0 @@ -tile_width = 256 -tile_height = 256 -image_width = 18432 -image_height = 18432 -n = 0 -# To get this number, look at the number of tiles -# generated, find the last tile number and add 1 -# e.g. tiles_99.png => total_tiles = 100 -total_tiles = 5184 - -tiles_per_column = image_width/tile_width - -#71 -row = 0 -column = 0 -(n...total_tiles).each do |i| - filename = "tile#{i}.jpg" # current filename - target = "map_#{column}_#{row}.jpg" # new filename - - puts "copy #{filename} to #{target}" - - # rename file - File.rename(filename, target) - - # work out next step - column = column + 1 - if column >= tiles_per_column - column = 0 - row = row + 1 - end -end \ No newline at end of file diff --git a/auxiliary/Upload.py b/auxiliary/Upload.py deleted file mode 100644 index 32a780c..0000000 --- a/auxiliary/Upload.py +++ /dev/null @@ -1,88 +0,0 @@ -import mysql.connector - -file = open('HeightMap.B3D', 'r') - -array = [] - -arrayCounter = 0 -startCollecting = 0 - -temp = "" - -#37761024 -magicNumber = 37761024 - -while arrayCounter <= magicNumber: - - char = file.read(1) - - if char == ')': - startCollecting = 0 - - - if startCollecting == 1: - if char == ',': - - array.append(float(temp)) - temp = "" - arrayCounter += 1 - - else: - temp += char - - if char == '(': - startCollecting = 1 - - -file.close() - -print("Writing Arrays into memory is done!") - -#MYSQL -mydb = mysql.connector.connect( - host="", - user="", - password="", - database="" -) - -mycursor = mydb.cursor() -i = 0 -ev = int(1) - -cancel= 0 - -while cancel == 0: - - sql = "INSERT INTO heightmap (altitude) VALUES " - - #Split into 100k junks - while i <= 100000 * ev: - - inserter = int(array[i] * 10000) - - if i == magicNumber: - sql = sql + "(" + str(inserter) + ")" - cancel = 1 - break - - if i < 100000*ev: - sql = sql + "(" + str(inserter) + "), " - - if i == 100000*ev: - sql = sql + "(" + str(inserter) + ")" - - i += 1 - - - mycursor.execute(sql) - mydb.commit() - - message = "Process " + str(ev) - print(message) - - ev += 1 - -print(i) -s = input('Job done, yee') - diff --git a/auxiliary/get impact distance (apply to player).sqf b/auxiliary/maaws-get-impact-distance.sqf similarity index 100% rename from auxiliary/get impact distance (apply to player).sqf rename to auxiliary/maaws-get-impact-distance.sqf diff --git a/auxiliary/Projectile Motion with Air Resistance.xlsx b/auxiliary/projectile-motion-with-air-resistance.xlsx similarity index 100% rename from auxiliary/Projectile Motion with Air Resistance.xlsx rename to auxiliary/projectile-motion-with-air-resistance.xlsx diff --git a/js-inactive/tiltOffset.js b/js-inactive/tiltOffset.js deleted file mode 100644 index 89bcdf6..0000000 --- a/js-inactive/tiltOffset.js +++ /dev/null @@ -1,321 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Cross product -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -function cross(A, B) { - - return [A[1] * B[2] - A[2] * B[1], A[2] * B[0] - A[0] * B[2], A[0] * B[1] - A[1] * B[0]]; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Dot product -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -function dot(A, B) { - return (A[0] * B[0] + A[2] * B[2] + A[1] * B[1]); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Multiply vector with scalar -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -function multiply_vector_Scalar(vector, scalar) { - return [vector[0] * scalar, vector[1] * scalar, vector[2] * scalar]; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Add vector and vector -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -function add_vector_vector(vector1, vector2) { - return [vector1[0] + vector2[0], vector1[1] + vector2[1], vector1[2] + vector2[2]]; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Turn a given vector on the basis of an angle and the desired axis -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -function rotate(inputvector, angle, axis) { - - var resultingVector1 = multiply_vector_Scalar(inputvector, (Math.cos(angle))); - var resultingVector2 = multiply_vector_Scalar(cross(axis, inputvector), Math.sin(angle)); - var resultingVector3 = multiply_vector_Scalar(multiply_vector_Scalar(axis, dot(axis, inputvector)), 1 - Math.cos(angle)); - var result = add_vector_vector(add_vector_vector(resultingVector1, resultingVector2), resultingVector3); - - return result; - -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Return the normalized version of a vector. [Vector with length of 1] -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -function magnitude(inputvector) { - - return Math.sqrt(Math.pow(inputvector[0], 2) + Math.pow(inputvector[1], 2) + Math.pow(inputvector[2], 2)); - -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Return the normalized version of a vector. [Vector with length of 1] -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -function normalize(inputvector) { - - var length = Math.sqrt(Math.pow(inputvector[0], 2) + Math.pow(inputvector[1], 2) + Math.pow(inputvector[2], 2)); - return [inputvector[0] / length, inputvector[1] / length, inputvector[2] / length]; - -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Display telemetry stuff of approximation function -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -function display(message, data, type) { - - if (type == "vector") { - console.log(message + ": v=(" + data[0].toFixed(2) + "," + data[2].toFixed(2) + "," + data[1].toFixed(2) + ")"); - } - - if (type == "scalar") { - console.log(message + ": " + data.toFixed(2)); - } - -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Calculate remaining direction -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -function getDir(vector1, vector2, axis) { - - if (axis == "top") { - - var vec1 = normalize([vector1[0], 0, vector1[2]]); - var vec2 = normalize([vector2[0], 0, vector2[2]]); - - var overflowChecker = (dot(vec1, vec2) / (magnitude(vec1) * magnitude(vec2))); - - if (overflowChecker > 1) { - overflowChecker = 1; - } - - return Math.acos(overflowChecker) / 2; - - } else { - - //1 Modified, 2 Target - - //var vec1 = normalize([vector1[0], vector2[1], vector1[2]]); - //var vec2 = normalize(vector2); - - var vec1 = [vector2[0], vector1[1], vector2[2]]; - var vec2 = vector2; - - return Math.acos(dot(vec1, vec2) / (magnitude(vec1) * magnitude(vec2))) / 2; - } -} - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Is used to receive height data -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//From left to right [x,y]: Center-Top -> Left-Center -> Center-Center -> Right-Center -> Center-Bottom -//var heightData = [NaN, NaN, NaN, NaN]; -var heightData = [NaN, NaN, NaN, NaN]; - -function gatherHeightDataCallback(message, number) { - heightData[number] = message; - - for (let i = 0; i < 4; i++) { - if (isNaN(heightData[i])) { - return; - } - } - - var vector1 = [0, heightData[0], 5]; - var vector2 = [-5, heightData[1], 0]; - var vector3 = [5, heightData[2], 0]; - var vector4 = [0, heightData[3], -5]; - - var normalVectorPlane1 = cross(vector2, vector1); //Normalvector for upper-left corner - var normalVectorPlane2 = multiply_vector_Scalar(cross(vector3, vector1), -1); //Normalvector for upper-right corner - var normalVectorPlane3 = multiply_vector_Scalar(cross(vector2, vector4), -1); //Normalvector for bottom-left corner - var normalVectorPlane4 = cross(vector3, vector4); //Normalvector for bottom-right corner - - var normalVectorTank = normalize(add_vector_vector(add_vector_vector(add_vector_vector(normalVectorPlane1, normalVectorPlane2), normalVectorPlane3), normalVectorPlane4)); - - elevationOffset(normalVectorTank); - - return; - -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Gather height data first, then call elevationoffset() when all 5 height points have arrived -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -var angle = NaN; -var elevation = NaN; -var objectCounter = NaN; - -function gatherHeightData(inputangle, inputelevation, position, counter) { - - angle = inputangle; - elevation = inputelevation; - objectCounter = counter; - - //We reuse the scheme requestHeight(game, mapp, message, mode, markerCounter, start) - //game: Coordinates / mapp: - / message: "" / mode: "offset" / markerCounter: Index of Array / start: - - var origin = [[position[0], position[1] + 5], [position[0] - 5, position[1]], [position[0] + 5, position[1]], [position[0], position[1] - 5]]; - for (let i = 0; i < 4; i++) { - requestHeight(origin[i], [0, 0], "", "offset", i, 0); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Calculate elevation offset based on sourrounding incline -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -function elevationOffset(normalVectorTank) { - - //Define some variables - var inputAngle = angle; - angle = angle * (Math.PI / 180); - - //Stich together target vector - elevation = elevation * (Math.PI / 180); - var targetVector = [Math.cos(elevation), Math.sin(elevation), 0]; - targetVector = rotate(targetVector, -1 * angle, [0, 1, 0]); - display("Target Vector", targetVector, "vector"); - - //Calculate normalvectors of all 4 planes - var origin = [0, 0, 0]; - var normalVectorPlane1 = cross([-5, 3 - origin[1], 0], [0, 2 - origin[1], 5]); //Normalvector for upper-left corner - var normalVectorPlane2 = multiply_vector_Scalar(cross([5, 1 - origin[1], 0], [0, 2 - origin[1], 5]), -1); //Normalvector for upper-right corner - var normalVectorPlane3 = multiply_vector_Scalar(cross([-5, 3 - origin[1], 0], [0, 2 - origin[1], -5]), -1); //Normalvector for bottom-left corner - var normalVectorPlane4 = cross([5, 1 - origin[1], 0], [0, 2 - origin[1], -5]); //Normalvector for bottom-left corner - display("Normal Vector", normalVectorTank, "vector"); - - //Decide if to add or to remove from angle - var condition = "Plus"; - - //Start Vector - if (normalVectorTank[0] == 0) { - var startVector = [1, 0, 0]; - } else { - var startVector = normalize([((-1 * normalVectorTank[1]) / normalVectorTank[0]), 1, 0]); - } - - if (startVector[0] < 0) { - startVector = rotate(startVector, -1 * Math.PI, normalVectorTank); - } - - display("Start Vector", startVector, "vector"); - - //Rotate turret - var before; - var modifiedVector = rotate(startVector, -1 * angle, normalVectorTank); - var after = getDir(startVector, modifiedVector, "top") * 2; - - if (angle > Math.PI) { - after = Math.PI + Math.PI - after; - } - - correctionTopSum = after; - - //Check if shooting is even possible - if (modifiedVector[1] > targetVector[1]) { - console.log("Angle too flat; Shooting not possible"); - - markerArray[objectCounter][0].setPopupContent(popupContent(NaN, NaN, NaN, "NaN")).openPopup(); - - //Reset these variables to be used again later - angle = NaN; - elevation = NaN; - heightData = [NaN, NaN, NaN, NaN]; - objectCounter = NaN; - - return; - } - - //Elevate the turret - var correctionSide = getDir(modifiedVector, targetVector, "side"); - perpendicular = normalize(cross(modifiedVector, normalVectorTank)); - modifiedVector = rotate(modifiedVector, correctionSide, perpendicular); - - //Check to which side the turret should be turning - var correctionTop = getDir(modifiedVector, targetVector, "top"); - var directionChecker = rotate(modifiedVector, correctionTop, normalVectorTank); - var newCorrectionTop = getDir(directionChecker, targetVector, "top"); - if (newCorrectionTop > correctionTop) { - condition = "Minus"; - } else { - condition = "Plus"; - } - - var correctionSideSum = correctionSide; - - //This counts the - var counter = 0; - while (counter < 15) { - - //Check which difference is bigger; - correctionTop = getDir(modifiedVector, targetVector, "top"); - correctionSide = getDir(modifiedVector, targetVector, "side"); - - //Decide with knowledge from before - if (condition == "Plus") { - correctionTop = correctionTop * -1; - } - - //Always correct the one with a bigger difference - if (Math.abs(correctionTop) > Math.abs(correctionSide)) { - - //Rotate turret - before = getDir(modifiedVector, targetVector, "top"); - modifiedVector = rotate(modifiedVector, correctionTop, normalVectorTank); - after = getDir(modifiedVector, targetVector, "top"); - - //We can add this to the total amount of angle - correctionTopSum += Math.abs(before - after); - - display("Approximation Vector TOP", modifiedVector, "vector"); - - } else { - - //Calculate perpendicular vector (Used as axis when elevating turret) - perpendicular = normalize(cross(modifiedVector, normalVectorTank)); - - //Elevate turret - modifiedVector = rotate(modifiedVector, correctionSide, perpendicular); - - //Add to the total amount of elevation - correctionSideSum += correctionSide; - } - - //Display the modified vector - display("Approximation Vector", modifiedVector, "vector"); - - //You don't have to calculate any further if this criteria is met: - if ((correctionTop * 180 / Math.PI) < 0.01 && (correctionSide * 180 / Math.PI) < 0.01) { - break; - } - - counter += 1; - - } - - display("End Vector", modifiedVector, "vector"); //correct - console.log("End Elevation: " + (correctionSideSum * 180 / Math.PI)); //correct - - console.log("Original Angle: " + transform(inputAngle, false)); - console.log("Strife: " + transform((correctionTopSum * 180 / Math.PI), false)); - - //console.log("Diviation from perfect direction: " + (correctionTop * 180 / Math.PI)); - //console.log("Diviation from perfect elevation: " + (correctionSide * 180 / Math.PI)); - - //Write into the objects - markerArray[objectCounter][2].gunElevation[2] = (correctionSideSum * 180 / Math.PI); - markerArray[objectCounter][2].direction[1] = transform((correctionTopSum * 180 / Math.PI), false); - - markerArray[objectCounter][0].setPopupContent(popupContent(markerArray[objectCounter][2].gunElevation, markerArray[objectCounter][2].direction, markerArray[objectCounter][2].firemode, "target")).openPopup(); - - //Reset these variables to be used again later - angle = NaN; - elevation = NaN; - heightData = [NaN, NaN, NaN, NaN]; - objectCounter = NaN; - - return - -}