Манипуляции со строками для пути VML

Привет, я пытаюсь проанализировать значение пути VML, используя манипуляции со строками Java. Я хочу восстановить все команды на пути, такие как MoveTo, LineTo, CurveTo, RLineTo (другие команды) и соответствующие им координаты/параметры x и y.

Вот примеры данных для анализа, каждая команда имеет свои собственные координаты x, y.

 1. m1,1 l1,200,200,200,200,1 xe
 2. m, l1,200,200,200,200,1 xe

Можете ли вы предложить алгоритм или код для получения команд и параметров для каждой команды? Например в №1.

Command = moveto 'm'

Command Parameters = (x=1,y=1).

Ссылка: http://www.w3.org/TR/NOTE-VML#_Toc416858391

Это что-то странное, но я пытался использовать StringTokenizer, например

StringTokenizer tokenizer = new StringTokenizer(path);

Друг предложил использовать StringTokenizer, и он сделал что-то близкое к моей цели, он дал мне следующие данные. Возможно, я смогу использовать StringTokenizer для своих нужд.

m1,1
l1,200,200,200,200,1
xe

Для № 1 вот идеальный результат. (псевдокод)

String command_type = "m"        List<String, String> parameters =   add("1", "1")
String command_type = "l"        List<String, String> parameters =   add("1", "200")
                                                                     add("200", "200")
                                                                     add("200", "1")
String command_type = "x"        (can have no parameter )
String command_type = "e"        (can have no parameter )

Для № 2 вот идеальный результат. (псевдокод)

String command_type = "m"        List<String, String> parameters =   add("0", "0")  // because the x and y parameters are not specified so I need to force them to 0,0
String command_type = "l"        List<String, String> parameters =   add("1", "200")
                                                                     add("200", "200")
                                                                     add("200", "1")
String command_type = "x"        (can have no parameter )
String command_type = "e"        (can have no parameter )

person Hilfritz    schedule 10.06.2014    source источник
comment
Можете ли вы дать требуемый результат для каждого из ваших 3 примеров?   -  person Robert3452    schedule 10.06.2014
comment
Привет, спасибо за быстрый ответ, я обновил образец и удалил третий. :-)   -  person Hilfritz    schedule 10.06.2014
comment
Токенизатор строк устарел, используйте String.split(regex) для того же эффекта   -  person Kyte    schedule 10.06.2014


Ответы (1)


Здесь важна хорошая спецификация, но, основываясь на ваших примерах ввода и вывода, я догадался:

Буква -> параметры, разделенные запятыми -> буква -> параметры, разделенные запятыми

Я также отметил, что команды не разделяются пробелами. например у вас есть xe как две отдельные команды. Это означает, что в вашем образце пробелы не имеют значения и могут быть проигнорированы.

Я также отмечаю, что все команды состоят из одной буквы. (Иначе xe не будет состоять из двух команд)

Также параметры должны идти парами и должны быть числами. Я не вижу отрицательных чисел в вашей выборке, но предполагаю, что они возможны. Я также предполагаю, что это целые числа, а не десятичные числа.

Итак, основываясь на предполагаемой спецификации, я могу предложить вам возможное решение, чтобы вы могли просмотреть и понять, что оно делает.

package ic.ac.uk.relationshipvisualiser.app;

import java.util.ArrayList;
import java.util.List;

public class TmpNoFXTest {

    private static class coOrd {
        int x = 0;
        int y = 0;
        public coOrd(int p_x,int p_y) {
            x=p_x;y=p_y;
        }
        public int getX() {return x;}
        public int getY() {return y;}
    }
    private static class command {
        String command = "";
        List<coOrd> param_list = new ArrayList<coOrd>();

        public command(String p_command) {
            command = p_command;
        }
        private String parseOneParam(String p_inp) {
            if (p_inp.equals("")) return "";
            if (isLetter(p_inp.substring(0,1))) return p_inp;
            int firstChar = 0;
            for (int c=0;c<p_inp.length();c++) {
                if (firstChar==0) {
                    if (isLetter(p_inp.substring(c,c+1))) {
                        firstChar = c;
                    }
                }
            }

            String parms = p_inp.substring(0,firstChar);
            if (parms.length()==0) return p_inp.substring(firstChar);
            int x = 0;
            int y = 0;

            int p = 0;
            String tmp = "";
            while ((p<parms.length()) && (!parms.substring(p,p+1).equals(","))) {
                tmp = tmp + parms.substring(p,p+1);
                p++;
            }
            p++;
            if (tmp.length()>0) {
                x = Integer.parseInt(tmp);
            }

            tmp = "";
            while ((p<parms.length()) && (!parms.substring(p,p+1).equals(","))) {
                tmp = tmp + parms.substring(p,p+1);
                p++;
            }

            if (p_inp.substring(p,p+1)==",") p++;

            if (tmp.length()>0) {
                y = Integer.parseInt(tmp);
            }

            param_list.add(new coOrd(x,y));

            return p_inp.substring(p);
        }
        public String parseParams(String p_inp) {
            if (p_inp.equals("")) return "";
            while (!isLetter(p_inp)) {
                p_inp = parseOneParam(p_inp);
            }
            return p_inp;
        }
        public String toString() {
            String ret = "";
            ret = "String command_type = \"" + command + "\"";
            if (param_list.size()==0) return ret + "     (can have no parameter )";


            for (int c=0;c<param_list.size();c++) {
                if (c>0) ret += "\n                         ";
                ret += "        List<String, String> parameters =   add(\"" + param_list.get(c).getX() + "\", \"" + param_list.get(c).getY() + "\")";               
            }

            return ret;
        }
    }
    private static boolean isLetter(String p_inp) {
        return p_inp.substring(0,1).matches("\\p{L}");
    }


    private static String parseSingleCommand(String p_inp, List<command> p_cmds) throws Exception {
        //Read a single command off the incoming string and pass the remaining input back

        String cmd = p_inp.substring(0,1);
        if (!isLetter(p_inp)) throw new Exception("Error command starts with non letter (" + cmd + ")");


        p_inp = p_inp.substring(1);
        command c = new command(cmd);
        p_inp = c.parseParams(p_inp);

        p_cmds.add(c);
        return p_inp;
    }

    private static List<command> parse(String p_inp) throws Exception {
        List<command> r = new ArrayList<command>();

        //spaces don't matter and I want to make this case-insensitive to minimise errors
        p_inp = p_inp.toLowerCase();
        p_inp = p_inp.replace(" ", "");

        while (p_inp.length()>0) {
            p_inp = parseSingleCommand(p_inp,r);
        }
        return r;
    }

    public static void main(String[] args) {
        System.out.println("Start tmpTest");

        List<String> tests = new ArrayList<String>();
        tests.add("m1,1 l1,200,200,200,200,1 xe");
        tests.add("m, l1,200,200,200,200,1 xe");

        for (int c=0;c<tests.size();c++) {
            System.out.println("Running test case " + c + " (" + tests.get(c) + ")");
            try {
                List<command> pr = parse(tests.get(c));

                for (int d=0;d<pr.size();d++) {
                    System.out.println(pr.get(d).toString());
                }

            } catch (Exception e) {
                e.printStackTrace();
                return;
            }
        };

        System.out.println("End tmpTest");
    }
}
person Robert3452    schedule 11.06.2014
comment
спасибо за это, это один очень хороший алгоритм для решения требования. Прямо сейчас я сталкиваюсь с более сложными строковыми значениями, такими как: m@0,l@0@0,0@0,0@2@0@2@0,21600@1,21600@1@2,21600@2,21600 @0@1@0@1,xe Сейчас я над этим работаю, буду очень благодарен за любую помощь. - person Hilfritz; 19.06.2014