Pergunta

I am trying to create a program that converts between multiple coordinate systems in Matlab.

I have different systems and want to transfer between them. There are different topocentric, geocentric & heliocentric systems. I have written the transformation matrices to transfer between these coordinate systems.

To simplify this problem I'll use an example.

If I have 3 coordinate systems:

Cartesian , Cylindrical & Spherical Coordinates

To convert from Cylindrical coordinates to Cartesian coordinates. I can apply:

x = r ∙ cos(ø)
y = r ∙ sin(ø)
z = z

To convert from Spherical coordinates to Cartesian coordinates. I can apply:

x = R ∙ sin(θ) ∙ cos(ø)
y = R ∙ sin(θ) ∙ sin(ø)
z = R ∙ cos(θ)

Assuming we don't convert Spherical Coordinates directly to Cylindrical Coordinates, we convert:

  • Spherical -> Cartesian
  • Cartesian -> Cylindrical

In my real problem, I have 8 different coordinate systems with transformations back and forth between each of them. The systems have only have two paths linking to different coordinate systems.

It looks like this:

A <-> B <-> C <-> D <-> E <-> F <-> G <-> H

I want to create a method for the user to choose a coordinate system, input coordinates and select the destination coordinate systems.

Instead of manually writing functions for: A -> C , A -> D , A -> E ... for 54 different steps

Is there a way I can create a system to connect the paths? Is there a way I can use a graph or nodes and apply functions which connect the nodes (A->C) What is this concept so I can read up more on it?

Foi útil?

Solução

You could implement something complicated with object oriented programming, but to keep things simple I propose to store all different types of coordinates as structs that all have a member type and whatever other members needed for that particular type of coordinate.

You could then define all your conversion functions that do a single step to all have the same function signature function out_coord = A2B(in_coord), e.g.:

function cart = sphere2cart(sphere)
assert(strcmp(sphere.type, 'sphere')) % make sure input is correct type
cart.type = 'cart';
cart.x = sphere.R * sin(sphere.theta) * cos(sphere.omega);
cart.y = sphere.R * sin(sphere.theta) * sin(sphere.omega);
cart.z = sphere.R * cos(sphere.theta);

These functions can be called from one universal convert function like this:

function output_coord = convert(input_coord, target_type)
output_coord = input_coord;
while ~strcmp(output_coord.type, target_type)
    func = get_next_conversion_func(input_coord.type, target_type);
    output_coord = func(output_coord);
end

which does one conversion step at a time, until output_coord has the correct type. The only missing step is then a function that determines which conversion to do next, based on the current type and the target type. In your case with a 'linear' conversion chain, this is not so hard. In more complex cases, where the types are connected in a complex graph, this might require some shortest path algorithm. Unfortunately, this is a bit cumbersome to implement in Matlab, but one hard-coded solution might be something like:

function func = get_next_conversion_func(current_type. target_type);
switch current_type
    case 'A'
        func = @A2B;
    case 'B'
        switch target_type
            case 'A'
                func = @B2A;
            case {'C','D','E'}
                func = @B2C;
        end
    case 'C'
        switch target_type
            case {'A','B'}
                func = @C2B;
            case {'D','E'}
                func = @C2D;
        end
    ...
end

For sure, there are smarter ways to implement this, this is basically a dispatch table that says in which direction to go based on the current type and the target type.

EDIT

Following Jonas' suggestion of doing all conversions via one central type (let's say C), all of this can be simplified to

function output_coord = convert(input_coord, target_type)
output_coord = input_coord;
if strcmp(output_coord.type, target_type)
    return % nothing to convert
end

if ~strcmp(output_coord.type, 'C')
    switch output_coord.type
        case 'A'
            output_coord = A2C(output_coord)
        case 'B'
            output_coord = B2C(output_coord)
        case 'D'
            output_coord = D2C(output_coord)
        case 'E'
            output_coord = E2C(output_coord)
    end
end

assert(strcmp(output_coord.type, 'C'))

if ~strcmp(output_coord.type, target_type)
    switch target_type
        case 'A'
            output_coord = C2A(output_coord)
        case 'B'
            output_coord = C2B(output_coord)
        case 'D'
            output_coord = C2D(output_coord)
        case 'E'
            output_coord = C2E(output_coord)
    end
end

Outras dicas

In your current logic, A <-> B <-> C <-> D <-> E <-> F <-> G <-> H, you will have to write 14 functions for converting (if A->B and B->A count as two).

I suggest that instead, you choose one reference coordinate system, say, A and write the functions A<->B, A<->C, etc.

This solution requires you to write the same number of functions as your solution, but the logic becomes trivial. Furthermore, each conversion takes a maximum of two conversion steps, which will avoid accumulating round-off errors when you perform a chain of conversions.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top