import twodsack.operation.basictypeoperation.*; import twodsack.operation.setoperation.*; import twodsack.set.*; import twodsack.setelement.*; import twodsack.setelement.datatype.basicdatatype.*; import twodsack.setelement.datatype.compositetype.*; import twodsack.util.collection.*; import twodsack.util.collectiontype.*; import twodsack.util.comparator.*; import twodsack.util.number.*; import twodsack.io.*; import twodsack.util.meshgenerator.*; import java.util.*; import java.lang.reflect.*; import java.io.*; /** * The ROSEAlgebra class implements the operations for the ROSE's data types Points, Lines and Regions. * The algebra itself was invented and described in two papers

* This implementation of the ROSE algebra and its data types (presented in the classes Points, Lines, Regions) * uses the 2D-SACK approach. That approach was invented by Dirk Ansorge * and R.H. Gueting. It shows how simplices and operations on them together with some generic set operations can be used * to reimplement the ROSE algebra. *

* This work is part of the Ph.D. thesis of Dirk Ansorge. *

*/ public class ROSEAlgebra { /* * fields */ //some static class definitions which are used over and over in the code below static final Class POINT_CLASS = (new Point()).getClass(); static final Class SEG_CLASS = (new Segment()).getClass(); static final Class TRI_CLASS = (new Triangle()).getClass(); static final Class PS_OPS_CLASS = (new PointSeg_Ops()).getClass(); static final Class PT_OPS_CLASS = (new PointTri_Ops()).getClass(); static final Class SS_OPS_CLASS = (new SegSeg_Ops()).getClass(); static final Class ST_OPS_CLASS = (new SegTri_Ops()).getClass(); static final Class EMS_CLASS = (new ElemMultiSet(new ElemComparator())).getClass(); final static Class[] PARAMLIST_P = { POINT_CLASS }; final static Class[] PARAMLIST_S = { SEG_CLASS }; final static Class[] PARAMLIST_T = { TRI_CLASS }; final static Class[] PARAMLIST_PS = { POINT_CLASS, SEG_CLASS }; final static Class[] PARAMLIST_PT = { POINT_CLASS, TRI_CLASS }; final static Class[] PARAMLIST_SS = { SEG_CLASS, SEG_CLASS }; final static Class[] PARAMLIST_ST = { SEG_CLASS, TRI_CLASS }; final static Class[] PARAMLIST_EMS = { EMS_CLASS }; static Class ELEM_CLASS; static { try { ELEM_CLASS = Class.forName("twodsack.setelement.Element"); } catch (Exception e) { e.printStackTrace(); throw new RoseAlgebraError("An error occurred while searching for the twodsack.setelement.Element class in the ROSEAlgebra."); }//catch }//static final static Class[] PARAMLIST_E = { ELEM_CLASS }; final static PointComparator POINT_COMPARATOR = new PointComparator(); final static SegmentComparator SEGMENT_COMPARATOR = new SegmentComparator(); final static TriangleComparator TRIANGLE_COMPARATOR = new TriangleComparator(); final static ElemComparator ELEMENT_COMPARATOR = new ElemComparator(); final static ElemPairComparator ELEMPAIR_COMPARATOR = new ElemPairComparator(); final static MeshGenerator MESHGENERATOR = new MeshGenerator(); /* * constructors */ /** * Don't use this constructor. */ private ROSEAlgebra() {} /* * methods */ /** * A supportive method - not part of the ROSE algebra. * It returns true if elements of both sets intersect. The pintersects method of the elements is used for this * predicate. * * @param ems1 the first set of elements * @param ems2 the second set of elements * @return true if there is at least one pair of intersecting elments */ private static boolean intersects (ElemMultiSet ems1, ElemMultiSet ems2) { if (ems1 == null || ems1.isEmpty() || ems2 == null || ems2.isEmpty()) return false; PairMultiSet pms = new PairMultiSet(ELEMPAIR_COMPARATOR); Class [] paramList = new Class [1]; Class c = ems1.first().getClass(); try { paramList[0] = Class.forName("twodsack.setelement.Element"); Method methodINTERSECTS = c.getMethod("pintersects",paramList); pms = SetOps.overlapJoin(ems1,ems2,methodINTERSECTS,true,true,false,0); } catch (Exception e) { throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch if (pms.isEmpty()) return false; else return true; }//end method intersects /****************************************************************** * the following operations are part of the original ROSE algebra * ******************************************************************/ /** * Returns true if both Points values are equal. * * @param p1 the first point set * @param p2 the second point set * @return true if both values are equal */ public static boolean pp_equal (Points p1, Points p2) { if (!p1.rect().hasCommonPoints(p2.rect())) return false; try { return SetOps.equal(p1.pointset,p2.pointset); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.pp_equal. Return false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method pp_equal /** * Returns true if both Lines values are equal. * * @param l1 the first Lines value * @param l2 the second Lines value * @return true if both values are equal */ public static boolean ll_equal (Lines l1, Lines l2) { if (!l1.rect().hasCommonPoints(l2.rect())) return false; try { return SetOps.equal(SupportOps.minimal(l1.segset,true,false,false),SupportOps.minimal(l2.segset,true,false,false)); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.ll_equal. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method ll_equal /** * Returns true if both Regions values are equal. * * @param r1 the first Regions value * @param r2 the second Regions value * @return true if both values are equal */ public static boolean rr_equal (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return false; try { return ll_equal(r1.border(),r2.border()); //return ll_equal(new Lines(SupportOps.contour(r1.triset,true,false)),new Lines(SupportOps.contour(r2.triset,true,false))); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_equal. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_equal /** * Returns true if the Points values are not equal. * * @param p1 the first Points value * @param p2 the second Points value * @return true if the values are not equal */ public static boolean pp_unequal (Points p1, Points p2) { if (!p1.rect().hasCommonPoints(p2.rect())) return true; try { return !pp_equal(p1,p2); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.pp_unequal. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method pp_unequal /** * Returns true if the Lines values are not equal. * * @param l1 the first Lines value * @param l2 the second Lines value * @return true if the values are not equal */ public static boolean ll_unequal (Lines l1, Lines l2) { if (!l1.rect().hasCommonPoints(l2.rect())) return true; try { return !ll_equal(new Lines(l1.segset),new Lines(l2.segset)); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.ll_unequal. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method ll_unequal /** * Returns true if the Regions values are not equal. * * @param r1 the first Regions value * @param r2 the second Regions value * @return true if the Regions are not equal */ public static boolean rr_unequal (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return true; try { return !rr_equal(r1,r2); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_unequal. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_unequal /** * Returns true if there is no single point which is element of both Points values. * * @param p1 the first Points value * @param p2 the second Points value * @return true if the intersection of both Points values is empty */ public static boolean pp_disjoint (Points p1, Points p2) { if (!p1.rect().hasCommonPoints(p2.rect())) return true; try { return SetOps.disjoint(p1.pointset,p2.pointset); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.pp_disjoint. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method pp_disjoint /** * Returns true if no two elements of both Lines values intersect. * Common points of two segments of the Lines values suffice to make this predicate true. * * @param l1 the first Lines value * @param l2 the second Lines value * @return true, if two intersecting segments exist */ public static boolean ll_disjoint (Lines l1, Lines l2) { if (!l1.rect().hasCommonPoints(l2.rect())) return true; try { return SetOps.disjoint(l1.segset,l2.segset); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.ll_disjoint. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method ll_disjoint /** * Returns true if no two elements of both Regions values intersect. * Common points on the border of the Regions values suffice to make this predicate true. * * @param r1 the first Regions value * @param r2 the second Regions value * @return true, if the Regions values have at least one common point */ public static boolean rr_disjoint (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return true; try { return SetOps.disjoint(r1.triset,r2.triset); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_disjoint. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_disjoint /** * Returns true, if p lies inside of r. * If p lies on the border of r false is returned. * * @param p the Points values * @param r the Regions value * @return true, if p properly lies inside of r */ public static boolean pr_inside (Points p, Regions r) { if (!p.rect().hasCommonPoints(r.rect())) return false; try { PointMultiSet retSet = null; PairMultiSet pms = null; Method methodINSIDE = PT_OPS_CLASS.getMethod("inside",PARAMLIST_PT); try { pms = SetOps.overlapJoin(p.pointset,r.triset,methodINSIDE,true,true,true,1); } catch (EarlyExit exit) { return false; }//catch retSet = PointMultiSet.convert(SetOps.rdup(SetOps.proj1(pms))); if (p.pointset.size() == retSet.size()) return true; else return false; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.pr_inside. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method pr_inside /** * Returns true, if l lies inside of r. * * @param l the Lines value * @param r the Regions value * @return true, if l lies inside of r */ public static boolean lr_inside (Lines l, Regions r) { if (!l.rect().hasCommonPoints(r.rect())) return false; try { SegMultiSet retSet = null; try { retSet = SupportOps.minus(l.segset,r.triset,true,false,1); } catch (EarlyExit exit) { return false; }//catch if (retSet.size() == 0) return true; else return false; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.lr_inside. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method lr_inside /** * Returns true, if one Regions value lies fully inside of the other one. * I.e. one region must be completely covered by the other region to make this predicate true. * * @param r1 the Regions value that covers the other one * @param r2 the Regions value that must be covered * @param true, if r2 is covered by r1 */ public static boolean rr_inside (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return false; try { return rr_minus(r1,r2).triset.isEmpty(); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_inside. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_inside /** * Returns true if both Regions values have no common area. * * @param r1 the first region * @param r2 the second region * @return true, if no common area exists */ public static boolean rr_area_disjoint (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return true; try { PairMultiSet pms = null; Method methodPINTERSECTS = TRI_CLASS.getMethod("pintersects",PARAMLIST_T); pms = SetOps.overlapJoin(r1.triset,r2.triset,methodPINTERSECTS,false,true,false,0); if (pms == null || pms.size() == 0) return true; else return false; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_area_disjoint. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_area_disjoint /** * Returns true, if both Regions have no common border. * * @param r1 the first Regions value * @param r2 the second Regions value * @return true, if no common border exists */ public static boolean rr_edge_disjoint (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return true; try { return (rr_area_disjoint(r1,r2) && !rr_border_in_common(r1,r2)); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_edge_disjoint. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_edge_disjoint /** * Returns true if r1 is edge_inside of r2. * For r1 being edge_inside of r2, it must have its complete border inside of r2 and * both regions must not have some overlapping border segments. * * @param r1 the first Regions value * @param r2 the second Regions value * @return true, if r1 is edge_inside of r2 */ public static boolean rr_edge_inside (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return false; try { SegMultiSet r1contour = SupportOps.contour(r1.triset,true,false); SegMultiSet r2contour = SupportOps.contour(r2.triset,true,false); return lr_inside(new Lines(r1contour),r2) && !ll_border_in_common(new Lines(r1contour), new Lines(r2contour)); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_edge_inside. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_edge_inside /** * Returns true, if r2 is vertex_inside of r1. * To be vertex_inside of r1, r2 must lie completely inside of r1 and must not * have equal vertices. * * @param r1 the first Regions value * @param r2 the second Regions value * @return true, if r2 is vertex_inside of r1 */ public static boolean rr_vertex_inside (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return false; try { PointMultiSet pmsR2 = r_vertices(r2).pointset; PairMultiSet pairs = null; PointMultiSet insidePoints = null; Method methodLIESON = null; Method methodISCOVERED = PT_OPS_CLASS.getMethod("isCovered",PARAMLIST_PT); methodLIESON = PS_OPS_CLASS.getMethod("liesOn",PARAMLIST_PS); try { pairs = SetOps.overlapJoin(pmsR2,r1.triset,methodISCOVERED,true,true,true,1); } catch (EarlyExit exit) { return false; }//catch insidePoints = PointMultiSet.convert(SetOps.rdup(SetOps.proj1(pairs))); if (pmsR2.size != insidePoints.size()) return false; //now check, whether any points of insidePoints lie on the border of r1 PointMultiSet retSet = null; try { retSet = PointMultiSet.convert(SetOps.rdup(SetOps.proj1(SetOps.overlapJoin(insidePoints,SupportOps.contour(r1.triset,true,false),methodLIESON,true,true,true,1)))); } catch (Exception EarlyExit) { return false; }//catch if (retSet.size != 0) return false; else return true; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_vertex_inside. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_vertex_inside /** * Returns true, if at least one pair of segments of l1,l2 has a proper intersection point. * A simple overlap of two segments doesn't suffice for this predicate to hold. * * @param l1 the first Lines value * @param l2 the second Lines value * @return true if l1,l2 intersect */ public static boolean ll_intersects (Lines l1, Lines l2) { if (!l1.rect().hasCommonPoints(l2.rect())) return false; try { PairMultiSet retSet = null; if (ll_border_in_common(l1,l2)) return false; Method methodINTERSECTS = SEG_CLASS.getMethod("intersects",PARAMLIST_E); retSet = SetOps.overlapJoin(l1.segset,l2.segset,methodINTERSECTS,true,true,false,0); int rsSize = retSet.size(); if (rsSize == 0) return false; Method methodPINTERSECTS = SEG_CLASS.getMethod("pintersects",PARAMLIST_E); retSet = SetOps.filter(retSet,methodPINTERSECTS,false); //If the number of elements decreasees, some segments pintersect. We can return true in that case. if (retSet.size() < rsSize) return true; Method methodOVERLAP = SS_OPS_CLASS.getMethod("overlap",PARAMLIST_SS); retSet = SetOps.filter(retSet,methodOVERLAP,false); Boolean[] retArr = SupportOps.evaluateIntersectionAndMeets(retSet); return retArr[0].booleanValue(); } catch (Exception e) { e.printStackTrace(); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method ll_intersects /** * Returns true, if l,r properly intersect. * This predicate doesn't hold, if l lies on the border of r. * * @param l the Lines value * @param r the Regions value * @return true, if the intersection of l,r is a Lines value */ public static boolean lr_intersects (Lines l, Regions r) { if (!l.rect().hasCommonPoints(r.rect())) return false; try { PairMultiSet retSet = null; //A problem is, that the lines object may lie on the triangles's border segments. //In that case, the result would be FALSE, even if the lines object overlaps the inner //borders and the correct answer would we TRUE. Therefore, first all segments which //overlap the border are removed from the set. Afterwards, all segments, that //are covered by triangles are truely intersecting. This is described in the old implementation. /* OLD IMPLEMENTATION Method mPINTERSECTS = ST_OPS_CLASS.getMethod("pintersects",PARAMLIST_ST); retSet = SetOps.overlapJoin(l.segset,r.triset,mPINTERSECTS,false,true,false,0); if (retSet.isEmpty()) return false; else return true; */ Lines opLines = ll_minus(l,new Lines(SupportOps.contour(r.triset,false,false))); Method mISCOVERED = ST_OPS_CLASS.getMethod("isCovered",PARAMLIST_ST); retSet = SetOps.overlapJoin(opLines.segset,r.triset,mISCOVERED,false,true,false,0); if (retSet.isEmpty()) return false; else return true; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.lr_intersects. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method lr_intersects /** * Returns true, if l,r properly intersect. * This predicate doesn't hold, if l lies on the border of r. * * @param r the Regions value * @param l the Lines value * @return true, if the intersection of l,r is a Lines value */ public static boolean rl_intersects (Regions r, Lines l) { if (!r.rect().hasCommonPoints(l.rect())) return false; try { return lr_intersects(l,r); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rl_intersects. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rl_intersects /** * Returns true, if r1,r2 have a common area. * * @param r1 the first Regions value * @param r2 the second Regions value * @return true if r1,r2 intersect */ public static boolean rr_intersects (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return false; try { return intersects(r1.triset,r2.triset); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_intersects. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_intersects /** * Returns true, if l1,l2 meet. * There must be at least one pair of line segments that meets, i.e. they have one common point. But there must not be * a pair of line segments that properly intersects. * * @param l1 the first Lines value * @param l2 the second Lines value * @return true, if l1,l2 meet */ public static boolean ll_meets (Lines l1, Lines l2) { //Compute a set with all intersecting lines. Then, check whether there are pairs of lines //that overlap or pintersect. If any, return false. If there are pairs left, they may be //lines that meet (but still can be lines that 'intersect' at endpoints; note, that //the _segment_ may meet in endpoints, but the _lines_ may intersects at exactly that point). //Construct a graph from this set and call checkVerticesForIntersectionAndMeets. if (!l1.rect().hasCommonPoints(l2.rect())) return false; try { PairMultiSet retSet = null; if (ll_border_in_common(l1,l2)) return false; Method methodINTERSECTS = SEG_CLASS.getMethod("intersects",PARAMLIST_E); retSet = SetOps.overlapJoin(l1.segset,l2.segset,methodINTERSECTS,true,true,false,0); int rsSize = retSet.size(); if (rsSize == 0) return false; Method methodPINTERSECTS = SEG_CLASS.getMethod("pintersects",PARAMLIST_E); retSet = SetOps.filter(retSet,methodPINTERSECTS,false); //If the number of elements decreases, some segments pintersect. This is not allowed //for two lines that meet. Return false. if (retSet.size() < rsSize) return false; Method methodOVERLAP = SS_OPS_CLASS.getMethod("overlap",PARAMLIST_SS); retSet = SetOps.filter(retSet,methodOVERLAP,false); //Same reason as above: Return false if number decreases. if (retSet.size() < rsSize) return false; Boolean[] retArr = SupportOps.evaluateIntersectionAndMeets(retSet); if (retArr[0].booleanValue() || !retArr[1].booleanValue()) return false; return true; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.ll_meets. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method ll_meets /** * Returns true, if l and r meet. * This predicate holds, if l doesn't intersect r, but meets its border. * * @param l the Lines value * @param r the Regions value * @return true, if l,r meet */ public static boolean lr_meets (Lines l, Regions r) { if (l.rect().hasCommonPoints(r.rect())) return false; try { return !lr_intersects(l,r) && ll_meets(l,new Lines(SupportOps.contour(r.triset,false,false))); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.lr_meets. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method lr_meets /** * Returns true, if l and r meet. * This predicate holds, if l doesn't intersect r, but meets its border. * * @param r the Regions value * @param l the Lines value * @return true, if l,r meet */ public static boolean rl_meets (Regions r, Lines l) { if (r.rect().hasCommonPoints(l.rect())) return false; try { return lr_meets(l,r); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rl_meets. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rl_meets /** * Returns true, if r1,r2 meet. * Two Regions values meet, if they don't have a common area, but the borders meet (in one point). * * @param r1 the first Regions value * @param r2 the second Regions value * @return true, if r1,r2 meet */ public static boolean rr_meets (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return false; try { PairMultiSet retSet = null; Method methodPINTERSECTS = TRI_CLASS.getMethod("pintersects",PARAMLIST_T); retSet = SetOps.overlapJoin(r1.triset,r2.triset,methodPINTERSECTS,false,true,false,0); return (retSet.size()) == 0 && ll_meets(new Lines(SupportOps.contour(r1.triset,false,false)), new Lines(SupportOps.contour(r2.triset,false,false))); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_meets. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_meets /** * Returns true, if l1,l2 have some border segments in common. * These common border doesn't have to consist of completely equal line segments. Overlapping line segments suffice * to make this predicate true. * * @param l1 the first Lines value * @param l2 the second Lines value * @return true, if l1,l2 have a common border */ public static boolean ll_border_in_common (Lines l1, Lines l2) { if (!l1.rect().hasCommonPoints(l2.rect())) return false; try { PairMultiSet retSet = null; Method methodOVERLAP = SS_OPS_CLASS.getMethod("overlap",PARAMLIST_SS); retSet = SetOps.overlapJoin(l1.segset,l2.segset,methodOVERLAP,true,true,false,0); if (retSet.isEmpty()) return false; else return true; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.ll_border_in_common. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method ll_border_in_common /** * Returns true, if l,r have a common border. * l has to overlap the border of r in order to make this predicate true. * * @param l the Lines value * @param r the Regions value * @return true, if l,r have a common border */ public static boolean lr_border_in_common (Lines l, Regions r) { if (!l.rect().hasCommonPoints(r.rect())) return false; try { PairMultiSet retSet = null; Method methodOVERLAP = SS_OPS_CLASS.getMethod("overlap",PARAMLIST_SS); retSet = SetOps.overlapJoin(l.segset,SupportOps.contour(r.triset,true,false),methodOVERLAP,true,true,false,0); if (retSet.isEmpty()) return false; else return true; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.lr_border_in_common. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method lr_border_in_common /** * Returns true, if l,r have a common border. * l has to overlap the border of r in order to make this predicate true. * * @param r the Regions value * @param l the Lines value * @return true, if l,r have a common border */ public static boolean rl_border_in_common (Regions r, Lines l) { if (!r.rect().hasCommonPoints(l.rect())) return false; try { return lr_border_in_common(l,r); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rl_border_in_common. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rl_border_in_common /** * Returns true, if r1,r2 have a common border. * Some part of the Regions value's border must overlap. Then, this predicate holds. * * @param r1 the first Regions value * @param r2 the second Regions value * @return true, if r1,r2 have a common border */ public static boolean rr_border_in_common (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return false; try { return ll_border_in_common(new Lines(SupportOps.contour(r1.triset,true,false)),new Lines(SupportOps.contour(r2.triset,true,false))); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_border_in_common. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_border_in_common /** * Returns true, if r1,r2 don't have a common area but have a comon boundary. * * @param r1 the first Regions value * @param r2 the second Regiond value * @return true, if r1,r2 are adjacent */ public static boolean rr_adjacent (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return false; try { PairMultiSet pms = null; Method methodPINTERSECTS = TRI_CLASS.getMethod("pintersects",PARAMLIST_T); pms = SetOps.overlapJoin(r1.triset,r2.triset,methodPINTERSECTS,false,true,false,0); boolean intersection = !(pms == null || pms.size() == 0); return !intersection && rr_border_in_common(r1,r2); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_adjacent. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_adjacent /** * Returns true, if r2 lies completely inside of holes of r1. * * @param r1 the first Regions value * @param r2 the second Regions value * @return true, if r1 encloses r2 */ public static boolean rr_encloses (Regions r1, Regions r2) { //The implementation of this operation works as follows: // - compute the cycles of r1 using Polygons.cyclesSegments //As result, we get a CycleListList which has for every face //of the region a list of cycles. These cycles are the holes //of that regions. (Note, that islands in holes are not supported //by Polygons.cyclesSegments.) // - store all hole cycles in HC // - compute a mesh for HC // - compute RES = minus(r2,HC) // - if RES is empty, return true, otherwise return false if (!r1.rect().hasCommonPoints(r2.rect())) return false; try { Polygons r1POL = new Polygons(r1.triset); CycleListList r1cycles = r1POL.cyclesSegments(); //store hole cycles in holePolygon SegMultiSet collectedHoleSegments = new SegMultiSet(SEGMENT_COMPARATOR); Iterator it = r1cycles.iterator(); Iterator it2 = null; Iterator it3 = null; CycleList actCycleList; LinkedList actCycle; while (it.hasNext()) { actCycleList = (CycleList)it.next(); //start with the second cycle, if there is one, because the first cycle //is the outer cycle for the actual face if (actCycleList.size() > 1) { it2 = actCycleList.listIterator(1); while (it2.hasNext()) { actCycle = (LinkedList)it2.next(); //store the segments of actCycle in collectedHoleSegments it3 = actCycle.iterator(); while (it3.hasNext()) { collectedHoleSegments.add((Segment)it3.next()); }//while it3 }//while it2 }//if size > 1 }//while it Regions resRegion = rr_minus(r2,new Regions(collectedHoleSegments)); if (resRegion.triset.size() == 0) return true; else return false; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_encloses. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_encloses /** * Returns true, if p lies on the border of l. * No single point of p may lie not on l. * * @param p the Points value * @param l the Lines value * @return true, if p lies on l */ public static boolean pl_on_border_of (Points p, Lines l) { if (!p.rect().hasCommonPoints(l.rect())) return false; try { PointMultiSet retSet = null; Method methodLIESON = PS_OPS_CLASS.getMethod("liesOn",PARAMLIST_PS); try { retSet = PointMultiSet.convert(SetOps.rdup(SetOps.proj1(SetOps.overlapJoin(p.pointset,l.segset,methodLIESON,true,false,true,1)))); } catch (EarlyExit exit) { return false; }//catch return pp_equal(new Points(retSet),p); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.pl_on_border_of. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method pl_on_border_of /** * Returns true, if p lies on the border of r. * * @param p the Points value * @param r the Regions value * @return true, if p lies on the border of r */ public static boolean pr_on_border_of (Points p, Regions r) { if (!p.rect().hasCommonPoints(r.rect())) return false; try { PointMultiSet retSet = null; Method methodLIESON = PS_OPS_CLASS.getMethod("liesOn",PARAMLIST_PS); try { retSet = PointMultiSet.convert(SetOps.rdup(SetOps.proj1(SetOps.overlapJoin(p.pointset,SupportOps.contour(r.triset,true,false),methodLIESON,true,true,true,1)))); } catch (Exception EarlyExit) { return false; }//catch return pp_equal(new Points(retSet),p); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.pr_on_border_of. Returning false by default."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method pr_on_border_of /** * Returns the intersection of two Points values. * Since a Points value represents a set of points, the result simply is the intersection of both sets. * * @param p1 the first Points value * @param p2 the second Points value * @return the intersection of p1,p2 */ public static Points pp_intersection (Points p1, Points p2) { if (!p1.rect().hasCommonPoints(p2.rect())) return new Points(); try { PointMultiSet retSet = null; retSet = PointMultiSet.convert(SetOps.intersection(p1.pointset,p2.pointset)); return new Points(retSet); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.pp_intersection. Returning empty Points value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method pp_intersection /** * Returns a new Points value which consists of the intersection points of l1,l2. * If there are no intersection points, an empty set is returned. * * @param l1 the first Lines value * @param l2 the second Lines value * @return the set of intersection points */ public static Points ll_intersection (Lines l1, Lines l2) { if (!l1.rect().hasCommonPoints(l2.rect())) return new Points(); try { ElemMultiSet retSet = null; Method m1 = SEG_CLASS.getMethod("intersects",PARAMLIST_E); Method m2 = SEG_CLASS.getMethod("intersection",PARAMLIST_S); retSet = SetOps.rdup(SetOps.map(SetOps.overlapJoin(l1.segset,l2.segset,m1,true,true,false,0),m2)); return new Points(PointMultiSet.convert(retSet)); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.ll_intersection. Returning empty Points value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method ll_intersection /** * For two intersection Regions values, this method returns a new Regions value that represents the common area of both. * If the Regions don't intersect, an empty Regions value is returned. * * @param r1 the first Regions value * @param r2 the second Regions value * @return the area representing the intersection of both regions */ public static Regions rr_intersection (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return new Regions(); try { Regions res = new Regions(SupportOps.intersection(r1.triset,r2.triset,true)); return res; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_intersection. Returning empty Regions value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_intersection /** * Returns that part of l that is covered by r. * * @param r the Regions value * @param l the Lines value * @return the covered part of l */ public static Lines rl_intersection (Regions r, Lines l) { if (!r.rect().hasCommonPoints(l.rect())) return new Lines(); try { SegMultiSet retSet = null; Method methodPINTERSECTS = ST_OPS_CLASS.getMethod("pintersects",PARAMLIST_ST); Method methodINTERSECTION = ST_OPS_CLASS.getMethod("intersection",PARAMLIST_ST); retSet = SupportOps.minimal(SegMultiSet.convert(SetOps.map(SetOps.overlapJoin(l.segset,r.triset,methodPINTERSECTS,true,true,false,0),methodINTERSECTION)),true,true,false); return new Lines(retSet); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rl_intersection. Returning empty Lines value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//return rl_intersection /** * Returns the union of p1,p2. * * @param p1 the first Points value * @param p2 the second Points value * @return the union of p1,p2 */ public static Points pp_plus (Points p1, Points p2) { try { PointMultiSet retSet = null; retSet = PointMultiSet.convert(SetOps.union(p1.pointset,p2.pointset)); return new Points(retSet); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.pp_plusturning empty Points value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method pp_plus /** * Returns the union of l1,l2. * Overlapping line segments are merged to new line segments. * * @param l1 the first Lines value * @param l2 the second Lines value * @return the union of l1,l2 */ public static Lines ll_plus (Lines l1, Lines l2) { //Explanation for ll_plus: This operation cannot be implemented similar to ll_minus. //The reason is that a segment l1 of L can overlap two segments m1,m2 of M. When //using the same mechanism, we would get two overlapping segments in the returned set //from Segment.plus. Therefore, we choose another algorithm: // - compute the union of l1,l2 // - compute overlapGroup with predicate SSO.overlap // - for every such group, call Segment.plus using the group's first element as // base element and the rest as parameter // - return the union of the results of Segment.plus try { SegMultiSet retSet = new SegMultiSet(SEGMENT_COMPARATOR); //compute union of l1,l2 SegMultiSet workSet = new SegMultiSet (SEGMENT_COMPARATOR); workSet.addAll(l1.segset); workSet.addAll(l2.segset); ElemMultiSetList emsl = null; Method methodPLUS = SEG_CLASS.getMethod("plus",PARAMLIST_EMS); //compute overlapGroup Method methodOVERLAP = SS_OPS_CLASS.getMethod("overlap",PARAMLIST_SS); emsl = SetOps.overlapGroup(workSet,methodOVERLAP,true); //for every group, compute Segment.plus Iterator it = emsl.iterator(); ElemMultiSet actGroup; while (it.hasNext()) { actGroup = (ElemMultiSet)it.next(); retSet.addAll(((Segment)actGroup.first()).plus(actGroup)); }//while return new Lines(retSet); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.ll_plus. Returning empty Lines value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method ll_plus /** * Returns the union of r1,r2. * * @param r1 the first Regions value * @param r2 the second Regions value * @return the union of r1,r2 */ public static Regions rr_plus (Regions r1, Regions r2) { try { Regions res; res = new Regions(SupportOps.plus(r1.triset,r2.triset,false,true)); return res; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_plus. Returning empty Regions value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_plus /** * Returns p1 minus p2. * Since Points values simply store sets of points, equal points are removed from p1 here. * * @param p1 the first Points value * @param p2 the second Points value * @return p1 - p2 */ public static Points pp_minus (Points p1, Points p2) { try { PointMultiSet retSet = null; retSet = PointMultiSet.convert(SetOps.difference(p1.pointset,p2.pointset)); return new Points(retSet); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.pp_minus. Returning empty Points value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method pp_minus /** * Subtracts l2 from l1. * If l2 has line segments that overlap line segments from l1, these parts are removed from l1. * * @param l1 the first set * @param l2 the second set * @return l1 - l2 */ public static Lines ll_minus (Lines l1, Lines l2) { try { SegMultiSet retSet = null; Method methodMINUS = SEG_CLASS.getMethod("minus",PARAMLIST_EMS); Method methodOVERLAP = SS_OPS_CLASS.getMethod("overlap",PARAMLIST_SS); LeftJoinPairMultiSet ljpms = SetOps.overlapLeftOuterJoin(l1.segset,l2.segset,methodOVERLAP,true,true,false,0); ljpms = SetOps.map(ljpms,null,methodMINUS); retSet = SegMultiSet.convert(SetOps.collect(ljpms)); return new Lines(retSet); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.ll_minus. Returning empty Lines value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method ll_minus /** * Subtracts r2 from r1. * The common part of r1,r2 is removed from r1. * * @param r1 the first Regions value * @param r2 the second Regions value * @return r1 - r2 */ public static Regions rr_minus (Regions r1, Regions r2) { try { Regions result = new Regions(SupportOps.minus(r1.triset,r2.triset,true)); return result; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_minus. Returning empty Regions value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_minus /** * Returns a new Lines value that stores the intersection of l1,l2 * * @param l1 the first Lines value * @param l2 the second Lines value * @return the intersection of l1,l2 */ public static Lines ll_common_border (Lines l1, Lines l2) { if (!l1.rect().hasCommonPoints(l2.rect())) return new Lines(); try { PairMultiSet joinSet = null; SegMultiSet retSet = null; Method methodOVERLAP = SS_OPS_CLASS.getMethod("overlap",PARAMLIST_SS); joinSet = SetOps.overlapJoin(l1.segset,l2.segset,methodOVERLAP,true,true,false,0); if (joinSet.isEmpty()) return new Lines(retSet); Method methodTHEOVERLAP = SS_OPS_CLASS.getMethod("theOverlap",PARAMLIST_SS); retSet = SupportOps.minimal(SegMultiSet.convert(SetOps.map(joinSet,methodTHEOVERLAP)),true,true,false); return new Lines(retSet); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.ll_common_border. Returning empty Lines value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method ll_common_border /** * Computes the intersection of l and the border of r. * * @param l the Lines value * @param r the Regions value * @return that part of l that overlaps the border of r */ public static Lines lr_common_border (Lines l, Regions r) { if (!l.rect().hasCommonPoints(r.rect())) return new Lines(); try { return ll_common_border(l,new Lines(SupportOps.contour(r.triset,true,false))); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.lr_common_border. Returning empty Lines value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method lr_common_border /** * Computes the intersection of l and the border of r. * * @param r the Regions value * @param l the Lines value * @return that part of l that overlaps the border of r */ public static Lines rl_common_border (Regions r, Lines l) { if (!r.rect().hasCommonPoints(l.rect())) return new Lines(); try { return lr_common_border(l,r); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rl_common_border. Returning empty Lines value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rl_common_border /** * Returns a new Lines value that stores the line segments that form the common border of r1,r2. * * @param r1 the first Regions value * @param r2 the second Regions value * @return the common border of r1,r2 */ public static Lines rr_common_border (Regions r1, Regions r2) { if (!r1.rect().hasCommonPoints(r2.rect())) return new Lines(); try { return ll_common_border(new Lines(SupportOps.contour(r1.triset,true,false)),new Lines(SupportOps.contour(r2.triset,true,false))); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_common_border. Returning empty Lines value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method rr_common_border /** * Returns all vertices of l. * The vertex set of l consists of all startpoints and endpoints of the line segments. Duplicates are removed. * * @param l the Lines value * @return the vertices of l */ public static Points l_vertices (Lines l) { try { PointMultiSet retSet = null; Method methodENDPOINTS = SEG_CLASS.getMethod("endpoints",null); retSet = PointMultiSet.convert(SetOps.rdup(SetOps.map(l.segset,methodENDPOINTS))); return new Points(retSet); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.l_vertices. Returning empty Points value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method l_vertices /** * Returns all vertices of r. * The vertex set of r consists of all startpoints and enspoints of the border of r. Duplicates are removed. * * @param r the Regions value * @return the set of vertices */ public static Points r_vertices (Regions r) { try { //return l_vertices(new Lines(SupportOps.contour(r.triset,true,true))); return l_vertices(r.border()); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.r_vertices. Returning empty Points value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method r_vertices /** * From a given Lines value, this method computes its interior, i.e. a new Regions value. * * @param l the Lines value * @return the interior of l */ public static Regions l_interior (Lines l) { try { return new Regions(Polygons.computeMesh(l.segset,true)); } catch (Exception e) { throw new RoseAlgebraError("The line object doesn't form proper cycles. Returning empty region value."); }//catch }//end method l_interior /** * Returns the contour of r. * The contour is not the same as the border. Instead, it consists of all outer cycles without holes. * * @param r the Regions value * @return the contour of r */ public static Lines r_contour(Regions r) { //Holes are omitted. try { if (r.triset.isEmpty()) return new Lines(); Polygons pol = new Polygons(r.triset); CycleListList polCLL = null; polCLL = pol.cyclesSegments2(); SegMultiSet sms = new SegMultiSet(SEGMENT_COMPARATOR); Iterator it = polCLL.iterator(); while (it.hasNext()) { //get the first cycle of every list sms.addAll(SegMultiSet.convert(SupportOps.convert( (LinkedList)((LinkedList)it.next()).getFirst()))); }//while return new Lines(sms); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.r_contour. Returning empty Lines value."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method r_contour /** * Returns the number of components of p. * The number of components is the number of (different) points. * * @param p the Points value * @return the number of components as int */ public static int p_no_of_components (Points p) { try { return SetOps.rdup(p.pointset).size(); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.p_no_of_components. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method p_no_of_components /** * Returns the number of components of l. * The number of components is the number of merged line segments. * * @param l the Lines value * @return the number of components as int */ public static int l_no_of_components (Lines l) { try { int retVal = 0; Method methodPOINTSINCOMMON = SS_OPS_CLASS.getMethod("pointsInCommon",PARAMLIST_SS); retVal = (SetOps.overlapGroup(l.segset,methodPOINTSINCOMMON,true)).size(); return retVal; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.l_no_of_components. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method l_no_of_components /** * Returns the number of components of r. * The number of components of a Regions value is the number of polygons it stores. * * @param r the Regions value * @return the number of compononts as int */ public static int r_no_of_components (Regions r) { try { int retVal = 0; Method methodINTERSECTS = TRI_CLASS.getMethod("intersects",PARAMLIST_E); retVal = (SetOps.overlapGroup(r.triset,methodINTERSECTS,true)).size(); return retVal; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.r_no_of_components. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method r_no_of_components /** * Returns the Eucledian distance between p1,p2. * This method returns the smallest distance between any two points of p1,p2. Returns * -1, if one of both Points values is empty. * * @param p1 the first Points values * @param p2 the second Ponits value * @return the distance as Rationsl */ public static Rational pp_dist (Points p1, Points p2) { Rational retVal = RationalFactory.constRational(0); try { Method methodDIST = POINT_CLASS.getMethod("dist",PARAMLIST_E); ElemPair retPair = SetOps.min(p1.pointset,p2.pointset,methodDIST); if (retVal != null) retVal = retPair.first.dist(retPair.second); else retVal = RationalFactory.constRational(-1); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.pp_dist. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch return retVal; }//end method pp_dist /** * Returns the Eucledian distance between p,l. * This method returns the smallest distance between any pair point/line segment of p,l. * Returns -1, if one of both values is empty. * * @param p the Points value * @param l the Lines value * @return the distance as Rationsl */ public static Rational pl_dist (Points p, Lines l) { Rational retVal = RationalFactory.constRational(0); try { Method methodDIST = PS_OPS_CLASS.getMethod("dist",PARAMLIST_PS); ElemPair retPair = SetOps.min(p.pointset,l.segset,methodDIST); if (retVal != null) retVal = PointSeg_Ops.dist((Point)retPair.first,(Segment)retPair.second); else retVal = RationalFactory.constRational(-1); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.pl_dist. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch return retVal; }//end method pl_dist /** * Returns the Eucledian distance between p,r. * This method returns the smallest distance between any pair point/polygon of p,r. * Returns -1, if one of both values is empty. * * @param p the Points value * @param r the Regions value * @return the distance as Rational */ public static Rational pr_dist (Points p, Regions r) { Rational retVal = RationalFactory.constRational(0); try { Method methodDIST = PT_OPS_CLASS.getMethod("dist",PARAMLIST_PT); ElemPair retPair = SetOps.min(p.pointset,r.triset,methodDIST); if (retVal != null) retVal = PointTri_Ops.dist((Point)retPair.first,(Triangle)retPair.second); else retVal = RationalFactory.constRational(-1); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.pr_dist. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch return retVal; }//end method pr_dist /** * Returns the Eucledian distance between p,l. * This method returns the smallest distance between any pair point/line segment of p,l. * Returns -1, if one of both values is empty. * * @param l the Lines value * @param p the Points value * @return the distance as Rationsl */ public static Rational lp_dist (Lines l, Points p) { return pl_dist(p,l); }//end method lp_dist /** * Returns the Eucledian distance between l1,l2. * This method returns the smallest distance between any two line segments of l1,l2. * Returns -1, if one of both values is empty. * * @param l1 the first Lines value * @param l2 the second Lines value * @return the distance as Rational */ public static Rational ll_dist (Lines l1, Lines l2) { Rational retVal = RationalFactory.constRational(0); try { if (!ll_disjoint(l1,l2)) return retVal; Method methodDIST = SEG_CLASS.getMethod("dist",PARAMLIST_E); ElemPair retPair = SetOps.min(l1.segset,l2.segset,methodDIST); if (retVal != null) retVal = retPair.first.dist(retPair.second); else retVal = RationalFactory.constRational(-1); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.ll_dist. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch return retVal; }//end method ll_dist /** * Returns the Eucledian distance between l,r. * This method returns the smallest distance between any pair line segment/polygon of l,r. * Returns -1, if one of both values is empty. * * @param l the Lines value * @param r the Regions value * @return the distance as Rational */ public static Rational lr_dist (Lines l, Regions r) { Rational retVal = RationalFactory.constRational(0); try { if (lr_intersects(l,r)) return retVal; Method methodDIST = ST_OPS_CLASS.getMethod("dist",PARAMLIST_ST); ElemPair retPair = SetOps.min(l.segset,r.triset,methodDIST); if (retVal != null) retVal = SegTri_Ops.dist((Segment)retPair.first,(Triangle)retPair.second); else retVal = RationalFactory.constRational(-1); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.lr_dist. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch return retVal; }//end method lr_dist /** * Returns the Eucledian distance between p,r. * This method returns the smallest distance between any pair point/polygon of p,r. * Returns -1, if one of both values is empty. * * @param r the Regions value * @param p the Points value * @return the distance as Rational */ public static Rational rp_dist (Regions r, Points p) { return pr_dist(p,r); }//end method rp_dist /** * Returns the Eucledian distance between l,r. * This method returns the smallest distance between any pair line segment/polygon of l,r. * Returns -1, if one of both values is empty. * * @param r the Regions value * @param l the Lines value * @return the distance as Rational */ public static Rational rl_dist (Regions r, Lines l) { return lr_dist(l,r); }//end method rl_dist /** * Returns the Eucledian distance between r1,r2. * This method returns the smallest distance between any two polygons of r1,r2. * Returns -1, if one of both values is empty. * * @param r1 the first Regions value * @param r2 the second Regions value * @return the distance as Rational */ public static Rational rr_dist (Regions r1, Regions r2) { Rational retVal = RationalFactory.constRational(0); try { if (!rr_disjoint(r1,r2)) return retVal; Method methodDIST = TRI_CLASS.getMethod("dist",PARAMLIST_E); ElemPair retPair = SetOps.min(r1.triset,r2.triset,methodDIST); if (retVal != null) retVal = retPair.first.dist(retPair.second); else retVal = RationalFactory.constRational(-1); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.rr_dist. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch return retVal; }//end method rr_dist /** * Returns the diameter of p. * * @param p the Points value * @return the diameter as Rational */ public static Rational p_diameter (Points p) { Rational retVal = RationalFactory.constRational(0); try { Method m = POINT_CLASS.getMethod("dist",PARAMLIST_E); ElemPair retPair = SetOps.max(p.pointset,p.pointset,m); retVal = retPair.first.dist(retPair.second); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.p_diameter. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch return retVal; }//end method p_diameter /** * Returns the diameter of l. * * @param l the Lines value * @return the diameter as Rational */ public static Rational l_diameter (Lines l) { return p_diameter(l_vertices(l)); }//end method l_diameter /** * Returns the diameter of r. * * @param r the Regions value * @return the diameter as Rational */ public static Rational r_diameter (Regions r) { return p_diameter(r_vertices(r)); }//end method r_diameter /** * Returns the length of l. * * @param l the Lines value * @return the length as double */ public static double l_length (Lines l) { try { double retSum = 0; Method methodLENGTH = SEG_CLASS.getMethod("length",null); retSum = SetOps.sum(l.segset,methodLENGTH); return retSum; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.l_length. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method l_length /** * Returns the area of r. * * @param r the Regions value * @return the area as double */ public static double r_area (Regions r) { try { double retVal = 0; Method methodAREA = TRI_CLASS.getMethod("area",null); retVal = SetOps.sum(r.triset,methodAREA); return retVal; } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.r_area. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method r_area /** * Returns the perimeter of r. * The perimeter of r is the length of its border. * * @param r the Regions value * @return the perimeter as double */ public static double r_perimeter (Regions r) { try { return l_length(new Lines(SupportOps.contour(r.triset,true,false))); } catch (Exception e) { e.printStackTrace(); System.out.println("There was an error when trying to execute ROSEAlgebra.r_perimeter. Returning 0."); throw new RoseAlgebraError("An error occurred during the execution of the RoseAlgebra operation."); }//catch }//end method r_perimeter /** * Using this method, the triangulator may be switched to another one. * The default triangulator ist "Mehlhorn" which has number 0. Two other triangulators are available. * They are "Triangle" (which has number 1) and "NetGen" (with number 2). No other numbers are * accepted by this method.

* Note, that "Triangle" and "NetGen" construct not only triangle sets, but meshes. * * @param int the number for the triangulator; 0..2 are accepted */ public static void chooseTriangulator (int i) { switch (i) { case 0 : { MESHGENERATOR.GENERATOR = "Mehlhorn"; return; }//case 0 case 1 : { MESHGENERATOR.GENERATOR = "Triangle"; return; }//case 1 case 2 : { MESHGENERATOR.GENERATOR = "NetGen"; return; }//case 2 }//switch }//end method chooseTriangulator /** * Chooses a deviance value for the Rational numbers. * * @param d the deviation value */ public static void setDeviationValue (double d) { RationalFactory.setDeviationDouble(d); }//end method setDevianceValue }//end class ROSEAlgebras