chiark / gitweb /
343bf52ea20c87613a2eee193415facf48d83da5
[cura.git] /
1 /*\r
2 <?xml version='1.0' standalone='yes' ?>\r
3 \r
4 <script>\r
5         <name>Import GNU Triangulated Surface</name>\r
6         <author>Enrique Perez</author>\r
7         <version>1.0</version>\r
8         <date>29-Apr-2008</date>\r
9         <description>\r
10 This script imports GNU Triangulated Surfaces as triangle meshes.\r
11     </description>\r
12         <licenseType>gpl</licenseType>\r
13 </script>\r
14 */\r
15 \r
16 /**\r
17 Add a delete the last object of the scene undo record, to the scene.\r
18 */\r
19 \r
20 void addUndoRecord() {\r
21   scene = window.getScene();\r
22   undoAdd = new UndoRecord ( window, false, UndoRecord.DELETE_OBJECT, new Object[] { new Integer( scene.getNumObjects() - 1 ) } );\r
23   window.setUndoRecord( undoAdd );\r
24 }\r
25 \r
26 int getSameVertexIndex( edgeFirst, edgeSecond )\r
27 {\r
28   for ( int endpointIndex = 0; endpointIndex < 2; endpointIndex++ ) {\r
29     endpoint = edgeFirst[ endpointIndex ];\r
30 \r
31     if ( endpoint == edgeSecond[ 0 ] ) {\r
32       return endpoint;\r
33     }\r
34 \r
35     if ( endpoint == edgeSecond[ 1 ] ) {\r
36       return endpoint;\r
37     }\r
38   }\r
39 \r
40   print( "Inconsistent GNU Triangulated Surface" );\r
41   print( edgeFirst );\r
42   print( edgeSecond );\r
43   return 0;\r
44 }\r
45 \r
46 /**\r
47 Import GNU Triangulated Surface from a file.\r
48 Quoted from http://gts.sourceforge.net/reference/gts-surfaces.html#GTS-SURFACE-WRITE\r
49 "All the lines beginning with GTS_COMMENTS (#!) are ignored. The first line contains three unsigned integers separated by spaces. The first integer is the number of vertices, nv, the second is the number of edges, ne and the third is the number of faces, nf.\r
50 \r
51 Follows nv lines containing the x, y and z coordinates of the vertices. Follows ne lines containing the two indices (starting from one) of the vertices of each edge. Follows nf lines containing the three ordered indices (also starting from one) of the edges of each face.\r
52 \r
53 The format described above is the least common denominator to all GTS files. Consistent with an object-oriented approach, the GTS file format is extensible. Each of the lines of the file can be extended with user-specific attributes accessible through the read() and write() virtual methods of each of the objects written (surface, vertices, edges or faces). When read with different object classes, these extra attributes are just ignored."\r
54 */\r
55 \r
56 void importFile( gnuFile )\r
57 {\r
58   bufferedReader = new BufferedReader( new FileReader( gnuFile ) );\r
59   Vector lineVector = new Vector();\r
60   line = bufferedReader.readLine();\r
61   name = gnuFile.getName();\r
62   int lastIndexOfDot = name.lastIndexOf( '.' );\r
63 \r
64   if ( lastIndexOfDot > 0 ) {\r
65     name = name.substring( 0, lastIndexOfDot );\r
66   }\r
67 \r
68   while ( line != null ) {\r
69 \r
70     if ( line.length() > 0 ) {\r
71       firstCharacter = line.charAt( 0 );\r
72 \r
73       if ( firstCharacter != '#' && firstCharacter != '!' ) {\r
74         lineVector.add( line );\r
75       }\r
76     }\r
77 \r
78     line = bufferedReader.readLine();\r
79   }\r
80 \r
81   splitLine = lineVector.get( 0 ).split( " " );\r
82   int numberOfVertices = Integer.valueOf( splitLine[ 0 ] );\r
83   int numberOfEdges = Integer.valueOf( splitLine[ 1 ] );\r
84   int numberOfFaces = Integer.valueOf( splitLine[ 2 ] );\r
85   edges = new int[ numberOfEdges ][ 2 ];\r
86   faces = new int[ numberOfFaces ][ 3 ];\r
87   vertices = new Vec3[ numberOfVertices ];\r
88 \r
89   for ( int vertexIndex = 0; vertexIndex < numberOfVertices; vertexIndex++ ) {\r
90     line = lineVector.get( vertexIndex + 1 );\r
91     splitLine = line.split( " " );\r
92     vertex = new Vec3( Double.valueOf( splitLine[ 0 ] ), Double.valueOf( splitLine[ 1 ] ), Double.valueOf( splitLine[ 2 ] ) );\r
93     vertices[ vertexIndex ] = vertex;\r
94   }\r
95 \r
96   int edgeStart = numberOfVertices + 1;\r
97 \r
98   for ( int edgeIndex = 0; edgeIndex < numberOfEdges; edgeIndex++ ) {\r
99     line = lineVector.get( edgeIndex + edgeStart );\r
100     splitLine = line.split( " " );\r
101     int[] edge = { Integer.valueOf( splitLine[ 0 ] ) - 1, Integer.valueOf( splitLine[ 1 ] ) - 1 };\r
102     edges[ edgeIndex ] = edge;\r
103   }\r
104 \r
105   int faceStart = edgeStart + numberOfEdges;\r
106 \r
107   for ( int faceIndex = 0; faceIndex < numberOfFaces; faceIndex++ ) {\r
108     line = lineVector.get( faceIndex + faceStart );\r
109     splitLine = line.split( " " );\r
110     edgeFirst = edges[ Integer.valueOf( splitLine[ 0 ] ) - 1 ];\r
111     edgeSecond = edges[ Integer.valueOf( splitLine[ 1 ] ) - 1 ];\r
112     edgeThird = edges[ Integer.valueOf( splitLine[ 2 ] ) - 1 ];\r
113     int[] vertexIndices = { getSameVertexIndex( edgeFirst, edgeSecond ), getSameVertexIndex( edgeSecond, edgeThird ), getSameVertexIndex( edgeThird, edgeFirst ) };\r
114     faces[ faceIndex ] = vertexIndices;\r
115   }\r
116 \r
117   CoordinateSystem coordinateSystem = new CoordinateSystem();\r
118 \r
119   while ( window.getScene().getObject( name ) != null ) {\r
120     name += "2";\r
121   }\r
122 \r
123   mesh = new TriangleMesh ( vertices, faces );\r
124   mesh.setSmoothingMethod( Mesh.NO_SMOOTHING );\r
125   window.addObject( mesh, coordinateSystem, name, null );\r
126   addUndoRecord();\r
127 }\r
128 \r
129 /**\r
130 Import GNU Triangulated Surface from a file or from files in a directory.\r
131 */\r
132 \r
133 void importFiles()\r
134 {\r
135   if ( openFileButton.getState() ) {\r
136     importFile( file );\r
137     return;\r
138   }\r
139 \r
140   filesInDirectory = file.getParentFile().listFiles();\r
141 \r
142   for ( int fileIndex = 0; fileIndex < filesInDirectory.length; fileIndex++ ) {\r
143     directoryFile = filesInDirectory[ fileIndex ];\r
144     String directoryFileName = directoryFile.getName();\r
145 \r
146     if ( directoryFileName.endsWith( ".gts" ) ) {\r
147       importFile( directoryFile );\r
148     }\r
149   }\r
150 }\r
151 \r
152 /**\r
153 Add radio button groups to the preference widgets.\r
154 \r
155 @param  radioButtonGroups radio button groups which will be added to the memorable widgets\r
156 @param  widgetVector memorable widgets\r
157 */\r
158 \r
159 void preferencesAddRadioButtonGroups( RadioButtonGroup[] radioButtonGroups, Vector widgetVector )\r
160 {\r
161   for ( int radioIndex = 0; radioIndex < radioButtonGroups.length; radioIndex++ ) {\r
162     radioButtonGroup = radioButtonGroups[ radioIndex ];\r
163     radioButtonGroupIterator = radioButtonGroup.getRadioButtons();\r
164 \r
165     while ( radioButtonGroupIterator.hasNext() ) {\r
166       radioButton = radioButtonGroupIterator.next();\r
167       preferencesAddWidgetWithString( radioButton, radioButton.getText(), widgetVector );\r
168     }\r
169   }\r
170 }\r
171 \r
172 /**\r
173 Add widgets which have titles.\r
174 \r
175 @param  widgets widgets which have titles\r
176 @param  widgetStrings widget titles\r
177 @param  widgetVector memorable widgets\r
178 */\r
179 \r
180 void preferencesAddWidgetsWithStrings( Widget[] widgets, String[] widgetStrings, Vector widgetVector )\r
181 {\r
182   for ( int widgetIndex = 0; widgetIndex < widgets.length; widgetIndex++ ) {\r
183     widget = widgets[ widgetIndex ];\r
184 \r
185     if ( widget instanceof BCheckBox || widget instanceof BOutline || widget instanceof BTextField || widget instanceof ValueField ) {\r
186       preferencesAddWidgetWithString( widget, widgetStrings[ widgetIndex ], widgetVector );\r
187     }\r
188   }\r
189 }\r
190 \r
191 /**\r
192 Give the widget a name and add it to the widget vector.\r
193 \r
194 @param  widget widget which will be given a name\r
195 @param  widgetStrings widget name\r
196 @param  widgetVector memorable widgets\r
197 */\r
198 \r
199 void preferencesAddWidgetWithString( Widget widget, String widgetString, Vector widgetVector )\r
200 {\r
201   widget.setName( widgetString );\r
202   widgetVector.add( widget );\r
203 }\r
204 \r
205 /**\r
206 Read widget settings from preferences file.\r
207 \r
208 @param  preferencesFilename preferences filename\r
209 @param  widgetVector memorable widgets\r
210 */\r
211 \r
212 void preferencesRead( String preferencesFilename, Vector widgetVector )\r
213 {\r
214   preferencesFile = new File( preferencesFilename );\r
215 \r
216   if ( !preferencesFile.canRead() ) {\r
217     return;\r
218   }\r
219 \r
220   BufferedReader preferencesReader = new BufferedReader( new FileReader( preferencesFile ) );\r
221 \r
222   line = preferencesReader.readLine();\r
223 \r
224   while ( line != null ) {\r
225     preferencesReadLine( line, widgetVector );\r
226     line = preferencesReader.readLine();\r
227   }\r
228 }\r
229 \r
230 /**\r
231 Read line of preferences and set widget to that line.\r
232 \r
233 @param  line line of preferences\r
234 @param  widgetVector memorable widgets\r
235 */\r
236 \r
237 void preferencesReadLine( String line, Vector widgetVector )\r
238 {\r
239   splitLine = line.split( "\t" );\r
240 \r
241   if ( splitLine.length < 2 ) {\r
242     return;\r
243   }\r
244 \r
245   name = splitLine[ 0 ];\r
246 \r
247   for ( int widgetIndex = 0; widgetIndex < widgetVector.size(); widgetIndex++ ) {\r
248     widget = widgetVector.elementAt( widgetIndex );\r
249 \r
250     if ( widget.getName().equals( name ) ) {\r
251       preferencesReadWidget( splitLine[ 1 ], widget );\r
252 \r
253       return;\r
254     }\r
255   }\r
256 }\r
257 \r
258 /**\r
259 Set widget to preferences value.\r
260 \r
261 @param  value preferences value\r
262 @param  widget widget to be set to value\r
263 */\r
264 \r
265 void preferencesReadWidget( String value, Widget widget )\r
266 {\r
267   if ( widget instanceof BCheckBox || widget instanceof BRadioButton ) {\r
268     widget.setState( Boolean.valueOf( value ) );\r
269 \r
270     return;\r
271   }\r
272 \r
273   if ( widget instanceof BOutline ) { // it would be better to save the value instead of index because the list might change, but I'm lazy\r
274     bList = widget.getContent().getContent();\r
275     selectedIndex = Integer.valueOf( value );\r
276     bList.setSelected( selectedIndex, true );\r
277     bList.scrollToItem( selectedIndex );\r
278 \r
279     return;\r
280   }\r
281 \r
282   if ( widget instanceof BTextField ) {\r
283     widget.setText( value );\r
284 \r
285     return;\r
286   }\r
287 \r
288   if ( widget instanceof ValueField ) {\r
289     widget.setValue( Double.valueOf( value ) );\r
290   }\r
291 }\r
292 \r
293 /**\r
294 Write widget settings to preferences file.\r
295 \r
296 @param  preferencesFilename preferences filename\r
297 @param  widgetVector memorable widgets\r
298 */\r
299 \r
300 void preferencesWrite( String preferencesFilename, Vector widgetVector )\r
301 {\r
302   preferencesFile = new File( preferencesFilename );\r
303 \r
304   if ( preferencesFile == null ) {\r
305     print( "Can not write preferences to " + preferencesFilename );\r
306 \r
307     return;\r
308   }\r
309 \r
310   BufferedWriter preferencesWriter = new BufferedWriter( new FileWriter( preferencesFile ) );\r
311 \r
312   for ( int widgetIndex = 0; widgetIndex < widgetVector.size(); widgetIndex++ ) {\r
313     widget = widgetVector.elementAt( widgetIndex );\r
314     preferencesWriteWidget( preferencesWriter, widget );\r
315   }\r
316 \r
317   //Close the output stream\r
318   preferencesWriter.close();\r
319 }\r
320 \r
321 /**\r
322 Write widget settings to line of preferences.\r
323 \r
324 @param  preferencesWriter buffered preferences file writer\r
325 @param  widget widget to be written\r
326 */\r
327 \r
328 void preferencesWriteWidget( BufferedWriter preferencesWriter, Widget widget )\r
329 {\r
330   widgetString = widget.getName() + "\t";\r
331 \r
332   if ( widget instanceof BCheckBox || widget instanceof BRadioButton ) {\r
333     preferencesWriter.write( widgetString + widget.getState().toString() + "\n" );\r
334 \r
335     return;\r
336   }\r
337 \r
338   if ( widget instanceof BOutline ) { // it would be better to save the value because the list might change, but I'm lazy\r
339     BList bList = widget.getContent().getContent();\r
340     bList = widget.getContent().getContent();\r
341     preferencesWriter.write( widgetString + bList.getSelectedIndex().toString() + "\n" );\r
342 \r
343     return;\r
344   }\r
345 \r
346   if ( widget instanceof BTextField ) {\r
347     preferencesWriter.write( widgetString + widget.getText() + "\n" );\r
348 \r
349     return;\r
350   }\r
351 \r
352   if ( widget instanceof ValueField ) {\r
353     preferencesWriter.write( widgetString + widget.getValue().toString() + "\n" );\r
354   }\r
355 }\r
356 \r
357 // Set default parameters.\r
358 directoryRadioButtonGroup = new RadioButtonGroup();\r
359 openDirectoryButton = new BRadioButton( "Import All GNU Triangulated Surface Files in a Directory", false, directoryRadioButtonGroup );\r
360 openFileButton = new BRadioButton( "Import File", true, directoryRadioButtonGroup );\r
361 directoryGridContainer = new GridContainer( 1, 2 );\r
362 directoryGridContainer.setDefaultLayout( new LayoutInfo( LayoutInfo.WEST, LayoutInfo.NONE, new Insets( 2, 2, 2, 2 ), null ) );\r
363 directoryGridContainer.add( openDirectoryButton, 0, 0 );\r
364 directoryGridContainer.add( openFileButton, 0, 1 );\r
365 gnuSurfaceFilenameTextField = new BTextField( "" );\r
366 String preferencesFilename = "import_gnu_triangulated_surface_preferences.csv";\r
367 \r
368 Widget[] widgets = new Widget[] {       directoryGridContainer };\r
369 String[] widgetStrings = new String[] { "Open File or Directory:" };\r
370 \r
371 // change the user interface parameters from default to preferences\r
372 Vector widgetVector = new Vector();\r
373 RadioButtonGroup[] radioButtonGroups = new RadioButtonGroup[] { directoryRadioButtonGroup };\r
374 preferencesAddRadioButtonGroups( radioButtonGroups, widgetVector );\r
375 preferencesAddWidgetsWithStrings( widgets, widgetStrings, widgetVector );\r
376 preferencesAddWidgetWithString( gnuSurfaceFilenameTextField, "GCode Filename:", widgetVector );\r
377 preferencesRead( preferencesFilename, widgetVector );\r
378 \r
379 dialog = new ComponentsDialog( window, "Import GNU Triangulated Surface File or Directory", widgets, widgetStrings );\r
380 \r
381 if ( !dialog.clickedOk() ) return;\r
382 \r
383 fileChooser = new BFileChooser( BFileChooser.OPEN_FILE, "Import GNU Triangulated Surface File");\r
384 gnuSurfaceFile = new File( gnuSurfaceFilenameTextField.getText() );\r
385 \r
386 if ( gnuSurfaceFile.canRead() ) {\r
387   fileChooser.setSelectedFile( gnuSurfaceFile );\r
388 }\r
389 \r
390 fileChooser.showDialog( window );\r
391 file = fileChooser.getSelectedFile();\r
392 \r
393 if ( file == null ) {\r
394   return;\r
395 }\r
396 \r
397 gnuSurfaceFilenameTextField.setText( file.getAbsolutePath() );\r
398 preferencesWrite( preferencesFilename, widgetVector );\r
399 importFiles();\r