package demos.nurbs.surfaceapp;
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 plochy, vystavěna podle návrhového vzoru Singleton
* @author Tomáš Hráský
*
*/
@Root(name="surface")
public class Surface {
/**
* Odkaz na instanci třídy
*/
private static Surface singleton;
/**
* Indikuje, zda je zadání plochy kompletní
*/
@Element(name="finished")
private boolean isSurfaceFinished=false;
/**
* Index aktuálního vybraného řídícího bodu
*/
private int bodIndex = -1;
/**
* Stupeň plocy ve směru parametru U
*/
@Element(name="orderU")
private int orderU=3;
/**
* Stupeň plochy ve směru parametru V
*/
@Element(name="orderV")
private int orderV=3;
/**
* Počet řídících bodů ve směru parametru V
*/
@Element(name="pointsInV")
private int pointsInV=4;
/**
* Počet řídících bodů ve směru parametru U
*/
@Element(name="pointsInU")
private int pointsInU=4;
/**
* Pole souřadnic řídícíh bodů
*
*/
private float[] ctrlPoints
// ={
// -150f,-150f, 400f,1f,
// -50f,-150f, 200f, 1f,
// 50f,-150f,-100f, 1f,
// 150f,-150f, 200f,1f,
// -150f,-50f, 100f, 1f,
// -50f,-50f, 300f, 1f,
// 50f,-50f, 0f, 1f,
// 150f,-50f,-100f,1f,
// -150f, 50f, 400f, 1f,
// -50f, 50f, 0f, 1f,
// 50f, 50f, 300f, 1f,
// 150f, 50f, 400f,1f,
// -150f, 150f,-200f, 1f,
// -50f, 150f,-200f, 1f,
// 50f, 150f, 0f, 1f,
// 150f, 150f,-100f,1f}
;
/**
* Pole hodnot uzlového vektoru ve směru parametru U
*/
private float knotsU[]
// ={0.0f, 0.0f, 0.0f, 0.0f,
// 1f, 1f, 1.0f, 1.0f}
;
/**
* Pole hodnot uzlového vektoru ve směru parametru V
*/
private float knotsV[]
// ={0.0f, 0.0f, 0.0f, 0.0f,
// 1f, 1f, 1.0f, 1.0f}
;
/**
* 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 ve směru parametru U
*/
@ElementList(name="knotsU",type=MyFloat.class)
private Vector<MyFloat> knotVectorU;
/**
* Kolekce vektor pro persistenci uzlového vektoru ve směru parametru V
*/
@ElementList(name="knotsV",type=MyFloat.class)
private Vector<MyFloat> knotVectorV;
/**
* Vytvoří prázdnou definici plochy
*/
public void clear(){
isSurfaceFinished=false;
ctrlPoints=new float[0];
knotsU=new float[0];
knotsV=new float[0];
orderU=3;
orderV=3;
pointsInU=0;
pointsInV=0;
}
/**
* 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);
knotVectorU=new Vector<MyFloat>(knotsU.length);
knotVectorV=new Vector<MyFloat>(knotsV.length);
for(Float ff:ctrlPoints)
ctrlVector.add(new MyFloat(ff));
for(Float ff:knotsU)
knotVectorU.add(new MyFloat(ff));
for(Float ff:knotsV)
knotVectorV.add(new MyFloat(ff));
Serializer s=new Persister();
try {
System.out.println("ukládám");
s.write(Surface.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();
Surface c=s.read(Surface.class,f);
initFromSurface(c);
}
/**
* Inicializuje objekt podle jiného objektu typu Curve
* @param c referenční objekt - křivka
*/
private void initFromSurface(Surface c) {
this.orderU=c.getOrderU();
this.orderV=c.getOrderV();
this.ctrlPoints=new float[c.getCtrlVector().size()];
this.knotsU=new float[c.getKnotVectorU().size()];
this.knotsV=new float[c.getKnotVectorV().size()];
int i=0;
for(MyFloat f:c.getCtrlVector())
ctrlPoints[i++]=f.getValue();
i=0;
for(MyFloat f:c.getKnotVectorU())
knotsU[i++]=f.getValue();
i=0;
for(MyFloat f:c.getKnotVectorV())
knotsV[i++]=f.getValue();
this.pointsInU=c.getPointsInU();
this.pointsInV=c.getPointsInV();
this.isSurfaceFinished=c.isSurfaceFinished();
}
/**
* Konstruktor, nastaví prázdné hodnoty polí definujících NURBS plochu
*/
private Surface(){
// ctrlPoints=new float[0];
// knotsU=new float[0];
// knotsV=new float[0];
// isSurfaceFinished=false;
clear();
}
/**
* Vrací instanci třídy (podle návrhového vzoru Singleton)
* @return instance třídy Curve
*/
public static Surface getInstance() {
if (singleton == null)
singleton = new Surface();
return singleton;
}
/**
* Vrací pole uzlového vektoru ve směru parametru U
* @return pole hodnot uzlového vektoru ve směru parametru U
*/
public float[] getKnotsU() {
return this.knotsU;
}
/**
* 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 plochy ve směru parametru U
* @return stupeň NURBS plochy ve směru parametru U
*/
public int getOrderU() {
return this.orderU;
}
/**
* 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í Z-ovou souadnici aktuálně vybraného řídícího bodu, přepočítává hodnotu z homogenních souřadnic
* @return Z-ová souadnice aktuálně vybraného řídícího bodu
*/
public float getActiveZ(){
if(bodIndex>=0){
return ctrlPoints[bodIndex*4+2]/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 Z-ovou souadnici aktuálně vybraného řídícího bodu, přepočítává hodnotu do homogenních souřadnic
* @param z Z-ová souřadnice aktuálně vybraného řídícího bodu
*/
public void setActiveZ(float z){
if(bodIndex>=0){
ctrlPoints[bodIndex*4+2]=z*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;
ctrlPoints[bodIndex*4+2]=ctrlPoints[bodIndex*4+2]/oldW*w;
}
}
}
/**
* Nastavuje uzlový vektor ve směru parametru U
* @param knots nový uzlový vektor ve směru parametru U
*/
public void setKnotsU(float[] knots) {
this.knotsU = knots;
}
/**
* Vrací informaci o stavu dokončení definice křvky
* @return true pokud je definice křivky kompletní, jinak false
*/
public boolean isSurfaceFinished() {
return isSurfaceFinished;
}
/**
* 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 setIsSurfaceFinished(boolean b) {
isSurfaceFinished=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 ve směru parametru U pro serializaci
* @return vektor prvků uzlového vektoru ve směru parametru U
*/
private Vector<MyFloat> getKnotVectorU() {
return knotVectorU;
}
/**
* Vrací stupeň plochy ve směru parametru U
* @param order stupeň plochy ve směru parametru U
*/
public void setOrderU(int order) {
this.orderU = order;
}
/**
* Vrací pole uzlového vektoru ve směru parametru V
* @return pole hodnot uzlového vektoru ve směru parametru V
*/
public float[] getKnotsV() {
return knotsV;
}
/**
* Nastavuje uzlový vektor ve směru parametru V
* @param knotsV nový uzlový vektor ve směru parametru V
*/
public void setKnotsV(float[] knotsV) {
this.knotsV = knotsV;
}
/**
* Vrací stupeň plochy ve směru parametru V
* @return stupeň plochy ve směru parametru V
*/
public int getOrderV() {
return orderV;
}
/**
* Nastavuje stupeň NURBS plochy ve směru parametru V
* @param orderV stupeň plochy ve směru parametru V
*/
public void setOrderV(int orderV) {
this.orderV = orderV;
}
/**
* Vrací vektor prvků uzlového vektoru ve směru parametru V pro serializaci
* @return vektor prvků uzlového vektoru ve směru parametru V
*/
private Vector<MyFloat> getKnotVectorV() {
return knotVectorV;
}
/**
* Vrací počet řídících bodů ve směru parametru V (tj. počet sloupců)
* @return počet řídících bodů ve směru parametru V
*/
public int getPointsInV() {
return pointsInV;
}
/**
* Nastavuje počet řídících bodů ve směru parametru V
* @param pointsInV počet řídících bodů ve směru parametru V
*/
public void setPointsInV(int pointsInV) {
this.pointsInV = pointsInV;
}
/**
* Vrací počet řídících bodů ve směru parametru U (tj. počet řádků)
* @return počet řídících bodů ve směru parametru U
*/
public int getPointsInU() {
return pointsInU;
}
/**
* Nastavuje počet řídících bodů ve směru parametru U
* @param pointsInU počet řídících bodů ve směru parametru U
*/
public void setPointsInU(int pointsInU) {
this.pointsInU = pointsInU;
}
}