From 90e0dbe8f3342596ca638f89fbdb0f3b56188503 Mon Sep 17 00:00:00 2001 From: Jakub Kolman <kubokolman@gmail.com> Date: Tue, 4 May 2021 00:50:08 +0200 Subject: [PATCH] [#81] feat: import/export of .fp format --- MeshModel/nbproject/project.properties | 0 .../provider/FeaturePointTypeProvider.java | 12 ++- .../services/FeaturePointExportService.java | 92 +++++++++++++++++++ ...ce.java => FeaturePointImportService.java} | 80 ++++++++-------- .../utils/FeaturePointFileFormatTypes.java | 40 ++++++++ .../src/main/resources/fp_text_default.csv | 2 +- .../FeaturePointExportServiceTest.java | 48 ++++++++++ ...ava => FeaturePointImportServiceTest.java} | 33 ++++--- .../FeaturePointTypeTypesServiceTest.java | 1 - .../analyst/feature/services/fp_head1_test.fp | 52 +++++++++++ MeshModel/test_file_landmarks.csv | 2 - 11 files changed, 305 insertions(+), 57 deletions(-) create mode 100644 MeshModel/nbproject/project.properties create mode 100644 MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointExportService.java rename MeshModel/src/main/java/cz/fidentis/analyst/feature/services/{FeaturePointImportExportService.java => FeaturePointImportService.java} (51%) create mode 100644 MeshModel/src/main/java/cz/fidentis/analyst/feature/utils/FeaturePointFileFormatTypes.java create mode 100644 MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointExportServiceTest.java rename MeshModel/src/test/java/cz/fidentis/analyst/feature/services/{FeaturePointImportExportServiceTest.java => FeaturePointImportServiceTest.java} (65%) create mode 100644 MeshModel/src/test/resources/cz/fidentis/analyst/feature/services/fp_head1_test.fp delete mode 100644 MeshModel/test_file_landmarks.csv diff --git a/MeshModel/nbproject/project.properties b/MeshModel/nbproject/project.properties new file mode 100644 index 00000000..e69de29b diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/provider/FeaturePointTypeProvider.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/provider/FeaturePointTypeProvider.java index 4b15f1fb..ca3eed37 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/provider/FeaturePointTypeProvider.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/provider/FeaturePointTypeProvider.java @@ -18,7 +18,7 @@ public class FeaturePointTypeProvider { private final Map<Integer, FeaturePointType> featurePointTypesById; private final Map<String, FeaturePointType> featurePointTypesByCode; - + // provide thread safe singleton private static class InstanceHolder { @@ -33,7 +33,8 @@ public class FeaturePointTypeProvider { /** * Access feature point types - * @return + * + * @return */ public static FeaturePointTypeProvider getInstance() { return InstanceHolder.instance; @@ -49,10 +50,15 @@ public class FeaturePointTypeProvider { /** * Get feature point by code + * * @param code - * @return + * @return */ public FeaturePointType getFeaturePointTypeByCode(String code) { return getFeaturePointTypesByCode().get(code); } + + public FeaturePointType getFeaturePointTypeById(int id) { + return getFeaturePointTypesById().get(id); + } } diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointExportService.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointExportService.java new file mode 100644 index 00000000..5f8e0837 --- /dev/null +++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointExportService.java @@ -0,0 +1,92 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package cz.fidentis.analyst.feature.services; + +import cz.fidentis.analyst.feature.FeaturePoint; +import cz.fidentis.analyst.feature.utils.FeaturePointFileFormatTypes; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author kubok + */ +public class FeaturePointExportService { + + public void exportFeaturePoints(List<FeaturePoint> featurePointList, String objectName, String format) throws FileNotFoundException, IOException { + switch (format) { + case FeaturePointFileFormatTypes.FORMAT_TYPE_OBJ: + exportFeaturePointsToCSV(featurePointList, objectName); + break; + case FeaturePointFileFormatTypes.FORMAT_TYPE_FP: + exportFeaturePointsToFP(featurePointList, objectName); + break; + default: + break; + } + } + + public void exportFeaturePointsToFP(List<FeaturePoint> featurePointList, String objectName) throws FileNotFoundException, IOException { + File csvOutputFile = new File(String.format("%s_landmarks.fp", objectName)); + // CSV is a normal text file, need a writer + try (BufferedWriter bw = new BufferedWriter(new FileWriter(csvOutputFile))) { + bw.write(String.format("<!--Saved by software Fidentis Analyst--><facialPoints model=\"%s\">", objectName)); + featurePointList.forEach(featurePoint -> { + try { + bw.newLine(); + bw.write(String.format("<facialPoint type=\"%s\">", featurePoint.getFeaturePointType().getType())); + bw.newLine(); + bw.write(String.format("<x>%f</x>", featurePoint.getX())); + bw.newLine(); + bw.write(String.format("<y>%f</y>", featurePoint.getY())); + bw.newLine(); + bw.write(String.format("<z>%f</z>", featurePoint.getZ())); + } catch (IOException ex) { + Logger.getLogger(FeaturePointImportService.class.getName()).log(Level.SEVERE, null, ex); + } + }); + bw.newLine(); + bw.write("</facialPoints>"); + } + + } + + private void exportFeaturePointsToCSV(List<FeaturePoint> featurePointList, String objectName) throws IOException { + File csvOutputFile = new File(String.format("%s_landmarks.fp", objectName)); + try (BufferedWriter bw = new BufferedWriter(new FileWriter(csvOutputFile))) { + bw.write("Scan name"); + featurePointList.forEach(featurePoint -> { + try { + bw.write(String.format(",%s x", featurePoint.getFeaturePointType().getCode())); + bw.write(String.format(",%s y", featurePoint.getFeaturePointType().getCode())); + bw.write(String.format(",%s z", featurePoint.getFeaturePointType().getCode())); + } catch (IOException ex) { + Logger.getLogger(FeaturePointImportService.class.getName()).log(Level.SEVERE, null, ex); + } + }); + bw.newLine(); + bw.write(String.format("%s", objectName)); + featurePointList.forEach(featurePoint -> { + try { + bw.write(","); + bw.write(Double.toString(featurePoint.getX())); + bw.write(","); + bw.write(Double.toString(featurePoint.getY())); + bw.write(","); + bw.write(Double.toString(featurePoint.getZ())); + } catch (IOException ex) { + Logger.getLogger(FeaturePointImportService.class.getName()).log(Level.SEVERE, null, ex); + } + }); + } + } +} diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointImportExportService.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointImportService.java similarity index 51% rename from MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointImportExportService.java rename to MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointImportService.java index 8452e8c0..0389f966 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointImportExportService.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/services/FeaturePointImportService.java @@ -10,33 +10,27 @@ import cz.fidentis.analyst.feature.exception.FeaturePointException; import cz.fidentis.analyst.feature.provider.FeaturePointTypeProvider; import cz.fidentis.analyst.feature.utils.FileResourcesUtils; import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; import java.io.IOException; -import java.io.InputStream; import java.io.InputStreamReader; -import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.stream.Stream; /** * * @author kubok */ -public class FeaturePointImportExportService { +public class FeaturePointImportService { private static final String COLUMN_DELIMETER = ","; private static final String CODE_PREFIX_DELIMETER = " "; + private static final String GREATER_THAN_DELIMETER = ">"; + private static final String LESS_THAN_DELIMETER = "<"; - public Optional<List<FeaturePoint>> importFeaturePoints(String path, String fileName) { + public Optional<List<FeaturePoint>> importFeaturePointsCSV(String path, String fileName) { FileResourcesUtils app = new FileResourcesUtils(); try (InputStreamReader streamReader = new InputStreamReader(app.getFileAsStream(path, fileName), StandardCharsets.UTF_8); @@ -79,34 +73,46 @@ public class FeaturePointImportExportService { return str.substring(0, str.indexOf(CODE_PREFIX_DELIMETER)); } - public void exportFeaturePoints(List<FeaturePoint> featurePointList, String objectName) throws FileNotFoundException, IOException { - File csvOutputFile = new File(String.format("%s_landmarks.csv", objectName)); - // CSV is a normal text file, need a writer - try (BufferedWriter bw = new BufferedWriter(new FileWriter(csvOutputFile))) { - bw.write("Scan name"); - featurePointList.forEach(featurePoint -> { - try { - bw.write(String.format(",%s x", featurePoint.getFeaturePointType().getCode())); - bw.write(String.format(",%s y", featurePoint.getFeaturePointType().getCode())); - bw.write(String.format(",%s z", featurePoint.getFeaturePointType().getCode())); - } catch (IOException ex) { - Logger.getLogger(FeaturePointImportExportService.class.getName()).log(Level.SEVERE, null, ex); - } - }); - bw.newLine(); - bw.write(String.format("%s", objectName)); - featurePointList.forEach(featurePoint -> { - try { - bw.write(","); - bw.write(Double.toString(featurePoint.getX())); - bw.write(","); - bw.write(Double.toString(featurePoint.getY())); - bw.write(","); - bw.write(Double.toString(featurePoint.getZ())); - } catch (IOException ex) { - Logger.getLogger(FeaturePointImportExportService.class.getName()).log(Level.SEVERE, null, ex); - } + public Optional<List<FeaturePoint>> importFeaturePointsFP(String path, String fileName) { + FileResourcesUtils app = new FileResourcesUtils(); + try (InputStreamReader streamReader + = new InputStreamReader(app.getFileAsStream(path, fileName), StandardCharsets.UTF_8); + BufferedReader reader = new BufferedReader(streamReader)) { + + Stream<String> lines = reader.lines(); + List<String> linesList = new ArrayList<>(); + + lines.forEach(line -> { + linesList.add(line); }); + + if (linesList.isEmpty()) { + throw new FeaturePointException(String.format("Feature point import file '%s' has wrong format", fileName)); + } + + List<FeaturePoint> points = new ArrayList<>(); + for (int i = 1; i < linesList.size() - 6; i += 5) { + FeaturePoint point = new FeaturePoint( + Double.parseDouble(linesList.get(i + 1).substring( + linesList.get(i + 1).indexOf(GREATER_THAN_DELIMETER) + 1, + linesList.get(i + 1).indexOf(LESS_THAN_DELIMETER, linesList.get(i + 1).indexOf(GREATER_THAN_DELIMETER)))), + Double.parseDouble(linesList.get(i + 2).substring( + linesList.get(i + 2).indexOf(GREATER_THAN_DELIMETER) + 1, + linesList.get(i + 2).indexOf(LESS_THAN_DELIMETER, linesList.get(i + 2).indexOf(GREATER_THAN_DELIMETER)))), + Double.parseDouble(linesList.get(i + 3).substring( + linesList.get(i + 3).indexOf(GREATER_THAN_DELIMETER) + 1, + linesList.get(i + 3).indexOf(LESS_THAN_DELIMETER, linesList.get(i + 3).indexOf(GREATER_THAN_DELIMETER)))), + FeaturePointTypeProvider.getInstance().getFeaturePointTypeById( + Integer.parseInt(linesList.get(i).replaceAll("[^0-9]", ""))) + ); + points.add(point); + } + return Optional.of(points); + + } catch (IOException e) { + throw new FeaturePointException(String.format("Feature point service cannot open file", fileName)); + } catch (NumberFormatException e1) { + throw new FeaturePointException(e1.getMessage()); } } diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/utils/FeaturePointFileFormatTypes.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/utils/FeaturePointFileFormatTypes.java new file mode 100644 index 00000000..8b8313c4 --- /dev/null +++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/utils/FeaturePointFileFormatTypes.java @@ -0,0 +1,40 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package cz.fidentis.analyst.feature.utils; + +/** + * + * @author kubok + */ +public class FeaturePointFileFormatTypes { + + public static final String FORMAT_TYPE_OBJ = "OBJ"; + public static final String FORMAT_TYPE_STL = "STL"; + public static final String FORMAT_TYPE_PLY = "PLY"; + public static final String FORMAT_TYPE_CSV = "CSV"; + public static final String FORMAT_TYPE_FP = "FP"; + public static final String FORMAT_TYPE_PP = "PP"; + public static final String FORMAT_TYPE_PTS = "PTS"; + public static final String FORMAT_TYPE_DTA = "DTA"; + public static final String FORMAT_TYPE_PNG = "PNG"; + public static final String FORMAT_TYPE_FID = "FID"; + public static final String FORMAT_TYPE_NONE = "NONE"; + + + enum formatType { + OBJ, + STL, + PLY, + CSV, + FP, + PP, + PTS, + DTA, + PNG, + FID, + NONE + } +} diff --git a/MeshModel/src/main/resources/fp_text_default.csv b/MeshModel/src/main/resources/fp_text_default.csv index 1b86ec7a..5139b380 100644 --- a/MeshModel/src/main/resources/fp_text_default.csv +++ b/MeshModel/src/main/resources/fp_text_default.csv @@ -59,4 +59,4 @@ Type;Name;Info;Acronym 58;Supercilium Lateralis R;No information;SUL_R 59;Supercilium Lateralis L;No information;SUL_L 60;Supercilium Medialis R;No information;SUM_R -61;Supercilium Medialis L;No information;SUM_L +61;Supercilium Medialis L;No information;SUM_L \ No newline at end of file diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointExportServiceTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointExportServiceTest.java new file mode 100644 index 00000000..c1fe2b94 --- /dev/null +++ b/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointExportServiceTest.java @@ -0,0 +1,48 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package cz.fidentis.analyst.feature.services; + +import cz.fidentis.analyst.feature.FeaturePoint; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.DisplayName; + +/** + * + * @author Jakub Kolman + */ +public class FeaturePointExportServiceTest { + + private static final Path testFileDirectory = Paths.get("src", "test", "resources", "cz", "fidentis", "analyst", "feature", "services"); + private static final String TEST_CSV_FILE = "00007_01_landmarks.csv"; + + @DisplayName("Test writing a CSV file") + @Test + void exportFeaturePointsCSVTest() throws IOException { + FeaturePointExportService service = new FeaturePointExportService(); + Optional<List<FeaturePoint>> featurePoints = loadFeaturePoints(); + service.exportFeaturePoints(featurePoints.get(), "test_file", "CSV"); + } + + @DisplayName("Test writing a FP file") + @Test + void exportFeaturePointsFPTest() throws IOException { + FeaturePointExportService service = new FeaturePointExportService(); + Optional<List<FeaturePoint>> featurePoints = loadFeaturePoints(); + service.exportFeaturePoints(featurePoints.get(), "test_file", "FP"); + } + + private Optional<List<FeaturePoint>> loadFeaturePoints() { + FeaturePointImportService service = new FeaturePointImportService(); + Optional<List<FeaturePoint>> featurePoints = service.importFeaturePointsCSV(testFileDirectory.toString(), TEST_CSV_FILE); + return featurePoints; + + } +} diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointImportExportServiceTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointImportServiceTest.java similarity index 65% rename from MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointImportExportServiceTest.java rename to MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointImportServiceTest.java index 5cc52b9a..deafe6e5 100644 --- a/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointImportExportServiceTest.java +++ b/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointImportServiceTest.java @@ -23,11 +23,12 @@ import org.junit.jupiter.api.DisplayName; * * @author Jakub Kolman */ -public class FeaturePointImportExportServiceTest { +public class FeaturePointImportServiceTest { private static final Path testFileDirectory = Paths.get("src", "test", "resources", "cz", "fidentis", "analyst", "feature", "services"); private static final String TEST_CSV_FILE = "00007_01_landmarks.csv"; + private static final String TEST_FP_FILE = "fp_head1_test.fp"; @Test() void fileExistsTest() throws IOException { @@ -37,7 +38,7 @@ public class FeaturePointImportExportServiceTest { @DisplayName("Test loading a CSV file") @Test - void importFeaturePointsTest() { + void importFeaturePointsCSVTest() { Optional<List<FeaturePoint>> featurePoints = loadFeaturePoints(); assertTrue(featurePoints.isPresent()); assertTrue(featurePoints.get().size() > 0); @@ -48,19 +49,25 @@ public class FeaturePointImportExportServiceTest { FeaturePointTypeProvider.getInstance().getFeaturePointTypeByCode("EX_R")) ); } - - @DisplayName("Test writing a CSV file") - @Test - void exportFeaturePointsTest() throws IOException { - FeaturePointImportExportService service = new FeaturePointImportExportService(); - Optional<List<FeaturePoint>> featurePoints = loadFeaturePoints(); - service.exportFeaturePoints(featurePoints.get(), "test_file"); - } private Optional<List<FeaturePoint>> loadFeaturePoints() { - FeaturePointImportExportService service = new FeaturePointImportExportService(); - Optional<List<FeaturePoint>> featurePoints = service.importFeaturePoints(testFileDirectory.toString(), TEST_CSV_FILE); + FeaturePointImportService service = new FeaturePointImportService(); + Optional<List<FeaturePoint>> featurePoints = service.importFeaturePointsCSV(testFileDirectory.toString(), TEST_CSV_FILE); return featurePoints; - + } + + @DisplayName("Test loading a FP file") + @Test + void importFeaturePointsFPTest() { + FeaturePointImportService service = new FeaturePointImportService(); + Optional<List<FeaturePoint>> featurePoints = service.importFeaturePointsFP(testFileDirectory.toString(), TEST_FP_FILE); + assertTrue(featurePoints.isPresent()); + assertTrue(featurePoints.get().size() > 0); + assertTrue(featurePoints.get().get(0).getX() == -40.429775 + && featurePoints.get().get(0).getY() == 45.756405 + && featurePoints.get().get(0).getZ() == 37.12462 + && featurePoints.get().get(0).getFeaturePointType().equals( + FeaturePointTypeProvider.getInstance().getFeaturePointTypeByCode("EX_R")) + ); } } diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointTypeTypesServiceTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointTypeTypesServiceTest.java index f0ff92a2..cada9ca4 100644 --- a/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointTypeTypesServiceTest.java +++ b/MeshModel/src/test/java/cz/fidentis/analyst/feature/services/FeaturePointTypeTypesServiceTest.java @@ -16,7 +16,6 @@ class FeaturePointTypeTypesServiceTest { @DisplayName("Test loading a CSV file") @Test void readResourcesTest() { - FeaturePointTypesService service = new FeaturePointTypesService(); Optional<Map<Integer, FeaturePointType>> featurePointTypes = service.readResources(); assertTrue(featurePointTypes.isPresent()); diff --git a/MeshModel/src/test/resources/cz/fidentis/analyst/feature/services/fp_head1_test.fp b/MeshModel/src/test/resources/cz/fidentis/analyst/feature/services/fp_head1_test.fp new file mode 100644 index 00000000..6a1414be --- /dev/null +++ b/MeshModel/src/test/resources/cz/fidentis/analyst/feature/services/fp_head1_test.fp @@ -0,0 +1,52 @@ +<!--Saved by software Fidentis Analyst--><facialPoints model="head01.obj"> +<facialPoint type="1"> +<x>-40.429775</x> +<y>45.756405</y> +<z>37.12462</z> +</facialPoint> +<facialPoint type="2"> +<x>-14.435408</x> +<y>47.491802</y> +<z>45.004395</z> +</facialPoint> +<facialPoint type="3"> +<x>16.292408</x> +<y>45.930874</y> +<z>43.787186</z> +</facialPoint> +<facialPoint type="4"> +<x>35.071796</x> +<y>44.352318</y> +<z>38.45862</z> +</facialPoint> +<facialPoint type="5"> +<x>8.0257435</x> +<y>31.204237</y> +<z>37.290848</z> +</facialPoint> +<facialPoint type="6"> +<x>-9.646407</x> +<y>28.970993</y> +<z>34.634415</z> +</facialPoint> +<facialPoint type="7"> +<x>-10.50379</x> +<y>-9.440336</y> +<z>41.965027</z> +</facialPoint> +<facialPoint type="8"> +<x>7.8041906</x> +<y>-9.892714</y> +<z>43.199005</z> +</facialPoint> +<facialPoint type="9"> +<x>-20.985464</x> +<y>-36.727818</y> +<z>31.406677</z> +</facialPoint> +<facialPoint type="10"> +<x>22.01368</x> +<y>-37.23364</y> +<z>30.561905</z> +</facialPoint> +</facialPoints> diff --git a/MeshModel/test_file_landmarks.csv b/MeshModel/test_file_landmarks.csv deleted file mode 100644 index e2d6288e..00000000 --- a/MeshModel/test_file_landmarks.csv +++ /dev/null @@ -1,2 +0,0 @@ -Scan name,EX_R x,EX_R y,EX_R z,EX_L x,EX_L y,EX_L z,EN_R x,EN_R y,EN_R z,EN_L x,EN_L y,EN_L z,PAS_R x,PAS_R y,PAS_R z,PAS_L x,PAS_L y,PAS_L z,PAI_R x,PAI_R y,PAI_R z,PAI_L x,PAI_L y,PAI_L z,G x,G y,G z,SN x,SN y,SN z,AL_R x,AL_R y,AL_R z,AL_L x,AL_L y,AL_L z,N x,N y,N z,PRN x,PRN y,PRN z,LS x,LS y,LS z,STO x,STO y,STO z,LI x,LI y,LI z,CH_R x,CH_R y,CH_R z,CH_L x,CH_L y,CH_L z,CP_R x,CP_R y,CP_R z,CP_L x,CP_L y,CP_L z,SL x,SL y,SL z,GN x,GN y,GN z,GOL_R x,GOL_R y,GOL_R z,GOL_L x,GOL_L y,GOL_L z,ZY_R x,ZY_R y,ZY_R z,ZY_L x,ZY_L y,ZY_L z,PG x,PG y,PG z,T_R x,T_R y,T_R z,T_L x,T_L y,T_L z,SA_R x,SA_R y,SA_R z,SA_L x,SA_L y,SA_L z,SBA_R x,SBA_R y,SBA_R z,SBA_L x,SBA_L y,SBA_L z,PA_R x,PA_R y,PA_R z,PA_L x,PA_L y,PA_L z,OBS_R x,OBS_R y,OBS_R z,OBS_L x,OBS_L y,OBS_L z,OBI_R x,OBI_R y,OBI_R z,OBI_L x,OBI_L y,OBI_L z,PRA_R x,PRA_R y,PRA_R z,PRA_L x,PRA_L y,PRA_L z -test_file,-45.3298,37.1466,-40.5415,44.3033,36.255,-42.623,-18.5134,33.2336,-36.7921,16.188,32.6379,-37.2197,-34.3363,41.5306,-33.6564,33.8288,39.5634,-34.2531,-34.4132,31.9017,-35.2642,33.5827,30.789,-36.755,0.12959,51.8853,-14.4235,-0.0356107,-13.0827,-16.9983,-16.6623,-4.05884,-19.1798,15.5038,-4.97323,-21.1836,0.044336,39.4236,-19.1853,-0.0291473,0.258132,-0.140334,-0.0901103,-29.1039,-16.7076,0.055705,-35.7511,-21.7819,0.0285089,-44.8791,-21.1852,-28.1537,-35.8802,-32.2677,24.4702,-34.6564,-34.317,-5.68164,-26.7827,-16.8184,5.63171,-26.3173,-17.4413,0.0403775,-52.2879,-27.0041,0.0981629,-80.2827,-43.5233,-57.0806,-39.8906,-118.469,50.4482,-38.958,-118.26,-63.254,40.8951,-53.951,59.7107,38.7682,-58.1024,0.0468024,-61.4376,-25.9881,-78.3702,26.048,-120.74,70.6534,28.1125,-122.519,-91.2689,55.5377,-137.688,87.5631,56.4117,-137.202,-75.6368,-4.45582,-120.828,70.4776,-1.8171,-120.704,-93.2421,34.1812,-155.155,90.0449,35.8349,-155.402,-82.7099,46.6375,-123.483,76.087,46.7891,-123.211,-72.0651,-5.47207,-119.272,64.1992,-3.95897,-118.937,-83.3521,40.1314,-121.805,75.3747,40.0263,-121.781 \ No newline at end of file -- GitLab