431 lines
9.9 KiB
Java
431 lines
9.9 KiB
Java
//This file is part of SECONDO.
|
|
|
|
//Copyright (C) 2004, University in Hagen, Department of Computer Science,
|
|
//Database Systems for New Applications.
|
|
|
|
//SECONDO is free software; you can redistribute it and/or modify
|
|
//it under the terms of the GNU General Public License as published by
|
|
//the Free Software Foundation; either version 2 of the License, or
|
|
//(at your option) any later version.
|
|
|
|
//SECONDO is distributed in the hope that it will be useful,
|
|
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
//GNU General Public License for more details.
|
|
|
|
//You should have received a copy of the GNU General Public License
|
|
//along with SECONDO; if not, write to the Free Software
|
|
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
package fuzzyobjects.simple;
|
|
|
|
import fuzzyobjects.basic.*;
|
|
import sj.lang.ListExpr;
|
|
|
|
/**
|
|
* this class provides fuzzy triangles
|
|
* @author Thomas Behr
|
|
*/
|
|
public class fTriangle implements SimpleObject{
|
|
|
|
/**
|
|
* creates a new fTriangle
|
|
* no check whether this results a valid triangle
|
|
* @param BP1,BP2,BP3 the location of this Triangle
|
|
* @param Z1,Z2,Z3 the degrees of fuzziness in the cornerpoints
|
|
*/
|
|
public fTriangle( BasicPoint BP1, double Z1,
|
|
BasicPoint BP2, double Z2,
|
|
BasicPoint BP3, double Z3 ) {
|
|
|
|
fEPoint[] fEPs = new fEPoint[3];
|
|
fEPs[0] = new fEPoint(BP1,Z1);
|
|
fEPs[1] = new fEPoint(BP2,Z2);
|
|
fEPs[2] = new fEPoint(BP3,Z3);
|
|
|
|
fEPoint.sort(fEPs);
|
|
|
|
CP_1 = (BasicPoint) fEPs[0].basic();
|
|
CP_2 = (BasicPoint) fEPs[1].basic();
|
|
CP_3 = (BasicPoint) fEPs[2].basic();
|
|
this.Z1 = fEPs[0].getZ();
|
|
this.Z2 = fEPs[1].getZ();
|
|
this.Z3 = fEPs[2].getZ();
|
|
}
|
|
|
|
/* create a triabgle from 3 fuzzy points */
|
|
public fTriangle(fEPoint P1,fEPoint P2,fEPoint P3){
|
|
fEPoint[] fEPs = new fEPoint[3];
|
|
fEPs[0] = P1;
|
|
fEPs[1] = P2;
|
|
fEPs[2] = P3;
|
|
fEPoint.sort(fEPs);
|
|
CP_1 = (BasicPoint) fEPs[0].basic();
|
|
CP_2 = (BasicPoint) fEPs[1].basic();
|
|
CP_3 = (BasicPoint) fEPs[2].basic();
|
|
this.Z1 = fEPs[0].getZ();
|
|
this.Z2 = fEPs[1].getZ();
|
|
this.Z3 = fEPs[2].getZ();
|
|
|
|
|
|
}
|
|
|
|
|
|
/* get the first corner point */
|
|
public fEPoint getP1(){
|
|
return new fEPoint(CP_1,Z1);
|
|
}
|
|
|
|
/* gte the second cornerpoint */
|
|
public fEPoint getP2(){
|
|
return new fEPoint(CP_2,Z2);
|
|
}
|
|
|
|
/* get the last corner point */
|
|
public fEPoint getP3(){
|
|
return new fEPoint(CP_3,Z3);
|
|
}
|
|
|
|
|
|
/**
|
|
* creates a new fTriangle
|
|
* whithout check of validity
|
|
* @param x?,y? the location of cornerpoints
|
|
* @param Z? the degree of fuzziness in a cornerpoint
|
|
*/
|
|
public fTriangle( int x1, int y1, double Z1,
|
|
int x2, int y2, double Z2,
|
|
int x3, int y3, double Z3){
|
|
this( ( new BasicPoint(x1,y1)), Z1,
|
|
( new BasicPoint(x2,y2)), Z2,
|
|
( new BasicPoint(x3,y3)), Z3);
|
|
|
|
}
|
|
|
|
/**
|
|
* creates a new fTriangle
|
|
* whithout check of validity
|
|
* @param BT the location of this Triangle
|
|
* @param Z? the degree of fuzziness in a cornerPoint
|
|
*/
|
|
public fTriangle( BasicTriangle BT, double Z1,
|
|
double Z2, double Z3){
|
|
this ( BT.getCP1(),Z1, BT.getCP2(), Z2, BT.getCP3(),Z3 );
|
|
}
|
|
|
|
/**
|
|
* returns whether this and fT are equal
|
|
*/
|
|
public boolean equals(fTriangle fT){
|
|
if(fT == null)
|
|
return false;
|
|
else{
|
|
return CP_1.equals(fT.CP_1) & CP_2.equals(fT.CP_2) &
|
|
CP_3.equals(fT.CP_3) & (Z1==fT.Z1) &
|
|
(Z2 == fT.Z2) & (Z3==fT.Z3);
|
|
}
|
|
|
|
}
|
|
|
|
/** returns a String representing this Triangle */
|
|
public String toString(){
|
|
return "FTriangle :["+ CP_1+","+Z1+"]["+
|
|
CP_2+","+Z2+"]["+CP_3+","+Z3+"]";
|
|
|
|
}
|
|
|
|
/** returns a copy of this */
|
|
public fTriangle copy(){
|
|
return new fTriangle(CP_1.copy(),Z1,
|
|
CP_2.copy(),Z2,
|
|
CP_3.copy(),Z3);
|
|
}
|
|
|
|
/** returns the location of this */
|
|
public BasicObject basic(){
|
|
BasicTriangle result = new BasicTriangle(CP_1,CP_2,CP_3);
|
|
return result;
|
|
}
|
|
|
|
/** returns the degree of fuzziness of the smallest point */
|
|
public double getZ1(){
|
|
return Z1;
|
|
}
|
|
|
|
/** returns the degree of fuzziness of the middle point */
|
|
public double getZ2(){
|
|
return Z2;
|
|
}
|
|
|
|
/** returns the degree of fuzziness of the greatest point */
|
|
public double getZ3(){
|
|
return Z3;
|
|
}
|
|
|
|
|
|
/** returns the degree of fuzziness on a given Point
|
|
* @param BP the given point
|
|
*/
|
|
public double Zfkt(BasicPoint BP){
|
|
double result=0.0;
|
|
if (BP.equals(CP_1))
|
|
result = Z1;
|
|
else
|
|
if (BP.equals(CP_2))
|
|
result=Z2;
|
|
else
|
|
if (BP.equals(CP_3))
|
|
result = Z3;
|
|
return result;
|
|
}
|
|
|
|
/** returns the degree of fuzziness on a given point
|
|
* this point must be contained in the pointset of this
|
|
* @param x,y the given Point
|
|
*/
|
|
public double Zfkt(double x, double y){
|
|
// returns the membership-value for this coordinate
|
|
// no check : (x,y) on Triangle
|
|
|
|
if (BasicPoint.isBasicPoint(x,y)){
|
|
BasicPoint BP = new BasicPoint( (int)x, (int) y);
|
|
return Zfkt(BP);
|
|
}
|
|
|
|
// not a BasicPoint
|
|
|
|
double x1 = CP_1.getX();
|
|
double y1 = CP_1.getY();
|
|
double z1 = Z1;
|
|
double x2 = CP_2.getX();
|
|
double y2 = CP_2.getY();
|
|
double z2 = Z2;
|
|
double x3 = CP_3.getX();
|
|
double y3 = CP_3.getY();
|
|
double z3 = Z3;
|
|
|
|
// sort by y-values
|
|
|
|
double y_max = Math.max(y1,Math.max(y2,y3));
|
|
double y_min = Math.min(y1,Math.min(y2,y3));
|
|
double y_mid = (y1+y2+y3) - y_max - y_min;
|
|
|
|
double x_max,x_mid,x_min,z_max,z_mid,z_min;
|
|
|
|
x_max = x_mid = x_min = z_max=z_mid=z_min=0;
|
|
|
|
if(y_max==y1){
|
|
x_max=x1;
|
|
z_max=z1;
|
|
if(y_mid==y2){
|
|
x_mid=x2;
|
|
z_mid=z2;
|
|
x_min=x3;
|
|
z_min=z3;
|
|
}
|
|
else{
|
|
x_mid=x3;
|
|
z_mid=z3;
|
|
x_min=x2;
|
|
z_min=z2;
|
|
}
|
|
}
|
|
else
|
|
if(y_max==y2){
|
|
x_max=x2;
|
|
z_max=z2;
|
|
if(y1==y_mid){
|
|
x_mid=x1;
|
|
z_mid=z1;
|
|
x_min=x3;
|
|
z_min=z3;
|
|
}
|
|
else{
|
|
x_mid=x3;
|
|
z_mid=z3;
|
|
x_min=x1;
|
|
z_min=z1;
|
|
}
|
|
}
|
|
else
|
|
if(y_max==y3){
|
|
x_max=x3;
|
|
z_max=z3;
|
|
if(y1==y_mid){
|
|
x_mid=x1;
|
|
z_mid=z1;
|
|
x_min=x2;
|
|
z_min=z2;
|
|
}
|
|
else{
|
|
x_mid=x2;
|
|
z_mid=z2;
|
|
x_min=x1;
|
|
z_min=z1;
|
|
}
|
|
}
|
|
|
|
|
|
// compute x and z-Values on Segment (y_min->y_max)
|
|
// whith scanline y
|
|
double delta1 = (y-y_min)/(y_max-y_min);
|
|
double x_sl_1 = (x_min) + delta1*(x_max-x_min);
|
|
double z_sl_1 = (z_min) + delta1*(z_max-z_min);
|
|
|
|
|
|
|
|
double x_sl_2;
|
|
double z_sl_2;
|
|
double delta2;
|
|
|
|
if(y>y_mid) { // scanline intersect line y_mid -> y_max
|
|
delta2 = (y-y_mid)/(y_max-y_mid);
|
|
x_sl_2 = x_mid + delta2*(x_max-x_mid);
|
|
z_sl_2 = z_mid + delta2*(z_max-z_mid);
|
|
}
|
|
else
|
|
if(y<y_mid) { // scanline intersect line y_min -> y_mid
|
|
delta2 = (y-y_min)/(y_mid-y_min);
|
|
x_sl_2 = x_min + delta2*(x_mid-x_min);
|
|
z_sl_2 = z_min + delta2*(z_mid-z_min);
|
|
}
|
|
else { // y==y_mid
|
|
delta2 = -1;
|
|
x_sl_2 = x_mid;
|
|
z_sl_2 = z_mid;
|
|
}
|
|
|
|
double delta3 = (x-x_sl_1)/(x_sl_2-x_sl_1);
|
|
double result = z_sl_1 + delta3*(z_sl_2-z_sl_1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* check whether this is a valid fuzzy Triangle
|
|
* @return true if the underlying BasicTriangles is valid,
|
|
* all degrees of fuzziness are in [0,1) and
|
|
* 1 degree is greater then 0
|
|
*/
|
|
public boolean isValid(){
|
|
boolean BasicIsValid =
|
|
(new BasicTriangle(CP_1,CP_2,CP_3)).isValid();
|
|
return BasicIsValid &&
|
|
0<=Z1 && Z1<=1 && 0<=Z2 && Z2 <=1 && 0<=Z3 && Z3<= 1 &&
|
|
(Z1+Z2+Z3)>0;
|
|
}
|
|
|
|
|
|
/**
|
|
* computes the volume "under" this Triangle
|
|
*/
|
|
public double volume(){
|
|
|
|
double Zmin = Math.min(Z1,Math.min(Z2,Z3));
|
|
double Zmax = Math.max(Z1,Math.max(Z2,Z3));
|
|
double Zmid = Z1+Z2+Z3 - Zmin - Zmax;
|
|
double a = fuzzyobjects.Params.a;
|
|
double b = fuzzyobjects.Params.b;
|
|
return (a*b/4)*Zmin + (( (Zmid-Zmin)+(Zmax-Zmin)/2)*a*b)/6;
|
|
|
|
}
|
|
|
|
/**
|
|
* computes the area of this fTriangles viewed as 3D-Triangle
|
|
*/
|
|
public double area3D(){
|
|
// Bronstein
|
|
|
|
double x1 = CP_1.getX();
|
|
double x2 = CP_2.getX();
|
|
double x3 = CP_3.getX();
|
|
double y1 = CP_1.getY();
|
|
double y2 = CP_2.getY();
|
|
double y3 = CP_3.getY();
|
|
double a2 = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
|
|
double b2 = (x3-x2)*(x3-x2) + (y3-y2)*(y3-y2);
|
|
double c2 = (x1-x3)*(x1-x3) + (y1-y3)*(y1-y3);
|
|
return Math.sqrt((2*a2*b2 + 2*a2*c2 +
|
|
2*b2*c2 -a2*a2 -b2*b2 -c2*c2)/2);
|
|
}
|
|
|
|
/** returns the greatest degree of fuzziness in this Triangle */
|
|
public double getMaxZ(){
|
|
return Math.max(Z1,Math.max(Z2,Z3));
|
|
}
|
|
|
|
|
|
/** returns the smallest degree of fuzziness in the Triangle */
|
|
public double getMinZ(){
|
|
return Math.min(Z1,Math.min(Z2,Z3));
|
|
}
|
|
|
|
public int getMinX(){
|
|
return Math.min(CP_1.getX(),
|
|
Math.min(CP_2.getX(),CP_3.getX()));
|
|
}
|
|
|
|
public int getMinY(){
|
|
return Math.min(CP_1.getY(),
|
|
Math.min(CP_2.getY(),CP_3.getY()));
|
|
}
|
|
public int getMaxX(){
|
|
return Math.max(CP_1.getX(),
|
|
Math.max(CP_2.getX(),CP_3.getX()));
|
|
}
|
|
public int getMaxY(){
|
|
return Math.max(CP_1.getY(),
|
|
Math.max(CP_2.getY(),CP_3.getY()));
|
|
}
|
|
|
|
/** returns the ListExpr for this fTriangle */
|
|
public ListExpr toListExpr(){
|
|
fEPoint P1 = new fEPoint(CP_1,Z1);
|
|
fEPoint P2 = new fEPoint(CP_2,Z2);
|
|
fEPoint P3 = new fEPoint(CP_3,Z3);
|
|
return ListExpr.threeElemList(P1.toListExpr(),P2.toListExpr(),
|
|
P3.toListExpr());
|
|
}
|
|
|
|
|
|
/** set the values of this fTriangle to LE,
|
|
* if LE represent a valid FTriangle
|
|
* @return true if LE is a valid fTriangle
|
|
*/
|
|
public boolean readFromListExpr(ListExpr LE){
|
|
if(LE.listLength()!=3)
|
|
return false;
|
|
fEPoint P1 = new fEPoint(0,0,0);
|
|
fEPoint P2 = new fEPoint(0,0,0);
|
|
fEPoint P3 = new fEPoint(0,0,0);
|
|
if(!( P1.readFromListExpr(LE.first()) &&
|
|
P2.readFromListExpr(LE.second())
|
|
&& P3.readFromListExpr(LE.third()) ))
|
|
return false;
|
|
BasicPoint BP1 = (BasicPoint) P1.basic();
|
|
BasicPoint BP2 = (BasicPoint) P2.basic();
|
|
BasicPoint BP3 = (BasicPoint) P3.basic();
|
|
if (! (BP1.neightbooring(BP2) && BP1.neightbooring(BP3) &&
|
|
BP2.neightbooring(BP3)))
|
|
return false;
|
|
|
|
this.CP_1 = BP1;
|
|
this.CP_2 = BP2;
|
|
this.CP_3 = BP3;
|
|
this.Z1 = P1.getZ();
|
|
this.Z2 = P2.getZ();
|
|
this.Z3 = P3.getZ();
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/** location of a cornerpoint */
|
|
private BasicPoint CP_1,CP_2,CP_3;
|
|
/** degree of fuzziness of a cornerpoint */
|
|
private double Z1,Z2,Z3;
|
|
|
|
} // class
|