Использование jzy3d для построения трехмерной поверхности на Java

У меня есть CSV-файл с разделителями-табуляциями, у которого есть заголовок, а его первый столбец - это метки для каждой строки. Например.

Label   Sample1   Sample2    Sample3    Sample4    Sample5
U.S.A.    10.1      3.2       5.6       6.9       7.3
Canada    9.8       4.5       5.7       6.8       7.9 

Я использую superCSV для анализа этого файла CSV и создания многоугольников для каждой точки, например: (1, 1, 10.1) [означает первую строку, первый столбец]. Точки добавляются в список полигонов. Затем я использую многоугольники для создания поверхности, но поверхность не является непрерывной. Я приложил снимок экрана с моим рисунком

введите описание изображения здесь

Часть моего кода выглядит следующим образом:

public void init() {


        /* build a list of polygons out of the CSV file */
        List<Polygon> polygons = null;
        try {
            polygons = parseCSV("my_CSVFile.csv");
        } catch (IOException e) {
            e.printStackTrace();
        }


        System.out.println("size of polygons is: " + polygons.size());


        // Creates the 3d object
        Shape surface = new Shape(polygons);
        surface.setColorMapper(new ColorMapper(new ColorMapRainbow(), surface.getBounds().getZmin(), surface.getBounds().getZmax(), new org.jzy3d.colors.Color(1,1,1,1f)));
        surface.setWireframeDisplayed(true);
        surface.setWireframeColor(org.jzy3d.colors.Color.BLACK);

        chart = AWTChartComponentFactory.chart(Quality.Advanced, getCanvasType());
//        chart = new Chart();
        chart.getScene().getGraph().add(surface);
    }

    public List<Polygon> parseCSV(String csvFile) throws IOException
    {
        if (csvFile.isEmpty())
            System.exit(-1);

        File inputFile = new File(csvFile);
        String[] header = null;  /* header row */

        if (inputFile.exists())
        {
            FileReader fr = new FileReader(inputFile);
            LineNumberReader lineReader = new LineNumberReader(fr);
            String headerLine = null;

            while (lineReader.getLineNumber() == 0)
            {
                headerLine = lineReader.readLine();
            }
            lineReader.close();


            if (headerLine != null)
            {
                header = headerLine.split("\\t");
            }

        }

        ICsvListReader listReader = null;
        List<Polygon> polygons = new ArrayList<Polygon>();

        try {
            listReader = new CsvListReader(new FileReader(csvFile), CsvPreference.TAB_PREFERENCE);
            listReader.getHeader(true);

            List<String> contentList;
            int rowIndex = 1;           // excluding the header row
            while((contentList = listReader.read()) != null)
            {
                if (contentList.size() != header.length) {
                    System.out.println("contentList size is: " + contentList.size() + ", header length is: " + header.length);
                    continue;
                }

                Polygon polygon = new Polygon();
                for (int i = 1; i < contentList.size(); i++)
                {
                    if (DoubleFactory.tryParseDouble(contentList.get(i)) != -1)  /* unsuccessful double parse returns -1 */
                    {
                        polygon.add(new Point(new Coord3d(rowIndex, i, Double.parseDouble(contentList.get(i)))));
                    }
                }
                rowIndex++;
                polygons.add(polygon);
            }


        } finally {
            if(listReader != null) {
                listReader.close();
            }
        }

        return polygons;

    }

    /* inner class for parsing string to double */
    private static class DoubleFactory
    {
        public static double tryParseDouble(final String number)
        {
            double result;
            try {
                result = Double.parseDouble(number);
            } catch (NumberFormatException e) {
                result = -1;  /* default failed parsing*/
            }

            return result;
        }
    }

Мне нужна помощь в создании непрерывной гладкой трехмерной поверхности из моего содержимого CSV (числа)


person TonyGW    schedule 04.06.2014    source источник


Ответы (2)


Мой код для создания списка многоугольников выглядит следующим образом

List<Polygon> polygons = new ArrayList<Polygon>();
for (int i = 0; i < m_data.rows-k; i++) {
    for (int j = 0; j < m_data.columns-k; j++) {
        Polygon polygon = new Polygon();
        polygon.add(new Point(new Coord3d(i,  j,  m_data.get(i,  j  ))));
        polygon.add(new Point(new Coord3d(i+1,j,  m_data.get(i+1,j  ))));
        polygon.add(new Point(new Coord3d(i+1,j+1,m_data.get(i+1,j+1))));
        polygon.add(new Point(new Coord3d(i,  j+1,m_data.get(i,  j+1))));
        polygons.add(polygon);
    }
}

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


Связанный вопрос: Постройте трехмерный график поверхности, используя координаты xyz с jzy3d

person Didii    schedule 29.07.2014

Когда вы рисуете многоугольник, он соединяет вершины в том порядке, в котором вы их добавляли. Посмотрите на линии на своем графике - они переходят от одной точки к другой, прыгая от конца одной строки к началу следующей.

Вам нужна поверхность. Я не знаком с jzy3d, но должно быть несколько встроенных генераторов поверхностей, где вы можете просто добавить все свои точки и попросить его вернуть поверхность. Если нет, вам просто нужно соединить группы из 3 (треугольников) или 4 (четырехугольников) вершин и нарисовать с ними многоугольник, как Didii уже закодировал для вас.

person Ruan Caiman    schedule 17.09.2014