示例#1
0
		/////////////TESTEDGE0////////////////////////////////////
		// testEdge0: 
		//

		/// <summary>
		/// Test if the edges intersect with the ZERO convex.
		//  The edges are given by the vertex vectors e[0-2]
		//	All constraints are great circles, so test if their intersect
		//  with the edges is inside or outside the convex.
		//  If any edge intersection is inside the convex, return true.
		//  If all edge intersections are outside, check whether one of
		//  the corners is inside the triangle. If yes, all of them must be
		//  inside -> return true.
		/// </summary>
		/// <param name="v0">vertex vector e[0]</param>
		/// <param name="v1">vertex vector e[1]</param>
		/// <param name="v2">vertex vector e[2]</param>
		/// <returns></returns>
		private bool testEdge0(Cartesian v0, Cartesian v1, Cartesian v2){
			// We have constructed the corners_ array in a certain direction.
			// now we can run around the convex, check each side against the 3
			// triangle edges. If any of the sides has its intersection INSIDE
			// the side, return true. At the end test if a corner lies inside
			// (because if we get there, none of the edges intersect, but it
			// can be that the convex is fully inside the triangle. so to test
			// one single edge is enough)
			edgeStruct[] edge = new edgeStruct[3];

			if (_corners.Count < 1) {
				throw new Exception("testEdge0: There are no corners");
			}
			// fill the edge structure for each side of this triangle
			Cartesian c01 = new Cartesian(v0);
			Cartesian c12 = new Cartesian(v1);
			Cartesian c20 = new Cartesian(v2);
			c01.crossMe(v1);
			c12.crossMe(v2);
			c20.crossMe(v0);
			edge[0].e = c01;
			edge[0].e1 = v0;
			edge[0].e2 = v1;
			edge[0].l = Math.Acos(v0.dot(v1));

			edge[1].e = c12;
			edge[1].e1 = v1;
			edge[1].e2 = v2;
			edge[1].l = Math.Acos(v1.dot(v2));

			edge[2].e = c20;
			edge[2].e1 = v2;
			edge[2].e2 = v0;
			edge[2].l = Math.Acos(v2.dot(v0));

			//			edge[0].e = v0 ^ v1; edge[0].e1 = &v0; edge[0].e2 = &v1;
			//			edge[1].e = v1 ^ v2; edge[1].e1 = &v1; edge[1].e2 = &v2;
			//			edge[2].e = v2 ^ v0; edge[2].e1 = &v2; edge[2].e2 = &v0;
			//			edge[0].l = Acos(v0 * v1);
			//			edge[1].l = Acos(v1 * v2);
			//			edge[2].l = Acos(v2 * v0);

			for(int i = 0; i < _corners.Count; i++) {
				int j = 0;
				if(i < _corners.Count - 1){
					j = i+1;
				}
				Cartesian a1 = new Cartesian();
				Cartesian tmp;
				double arg1, arg2;
				double l1,l2;   // lengths of the arcs from intersection to edge corners

				double cedgelen = Math.Acos(
					((Cartesian) _corners[i]).dot 
					((Cartesian) _corners[j]));  // length of edge of convex

				// calculate the intersection - all 3 edges
				for (int iedge = 0; iedge < 3; iedge++) {
					a1.assign(edge[iedge].e);
					tmp = 
						((Cartesian) _corners[i]).cross
						((Cartesian) _corners[j]);
					a1.crossMe(tmp);

					if (a1.normalizeMeSafely()){
						// WARNING
						// Keep your eye on this, used to crash here...
						//
						// if the intersection a1 is inside the edge of the convex,
						// its distance to the corners is smaller than the edgelength.
						// this test has to be done for both the edge of the convex and
						// the edge of the triangle.
						for(int k = 0; k < 2; k++) {
							l1 = Math.Acos(((Cartesian) _corners[i]).dot(a1));
							l2 = Math.Acos(((Cartesian) _corners[j]).dot(a1));
							if( l1 - cedgelen <= Cartesian.Epsilon && 
								l2 - cedgelen <= Cartesian.Epsilon){
								arg1 =  (edge[iedge].e1).dot(a1);
								arg2 =  (edge[iedge].e2).dot(a1);
								if (arg1 > 1.0) arg1 = 1.0;
								if (arg2 > 1.0) arg2 = 1.0;
								l1 = Math.Acos(arg1);
								l2 = Math.Acos(arg2);
								if( l1 - edge[iedge].l <= Cartesian.Epsilon &&
									l2 - edge[iedge].l <= Cartesian.Epsilon)
									return true;
							}
							a1.scaleMe(-1.0); // do the same for the other intersection
						}
					}
				}
			}
			return testVectorInside(v0,v1,v2,(Cartesian) _corners[0]);
		}
示例#2
0
		/////////////SIMPLIFY0////////////////////////////////////
		// 
		//

		/// <summary>
		/// Simplify ZERO convexes. calculate corners of convex
		/// and the bounding circle.
		///
		/// ZERO convexes are made up of constraints which are all great
		/// circles. It can happen that some of the constraints are redundant.
		/// For example, if 3 of the great circles define a triangle as the convex
		/// which lies fully inside the half sphere of the fourth constraint,
		/// that fourth constraint is redundant and will be removed.
		///
		/// The algorithm is the following:
		///
		/// zero-constraints are half-spheres, defined by a single normalized
		/// vector v, pointing in the direction of that half-sphere.
		///
		/// Two zero-constraints intersect at
		///
		///    i    =  +- v  x v
		///     1,2        1    2
		///
		/// the vector cross product of their two defining vectors.
		///
		/// The two vectors i1,2 are tested against every other constraint in
		/// the convex if they lie within their half-spheres. Those
		/// intersections i which lie within every other constraint, are stored
		/// into corners_.
		///
		/// Constraints that do not have a single corner on them, are dropped.
		/// </summary>
		private void simplify0() {
			int i;
			int j,k;
			Cartesian vi1, vi2;
			//typedef std::vector<size_t> ValueVectorSzt;
			//ValueVectorSzt cornerConstr1, cornerConstr2, removeConstr;
			//ValueVectorSpvec corner;
			// bool ruledout;
			ArrayList corner = new ArrayList();
			
			ArrayList cornerConstr1 = new ArrayList();
			ArrayList cornerConstr2 = new ArrayList();
			ArrayList removeConstr = new ArrayList();

			bool vi1ok, vi2ok;
			bool[] ruledout = null;

			if (_halfspaces.Count == 1) { // for one constraint, it is itself the BC
				_boundingCircle.copy((Halfspace) _halfspaces[0]);
				return;
			} else if(_halfspaces.Count == 2) {
				// For 2 constraints, take the bounding circle a 0-constraint...
				// this is by no means optimal, but the code is optimized for at least
				// 3 ZERO constraints... so this is acceptable.

				// test for constraints being identical - rule 1 out
				Halfspace hs0, hs1;
				hs0 = (Halfspace) _halfspaces[0];
				hs1 = (Halfspace) _halfspaces[1];
				if(hs0.sv.eq(hs1.sv)){
					// delete 1
					_halfspaces[1] = null; // was:constraints_.erase(constraints_.end()-1);
					_boundingCircle.copy(hs0);
					return;
				}
				// test for constraints being two disjoint half spheres - empty convex!
				if(hs0.sv.opposite(hs1.sv)){
					_halfspaces.Clear();
					return;
				}
				_boundingCircle = new Halfspace(); // TODO: halfspace constructor from sum of two vectors
				_boundingCircle.d = 0;
				_boundingCircle.sv.assign(hs0.sv);
				_boundingCircle.sv.addMe(hs1.sv);
				_boundingCircle.sv.normalizeMe();

				//	SpatialConstraint(constraints_[0].v() +
				//	constraints_[1].v(),0);
				return;
			}

			// Go over all pairs of constraints
			ruledout = new bool[_halfspaces.Count];
			for(i=0; i<(int)_halfspaces.Count; i++){
				ruledout[i] = true;
			}
			for(i = 0; i < _halfspaces.Count - 1; i++) {
				// ruledout = true;
				// was:
				Halfspace hi, hj;
				hi = (Halfspace) _halfspaces[i];
				for(j = i+1; j < _halfspaces.Count; j ++) {
					hj = (Halfspace) _halfspaces[j];
					// test for constraints being identical - rule i out
					if(hi.sv.eq(hj.sv))		//constraints_[i].a_ == constraints_[j].a_) 
						break;
					// test for constraints being two disjoint half spheres - empty convex!
					if(hi.sv.opposite(hj.sv)){
						_halfspaces.Clear();
						return;
					}
					
					// vi1 and vi2 are their intersection points
//					vi1 = constraints_[i].a_ ^ constraints_[j].a_ ;
//					vi1.normalize();
//					vi2 = (-1.0) * vi1;

					vi1 = new Cartesian(hi.sv);
					vi1.crossMe(hj.sv);
					vi1.normalizeMe();
					vi2 = new Cartesian(vi1);
					vi2.scaleMe(-1.0);

					vi1ok = true;
					vi2ok = true;
					//
					// now test whether vi1 or vi2 or both are inside every constraint.
					// other than i or j
					// if yes, store them in the corner array.
					// vi1ok is false, if vi1 is outisde even one constraint
					//
					for(k = 0; k < _halfspaces.Count; k++) {
						Halfspace hk;
						if( k == i || k == j) continue;
						hk = (Halfspace)_halfspaces[k];
						if(vi1ok && vi1.dot(hk.sv) <= 0.0) {
							vi1ok = false;
						}
						if(vi2ok && vi2.dot(hk.sv) <= 0.0) {
							vi2ok = false;
						}
						if(!vi1ok && !vi2ok) // don't look further
							break;
					}
					if(vi1ok) { // vi1 is inside all other constraints
						corner.Add(vi1);
						// was: corner.push_back(vi1);
						cornerConstr1.Add(i);
						cornerConstr2.Add(j);

						// was: cornerConstr1.push_back(i);
						// was: cornerConstr2.push_back(j);
	
						ruledout[i] = false;
						ruledout[j] = false;
						// ruledout = false;
					}
					if(vi2ok) {
//						corner.push_back(vi2);
//						cornerConstr1.push_back(i);
//						cornerConstr2.push_back(j);
						corner.Add(vi2);
						cornerConstr1.Add(i);
						cornerConstr2.Add(j);
						ruledout[i] = false;
						ruledout[j] = false;
	
						// ruledout = false;
					}
				} // END of J loop
				// is this constraint ruled out? i.e. none of its intersections
				// with other constraints are corners... remove it from constraints_ list.
				/******************** WAS:
				if(ruledout) {
					removeConstr.push_back(i);
				}
				**********************************************/
			} // END of i loop

			// See if you can rule out a constraint
			//
			for(i=0; i< (int) _halfspaces.Count; i++){
				if (ruledout[i]){
					removeConstr.Add(i);
				}
			}
			ruledout = null; // delete ruledout;


			// Now set the corners into their correct order, which is an
			// anti-clockwise walk around the polygon.
			//
			// start at any corner. so take the first.
			if (corner.Count == 0){
				_halfspaces.Clear();
				return;
			}
 
			_corners.Clear();
			_corners.Add(corner[0]);

			// The trick is now to start off into the correct direction.
			// this corner has two edges it can walk. we have to take the
			// one where the convex lies on its left side.
			i = (int) cornerConstr1[0];		// the i'th constraint and j'th constraint
			j = (int) cornerConstr2[0];		// intersect at 0'th corner
			int c1,c2,k1,k2;
			// Now find the other corner where the i'th and j'th constraints intersect.
			// Store the corner in vi1 and vi2, and the other constraint indices
			// in c1,c2.
			c1 = c2 = k1 = k2 = -1;
			vi1 = null;
			vi2 = null;
			for( k = 1; k < cornerConstr1.Count; k ++) {
				if((int) cornerConstr1[k] == i) {
					vi1 = (Cartesian) corner[k];
					c1 = (int) cornerConstr2[k];
					k1 = k;
				}
				if((int) cornerConstr2[k] == i) {
					vi1 = (Cartesian) corner[k];
					c1 = (int) cornerConstr1[k];
					k1 = k;
				}
				if((int) cornerConstr1[k] == j) {
					vi2 = (Cartesian) corner[k];
					c2 = (int) cornerConstr2[k];
					k2 = k;
				}
				if((int) cornerConstr2[k] == j) {
					vi2 = (Cartesian) corner[k];
					c2 = (int) cornerConstr1[k];
					k2 = k;
				}
			}
			// Now test i'th constraint-edge ( corner 0 and corner k ) whether
			// it is on the correct side (left)
			//
			//  ( (corner(k) - corner(0)) x constraint(i) ) * corner(0)
			//
			// is >0 if yes, <0 if no...
			//
			int c,currentCorner;
			Cartesian va;
			va = new Cartesian(vi1);
			va.subMe((Cartesian) corner[0]);
			va.crossMe( ((Halfspace) _halfspaces[i]).sv);
			if (va.dot((Cartesian) corner[0]) > 0.0){
				if (k1 == -1) {
					throw (new Exception("Simplify0:k1 uninitialized"));
				}
				_corners.Add(vi1);
				c = c1;
				currentCorner = k1;
			} else {
				if (k2 == -1) {
					throw (new Exception("Simplify0:k2 uninitialized"));
				}
				_corners.Add(vi2);
				c = c2;
				currentCorner = k2;
			}
//			if( ((vi1 - corner[0]) ^ constraints_[i].a_) * corner[0] > 0 ) {
//				corners_.push_back(vi1);
//				c = c1;
//				currentCorner = k1;
//			} else {
//				corners_.push_back(vi2);
//				c = c2;
//				currentCorner = k2;
//			}

			
			// Now append the corners that match the index c until we got corner 0 again
			// currentCorner holds the current corners index
			// c holds the index of the constraint that has just been intersected with
			// So:
			// x We are on a constraint now (i or j from before), the second corner
			//   is the one intersecting with constraint c.
			// x Find other corner for constraint c.
			// x Save that corner, and set c to the constraint that intersects with c
			//   at that corner. Set currentcorner to that corners index.
			// x Loop until 0th corner reached.
			while( currentCorner > 0 ) {
				for (k = 0; k < cornerConstr1.Count; k++) {
					if(k == currentCorner)continue;
					if( (int) cornerConstr1[k] == c) {
						if( (currentCorner = k) == 0) break;
						_corners.Add(corner[k]);
						c = (int) cornerConstr2[k];
						break;
					}
					if((int) cornerConstr2[k] == c) {
						if( (currentCorner = k) == 0) break;
						_corners.Add(corner[k]);
						c = (int) cornerConstr1[k];
						break;
					}
				}
			}
			// Remove all redundant constraints
			for ( i = removeConstr.Count - 1; i>=0; i--){ //Start from END
				// WAS earlier: constraints_.erase(constraints_.end()-removeConstr[i]-1); 
				/// in C++:constraints_.erase(constraints_.begin()+removeConstr[i]);
				_halfspaces.RemoveAt( (int) removeConstr[i]);
			}
			// Now calculate the bounding circle for the convex.
			// We take it as the bounding circle of the triangle with
			// the widest opening angle. All triangles made out of 3 corners
			// are considered.
			_boundingCircle.d = 1.0;
			if (_halfspaces.Count >=3 ) {
				for(i = 0; i < (int) _corners.Count; i++){
					for(j = i+1; j < _corners.Count; j++){
						for(k = j+1; k < _corners.Count; k++) {
							Cartesian v = new Cartesian();
							Cartesian tv = new Cartesian();
							v.assign((Cartesian) _corners[j]);
							v.subMe((Cartesian) _corners[i]);
							tv.assign((Cartesian) _corners[k]);
							tv.subMe((Cartesian) _corners[j]);
							v.crossMe(tv);
							v.normalizeMe();

							//	SpatialVector v = ( corners_[j] - corners_[i] ) ^
							//	( corners_[k] - corners_[j] );
							//	v.normalize();
							// Set the correct opening angle: Since the plane cutting
							// out the triangle also correctly cuts out the bounding cap
							// of the triangle on the sphere, we can take any corner to
							// calculate the opening angle
							double d = v.dot((Cartesian) _corners[i]);
							if(_boundingCircle.d > d){
								_boundingCircle.d = d;
								_boundingCircle.sv.assign(v);
								//new Halfspace(v,d);
							}
						}
					}
				}
			}
		}
示例#3
0
		private bool testHole(Cartesian v0, Cartesian v1, Cartesian v2){
			Cartesian r1, r2, r3;
			bool test = false;
			Halfspace hs;
			r1 = new Cartesian();
			r2 = new Cartesian();
			r3 = new Cartesian();
			for(int i = 0; i < _halfspaces.Count; i++) {
				hs = (Halfspace) _halfspaces[i];
				if ( hs.sign < 0) {  
					// test only 'holes'
					// If (a ^ b * c) < 0, vectors abc point clockwise.
					// -> center c not inside triangle, since vertices a,b are ordered
					// counter-clockwise. The comparison here is the other way
					// round because c points into the opposite direction as the hole
					//
					// The old code said this:
					//					if ( ( ( v0 ^ v1 ) *
					//						_halfspaces[i].a_) > 0.0L ) continue;
					//					if ( ( ( v1 ^ v2 ) *
					//						_halfspaces[i].a_) > 0.0L ) continue;
					//					if ( ( ( v2 ^ v0 ) *
					//						_halfspaces[i].a_) > 0.0L ) continue;
					
					r1.assign(v0);
					r1.crossMe(v1);
					if ( r1.dot( hs.sv) > 0.0) continue;

					r1.assign(v1);
					r1.crossMe(v2);
					if ( r1.dot( hs.sv) > 0.0) continue;

					r1.assign(v2);
					r1.crossMe(v0);
					if ( r1.dot( hs.sv) > 0.0) continue;
					test = true;
					break;
				}
			}
			return test;
		}
示例#4
0
		public Polygon.Error add(double[] x, double[] y, double[] z, int len){
			
			bool DIRECTION = false;
			bool FIRST_DIRECTION = false;
			// The constraint we have for each side is a 0-constraint (great circle)
			// passing through the 2 corners. Since we are in counterclockwise order,
			// the vector product of the two successive corners just gives the correct
			// constraint.
			// 
			// Polygons should be counterclockwise
			// Polygons are assumed to be convex, otherwise windingerror is
			// computed wrong.
			int ix;
			Cartesian v = new Cartesian();
			Convex cvx = 
				new Convex(Convex.Mode.Normal);
			int i;

			/* PASS 1: check for winding error */

			for(i = 0; i < len; i++) {
				// Keep track of winding direction. Should be positive
				// that is, CCW.
				ix = (i==len-1 ? 0 : i+1); 
				if (i>0){
					// test third corner against the constraint just formed
					// v is computed in the previous iteration
					// Look at a corner dot v

					if (v.dot(x[ix], y[ix], z[ix]) < Cartesian.Epsilon) {
						DIRECTION = true;
						if (i == 1) {
							FIRST_DIRECTION = true;
						}
						// break; 		// Move to pass 2
					} else {
						DIRECTION = false;
						if (i == 1) {
							FIRST_DIRECTION = false;
						}
					}
					if (i > 1) {
						if (DIRECTION != FIRST_DIRECTION) {
							// C++: must clea up new Cartesian and convex
							// or better yet, do no allocate on top until you know
							// you need it
							return Polygon.Error.errBowtieOrConcave; // BOWTie error
						}
					}
				}
				// v = corners[i] ^ corners[ i == len-1 ? 0 : i + 1];
				v.assign(x[i], y[i], z[i]);
				v.crossMe(x[ix], y[ix], z[ix]);
				if (v.isLength(0.0, Cartesian.Epsilon)) {
					return Polygon.Error.errZeroLength;
				}
				// WARNING! if v = zerovector, then edge error!!!
			}
			/* PASS 2: build convex in either original or reverse
			   order */

			/* forward:
			   Go from 0 to len-1 by +1, cross i and i+1 (or 0)
			   reverse:
			   Go from len-1 to 0 by -1, cross i and i-1 (or len-1)
			*/
			if (DIRECTION) {
				for(i=len-1; i>=0; i--){
					// v = corners[i] ^ corners[ i == 0 ? len-1 : i-1];
					// v.normalize();
					ix = (i==0? len-1 : i-1);
					v.assign(x[i], y[i], z[i]);
					v.crossMe(x[ix], y[ix], z[ix]);
					// WARNING! if v = zerovector, then edge error!!!

					v.normalizeMe();
					Halfspace c = new Halfspace(v, 0.0);
					// SpatialConstraint c(v,0);
					cvx.add(c);
				}
			} else {
				for(i=0; i<len; i++){

					//v = corners[i] ^ corners[ i == len-1 ? 0 : i+1];
					// v.normalize();
					ix = (i==len-1 ? 0 : i+1);
					v.assign(x[i], y[i], z[i]);
					v.crossMe(x[ix], y[ix], z[ix]);
					// WARNING! if v = zerovector, then edge error!!!

					v.normalizeMe();
					Halfspace c = new Halfspace(v, 0.0);
					cvx.add(c);
				}
			}
			_reg.add(cvx);
			return Polygon.Error.Ok;
		}