package cz.fidentis.analyst.symmetry; import cz.fidentis.analyst.canvas.Canvas; import cz.fidentis.analyst.core.ControlPanelAction; import cz.fidentis.analyst.visitors.mesh.CrossSection; import org.openide.filesystems.FileChooserBuilder; import javax.swing.JTabbedPane; import javax.swing.JToggleButton; import javax.swing.filechooser.FileNameExtensionFilter; import javax.vecmath.Point3d; import java.awt.event.ActionEvent; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.List; /** * Action listener for the manipulation with the cutting plane. * * @author Dominik Racek */ public class ProfilesAction extends ControlPanelAction { /* * GUI elements */ private final ProfilesPanel controlPanel; private final JTabbedPane topControlPanel; /* * Calculated profiles */ private List<Point3d> primaryPoints; private List<Point3d> secondaryPoints; private List<Point3d> primaryMirrorPoints; private List<Point3d> secondaryMirrorPoints; /** * Constructor. * * @param canvas OpenGL canvas * @param topControlPanel Top component for placing control panels */ public ProfilesAction(Canvas canvas, JTabbedPane topControlPanel) { super(canvas, topControlPanel); this.topControlPanel = topControlPanel; recomputePrimaryProfile(); if (getSecondaryDrawableFace() != null) { recomputeSecondaryProfile(); controlPanel = new ProfilesPanel(this, this.primaryPoints, this.secondaryPoints); controlPanel.setSecondaryMirrorPoints(this.secondaryMirrorPoints); } else { controlPanel = new ProfilesPanel(this, this.primaryPoints); } controlPanel.setPrimaryMirrorPoints(this.primaryMirrorPoints); // Place control panel to the topControlPanel this.topControlPanel.addTab(controlPanel.getName(), controlPanel.getIcon(), controlPanel); this.topControlPanel.addChangeListener(e -> { // If the symmetry panel is focused... if (((JTabbedPane) e.getSource()).getSelectedComponent() instanceof ProfilesPanel) { getCanvas().getScene().setDefaultColors(); if (controlPanel.isShowPlaneChecked()) { getCanvas().getScene().showCuttingPlanes(); } if (controlPanel.isMirrorCutsChecked()) { getCanvas().getScene().showMirrorPlanes(); } } else { getCanvas().getScene().hideCuttingPlanes(); getCanvas().getScene().hideMirrorPlanes(); } }); getCanvas().getScene().hideCuttingPlanes(); getCanvas().getScene().hideMirrorPlanes(); } private void exportProfile(List<Point3d> points, String title) { File file = new FileChooserBuilder(ProfilesAction.class) .setTitle(title) .setDefaultWorkingDirectory(new File(System.getProperty("user.home"))) .setFilesOnly(true) .setFileFilter(new FileNameExtensionFilter("csv files (*.csv)", "csv")) .setAcceptAllFileFilterUsed(true) .showSaveDialog(); if (file == null) { return; } // If chosen file exists, use the exact file path // If chosen file does not exist and does not have an extension, add it if (!file.exists()) { if (!file.getAbsolutePath().endsWith(".csv")) { file = new File(file.getAbsolutePath() + ".csv"); } } try { file.createNewFile(); PrintWriter writer = new PrintWriter(file.getAbsoluteFile(), "UTF-8"); writer.println("N,X-Coordinate,Z-Coordinate"); for (int i = 0; i < points.size(); ++i) { writer.println((i+1) + "," + points.get(i).x + "," + points.get(i).z); } writer.close(); } catch (IOException ex) { System.out.println("ERROR writing to a file: " + ex); } } private void recomputePrimaryProfile() { //Main profile CrossSection cs = new CrossSection(getScene().getDrawableCuttingPlane(0).getFacets().get(0)); getPrimaryDrawableFace().getModel().compute(cs); this.primaryPoints = cs.getPoints(); //Mirror profile CrossSection mcs = new CrossSection(getScene().getDrawableMirrorPlane(0).getFacets().get(0)); getPrimaryDrawableFace().getModel().compute(mcs); this.primaryMirrorPoints = mcs.getPoints(); } private void recomputeSecondaryProfile() { //Main profile CrossSection cs = new CrossSection(getScene().getDrawableCuttingPlane(1).getFacets().get(0)); getSecondaryDrawableFace().getModel().compute(cs); this.secondaryPoints = cs.getPoints(); //Mirror profile CrossSection mcs = new CrossSection(getScene().getDrawableMirrorPlane(1).getFacets().get(0)); getSecondaryDrawableFace().getModel().compute(mcs); this.secondaryMirrorPoints = mcs.getPoints(); } private void recomputeProfiles() { recomputePrimaryProfile(); controlPanel.setPrimaryPoints(this.primaryPoints); controlPanel.setPrimaryMirrorPoints(this.primaryMirrorPoints); if (getSecondaryDrawableFace() != null) { recomputeSecondaryProfile(); controlPanel.setSecondaryPoints(this.secondaryPoints); controlPanel.setSecondaryMirrorPoints(this.secondaryMirrorPoints); } } private void setCuttingPlaneOffset(int index, double value) { for (int i = 0; i < 4; ++i) { getScene().getDrawableCuttingPlane(index).getFacets().get(0).getVertex(i).getPosition().x = value; getScene().getDrawableMirrorPlane(index).getFacets().get(0).getVertex(i).getPosition().x = value * -1.0; } } @Override public void actionPerformed(ActionEvent ae) { String action = ae.getActionCommand(); switch (action) { case ProfilesPanel.ACTION_COMMAND_SHOW_HIDE_PLANE: if (((JToggleButton) ae.getSource()).isSelected()) { getScene().showCuttingPlanes(); } else { getScene().hideCuttingPlanes(); } break; case ProfilesPanel.ACTION_COMMAND_EXPORT: exportProfile(this.primaryPoints, "Export primary face profile to file"); if (getSecondaryDrawableFace() != null) { exportProfile(this.secondaryPoints, "Export secondary face profile to file"); } break; case ProfilesPanel.ACTION_OFFSET_CUTTING_PLANE: double value = controlPanel.getOffsetValue(); double multiplier = 150; setCuttingPlaneOffset(0, multiplier * (value - 0.5)); if (getSecondaryDrawableFace() != null) { setCuttingPlaneOffset(1, multiplier * (value - 0.5)); } recomputeProfiles(); break; case ProfilesPanel.ACTION_COMMAND_RECOMPUTE: recomputeProfiles(); break; case ProfilesPanel.ACTION_ALIGN_PROFILES: controlPanel.setAlignProfiles(); break; case ProfilesPanel.ACTION_MIRROR_CUTS: controlPanel.setMirrorCuts(); if (controlPanel.isMirrorCutsChecked()) { getCanvas().getScene().showMirrorPlanes(); } else { getCanvas().getScene().hideMirrorPlanes(); } break; default: // do nothing } renderScene(); } }