//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.composite; import fuzzyobjects.basic.*; import fuzzyobjects.simple.*; import java.util.Vector; import sj.lang.ListExpr; import java.io.*; /** * this class provides a implementation of fuzzy Lines * in the X-triangulation * @author Thomas Behr */ public class FLine implements CompositeObject{ /** * the factor of scale */ protected double SF; /** the fuzzy segments */ protected SortedObjects fSeg; /** returns the SortedObjects of this Line */ SortedObjects getSortedObjects(){ return fSeg; } /** remove all conataing segments */ public void clear(){ fSeg.makeEmpty(); } /** returns the number of containing fuzzy segments */ public int getSize(){ return fSeg.getSize(); } /* retuns the fuzzy segment at position index, if this object not exists null is returned */ public fSegment getSegmentAt(int index){ if(index<0 || index>=fSeg.getSize()) return null; return (fSegment) fSeg.get(index); } /** the bounding box */ protected BoundingBox BB = new BoundingBox(); /** returns the bounding box of this line */ public BoundingBox getBoundingBox(){ return BB; } /** overwrite the given Path by a new FLine by * linear aprox. */ public boolean overwritePath(Path P, double Start, double End){ if(P==null | Start<0 | Start>1 | End<0 | End>1) return false; else{ boolean removePath = (Start+End==0); double length = P.getLength(); double currentLength = 0; int max = P.getNumberOfSegments(); double delta = End-Start; double CLength; BasicSegment C; double M1,M2; BasicPoint BP; for(int i=0;i maxX) maxX = cX; if(cY > maxY) maxY = cY; } BB.setBox(minX,minY,maxX,maxY); } } /** * creates a new FLine * with scale as factor of scale */ public FLine(double scale){ fSeg = new SortedObjects(); SF = scale; } /** set the new factor of scale */ public boolean setSF(double SF){ if(SF>0){ this.SF=SF; return true; } else return false; } /** * creates a new FLine * with 1 as factor of scale */ public FLine() { this(1.0); } /** get the factor of scale */ public double getSF(){ return SF; } /** * get the dimension of a line * i.e. 1 */ public int getDim(){ return 1; } /** * is this a valid line in the X-triangulation ? * i.e. check whether SF greater then 0 and all * containing fuzzy segments are valid */ public boolean isValid(){ return SF>0 & fSeg.allValid(); } /** * returns a readable String of this FLine */ public String toString(){ return "FLine (SF="+SF+")\n" + fSeg.toString(); } /** * adds a new fuzzy Segment to this Line * if this FLine contains a segment whith same basic as fS * the fS not added and the result ist false */ public boolean add(fSegment fS){ boolean first = fSeg.isEmpty(); boolean ok = fSeg.insert(fS.copy()); if(ok) { // update bounding box if(!first){ int minX = BB.getMinX(); int minY = BB.getMinY(); int maxX = BB.getMaxX(); int maxY = BB.getMaxY(); if(minX>fS.getMinX()) minX = fS.getMinX(); if(minY>fS.getMinY()) minY = fS.getMinY(); if(maxXfS.getMinX()) minX = fS.getMinX(); if(minY>fS.getMinY()) minY = fS.getMinY(); if(maxX * overwrite(fSegment) */ public boolean overwrite(int x1,int y1,double Z1, int x2,int y2,double Z2 ){ fSegment fS = new fSegment(x1,y1,Z1, x2,y2,Z2); if (fS.isValid()){ overwrite(fS); return true; } else return false; } /** * deletes the fuzzy Segment from this FLine * with basic BS * returns false if this FLine not contains such fSegment */ public boolean delete(BasicSegment BS){ boolean ok = fSeg.delete(BS); if(ok & ( BS.getMinX()==BB.getMinX() | BS.getMaxX()==BB.getMaxX() | BS.getMinY()==BB.getMinY() | BS.getMaxY()==BB.getMaxY() ) ) computeBoundingBox(); return ok; } /** * computes all membershipvalues on (x,y) */ public double[] ZRel(double x, double y) { double[] result; BasicSegment[] Segs = BasicSegment.getSegments(x,y); if(Segs == null){ result = new double[1]; result[0]=0; } else{ Vector tmp = new Vector(); fSegment current; Double Z; for(int i=0;iresult) result=cand[i]; return result; } /** computes the maximal membershipvalue on (x,y) */ public double maxZfkt(double x, double y){ double[] values = ZRel(x,y); double result =0; for(int i=0;iresult) result = values[i]; return result; } /** computes the minimal membershipvalue on (x,y) */ public double minZfkt(double x, double y){ double[] values = ZRel(x,y); double result =1; for(int i=0;i Math.min(current.getZ1(),current.getZ2()) ) min = Math.min(current.getZ1(), current.getZ2()); } return min; } // minZ /** returns a copy from this FLine */ public FLine copy(){ FLine C = new FLine(SF); C.fSeg = fSeg.copy(); C.BB = BB.copy(); return C; } /** check whether this FLine contains elements */ public boolean isEmpty(){ return fSeg.isEmpty(); } /** set the containing segments from this on the same * as L2's one */ protected static void setfSeg(FLine L1, FLine L2){ L1.fSeg = L2.fSeg; L1.BB = L2.BB; } /** computes the selfcuts of this Line */ public BasicPoint[] selfcuts(){ BasicSegment Current; BasicPoint BP; int n; boolean found; Vector tmp = new Vector(fSeg.getSize()); for(int i=0;i2){ found=false; for(int j=0;j2){ found=false; for(int j=0;jalpha; else isValid = midZ>= alpha; if(isValid) CutL.fSeg.insert(Current.copy()); } CutL.computeBoundingBox(); return CutL; } /** * computes the length of the basic of this FLine */ public double basicLen(){ double sum = 0.0; for(int i=0;i0; } /** * check whether BP is on boundary of this FLine */ public boolean isEndPoint(BasicPoint BP){ return numberOfSegments(BP)==1; } /** * returns the number of Basicsegments containing in this FLine * having BP as endpoint */ public int numberOfSegments(BasicPoint BP){ BasicPoint[] Neightboors = BP.getNeightboors(); int found =0; for(int i=0;i0 is nothing to do } // not the first Segment } // current Line contains unprocessing Segments } // for all Lines if(!allready){ double Z1=0,Z2=0; BasicSegment BS = (BasicSegment) ((fSegment) allSmallest.get(0)).basic(); fSegment CS; for(int i=0;i0 is nothing to do } // not the first Segment } // current Line contains unprocessing Segments } // for all Lines if(!allready){ double Z1=0,Z2=0; BasicSegment BS = (BasicSegment) ((fSegment) allSmallest.get(0)).basic(); fSegment CS; for(int i=0;iand * not endpoint of a common segment of this FLines */ public FPoint commonPoints(FLine L2){ FPoint result = new FPoint(); FLine SI = operator(L2,SHARPINTERSECTION); BasicSegment current; BasicPoint BP1,BP2; for(int i=0;i0){ newFS = new fSegment((BasicSegment) F1.basic(), Z1,Z2 ); Goal.fSeg.insert(newFS); } } } break; case ADD : { if(F1==null) Goal.fSeg.insert(F2.copy()); else if(F2==null) Goal.fSeg.insert(F1.copy()); else { // both fSegments are not null Z1 = Math.min(1,F1.getZ1()+F2.getZ1()); Z2 = Math.min(1,F1.getZ2()+F2.getZ2()); newFS = new fSegment((BasicSegment) F1.basic(), Z1,Z2); Goal.fSeg.insert(newFS); } // else } break; case SUBTRACT :{ if(F1 == null) ; else if(F2==null) Goal.fSeg.insert(F1.copy()); else { // both not null Z1 = Math.max(0,F1.getZ1()-F2.getZ1()); Z2 = Math.max(0,F1.getZ2()-F2.getZ2()); if ((Z1+Z2)>0) { newFS = new fSegment( (BasicSegment) F1.basic(),Z1,Z2); Goal.fSeg.insert(newFS); } } } break; case SCALEDUNION : { fSegment newSegment; if (F1==null) newSegment = new fSegment( (BasicSegment) F2.basic(), F2.getZ1()*scale2, F2.getZ2()*scale2); else if (F2==null) newSegment = new fSegment( (BasicSegment) F1.basic(), F1.getZ1()*scale1, F1.getZ2()*scale1); else { Z1 = Math.max(F1.getZ1()*scale1, F2.getZ1()*scale2); Z2 = Math.max(F1.getZ2()*scale1, F2.getZ2()*scale2); newSegment = new fSegment( (BasicSegment) F1.basic(), Z1,Z2); } // else Goal.add(newSegment); } break; // scaled union case SCALEDINTERSECTION : if (F1==null || F2==null) ; else { Z1 = Math.min(F1.getZ1()*scale1, F2.getZ1()*scale2); Z2 = Math.min(F1.getZ2()*scale1, F2.getZ2()*scale2); Goal.add(new fSegment( (BasicSegment) F1.basic(), Z1,Z2)); } break; case SCALEDADD : { if(F1==null) Goal.add(new fSegment( (BasicSegment) F2.basic(), F2.getZ1()*scale2, F2.getZ2()*scale2)); else if(F2==null) Goal.add(new fSegment( (BasicSegment) F1.basic(), F1.getZ1()*scale1, F1.getZ2()*scale1)); else { Goal.add(new fSegment( (BasicSegment) F1.basic(), F1.getZ1()*scale1 + F2.getZ1()*scale2 , F1.getZ2()*scale1 + F2.getZ2()*scale2 )); } } break; case SCALEDDIFFERENCE : { if(F1==null) Goal.add(new fSegment( (BasicSegment) F2.basic(), -F2.getZ1()*scale2, -F2.getZ2()*scale2)); else if(F2==null) Goal.add(new fSegment( (BasicSegment) F1.basic(), F1.getZ1()*scale1, F1.getZ2()*scale1)); else { Goal.add(new fSegment( (BasicSegment) F1.basic(), F1.getZ1()*scale1 - F2.getZ1()*scale2 , F1.getZ2()*scale1 - F2.getZ2()*scale2 )); } } break; case SHARPINTERSECTION :{ if (F1==null | F2==null) ; else { newFS = new fSegment((BasicSegment)F1.basic(),1,1); Goal.fSeg.insert(newFS); } } break; default : System.err.println("operator not implemented"); } // switch } // processElements /** the 'template' for many operators */ protected FLine operator(FLine FL, int op){ // a kind of mergesort int my = 0; int fromFL = 0; // already processed int maxMy = fSeg.getSize(); // numbers of elements int maxFromFL = FL.fSeg.getSize(); FLine result = new FLine(1); fSegment myFirst=null; // the first unprocessed elements fSegment FLFirst=null; if(maxMy>0) myFirst = (fSegment) fSeg.get(0); if(maxFromFL>0) FLFirst = (fSegment) FL.fSeg.get(0); if (maxMy >0 && maxFromFL>0){ myFirst = (fSegment) fSeg.get(my); FLFirst = (fSegment) FL.fSeg.get(fromFL); int compareResult; while(my 0){ processElements(null,SF,FLFirst,FL.SF,result,op); fromFL++; if(fromFLZmax) Zmax = Current.getMaxZ(); if(Current.getMinZ() 0) Zmin=0; if(Zmax==0 & Zmin==0) fSeg.makeEmpty(); else{ double SFnew = Zmax - Zmin; SortedObjects newfSeg = new SortedObjects(); double Z1,Z2,Z3; fSegment fSnew; for(int i=0;i0) newfSeg.insert(fSnew); } // for SF = SFnew*SF; fSeg = newfSeg; } computeBoundingBox(); } /************************************************************* * * * topological Relationships * * * *************************************************************/ /************************************************************* * * * Topology in the basic * * * *************************************************************/ /** helping method to compute the top Rel in the basic */ private static void checkPointsBasic( int Segs1, int Segs2, M9Int goal ){ /* this method checks the intersection of two lines in a BasicPoint BP Paramters : Segs1, Segs2 : numberOfSegments of each Line in BP Z1,Z2 : maxZfkt(BP) for each Line fuzzy : basic or fuzzy intersections ? goal : here saving the result(s) */ if(Segs1==0) { // exterior of L1 if(Segs2==0) // exterior goal.setValue(true,M9Int.EXTERIOR,M9Int.EXTERIOR); if(Segs2==1) // boundary goal.setValue(true,M9Int.EXTERIOR,M9Int.BOUNDARY); if(Segs2>1){ // interior goal.setValue(true,M9Int.EXTERIOR,M9Int.INTERIOR); } // interior of l2 } // exterior of L1 if(Segs1==1) { // boundary of L1 if(Segs2==0) goal.setValue(true,M9Int.BOUNDARY,M9Int.EXTERIOR); if(Segs2==1) goal.setValue(true,M9Int.BOUNDARY,M9Int.BOUNDARY); if(Segs2>1){ // interior of L2 goal.setValue(true,M9Int.BOUNDARY,M9Int.INTERIOR); }// interior of L2 } // boundary of L1 if(Segs1>1) { // a interior Point of Line 1 if(Segs2==0){ goal.setValue(true,M9Int.INTERIOR,M9Int.EXTERIOR); } // Segs1==0 if(Segs2==1){ // boundary of L2 goal.setValue(true,M9Int.INTERIOR,M9Int.BOUNDARY); } // boundary of L2 if(Segs2>1){ // intersection of both interiors goal.setValue(true,M9Int.INTERIOR,M9Int.INTERIOR); } // both interiors } // interior of L1 } // checkPointsBasic /** helping method to compute top Rel in the basic */ private static void checkEndPoints(FLine L1,FLine L2, BasicPoint BP, M9Int goal){ int Segs1 = L1.numberOfSegments(BP); int Segs2 = L2.numberOfSegments(BP); checkPointsBasic(Segs1,Segs2,goal); } /** * computed the 9-Intersection-matrix from this FLine and L2 */ M9Int basicTopolRelation(FLine L2){ M9Int result = new M9Int(); if (this.isEmpty() || L2.isEmpty()) return null; result.setValue(true,M9Int.EXTERIOR,M9Int.EXTERIOR); int currentThis=0; int currentL2=0; int maxThis = fSeg.getSize(); int maxL2 = L2.fSeg.getSize(); fSegment thisFirst; fSegment L2First; BasicSegment thisBasic; BasicSegment L2Basic; BasicSegment Smallest=null; BasicPoint BP1,BP2; int compare; int thisSegs; int L2Segs; while(currentThis 0) { // process single Segment of L2 result.setValue(true,M9Int.EXTERIOR,M9Int.INTERIOR); Smallest=L2Basic; currentL2++; } // process Endpoints of Segment(s) BP1 = Smallest.getEP1(); BP2 = Smallest.getEP2(); checkEndPoints(this,L2,BP1,result); checkEndPoints(this,L2,BP2,result); }// while while(currentThis * pos must be in [0,1] */ double getMaxValue(BasicSegment BS, double pos){ if(pos<0 || pos>1) return 0; fSegment FS = (fSegment) fSeg.search(BS); if(FS==null) return 0; double Z1,Z2; Z1 = FS.getZ1(); Z2 = FS.getZ2(); return Z1+pos*(Z2-Z1); } /** compute the top Rel between this and L */ public FuzzyTopRel topolRelation(FLine L){ int currentThis=0; int currentL=0; int maxThis=fSeg.getSize(); int maxL = fSeg.getSize(); fSegment fST,fSL; BasicSegment BST,BSL; int compare; BasicPoint BP1,BP2; double Z1T,Z2T,Z1L,Z2L; FuzzyTopRel result = new FuzzyTopRel(); while(currentThis0){ // test on boundary of this currentL++; BP1 = BSL.getEP1(); BP2 = BSL.getEP2(); if(this.contains(BP1)){ Z1L = fSL.getZ1(); Z1T = this.maxZfkt(BP1); result.computeValue(Z1T,Z1L); } if(this.contains(BP2)){ Z1L = fSL.getZ2(); Z1T = this.maxZfkt(BP2); result.computeValue(Z1T,Z1L); } } if(compare==0){ // common segment currentL++; currentThis++; Z1T = fST.getZ1(); Z2T = fST.getZ2(); Z1L = fSL.getZ1(); Z2L = fSL.getZ2(); if( Z1T==Z1L | Z2T==Z2L){ result.computeValue(Z1T,Z1L); result.computeValue(Z2T,Z2L); } else{ if( (Z1T>Z1L & Z2T>Z2L) | (Z1T equal value result.computeValue(0.5,0.5); if( (Z1L==Z1R) & (Z2L==Z2R) ) // equals segments result.computeValue(0.5,0.5); } else{ // in the regions exists crossing triangles over this BS Z1R = values[0]; Z2R = values[1]; double ZMR = values[3]; double ZML = Z1L + values[2]*(Z2L-Z1L); if(Z1L!=Z1R) // only inner values result.computeValue(Z1L,Z1R); result.computeValue(ZML,ZMR); if(Z2L!=Z2R) result.computeValue(Z2L,Z2R); if( ((Z1L-Z1R)*(ZML-ZMR)<0) || ((ZML-ZMR)*(Z2L-Z2R)<0) ) result.computeValue(0.5,0.5); } } // R contains Segment if(R.contains(BP1)){ Z1R = R.maxZfkt(BP1); result.computeValue(Z1L,Z1R); } if(R.contains(BP2)){ Z2R = R.maxZfkt(BP2); result.computeValue(Z2L,Z2R); } } // for return result; } /** computes the top.rel. between this and CO */ public FuzzyTopRel topolRelation(CompositeObject CO){ FuzzyTopRel result; if(CO instanceof FPoint){ result = ((FPoint) CO).topolRelation(this); result.makeSym(); return result; } if(CO instanceof FLine) return topolRelation((FLine) CO); if(CO instanceof FRegion) return topolRelation((FRegion) CO); return null; } /** returns the ListExpr representation of this FLine * (SF , ()) */ public ListExpr toListExpr(){ // first create the SegmentList ListExpr Segments; ListExpr Last=null; if(fSeg.getSize()==0) Segments = ListExpr.theEmptyList(); else { Segments = ListExpr.oneElemList( ((fSegment)fSeg.get(0)).toListExpr()); Last = Segments; } fSegment NextSegment; for(int i=1;i*/ public ListExpr toTypedListExpr(){ return ListExpr.twoElemList( ListExpr.symbolAtom("fline"),toListExpr()); } /** read this FLine from a ListExpr * @return true if LE is a valid Representaion of a FLine * all valid Segments of this List are inserted */ public boolean readFromListExpr(ListExpr LE){ SF = 1.0; fSeg.makeEmpty(); computeBoundingBox(); if(LE==null) return false; if(LE.listLength()!=2) return false; ListExpr SFList = LE.first(); if( !( SFList.isAtom() && (SFList.atomType()==ListExpr.INT_ATOM || SFList.atomType()==ListExpr.REAL_ATOM))) return false; double z= SFList.atomType()==ListExpr.INT_ATOM ? SFList.intValue() : SFList.realValue(); if(z<=0) return false; this.SF = z; ListExpr Segments = LE.second(); fSegment S; boolean ok = true; while( !Segments.isEmpty() & ok) { S = new fSegment(0,0,0,0,0,0); if(S.readFromListExpr(Segments.first())){ add(S); Segments=Segments.rest(); } else ok = false; } return ok; } /** returns a String representation of * the corresponding ListExpr */ public String toListString(){ return toListExpr().writeListExprToString(); } /** read the FLine from a String representation of a ListExpr * @return true if List is a String of a ListExpr * containing a correct FLine */ public boolean readFromListString(String List){ ListExpr LE = new ListExpr(); if(LE.readFromString(List)!=0){ return false; } else{ return readFromListExpr(LE); } } /** this method is used for reading a fuzzy line * from a byte array; * returns null if the construction of the object failed */ public static FLine readFrom(byte[] buffer){ try{ ObjectInputStream ois; ois= new ObjectInputStream( new ByteArrayInputStream(buffer)); FLine res = (FLine) ois.readObject(); ois.close(); return res; } catch(Exception e){ return null; } } /** this method serialized an object */ public byte[] writeToByteArray(){ try{ ByteArrayOutputStream byteout; byteout = new ByteArrayOutputStream(fSeg.getSize()*16+25); ObjectOutputStream objectout; objectout = new ObjectOutputStream(byteout); objectout.writeObject(this); objectout.flush(); byte[] res = byteout.toByteArray(); objectout.close(); return res; } catch(Exception e){ return null; } } /** computes a hash-value for this FPoint */ public int getHashValue(){ return Math.abs((BB.getMaxX()-BB.getMinX())* (BB.getMaxY()-BB.getMinY())+BB.getMinX() +BB.getMinY()); } // define constants for the operators private static final int UNION = 0; private static final int INTERSECTION=1; private static final int ADD=2; private static final int SUBTRACT=3; private static final int SCALEDUNION=4; private static final int SCALEDINTERSECTION=5; private static final int SCALEDADD=6; private static final int SCALEDDIFFERENCE=7; private static final int SHARPINTERSECTION=8; // == intersection(sharp(L1),sharp(L2)) } // FLine;