OpenOrienteering/mapper

Enhancement: rotate tool can rotate objects from their respective origins

Opened this issue · 1 comments

It would be great to have rotate functionality where a selection of objects are rotated independently from their respective origins, instead of around one common origin. Similar to the scale functionality added in PR #1211, but with the rotate tool. It could even be activated in the same way, by using the Ctrl key, for consistency.

This functionality would be very useful when replacing a symbol set, for example. Often directional point symbols (e.g. minimum cliff/crossing point etc.) are 90/180˚ out once replaced by the new symbol and all need to be rotated. The only way to fix this currently is to redefine the symbol or to go around and independently rotate each instance of the symbol on the map. This enhancement would provide a simple solution.

Here's a quick and dirty implementation I hacked up in Python that interfaces with omap/xmap files which can be used for now:

import xml.etree.ElementTree as ET
from sys import argv
import math

mapperns = "http://openorienteering.org/apps/mapper/xml/v2"
ET.register_namespace("", mapperns)
ns = {"mapper": mapperns}

file = argv[1]
symbol_code = input("symbol code to rotate: ")
rotation = float(input("amount to rotate (in DEG): ")) * math.pi / 180

omap = ET.parse(argv[1])
root = omap.getroot()

symbol_id = root.find(f".//mapper:symbol[@code='{symbol_code}']", ns).attrib["id"]
symbols = root.findall(f".//mapper:object[@symbol={repr(symbol_id)}]", ns)
for symbol in symbols:
    try:
        old_rotation = float(symbol.attrib["rotation"])
        new_rotation = (old_rotation + rotation) % (2 * math.pi)
        symbol.set("rotation", f"{new_rotation:.5f}")
        print(f"{symbol_code}: {old_rotation} -> {new_rotation:.5f}")
    except KeyError:
        pass

omap.write(file, encoding="UTF-8", xml_declaration=True)

Note that the file needs to be opened and saved again in Mapper as the script does not respect Mapper's xml formatting.