Forged Alliance Forever Forged Alliance Forever Forums 2015-08-01T05:26:55+02:00 /feed.php?f=53&t=10413 2015-08-01T05:26:55+02:00 2015-08-01T05:26:55+02:00 /viewtopic.php?t=10413&p=106320#p106320 <![CDATA[Re: Object Coordinate Transformation Script]]> Statistics: Posted by nine2 — 01 Aug 2015, 05:26


]]>
2015-08-01T03:50:50+02:00 2015-08-01T03:50:50+02:00 /viewtopic.php?t=10413&p=106318#p106318 <![CDATA[Re: Object Coordinate Transformation Script]]>
Okay, it can do this now:

sym3.jpg



Will now try to incorporate docopt... have not quite figured it out yet...


Once I am done with the first pass I might actually redo the whole thing in a more sophisticated manner. For that I will need to read data from the files and build objects from it, that I can modify, which have printing methods that produce the correct lua string representations again. This way multiple transformation operations could be applied to the same object.

(probably learning some lua would be less of a hassle, but oh well^^)

Statistics: Posted by Lionhardt — 01 Aug 2015, 03:50


]]>
2015-08-01T02:22:18+02:00 2015-08-01T02:22:18+02:00 /viewtopic.php?t=10413&p=106313#p106313 <![CDATA[Re: Object Coordinate Transformation Script]]> Statistics: Posted by ZenTractor — 01 Aug 2015, 02:22


]]>
2015-07-31T23:10:31+02:00 2015-07-31T23:10:31+02:00 /viewtopic.php?t=10413&p=106296#p106296 <![CDATA[Re: Object Coordinate Transformation Script]]>
Anybody any idea what the second entry in the orientations data structure are?

Code:
['UNIT_1'] = {

                                type = 'ura0303',

                                orders = '',

                                platoon = '',

                                Position = { 128.000000, 64.000000, 144.000000 },

                                Orientation = { 0.000000, 0.000000, 0.000000 },

                            },

                            ['UNIT_2'] = {

                                type = 'ura0303',

                                orders = '',

                                platoon = '',

                                Position = { 128.000000, 64.000000, 147.000000 },

                                Orientation = { 0.000000, 1.553343, 0.000000 }, -- corresponds to approx. 90 degree rotation

                            },

                            ['UNIT_3'] = {

                                type = 'ura0303',

                                orders = '',

                                platoon = '',

                                Position = { 128.000000, 64.000000, 150.000000 },

                                Orientation = { 0.000000, 3.115413, 0.000000 }, -- corresponds to approx. 180 degree rotation

                            },

                            ['UNIT_4'] = {

                                type = 'ura0303',

                                orders = '',

                                platoon = '',

                                Position = { 128.000000, 64.000000, 153.000000 },

                                Orientation = { 0.000000, 4.738566, 0.000000 }, -- corresponds to approx. 270 degree rotation

                            },

Statistics: Posted by Lionhardt — 31 Jul 2015, 23:10


]]>
2015-07-29T20:24:52+02:00 2015-07-29T20:24:52+02:00 /viewtopic.php?t=10413&p=106117#p106117 <![CDATA[Re: Object Coordinate Transformation Script]]> Statistics: Posted by Lionhardt — 29 Jul 2015, 20:24


]]>
2015-07-29T16:26:29+02:00 2015-07-29T16:26:29+02:00 /viewtopic.php?t=10413&p=106067#p106067 <![CDATA[Re: Object Coordinate Transformation Script]]>
Lionhardt wrote:
Because the editor lacks any such tool I made a script that does the job for me. Its quick and dirty. But it "just works".


Nice tool lionhardt, thanks for putting time into making that :)

I'd recommend you to use http://docopt.org/ for documenting scripts like this in the future. Otherwise looks nice and useful :)

Statistics: Posted by Sheeo — 29 Jul 2015, 16:26


]]>
2015-07-29T16:09:12+02:00 2015-07-29T16:09:12+02:00 /viewtopic.php?t=10413&p=106064#p106064 <![CDATA[Re: Object Coordinate Transformation Script]]>
As I said, I am writing this in python, because I don't know lua. And the files I manipulate are apparently lua files. Because of that I do all operations as string manipulation, which is incredibly hacky. And the more complex the stuff the worse it gets with this hacky approach. So, as of now I cannot really rotate an object and then pass it to the translation function.. because I am merely manipulating strings, as I don't parse the files with lua.

Statistics: Posted by Lionhardt — 29 Jul 2015, 16:09


]]>
2015-07-29T13:01:35+02:00 2015-07-29T13:01:35+02:00 /viewtopic.php?t=10413&p=106040#p106040 <![CDATA[Re: Object Coordinate Transformation Script]]>
This website has some details: http://www.euclideanspace.com/maths/geo ... oundPoint/
It's in 3d, and rather maths-y, but if you can grok it it should give you a usable method.

Statistics: Posted by ZenTractor — 29 Jul 2015, 13:01


]]>
2015-07-29T06:09:31+02:00 2015-07-29T06:09:31+02:00 /viewtopic.php?t=10413&p=106019#p106019 <![CDATA[Re: Object Coordinate Transformation Script]]> Statistics: Posted by nine2 — 29 Jul 2015, 06:09


]]>
2015-07-29T16:47:55+02:00 2015-07-29T05:58:17+02:00 /viewtopic.php?t=10413&p=106016#p106016 <![CDATA[Re: Object Coordinate Transformation Script]]>
I hope I didn't break any previous stuff. Was too lazy to test.



And ...omgThisCodeIsSoMessyPleaseDontLookAtItItsEmbarrassing

Statistics: Posted by Lionhardt — 29 Jul 2015, 05:58


]]>
2015-08-01T03:56:30+02:00 2015-07-26T01:42:27+02:00 /viewtopic.php?t=10413&p=105616#p105616 <![CDATA[Object Coordinate Transformation Script]]>

Okay, so you need python to run this and it does the following:


translate.jpg

project.jpg

resize.jpg


Transforming object coordinates is required when porting and resizing maps.

Here's the code:


Code:
# Quick and dirty hacky script for transforming the coordinates of decals,
# props, markers and units.
# Absolute values are used, because the input format is fixed anyway.
# This script can be destructive, if handled incorrectly. Never operate
# on original map files!
# Also note, that importing decals and props will ADD props at the new
# positions. Old props and decals will persit until deleted manually.
# To transform marker unit positions, pass in the <map>_save.lua
# To transform prop positions, pass in the props file (export from editor)
# To transform decals positions, pass in the decals file (export from editor)
# version: 1, author: Lionhardt, date: 25.07.2015

from sys import argv
import sys
from math import sin
from math import cos
from math import radians

########################################################################
# translation sub-functions and objects
########################################################################
# function object for translation
class Translation:
   def __init__(self, x_index, y_index, x_offset, y_offset):
      self.x_index = x_index
      self.y_index = y_index
      self.x_offset = x_offset
      self.y_offset = y_offset
########################################################################
def _trans(coord, offset):
   return str(float(coord)+offset)
########################################################################
def _translate(string, offset):
   if string[-1] == ",":
      return _trans(_isolate(string), offset)+","
   else:
      return _trans(string, offset)
########################################################################
# projection sub-functions and objects
########################################################################
# function object for projection
class Projection:
   def __init__(self, x_index, y_index, scale_factor):
      self.x_index = x_index
      self.y_index = y_index
      self.factor = scale_factor
########################################################################
def _proj(coord, factor):
   return str(float(coord)*factor)
########################################################################
def _project(string, factor):
   if string[-1] == ",":
      return _proj(_isolate(string), factor)+","
   else:
      return _proj(string, factor)
########################################################################
# resizing sub-functions and objects
########################################################################
# function object for resizing
class Resizing:
   def __init__(self, x_index, y_index, center_coordinate, scale_factor):
      self.x_index = x_index
      self.y_index = y_index
      self.factor = scale_factor
      self.center = center_coordinate
########################################################################
def _res(coord, c_coord, factor):
   # get direction vector (point to translate) - (center)
   # multiply direction vector by scale factor
   # add scaled direction vector to center to get traslated point
   return str(c_coord+((float(coord) - c_coord)*factor))
########################################################################
def _resize(string, center, factor):
   if string[-1] == ",":
      return _res(_isolate(string), center[0], factor)+","
   else:
      return _res(string, center[1], factor)
########################################################################
# symmetrization sub-functions and objects
########################################################################
# function object for symmetrization
class uSymmetrization:
   def __init__(self, x_index, y_index, center_coordinate, rot_angle, uID):
      self.x_index = x_index
      self.y_index = y_index
      self.angle = rot_angle
      self.center = center_coordinate
      self.ID = uID

   def new_ID(self):
      self.ID[0]+=1
      return self.ID[0]
########################################################################
# function object for symmetrization
class mSymmetrization:
   def __init__(self, x_index, y_index, center_coordinate, rot_angle, mIDs):
      self.x_index = x_index
      self.y_index = y_index
      self.angle = rot_angle
      self.center = center_coordinate
      self.IDs = mIDs

   def new_ID(self, m):
      self.IDs[m]+=1
      return self.IDs[m]
########################################################################
def _duplicate(lines, begin, end, FO, marker, option):
   ret = str()
   times = 360/int(FO.angle)
   for t in range(1,times):
      ret += make_head(lines[begin], FO, marker, option)
      for l in lines[begin+1:end-2]:
         ret+=l
      if option == "marker":
         ret+=lines[end-2]
         posLine = lines[end-1].split(" ")
      elif option == "unit":
         posLine = lines[end-2].split(" ")

      new_point_coords = _symmetrize(posLine[FO.x_index],
                                                    posLine[FO.y_index], FO, t)
      posLine[FO.x_index] = str(new_point_coords[0])+","
      posLine[FO.y_index] = str(new_point_coords[1])

      ret+=(" ".join(posLine))
      if option == "unit":
         ret+=_rotate((lines[end-1]), FO, t)
      ret+=(lines[end])
   return ret
########################################################################
def _rotate(line, FO, factor):
   line = line.split(" ")
   orientation = float(_isolate(line[-3]))
   line[-3] = str(radians(-1*factor*FO.angle)+orientation)+","
   return " ".join(line)
########################################################################
def make_head(headline, FO, marker, option):

   if option == "unit":

      nID = FO.new_ID()
      if nID < 10:
         nID = "0"+str(nID)
      else:
         nID = str(nID)
      head = headline.split("_") #[ "['UNIT", "3']" ]
      head = head[0]+ "_"+str(nID)+"'] = {\r\n"
      return head

   elif option == "marker":
      nID = FO.new_ID(marker)
      if nID < 10:
         nID = "0"+str(nID)
      else:
         nID = str(nID)
      head = headline.split(" ")
      head[-3] = nID+"']"
      return " ".join(head)
########################################################################
def exists_marker(line, markers):
   for m, c in markers.iteritems():
      if (m in line) and ("{\r\n" in line):
         return m
   return False
########################################################################
def exists_unit(line):
   if ("UNIT" in line) and ("{\r\n" in line):
      return True
   return False
########################################################################
def find_end_of_block(i, lines):
   j = i
   for line in lines[i:]:
      if "},\r\n" in line and line[line.index("},\r\n")-2] == " ":
         return j
      j+=1
########################################################################
def _sym(x, y, FO, f):
   a = FO.angle
   x = x-FO.center[0]
   y = y-FO.center[1]

   sin_a = sin(f*radians(a))
   cos_a = cos(f*radians(a))

   x1 = cos_a*x + (-1*sin_a*y)
   y1 = sin_a*x + cos_a*y

   x = x1+FO.center[0]
   y = y1+FO.center[1]
   return (x, y)
########################################################################
def _symmetrize(string_x, string_y, FO, factor):
   x = float(_isolate(string_x))
   y = float(string_y)
   return _sym(x, y, FO, factor)
########################################################################
# general sub-functions
########################################################################
def _isolate(string):
   return string.split(",")[0]
########################################################################
def _alter(line, FO, mode):
   if mode == "-t":
      line[FO.x_index] = _translate(line[FO.x_index], FO.x_offset)
      line[FO.y_index] = _translate(line[FO.y_index], FO.y_offset)
   elif mode == "-p":
      line[FO.x_index] = _project(line[FO.x_index], FO.factor)
      line[FO.y_index] = _project(line[FO.y_index], FO.factor)
   elif mode == "-r":
      line[FO.x_index] = _resize(line[FO.x_index], FO.center, FO.factor)
      line[FO.y_index] = _resize(line[FO.y_index], FO.center, FO.factor)
   return line
########################################################################
def find_unit(line, max_id):
   if "UNIT" in line:
      line = line.split("_")
      # get unit ID
      u_id = int(line[1].split("'")[0])
      # update max unit id if necessary
      if u_id > max_id[0]:
         return [u_id]
   return max_id
########################################################################
def find_marker(line, max_ids):
   # get the marker name that might be n line
   markers = [m for m in max_ids if m in line]
   line = line.split(" ")
   if (len(markers) > 0) and ("{\r\n" in line):
      m = markers[0]
      # isolate the marker ID
      m_id = int(line[-3].split("'")[0])
      # compare if larger than largest ID for marker type
      if m_id > max_ids[m]:
         max_ids[m] = m_id
   return max_ids
########################################################################
# driver functions
########################################################################
# translates coordinates
def translate(option, x_offset, y_offset, iFile, oFile):

   with open(iFile, "r") as I:
      with open(oFile, "w") as O:

         # replace decal or prop coords
         if option in ["-p", "-d"]:
            for line in I:
               line = line.split(" ")
               if line[0] == "position":
                  line = _alter(line, Translation(3, 5, x_offset, y_offset),
                                argv[1])
               line = " ".join(line)
               O.write(line)

         # replace unit and marker coords
         if option == "-mu":
            for line in I:
               line = line.split(" ")
               if "['position']" in line:
                  line = _alter(line, Translation(23, 25, x_offset, y_offset),
                                argv[1])
               if "Position" in line:
                  line = _alter(line, Translation(35, 37, x_offset, y_offset),
                                argv[1])
               line = " ".join(line)
               O.write(line)
########################################################################
# projects coordinates
def project(option, factor, iFile, oFile):

   with open(iFile, "r") as I:
      with open(oFile, "w") as O:

         # replace decal or prop coords
         if option in ["-p", "-d"]:
            for line in I:
               line = line.split(" ")
               if line[0] == "position":
                  line = _alter(line, Projection(3, 5, factor), argv[1])
               line = " ".join(line)
               O.write(line)

         # replace unit and marker coords
         if option == "-mu":
            for line in I:
               line = line.split(" ")
               if "['position']" in line:
                  line = _alter(line, Projection(23, 25, factor), argv[1])
               if "Position" in line:
                  line = _alter(line, Projection(35, 37, factor), argv[1])
               line = " ".join(line)
               O.write(line)
########################################################################
# scales coordinates
def resize(option, center_x, center_y, factor, iFile, oFile):

   center = tuple((center_x, center_y))

   with open(iFile, "r") as I:
      with open(oFile, "w") as O:

         # replace decal or prop coords
         if option in ["-p", "-d"]:
            for line in I:
               line = line.split(" ")
               if line[0] == "position":
                  line = _alter(line, Resizing(3, 5, center, factor), argv[1])
               line = " ".join(line)
               O.write(line)

         # replace unit and marker coords
         if option == "-mu":
            for line in I:
               line = line.split(" ")
               if "['position']" in line:
                  line = _alter(line, Resizing(23, 25, center, factor), argv[1])
               if "Position" in line:
                  line = _alter(line, Resizing(35, 37, center, factor), argv[1])
               line = " ".join(line)
               O.write(line)
########################################################################
def symmetrize(option, center_x, center_y, angle, iFile, oFile):

   center = tuple((center_x, center_y))

   # first get the highest Marker and Unit IDs
   m_max = {"Blank":-1, "Camera":-1, "Combat":-1, "Defensive":-1,
            "Expansion":-1, "Hydrocarbon":-1, "Island":-1, "Mass":-1,
            "Naval":-1, "Experimental":-1, "Rally":-1, "Definition":-1,
            "Generator":-1}
   u_max = [0]

   with open(iFile, "r") as I:
      for line in I:
         m_max = find_marker(line, m_max)
         u_max = find_unit(line, u_max)

   with open(iFile, "r") as I:
      with open(oFile, "w") as O:

         lines = I.readlines()
         i = 0
         j = None

         for line in lines:
            O.write(line)
            marker = exists_marker(line, m_max)
            unit = exists_unit(line)

            if marker:
               j = find_end_of_block(i, lines)
               ms = mSymmetrization(23, 25, center, angle, m_max)
               new_entries = _duplicate(lines, i, j, ms, marker, "marker")
               m_max = ms.IDs

            elif unit:
               j = find_end_of_block(i, lines)
               us = uSymmetrization(35, 37, center, angle, u_max)
               new_entries = _duplicate(lines, i, j, us, marker, "unit")

            if i == j:
               j = None
               O.write(new_entries)
            i+=1
########################################################################
#
########################################################################
if __name__ == "__main__":

   if len(argv) == 1:
      print ("-h for usage")
   elif len(argv) == 2 and argv[1] == "-h":
      print (
      "\nLionhardt's coordinate transformation script\n\n"
    "-t -- translate\t(wirte t for more info)\n"
    "-p -- project\t(write p for more info)\n"
    "-r -- resize\t(write r for more info)\n"
    "-s -- rotate\t(write ro for more info)\n"
    )
      o = raw_input()
      while o not in ["t", "p", "r", "s"]:
         print "invalid option"
         o = raw_input()
      if o == "t":
         print (
         "\nTRANSLATE\n---------\n"
          "Moves objects without altering their relative distances to"
          " each other.\n"
          "usage: python transform -r [-d, -p, -mu] <x-offset> <y-offset>"
          " <input file> <output file>\n"
          "choose -d for decals, -p for props and -mu for markers and"
          " units"
          )

      elif o == "p":
         print (
         "\nPROJECT\n-------\n"
         "Projects objects onto a different map size, preserving"
         " relative distances.\n"
         "usage: python transform -p [-d, -p, -mu] <scale factor>"
         " <input file> <output file>\n"
         "choose -d for decals, -p for props and -mu for markers and"
         " units"
         )

      elif o == "r":
       print (
       "\nRESIZE\n------\n"
       "Alters distances between objects through a center projection\n"
       "usage: python transform -r [-d, -p, -mu] <center x-coordinate>"
       " <center y-coordinate> <scale factor> <input file> <output file>\n"
       "choose -d for decals, -p for props and -mu for markers and"
       " units\n"
       )

      elif o == "s":
         print (
         "\SYMMETRIZE\n----------\n"
         "Rotates objects around center point and copies them <360/angle>"
         " times, rounding down.\n"
         "usage: python transform -ro [-mu] <center x-coordinate>"
         " <center y-coordinate> <angle> <input file> <output file>\n"
         "choose -d for decals, -p for props and -mu for markers and"
         " units\n"
         )

   else:

      if argv[-2] == argv[-1]:
            sys.stderr.write(
            "Error: input file must be different from output file\n"
            )

      elif (argv[1] == "-t") and (len(argv) == 7):
         translate(argv[2], float(argv[3]), float(argv[4]), argv[5], argv[6])

      elif (argv[1] == "-p") and (len(argv) == 6):
         project(argv[2], float(argv[3]), argv[4], argv[5])

      elif (argv[1] == "-r") and (len(argv) == 8):
         resize(argv[2], float(argv[3]), float(argv[4]), float(argv[5]),
                argv[6], argv[7])

      elif (argv[1] == "-s") and (len(argv) == 8):
         symmetrize(argv[2], float(argv[3]), float(argv[4]), float(argv[5]),
                argv[6], argv[7])

# example call:
# py transform.py -t -mu -200 -200 MyMap_save.lua MyMap_save.lua.trans

Statistics: Posted by Lionhardt — 26 Jul 2015, 01:42


]]>