summaryrefslogtreecommitdiffstats
path: root/src/demos/nurbs/curveapp
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2009-06-15 23:12:27 +0000
committerKenneth Russel <[email protected]>2009-06-15 23:12:27 +0000
commit41cd6c47b23975098cd155517790e018670785e7 (patch)
tree247333528ad674d427ba96b1e05810f7961d609e /src/demos/nurbs/curveapp
parent935d2596c13371bb745d921dbcb9f05b0c11a010 (diff)
Copied JOGL_2_SANDBOX r350 on to trunk; JOGL_2_SANDBOX branch is now closed
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/jogl-demos/trunk@352 3298f667-5e0e-4b4a-8ed4-a3559d26a5f4
Diffstat (limited to 'src/demos/nurbs/curveapp')
-rwxr-xr-xsrc/demos/nurbs/curveapp/ActListener.java114
-rwxr-xr-xsrc/demos/nurbs/curveapp/Curve.java313
-rwxr-xr-xsrc/demos/nurbs/curveapp/CurveApp.java659
-rwxr-xr-xsrc/demos/nurbs/curveapp/CurveMouseListener.java180
-rwxr-xr-xsrc/demos/nurbs/curveapp/GLListener.java148
-rwxr-xr-xsrc/demos/nurbs/curveapp/MyFloat.java55
-rwxr-xr-xsrc/demos/nurbs/curveapp/SpinnerListener.java47
7 files changed, 1516 insertions, 0 deletions
diff --git a/src/demos/nurbs/curveapp/ActListener.java b/src/demos/nurbs/curveapp/ActListener.java
new file mode 100755
index 0000000..52e89b8
--- /dev/null
+++ b/src/demos/nurbs/curveapp/ActListener.java
@@ -0,0 +1,114 @@
+package demos.nurbs.curveapp;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.ImageIcon;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+
+import demos.nurbs.icons.*;
+
+/**
+ * Class reacting to events from toolbar and menu
+ * Třída reagující na události z nástrojové lišty a menu
+ * @author Tomáš Hráský
+ *
+ */
+@SuppressWarnings("serial")
+public class ActListener extends AbstractAction
+{
+
+ /**
+ * Parent window
+ * Odkaz na rodičovské okno
+ */
+ private CurveApp app;
+ /**
+ * File chooser object
+ * Objekt pro výběr souboru
+ */
+ private JFileChooser fc;
+
+ /**
+ * Creates instance of object with pointer to parent window
+ * Vytvoří instanci objektu s odkazem na rodičovské okno
+ * @param app parent window
+ */
+ public ActListener(CurveApp app) {
+ this.app=app;
+ fc=new JFileChooser("./");
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+ */
+ public void actionPerformed(ActionEvent e) {
+
+
+ if(e.getActionCommand()==CurveApp.PRIDAT_AC){
+
+ }else if(e.getActionCommand()==CurveApp.SMAZAT_AC){
+
+ }else if(e.getActionCommand()==CurveApp.UZAVRENY_AC){
+ app.uzavernyKV();
+ }else if(e.getActionCommand()==CurveApp.OTEVRENY_AC){
+ app.otevrenyKV();
+ }else if(e.getActionCommand()==CurveApp.ULOZIT_AC){
+ if(fc.showSaveDialog(app)==JFileChooser.APPROVE_OPTION){
+ Curve.getInstance().persist(fc.getSelectedFile());
+ }
+ }else if(e.getActionCommand()==CurveApp.NACIST_AC){
+ if(fc.showOpenDialog(app)==JFileChooser.APPROVE_OPTION){
+ try {
+ Curve.getInstance().unPersist(fc.getSelectedFile());
+ app.updateGLCanvas();
+ app.selectMoveButt();
+ app.updateJKnotSlider();
+ } catch (Exception e1) {
+ //JOptionPane.showMessageDialog(app,"Chyba při načítání ze souboru","Chyba",JOptionPane.ERROR_MESSAGE);
+ JOptionPane.showMessageDialog(app,"Error loading file","Error",JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }else if(e.getActionCommand()==CurveApp.NOVA_AC){
+ Curve.getInstance().clear();
+ app.getMouseListener().setBodIndex(-1);
+ Curve.getInstance().setBodIndex(-1);
+ app.updateGLCanvas();
+ app.updateJKnotSlider();
+ }else if(e.getActionCommand()==CurveApp.EXIT_AC){
+ //TODO exit confirmation ?
+ System.exit(0);
+ }else if(e.getActionCommand()==CurveApp.STUPEN_AC){
+ try{
+ //String retval = JOptionPane.showInputDialog(null,"Zadejte stupeň křivky",new Integer(Curve.getInstance().getOrder()));
+ String retval = JOptionPane.showInputDialog(null,"Curve degree",new Integer(Curve.getInstance().getOrder()));
+ if(retval!=null){
+ int stupen=(new Integer(retval)).intValue();
+ Curve.getInstance().setOrder(stupen);
+ Curve.getInstance().setIsCurveFinished(false);
+ }
+ }catch (NumberFormatException ex){
+ //JOptionPane.showMessageDialog(null,"Chybný formát přirozeného čísla","Chyba!",JOptionPane.ERROR_MESSAGE);
+ JOptionPane.showMessageDialog(null,"Wrong natural number format","Error!",JOptionPane.ERROR_MESSAGE);
+ }
+ }else if(e.getActionCommand()==CurveApp.INFO_AC){
+ /*
+ JOptionPane.showMessageDialog(null,"Ukázková aplikace rozšířené funkcionality knihovny JOGL\n" +
+ "Autor: Tomáš Hráský\n" +
+ "Součást bakalářské práce na téma Softwarová implementace NURBS křivek a ploch\n" +
+ "2007 Fakulta Informatiky a Managementu UHK\n" +
+ "Pro serializaci objektů využívá open source framework Simple XML - http://simple.sourceforge.net/","O aplikaci",JOptionPane.INFORMATION_MESSAGE,IconFactory.getIcon("demos/nurbs/icons/info.png"));
+ */
+ JOptionPane.showMessageDialog(null,"Example aplication of extended functionality JOGL library\n" +
+ "Author: Tomáš Hráský\n" +
+ "Part of bachelor's degree thesis Software implementation of NURBS curves and surfaces\n" +
+ "2007 Faculty of Informatics and Management University of Hradec Králové\n" +
+ "Simple XML framework is used for object serialization - http://simple.sourceforge.net/","About",JOptionPane.INFORMATION_MESSAGE,IconFactory.getIcon("demos/nurbs/icons/info.png"));
+ }
+
+ app.getMouseListener().setActionType(e.getActionCommand());
+
+
+ }
+}
diff --git a/src/demos/nurbs/curveapp/Curve.java b/src/demos/nurbs/curveapp/Curve.java
new file mode 100755
index 0000000..b772973
--- /dev/null
+++ b/src/demos/nurbs/curveapp/Curve.java
@@ -0,0 +1,313 @@
+package demos.nurbs.curveapp;
+
+import java.io.File;
+import java.util.Vector;
+
+import simple.xml.Element;
+import simple.xml.ElementList;
+import simple.xml.Root;
+import simple.xml.Serializer;
+import simple.xml.load.Persister;
+
+/**
+ * Třída definice NURBS křivky, vystavěna podle návrhového vzoru Singleton
+ * @author Tomáš Hráský
+ *
+ */
+@Root(name="curve")
+public class Curve
+{
+ /**
+ * Odkaz na instanci třídy
+ */
+ private static Curve singleton;
+ /**
+ * Indikuje, zda je zadání křivky kompletní
+ */
+ @Element(name="finished")
+ private boolean isCurveFinished;
+
+ /**
+ * Index aktuálního vybraného řídícího bodu
+ */
+ private int bodIndex = -1;
+
+ /**
+ * Stupeň křivky
+ */
+ @Element(name="order")
+ private int order=3;
+
+ /**
+ * Pole souřadnic řídícíh bodů
+ *
+ */
+ private float[] ctrlPoints;
+
+ /**
+ * Pole hodnot uzlového vektoru
+ */
+ private float knots[];
+
+ /**
+ * Kolekce vektor pro persistenci souřadnic řídících bodů
+ */
+ @ElementList(name="ctrlpoints",type=MyFloat.class)
+ private Vector<MyFloat> ctrlVector;
+
+ /**
+ * Kolekce vektor pro persistenci uzlového vektoru
+ */
+ @ElementList(name="knots",type=MyFloat.class)
+ private Vector<MyFloat> knotVector;
+
+ /**
+ * Vytvoří prázdnou definici křivky
+ */
+ public void clear(){
+ isCurveFinished=false;
+ ctrlPoints=new float[0];
+ knots=new float[0];
+ order=3;
+ }
+
+ /**
+ * Pomocí framweorku Simple serializuje definici křivky do XML souboru
+ * @param f soubor pro uložení
+ */
+ public void persist(File f){
+ ctrlVector=new Vector<MyFloat>(ctrlPoints.length);
+ knotVector=new Vector<MyFloat>(knots.length);
+
+ for(Float ff:ctrlPoints)
+ ctrlVector.add(new MyFloat(ff));
+
+ for(Float ff:knots)
+ knotVector.add(new MyFloat(ff));
+
+ Serializer s=new Persister();
+ try {
+ System.out.println("ukládám");
+ s.write(Curve.getInstance(),f);
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+
+
+ }
+
+ /**
+ * Vytvoří pomocí frameworku Simple křivku z definice uložené v XML souboru
+ * @param f soubor,z něhož se má definice načíst
+ * @throws Exception chyba při čtení ze souboru
+ */
+ public void unPersist(File f) throws Exception{
+ Serializer s=new Persister();
+ Curve c=s.read(Curve.class,f);
+ initFromCurve(c);
+ }
+
+ /**
+ * Inicializuje objekt podle jiného objektu typu Curve
+ * @param c referenční objekt - křivka
+ */
+ private void initFromCurve(Curve c) {
+ this.order=c.getOrder();
+ this.ctrlPoints=new float[c.getCtrlVector().size()];
+ this.knots=new float[c.getKnotVector().size()];
+ int i=0;
+ for(MyFloat f:c.getCtrlVector())
+ ctrlPoints[i++]=f.getValue();
+ i=0;
+ for(MyFloat f:c.getKnotVector())
+ knots[i++]=f.getValue();
+
+ this.isCurveFinished=c.isCurveFinished();
+ }
+
+ /**
+ * Konstruktor, nastaví prázdné hodnoty polí definujících NURBS křivku
+ */
+ private Curve(){
+ ctrlPoints=new float[0];
+ knots=new float[0];
+ isCurveFinished=false;
+ }
+
+ /**
+ * Vrací instanci třídy (podle návrhového vzoru Singleton)
+ * @return instance třídy Curve
+ */
+ public static Curve getInstance() {
+ if (singleton == null)
+ singleton = new Curve();
+ return singleton;
+
+ }
+
+ /**
+ * Vrací pole uzlového vektoru
+ * @return pole hodnot uzlového vektoru
+ */
+ public float[] getKnots() {
+ return this.knots;
+ }
+
+ /**
+ * Vrací pole s hodnotami souřadnic řídících bodů
+ * @return pole souřadnic řídících bodů
+ */
+ public float[] getCtrlPoints() {
+ return this.ctrlPoints;
+ }
+
+ /**
+ * Vrací stupeň NURBS křivky
+ * @return stupeň NURBS křivky
+ */
+ public int getOrder() {
+ return this.order;
+ }
+
+ /**
+ * Vrací index aktuálně vybraného řídícího bodu
+ * @return index aktuálně vybraného řídícího bodu
+ */
+ public int getBodIndex() {
+ return bodIndex;
+ }
+
+ /**
+ * Nastavuje index požadovaného aktuálně vybraného řídícího bodu
+ * @param bodIndex index požadovaného aktuálně vybraného řídícího bodu
+ */
+ public void setBodIndex(int bodIndex) {
+ this.bodIndex = bodIndex;
+ }
+
+ /**
+ * Vrací X-ovou souadnici aktuálně vybraného řídícího bodu, přepočítává hodnotu z homogenních souřadnic
+ * @return X-ová souadnice aktuálně vybraného řídícího bodu
+ */
+ public float getActiveX(){
+ if(bodIndex>=0){
+ return ctrlPoints[bodIndex*4]/ctrlPoints[bodIndex*4+3];
+ }
+ else return 0;
+ }
+ /**
+ * Vrací Y-ovou souadnici aktuálně vybraného řídícího bodu, přepočítává hodnotu z homogenních souřadnic
+ * @return Y-ová souadnice aktuálně vybraného řídícího bodu
+ */
+ public float getActiveY(){
+ if(bodIndex>=0){
+ return ctrlPoints[bodIndex*4+1]/ctrlPoints[bodIndex*4+3];
+ }
+ else return 0;
+ }
+
+ /**
+ * Vrací váhu aktuálně vybraného řídícího bodu
+ * @return váha aktuálně vybraného řídícího bodu
+ */
+ public float getActiveW(){
+ if(bodIndex>=0){
+ return ctrlPoints[bodIndex*4+3];
+ }
+ else return 0;
+ }
+
+ /**
+ * Nastavuje X-ovou souadnici aktuálně vybraného řídícího bodu, přepočítává hodnotu do homogenních souřadnic
+ * @param x X-ová souřadnice aktuálně vybraného řídícího bodu
+ */
+ public void setActiveX(float x){
+ if(bodIndex>=0){
+ ctrlPoints[bodIndex*4]=x*ctrlPoints[bodIndex*4+3];
+ }
+ }
+ /**
+ * Nastavuje Y-ovou souadnici aktuálně vybraného řídícího bodu, přepočítává hodnotu do homogenních souřadnic
+ * @param y Y-ová souřadnice aktuálně vybraného řídícího bodu
+ */
+
+ public void setActiveY(float y){
+ if(bodIndex>=0){
+ ctrlPoints[bodIndex*4+1]=y*ctrlPoints[bodIndex*4+3];
+ }
+ }
+
+ /**
+ *Nastavuje váhu aktuálně vybraného řídícího bodu, upravuje hodnoty stávajícíh souřadic vzhledem k váze a použití homogenních souřadnic
+ * @param w váha aktuálně vybraného řídícího bodu
+ */
+ public void setActiveW(float w){
+ if(bodIndex>=0){
+ float oldW=ctrlPoints[bodIndex*4+3];
+ if(w>0){
+ ctrlPoints[bodIndex*4+3]=w;
+ //úprava souřadnic
+ ctrlPoints[bodIndex*4]=ctrlPoints[bodIndex*4]/oldW*w;
+ ctrlPoints[bodIndex*4+1]=ctrlPoints[bodIndex*4+1]/oldW*w;
+ }
+
+ }
+ }
+
+ /**
+ * Nastavuje uzlový vektor
+ * @param knots nový uzlový vektor
+ */
+ public void setKnots(float[] knots) {
+ this.knots = knots;
+ }
+
+ /**
+ * Vrací informaci o stavu dokončení definice křvky
+ * @return true pokud je definice křivky kompletní, jinak false
+ */
+ public boolean isCurveFinished() {
+ return isCurveFinished;
+ }
+
+ /**
+ * Nastavuje řídící body
+ * @param ctrlPoints pole souřadnic řídících bodů
+ */
+ public void setCtrlPoints(float[] ctrlPoints) {
+ this.ctrlPoints = ctrlPoints;
+ }
+
+ /**
+ * Nastavuje stav dokončení definice křivky
+ * @param b stav dokončení definice křivky
+ *
+ */
+ public void setIsCurveFinished(boolean b) {
+ isCurveFinished=b;
+ }
+
+ /**
+ * Vrací vektor souřadnic řídích bodů pro serializaci
+ * @return vektor souřadnic řídících bodů
+ */
+ private Vector<MyFloat> getCtrlVector() {
+ return ctrlVector;
+ }
+
+ /**
+ * Vrací vektor prvků uzlového vektoru pro serializaci
+ * @return vektor prvků uzlového vektoru
+ */
+ private Vector<MyFloat> getKnotVector() {
+ return knotVector;
+ }
+
+ /**
+ * Nastaví stupeň křivky
+ * @param order požadovaný stupeň
+ */
+ public void setOrder(int order) {
+ this.order = order;
+ }
+}
diff --git a/src/demos/nurbs/curveapp/CurveApp.java b/src/demos/nurbs/curveapp/CurveApp.java
new file mode 100755
index 0000000..ff70f68
--- /dev/null
+++ b/src/demos/nurbs/curveapp/CurveApp.java
@@ -0,0 +1,659 @@
+package demos.nurbs.curveapp;
+
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.media.opengl.GLCanvas;
+import javax.swing.ButtonGroup;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JSeparator;
+import javax.swing.JSpinner;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.ToolTipManager;
+
+import demos.nurbs.icons.*;
+import demos.nurbs.knotslidercomponent.JKnotSlider;
+
+/**
+ * Main class of application demostrating capabilities of JOGL when working with NURBS curves
+ * Hlavní třída aplikace demonstrující shopnosti knihovny JOGL při práci s NURBS křivkami
+ * @author Tomáš Hráský
+ *
+ */
+@SuppressWarnings("serial")
+public class CurveApp extends JFrame implements ActionListener
+{
+
+ /**
+ * Name of X-coord editing component of actually selected control point
+ * Jméno komponenty pro editaci X-ové souřadnice aktuálního bodu
+ */
+ public static final String X_SPINNER_NAME = "xspinner";
+ /**
+ * Name of Y-coord editing component of actually selected control point
+ * Jméno komponenty pro editaci Y-ové souřadnice aktuálního bodu
+ */
+ public static final String Y_SPINNER_NAME = "yspinner";
+ /**
+ * Name of weight editing component of actually selected control point
+ * Jméno komponenty pro editaci váhy aktuálního bodu
+ */
+ public static final String W_SPINNER_NAME = "wspinner";
+
+ /**
+ * Name of ADD CONTROL POINT event
+ * Jméno události přidání řídícího bodu
+ */
+ public static final String PRIDAT_AC = "PRIDAT";
+
+ /**
+ * Name of SET CURVE DEGREE event
+ * Jméno události zadání stupně křivky
+ */
+ public static final String STUPEN_AC="STUPEN";
+ /**
+ * Name of DELETE CONTROL POINT event
+ * Jméno události smazání řídícího bodu
+ */
+ public static final String SMAZAT_AC = "SMAZAT";
+ /**
+ * Name of MAKE CLOSED KNOTVECTOR event
+ * Jméno události vytvoření uzavřeného uzlového vektoru
+ */
+ public static final String UZAVRENY_AC = "UZAVRENY";
+ /**
+ * Name of MAKE OPEN (UNIFORM) KNOTVECTOR event
+ * Jméno události vytvoření otevřeného (uniformního) uzlového vektoru
+ */
+ public static final String OTEVRENY_AC = "OTEVRENY";
+ /**
+ * Name of SAVE CURVE event
+ * Jméno události uložení křivky
+ */
+ public static final String ULOZIT_AC = "ULOZIT";
+ /**
+ * Name of LOAD CURVE event
+ * Jméno události načetení uložené definice křivky
+ */
+ public static final String NACIST_AC = "NACIST";
+ /**
+ * Name of MOVE CONTROL POINT event
+ * Jméno události pohybu řídícího bodu
+ */
+ private static final String MOVE_AC = "MOVE";
+
+ /**
+ * Name of CREATE NEW CURVE event
+ * Jméno události vytvoření nové křivky
+ */
+ static final String NOVA_AC = "NEWCURVE";
+
+ /**
+ * Name of EXIT APP event
+ * Jméno události ukončení aplikace
+ */
+ public static final String EXIT_AC = "EXIT";
+ /**
+ * Name of SHOW ABOUT event
+ * Jméno události zobrazení okna o aplikaci
+ */
+ public static final String INFO_AC = "INFO";
+
+ /**
+ * OpenGL canvas
+ * Plátno pro vykreslování pomocí OpenGL
+ */
+ private GLCanvas glCanvas;
+
+ /**
+ * X-coord editing component
+ * Komponenta pro editaci X-ové souřadnice aktuálního bodu
+ */
+ private JSpinner xSpinner;
+ /**
+ * Y-coord editing component
+ * Komponenta pro editaci Y-ové souřadnice aktuálního bodu
+ */
+ private JSpinner ySpinner;
+ /**
+ * Weight editing component
+ * Komponenta pro editaci váhy aktuálního bodu
+ */
+ private JSpinner wSpinner;
+
+ /**
+ * Mouse events listener
+ * Listener událostí myši
+ */
+ private CurveMouseListener mouseListener;
+
+ /**
+ * Knot vector editing component
+ * Komponenta pro editaci uzlového vektoru
+ */
+ private JKnotSlider knotSlider;
+
+ /**
+ * Start "move control point" mode
+ * Tlačítko pro zapnutí módu pohybu řídících bodů
+ */
+ private JToggleButton moveTB;
+
+ /**
+ * Constructor, initializes GUI
+ * Konstruktor, vytvoří grafické uživatelské rozhraní
+ */
+ public CurveApp() {
+ super("Tomáš Hráský - example application demonstrating GLU NURBS capabilites - JOGL");
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ initGUI();
+ }
+
+ /**
+ * GUI initialization
+ * Inicializace grafického uživatelského rozhraní
+ */
+ private void initGUI() {
+ JPopupMenu.setDefaultLightWeightPopupEnabled(false);
+ ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
+
+ this.glCanvas = new GLCanvas();
+ glCanvas.setSize(new Dimension(750, 500));
+ glCanvas.addGLEventListener(new GLListener());
+ mouseListener = new CurveMouseListener(this);
+ glCanvas.addMouseListener(mouseListener);
+ glCanvas.addMouseMotionListener(mouseListener);
+ setLayout(new GridBagLayout());
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = GridBagConstraints.BOTH;
+
+ c.gridy = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+
+ ActListener listener = new ActListener(this);
+
+ JMenuBar menuBar = new JMenuBar();
+ getContentPane().add(menuBar, c);
+
+ //JMenu aplikaceMenu = new JMenu("Aplikace");
+ JMenu aplikaceMenu = new JMenu("Application");
+ menuBar.add(aplikaceMenu);
+
+ //JMenuItem aboutMI=new JMenuItem("O aplikaci");
+ JMenuItem aboutMI=new JMenuItem("About");
+ aboutMI.setActionCommand(INFO_AC);
+ aboutMI.addActionListener(listener);
+ aplikaceMenu.add(aboutMI);
+
+ aplikaceMenu.add(new JSeparator());
+
+ //JMenuItem konecMI=new JMenuItem("Ukončit");
+ JMenuItem konecMI=new JMenuItem("Exit");
+ konecMI.addActionListener(listener);
+ konecMI.setActionCommand(EXIT_AC);
+ aplikaceMenu.add(konecMI);
+
+ //JMenu krivkaMenu = new JMenu("Křivka");
+ JMenu krivkaMenu = new JMenu("Curve");
+ menuBar.add(krivkaMenu);
+
+ //JMenuItem pridatBodyMI = new JMenuItem("Přidat body");
+ JMenuItem pridatBodyMI = new JMenuItem("Add control points");
+ krivkaMenu.add(pridatBodyMI);
+ pridatBodyMI.addActionListener(listener);
+
+
+ pridatBodyMI.setActionCommand(PRIDAT_AC);
+ JMenuItem smazatBodyMI = new JMenuItem(
+ //"Smazat body");
+ "Delete points");
+ krivkaMenu.add(smazatBodyMI);
+ smazatBodyMI.addActionListener(listener);
+
+ smazatBodyMI.setActionCommand(SMAZAT_AC);
+
+ //JMenuItem stupenMI=new JMenuItem("Zadat stupeň křivky");
+ JMenuItem stupenMI=new JMenuItem("Set curve degree");
+ krivkaMenu.add(stupenMI);
+ stupenMI.addActionListener(listener);
+ stupenMI.setActionCommand(STUPEN_AC);
+
+ //JMenu knotVecMenu = new JMenu("Vytvořit uzlový vektor");
+ JMenu knotVecMenu = new JMenu("Create knot vector");
+ krivkaMenu.add(knotVecMenu);
+
+ //JMenuItem clampedKVMI = new JMenuItem("Okrajový");
+ JMenuItem clampedKVMI = new JMenuItem("Clamped");
+ knotVecMenu.add(clampedKVMI);
+ clampedKVMI.setActionCommand(UZAVRENY_AC);
+ clampedKVMI.addActionListener(listener);
+ //JMenuItem unclampedKVMI = new JMenuItem("Uniformní");
+ JMenuItem unclampedKVMI = new JMenuItem("Uniform");
+ knotVecMenu.add(unclampedKVMI);
+ unclampedKVMI.setActionCommand(OTEVRENY_AC);
+ unclampedKVMI.addActionListener(listener);
+
+ //JMenuItem moveMI=new JMenuItem("Hýbat body");
+ JMenuItem moveMI=new JMenuItem("Move points");
+ krivkaMenu.add(moveMI);
+ moveMI.setActionCommand(MOVE_AC);
+ moveMI.addActionListener(listener);
+
+ krivkaMenu.add(new JSeparator());
+
+ krivkaMenu.add(new JSeparator());
+
+ //JMenuItem novaMI=new JMenuItem("Nová křivka");
+ JMenuItem novaMI=new JMenuItem("New curve");
+ krivkaMenu.add(novaMI);
+ novaMI.setActionCommand(NOVA_AC);
+ novaMI.addActionListener(listener);
+
+ //JMenuItem ulozitMI = new JMenuItem("Uložit křivku jako...");
+ JMenuItem ulozitMI = new JMenuItem("Save curve as...");
+ krivkaMenu.add(ulozitMI);
+ ulozitMI.setActionCommand(ULOZIT_AC);
+ ulozitMI.addActionListener(listener);
+ //JMenuItem nacistMI = new JMenuItem("Načíst křivku");
+ JMenuItem nacistMI = new JMenuItem("Load curve");
+ krivkaMenu.add(nacistMI);
+ nacistMI.setActionCommand(NACIST_AC);
+ nacistMI.addActionListener(listener);
+
+ c.gridy++;
+ JToolBar toolBar = new JToolBar();
+ getContentPane().add(toolBar, c);
+
+ ButtonGroup bg = new ButtonGroup();
+
+
+ JButton novaB=new JButton();
+ // novaB.setText("Nová");
+ //novaB.setToolTipText("Nová křivka");
+ novaB.setToolTipText("New curve");
+ novaB.setIcon(IconFactory.getIcon("demos/nurbs/icons/folder_new.png"));
+ novaB.setActionCommand(NOVA_AC);
+ novaB.addActionListener(listener);
+ toolBar.add(novaB);
+
+ JButton ulozitB=new JButton();
+ ulozitB.setIcon(IconFactory.getIcon("demos/nurbs/icons/adept_sourceseditor.png"));
+ // ulozitB.setText("Uložit");
+ //ulozitB.setToolTipText("Uložit");
+ ulozitB.setToolTipText("Save");
+ ulozitB.setActionCommand(ULOZIT_AC);
+ ulozitB.addActionListener(listener);
+ toolBar.add(ulozitB);
+
+ JButton nahratB=new JButton();
+ // nahratB.setText("Nahrát");
+ //nahratB.setToolTipText("Nahrát uloženou křivku");
+ nahratB.setToolTipText("Load curve");
+ nahratB.setIcon(IconFactory.getIcon("demos/nurbs/icons/fileimport.png"));
+ nahratB.setActionCommand(NACIST_AC);
+ nahratB.addActionListener(listener);
+ toolBar.add(nahratB);
+
+ toolBar.add(new JToolBar.Separator());
+
+ JToggleButton pridatTB = new JToggleButton();
+ // pridatTB.setText("Přidat body");
+ //pridatTB.setToolTipText("Přidat body");
+ pridatTB.setToolTipText("Add points");
+ toolBar.add(pridatTB);
+ pridatTB.setIcon(IconFactory.getIcon("demos/nurbs/icons/add.png"));
+ pridatTB.setActionCommand(PRIDAT_AC);
+ pridatTB.addActionListener(listener);
+ bg.add(pridatTB);
+ JToggleButton smazatTB = new JToggleButton();
+ // smazatTB.setText("Smazat body");
+ //smazatTB.setToolTipText("Smazat body");
+ smazatTB.setToolTipText("Delete points");
+ toolBar.add(smazatTB);
+ smazatTB.setIcon(IconFactory.getIcon("demos/nurbs/icons/fileclose.png"));
+ smazatTB.setActionCommand(SMAZAT_AC);
+ smazatTB.addActionListener(listener);
+ bg.add(smazatTB);
+
+ JToggleButton stupenTB = new JToggleButton();
+ // stupenTB.setText("Smazat body");
+ //stupenTB.setToolTipText("Zadat stupeň křivky");
+ stupenTB.setToolTipText("Set curve degree");
+ toolBar.add(stupenTB);
+ stupenTB.setIcon(IconFactory.getIcon("demos/nurbs/icons/math_rsup.png"));
+ stupenTB.setActionCommand(STUPEN_AC);
+ stupenTB.addActionListener(listener);
+ bg.add(stupenTB);
+
+
+ final JPopupMenu popup = new JPopupMenu();
+
+ //JMenuItem uzavrenyPopupMI = new JMenuItem("Okrajový");
+ JMenuItem uzavrenyPopupMI = new JMenuItem("Clamped");
+ popup.add(uzavrenyPopupMI);
+ uzavrenyPopupMI.setActionCommand(UZAVRENY_AC);
+ uzavrenyPopupMI.addActionListener(listener);
+ //JMenuItem otevrenyPopupMI = new JMenuItem("Uniformní");
+ JMenuItem otevrenyPopupMI = new JMenuItem("Uniform");
+ popup.add(otevrenyPopupMI);
+ otevrenyPopupMI.setActionCommand(OTEVRENY_AC);
+ otevrenyPopupMI.addActionListener(listener);
+
+ JToggleButton vytvoritButton = new JToggleButton();
+ // vytvoritButton.setText("Vytvořit uzlový vektor");
+ //vytvoritButton.setToolTipText("Vytvořit uzlový vektor");
+ vytvoritButton.setToolTipText("Create knot vector");
+ vytvoritButton.setIcon(IconFactory.getIcon("demos/nurbs/icons/newfunction.png"));
+ bg.add(vytvoritButton);
+
+ vytvoritButton.addMouseListener(new
+ /**
+ * @author Tomáš Hráský
+ * Class connecting context menu to button on toolbar
+ * Třída pro připojení kontextového menu na tlačítko na liště nástrojů
+ */
+ MouseAdapter() {
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ super.mouseClicked(e);
+ e.isPopupTrigger();
+ popup.show(e.getComponent(), e.getX(), e.getY());
+ }
+
+ });
+ popup.setInvoker(vytvoritButton);
+ toolBar.add(vytvoritButton);
+
+ moveTB=new JToggleButton();
+ // moveTB.setText("Hýbat body");
+ //moveTB.setToolTipText("Hýbat body");
+ moveTB.setToolTipText("Move points");
+ moveTB.setIcon(IconFactory.getIcon("demos/nurbs/icons/mouse.png"));
+ toolBar.add(moveTB);
+ moveTB.setActionCommand(MOVE_AC);
+ moveTB.addActionListener(listener);
+ bg.add(moveTB);
+ toolBar.add(new JToolBar.Separator());
+ JButton infoB=new JButton();
+ // infoB.setText("Ukončit");
+ //infoB.setToolTipText("O aplikaci");
+ infoB.setToolTipText("About");
+
+ infoB.setIcon(IconFactory.getIcon("demos/nurbs/icons/info.png"));
+ toolBar.add(infoB);
+ infoB.setActionCommand(INFO_AC);
+ infoB.addActionListener(listener);
+ toolBar.add(new JToolBar.Separator());
+
+ JButton exitB=new JButton();
+ // exitB.setText("Ukončit");
+ //exitB.setToolTipText("Ukončit");
+ exitB.setToolTipText("Exit");
+
+ exitB.setIcon(IconFactory.getIcon("demos/nurbs/icons/exit.png"));
+ toolBar.add(exitB);
+ exitB.setActionCommand(EXIT_AC);
+ exitB.addActionListener(listener);
+
+ c.gridwidth = 1;
+
+ c.gridx = 0;
+ c.gridy = 2;
+
+ c.weightx = 1;
+ c.weighty = 1;
+
+ getContentPane().add(glCanvas, c);
+ c.gridx = 1;
+ JPanel rightPanel = new JPanel(new GridBagLayout());
+ GridBagConstraints cc = new GridBagConstraints();
+ cc.insets = new Insets(5, 5, 5, 5);
+ xSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10000.0, 1));
+ ySpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10000.0, 1));
+ wSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10000.0, .05));
+
+ SpinnerListener spinnerListener = new SpinnerListener(this);
+ xSpinner.addChangeListener(spinnerListener);
+ xSpinner.setName(X_SPINNER_NAME);
+ ySpinner.addChangeListener(spinnerListener);
+ ySpinner.setName(Y_SPINNER_NAME);
+ wSpinner.addChangeListener(spinnerListener);
+ wSpinner.setName(W_SPINNER_NAME);
+
+ cc.gridx = 0;
+ cc.gridy = 0;
+
+ cc.gridwidth = 2;
+ cc.weighty = 1;
+ rightPanel.add(new JPanel(), cc);
+ cc.weighty = 0;
+ cc.gridwidth = 1;
+
+ cc.gridy++;
+ rightPanel.add(new JLabel("X"), cc);
+ cc.gridy++;
+ rightPanel.add(new JLabel("Y"), cc);
+ cc.gridy++;
+ rightPanel.add(new JLabel("W"), cc);
+
+ cc.gridx = 1;
+ cc.gridy = 1;
+ rightPanel.add(xSpinner, cc);
+ cc.gridy++;
+ rightPanel.add(ySpinner, cc);
+ cc.gridy++;
+ rightPanel.add(wSpinner, cc);
+
+ xSpinner.setEnabled(false);
+ ySpinner.setEnabled(false);
+ wSpinner.setEnabled(false);
+
+ c.weightx = 0;
+ c.weighty = 0;
+ getContentPane().add(rightPanel, c);
+
+ c.gridx = 0;
+ c.gridy++;
+
+ knotSlider = new JKnotSlider(Curve.getInstance().getKnots());
+ knotSlider.addActionListener(this);
+ getContentPane().add(knotSlider, c);
+
+ pack();
+ invalidate();
+ setVisible(true);
+ }
+
+ /**
+ * Main method starting application
+ * Metoda pro spuštění aplikace
+ * @param args no arguments accepted
+ *
+ */
+ public static void main(String[] args) {
+ new CurveApp();
+
+ }
+
+ /**
+ * Reaction to request for redrive OpenGL canvas - repaints canvas, sets actually selected control points coords to editing components
+ * Reakce na požadavek překreslení OpenGL plátna, překreslí plátno a nastaví souřadnice aktuálního vybraného bodu do editačních komponent
+ */
+ public void updateGLCanvas() {
+ glCanvas.repaint();
+ if (Curve.getInstance().getBodIndex() >= 0) {
+ xSpinner.setEnabled(true);
+ ySpinner.setEnabled(true);
+ wSpinner.setEnabled(true);
+
+ xSpinner.setValue(Double.valueOf(Math.round(Curve.getInstance()
+ .getActiveX())));
+ ySpinner.setValue(Double.valueOf(Math.round(Curve.getInstance()
+ .getActiveY())));
+ wSpinner.setValue(Double.valueOf(Curve.getInstance().getActiveW()));
+ } else {
+ xSpinner.setEnabled(false);
+ ySpinner.setEnabled(false);
+ wSpinner.setEnabled(false);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+ */
+ public void actionPerformed(ActionEvent e) {
+ JKnotSlider src = (JKnotSlider) e.getSource();
+ if(src.checkKnotMulti(Curve.getInstance().getOrder())){
+ Curve.getInstance().setKnots(src.getKnotsFloat());
+ }else{
+ //JOptionPane.showMessageDialog(this,"Překročení maximální násobnosti uzlu","Chyba",JOptionPane.ERROR_MESSAGE);
+ JOptionPane.showMessageDialog(this,"Maximum knot multiplicity exceeded","Error",JOptionPane.ERROR_MESSAGE);
+ src.setKnots(Curve.getInstance().getKnots());
+ }
+ updateGLCanvas();
+ }
+
+ /**
+ * Returns OpenGL canvas
+ * Vrací OpenGL plátno
+ * @return OpenGL canvas
+ */
+ public GLCanvas getGlCanvas() {
+ return glCanvas;
+ }
+
+ /**
+ * Returns mouse events listener
+ * Vrací listener událostí myši
+ * @return mouse listener
+ */
+ public CurveMouseListener getMouseListener() {
+ return mouseListener;
+ }
+
+ /**
+ * Creates NURBS curve with clamped knot vector
+ * Vytvoří NURBS křivku s okrajovým uzlovým vektorem
+ */
+ public void uzavernyKV() {
+ int stupen = Curve.getInstance().getOrder();
+ int pocetBodu = Curve.getInstance().getCtrlPoints().length / 4;
+ if (stupen <= pocetBodu) {
+ int knotCount = stupen + pocetBodu;
+ int middlePartSize = knotCount - 2 * stupen;
+ float[] newKnots = new float[knotCount];
+ int i;
+ int j = 0;
+ float middleStep = 1f / (middlePartSize + 2);
+ float knot = middleStep;
+
+ // knot=.5f;
+
+ for (i = 0; i < stupen; i++)
+ newKnots[j++] = 0;
+ for (i = 0; i < middlePartSize; i++) {
+ newKnots[j++] = knot;
+ knot += middleStep;
+ }
+ for (i = 0; i < stupen; i++)
+ newKnots[j++] = 1;
+
+ postNewKnot(newKnots);
+
+ } else
+ //errorMessage("Malý počet řídících bodů vzhledem k zadanému stupni křivky");
+ errorMessage("Too few control points regarding set curve degree");
+ }
+
+ /**
+ * Displays modal window with error report
+ * Zobrazí modální okno s hlášením chyby
+ * @param error error message
+ */
+ public void errorMessage(String error){
+ //JOptionPane.showMessageDialog(this,error,"Chyba!",JOptionPane.ERROR_MESSAGE);
+ JOptionPane.showMessageDialog(this,error,"Error!",JOptionPane.ERROR_MESSAGE);
+ }
+
+ /**
+ * Creates NURBS curves with uniform knot vector
+ * Vytvoří NURBS křivku s uniformním uzlovým vektorem
+ */
+ public void otevrenyKV() {
+ int stupen = Curve.getInstance().getOrder();
+ int pocetBodu = Curve.getInstance().getCtrlPoints().length / 4;
+ if (stupen <= pocetBodu) {
+ int knotCount = stupen + pocetBodu;
+ int middlePartSize = knotCount;
+ float[] newKnots = new float[knotCount];
+ int i;
+ int j = 0;
+ float middleStep = 1f / (middlePartSize - 1);
+ float knot = 0;
+
+ // knot=.5f;
+
+ // for(i=0;i<stupen;i++)
+ // newKnots[j++]=0;
+ for (i = 0; i < middlePartSize; i++) {
+ newKnots[j++] = knot;
+ knot += middleStep;
+ }
+ // for(i=0;i<stupen;i++)
+ // newKnots[j++]=1;
+
+ postNewKnot(newKnots);
+ }
+ else
+ //errorMessage("Malý počet řídících bodů vzhledem k zadanému stupni křivky");
+ errorMessage("Too few control points regarding set curve degree");
+ }
+
+ /**
+ * Method called after adding new knot
+ * Metoda volaná po přidání nového uzlu
+ * @param newKnots new knot vector
+ */
+ private void postNewKnot(float[] newKnots) {
+ Curve.getInstance().setKnots(newKnots);
+ knotSlider.setKnots(newKnots);
+ Curve.getInstance().setIsCurveFinished(true);
+ updateGLCanvas();
+ moveTB.setSelected(true);
+ }
+
+ /**
+ * Activates MOVE MODE button
+ * Aktivuje tlačítko módu pohybu řícími body
+ */
+ public void selectMoveButt() {
+ moveTB.setSelected(true);
+ }
+
+ /**
+ * Sets data source for knot editing component from knot vector of curve object
+ * Nastaví zdroj dat komponenty pro editaci uzlového vektoru podle uz. vektoru v objektu křivky
+ */
+ public void updateJKnotSlider() {
+ knotSlider.setKnots(Curve.getInstance().getKnots());
+ }
+}
diff --git a/src/demos/nurbs/curveapp/CurveMouseListener.java b/src/demos/nurbs/curveapp/CurveMouseListener.java
new file mode 100755
index 0000000..b74e1cf
--- /dev/null
+++ b/src/demos/nurbs/curveapp/CurveMouseListener.java
@@ -0,0 +1,180 @@
+package demos.nurbs.curveapp;
+
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
+/**
+ * Class reacting to mouse events (implements interface for button press, drag and movement)
+ * Třída zpracovávající události myši (implementuje rozhraní zpracovávající stisk tlačítek i pohyb a tažení myší)
+ * @author Tomáš Hráský
+ *
+ */
+public class CurveMouseListener implements MouseListener, MouseMotionListener {
+ /**
+ * Actually selected control point index
+ * Index aktuálně vybraného řídícího bodu
+ */
+ private int bodIndex;
+
+ /**
+ * Window listener is connected to
+ * Okno k nemuž listener patří
+ */
+ private CurveApp appWindow;
+
+ /**
+ * Action type
+ * Typ prováděné činnosti
+ */
+ private String actionType;
+
+ /**
+ * Pixel tolerance when selecting control point by clicking
+ * Tolerance pro indikaci kliku na řídící bod
+ */
+ private static final int TOLERANCE=10;
+
+ /**
+ * Creates new listener with connection to given app window
+ * Vytvoří listener s odkazem na zadané okno
+ * @param app rodičovské okno
+ */
+ public CurveMouseListener(CurveApp app) {
+ this.appWindow=app;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
+ */
+ public void mouseClicked(MouseEvent e) {
+ if(actionType==CurveApp.PRIDAT_AC){
+ Curve.getInstance().setIsCurveFinished(false);
+ float x=e.getX();
+ float y=e.getY();
+ float z=0;
+ float w=1;
+ int size;
+ float[] newCtrls;
+ try{
+ size=Curve.getInstance().getCtrlPoints().length;
+ }catch (Exception ex) {
+ size=0;
+ }
+ newCtrls=new float[size+4];
+ System.arraycopy(Curve.getInstance().getCtrlPoints(),0,newCtrls,0,size);
+
+ newCtrls[size]=x;
+ newCtrls[size+1]=y;
+ newCtrls[size+2]=z;
+ newCtrls[size+3]=w;
+ Curve.getInstance().setCtrlPoints(newCtrls);
+ }else if(actionType==CurveApp.SMAZAT_AC&&bodIndex>=0){
+ Curve.getInstance().setIsCurveFinished(false);
+ int size=Curve.getInstance().getCtrlPoints().length;
+ float[] newCtrls=new float[size-4];
+
+ int firstPartSize=(bodIndex)*4;
+ int secondPartSize=newCtrls.length-firstPartSize;
+ System.arraycopy(Curve.getInstance().getCtrlPoints(),0,newCtrls,0,firstPartSize);
+ System.arraycopy(Curve.getInstance().getCtrlPoints(),firstPartSize+4,newCtrls,firstPartSize,secondPartSize);
+ bodIndex=-1;
+ Curve.getInstance().setBodIndex(bodIndex);
+ Curve.getInstance().setCtrlPoints(newCtrls);
+ }
+ appWindow.updateGLCanvas();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
+ */
+ public void mousePressed(MouseEvent e) {
+ // if(actionType==MOVE_AC){
+ float[] ctrlpoints=Curve.getInstance().getCtrlPoints();
+ int x=e.getX();
+ int y=e.getY();
+ this.bodIndex=-1;
+ // System.out.println(ctrlpoints.length);
+ for(int i=0;i<ctrlpoints.length/4;i++){
+ float xS = ctrlpoints[i*4]/ctrlpoints[i*4+3];
+ float yS = ctrlpoints[i*4+1]/ctrlpoints[i*4+3];
+ if(x>=xS-TOLERANCE&&x<=xS+TOLERANCE&&y>=yS-TOLERANCE&&y<=yS+TOLERANCE){
+ this.bodIndex=i;
+ }
+ }
+
+ Curve.getInstance().setBodIndex(bodIndex);
+ // }
+ appWindow.updateGLCanvas();
+
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
+ */
+ public void mouseReleased(MouseEvent e) {
+ // this.bodIndex=-1;
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
+ */
+ public void mouseEntered(MouseEvent e) {
+
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
+ */
+ public void mouseExited(MouseEvent e) {
+
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
+ */
+ public void mouseDragged(MouseEvent e) {
+ if(this.bodIndex>=0){
+ int x=e.getX();
+ int y=e.getY();
+
+ Curve.getInstance().setActiveX(x);
+ Curve.getInstance().setActiveY(y);
+ }
+ appWindow.updateGLCanvas();
+ }
+
+ /* (non-Javadoc)
+ * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
+ */
+ public void mouseMoved(MouseEvent e) {
+
+ }
+
+ /**
+ * Set action type
+ * Nastaví typ prováděné činnosti
+ * @param action Action type
+ */
+ public void setActionType(String action) {
+ this.actionType=action;
+ }
+
+ /**
+ * Returns actually selected control point index
+ * Vrací index aktuálně vybraného řídícího bodu
+ * @return actually selected control point index
+ */
+ public int getBodIndex() {
+ return bodIndex;
+ }
+
+ /**
+ * Sets actually selected control point index
+ * Nastavuje index aktuálně vybraného řídícího bodu
+ * @param bodIndex actually selected control point index
+ */
+ public void setBodIndex(int bodIndex) {
+ this.bodIndex = bodIndex;
+ }
+}
diff --git a/src/demos/nurbs/curveapp/GLListener.java b/src/demos/nurbs/curveapp/GLListener.java
new file mode 100755
index 0000000..3a1f47a
--- /dev/null
+++ b/src/demos/nurbs/curveapp/GLListener.java
@@ -0,0 +1,148 @@
+package demos.nurbs.curveapp;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.glu.*;
+
+import com.sun.opengl.util.GLUT;
+
+/**
+ * Listener raacting to OpenGL canvas events
+ * Listener reagující na události na OpenGL plátně
+ * @author Tomáš Hráský
+ *
+ */
+public class GLListener implements GLEventListener {
+
+ /**
+ * OpenGL object
+ * objekt realizující základní OpenGL funkce
+ */
+ private GL gl;
+
+ /**
+ * GLU
+ * Objekt realizující funkce nadstavbové knihovny GLU
+ */
+ private GLU glu;
+
+ /**
+ * GLUT object
+ * Objekt realizující funkce nadstavbové knihovny GLUT
+ */
+ private GLUT glut;
+
+ /**
+ * NURBS curve object
+ * OpenGL Objekt NURBS křivky
+ */
+ private GLUnurbs nurbs;
+
+
+ /* (non-Javadoc)
+ * @see javax.media.opengl.GLEventListener#init(javax.media.opengl.GLAutoDrawable)
+ */
+ public void init(GLAutoDrawable drawable) {
+ this.gl = drawable.getGL();
+ this.glu = new GLU();
+ this.glut=new GLUT();
+
+ this.nurbs = glu.gluNewNurbsRenderer();
+ gl.glClearColor(1, 1, 1, 1);
+ }
+
+ public void dispose(GLAutoDrawable drawable) {
+ this.gl = null;
+ this.glu = null;
+ this.glut=null;
+ this.nurbs = null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.media.opengl.GLEventListener#display(javax.media.opengl.GLAutoDrawable)
+ */
+ public void display(GLAutoDrawable drawable) {
+
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+
+ gl.glMatrixMode(GL2ES1.GL_MODELVIEW);
+ gl.glLoadIdentity();
+
+ float[] knots = Curve.getInstance().getKnots();
+ float[] ctrlpoints = Curve.getInstance().getCtrlPoints();
+
+ gl.glEnable(GL.GL_LINE_SMOOTH);
+ gl.glEnable(GL.GL_BLEND);
+ gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
+ gl.glHint(GL.GL_LINE_SMOOTH_HINT, GL.GL_DONT_CARE);
+
+ gl.glLineWidth(3);
+
+ if(Curve.getInstance().isCurveFinished()){
+ glu.gluBeginCurve(nurbs);
+ glu.gluNurbsCurve(nurbs, knots.length, knots, 4, ctrlpoints, Curve.getInstance().getOrder(), GL.GL_MAP1_VERTEX_4);
+ glu.gluEndCurve(nurbs);
+ }
+
+ gl.glColor3f(0,0,0);
+ gl.glPointSize(5);
+ gl.glBegin(GL.GL_POINTS);
+ for (int i = 0; i < ctrlpoints.length / 4; i++) {
+ // if(i!=Curve.getInstance().getBodIndex())
+ gl.glVertex3d(ctrlpoints[i * 4]/ctrlpoints[i * 4 + 3], ctrlpoints[i * 4 + 1]/ctrlpoints[i * 4 + 3],
+ ctrlpoints[i * 4 + 2]/ctrlpoints[i * 4 + 3]);
+ }
+ gl.glEnd();
+
+
+ for (int i = 0; i < ctrlpoints.length / 4; i++) {
+ // if(i!=Curve.getInstance().getBodIndex())
+ // gl.glPushMatrix();
+ gl.glRasterPos2f(ctrlpoints[i * 4]/ctrlpoints[i * 4 + 3], ctrlpoints[i * 4 + 1]/ctrlpoints[i * 4 + 3]-5);
+ glut.glutBitmapString(GLUT.BITMAP_HELVETICA_18,String.valueOf(i+1));
+ // gl.glPopMatrix();
+ }
+
+
+ gl.glLineWidth(1);
+ gl.glBegin(GL.GL_LINE_STRIP);
+ for (int i = 0; i < ctrlpoints.length / 4; i++) {
+ // if(i!=Curve.getInstance().getBodIndex())
+ gl.glVertex3d(ctrlpoints[i * 4]/ctrlpoints[i * 4 + 3], ctrlpoints[i * 4 + 1]/ctrlpoints[i * 4 + 3],
+ ctrlpoints[i * 4 + 2]/ctrlpoints[i * 4 + 3]);
+ }
+ gl.glEnd();
+ gl.glColor3f(0,0,1);
+ if(Curve.getInstance().getBodIndex()>=0){
+ gl.glPointSize(8);
+ gl.glBegin(GL.GL_POINTS);
+ int i=Curve.getInstance().getBodIndex();
+ gl.glVertex3d(ctrlpoints[i * 4]/ctrlpoints[i * 4 + 3], ctrlpoints[i * 4 + 1]/ctrlpoints[i * 4 + 3],
+ ctrlpoints[i * 4 + 2]/ctrlpoints[i * 4 + 3]);
+ gl.glEnd();
+ }
+
+
+
+ }
+
+ /* (non-Javadoc)
+ * @see javax.media.opengl.GLEventListener#reshape(javax.media.opengl.GLAutoDrawable, int, int, int, int)
+ */
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width,
+ int height) {
+ gl.glMatrixMode(GL2ES1.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glOrtho(0, drawable.getWidth(), 0, drawable.getHeight(), -1, 1);
+ gl.glScalef(1, -1, 1);
+ gl.glTranslatef(0, -drawable.getHeight(), 0);
+
+ }
+
+ /* (non-Javadoc)
+ * @see javax.media.opengl.GLEventListener#displayChanged(javax.media.opengl.GLAutoDrawable, boolean, boolean)
+ */
+ public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean arg2) {
+ }
+}
diff --git a/src/demos/nurbs/curveapp/MyFloat.java b/src/demos/nurbs/curveapp/MyFloat.java
new file mode 100755
index 0000000..6adc2ef
--- /dev/null
+++ b/src/demos/nurbs/curveapp/MyFloat.java
@@ -0,0 +1,55 @@
+package demos.nurbs.curveapp;
+
+import simple.xml.Attribute;
+import simple.xml.Root;
+
+/**
+ * Class for serializing decimal point number using SimpleXML
+ * Třída umožňující serializaci desetinného čísla ve formátu plovoucí čárky (float)
+ * @author Tomáš Hráský
+ *
+ */
+@Root(name="floatval")
+public class MyFloat {
+ /**
+ * Value
+ * Hodnota
+ */
+ @Attribute(name="val")
+ private float value;
+
+ /**
+ * Constructor, sets value to 0
+ * Konstrktor, hodnota je defaultně 0
+ */
+ public MyFloat(){
+ value=0;
+ }
+
+ /**
+ * Creates instance with specified value
+ * Vytvoří instanci objektu s požadovanou hodnotou
+ * @param f value
+ */
+ public MyFloat(float f) {
+ value = f;
+ }
+
+ /**
+ * Returns value of decimal number
+ * Vrací hodnotu des. čísla
+ * @return value
+ */
+ public float getValue() {
+ return value;
+ }
+
+ /**
+ * Sets value
+ * Nastavuje hodnotu objektu
+ * @param value value
+ */
+ public void setValue(float value) {
+ this.value = value;
+ }
+}
diff --git a/src/demos/nurbs/curveapp/SpinnerListener.java b/src/demos/nurbs/curveapp/SpinnerListener.java
new file mode 100755
index 0000000..ccc5ac4
--- /dev/null
+++ b/src/demos/nurbs/curveapp/SpinnerListener.java
@@ -0,0 +1,47 @@
+package demos.nurbs.curveapp;
+
+import javax.swing.JSpinner;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+/**
+ * Listener reacting to events on GUI components setting coords and weight of selected control point
+ * Listener zpracovávající události na komponentách editujících souřadnice a váhu vybraného řídícícho bodu
+ * @author Tomáš Hráský
+ *
+ */
+public class SpinnerListener implements ChangeListener {
+
+ /**
+ * Application window
+ * Okno aplikace, k němuž listener patří
+ */
+ private CurveApp appWindow;
+
+ /**
+ * Creates new instance with link to parent window
+ * Vytvoří instanci objektu s odkazem na rodičovské okno
+ * @param app app window
+ */
+ public SpinnerListener(CurveApp app) {
+ this.appWindow=app;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent)
+ */
+ public void stateChanged(ChangeEvent e) {
+ JSpinner src=(JSpinner) e.getSource();
+ float val = 0;
+ if(src.getValue() instanceof Double) val=((Double) src.getValue()).floatValue();
+ if(src.getValue() instanceof Float) val=((Float) src.getValue()).floatValue();
+
+ if(src.getName()==CurveApp.X_SPINNER_NAME)
+ Curve.getInstance().setActiveX(val);
+ if(src.getName()==CurveApp.Y_SPINNER_NAME)
+ Curve.getInstance().setActiveY(val);
+ if(src.getName()==CurveApp.W_SPINNER_NAME)
+ Curve.getInstance().setActiveW(val);
+ appWindow.updateGLCanvas();
+ }
+}