Example #1
0
		/// <summary>
		/// Maintain halfspaces in ascending opening angle order
		/// Called after each add, which puts a new halfspace at the
		/// end of the arraylist. "Bubble" the new addition to its proper
		/// place. Also assign a "Sign" from to this Convex
		/// One of: Positive, negative, zero, mixed.
		/// </summary>
		/// <param name="sign">The sign of the most recently added halfspace</param>
		private void sortandsign(Halfspace.Sign sign) {
			int i;
			int cnt;
			Halfspace hs;
			Halfspace hsprev;
			Object o;
			cnt = _halfspaces.Count;
			for(i = cnt-1; i>0; i--){
				hs = (Halfspace) _halfspaces[i];
				hsprev = (Halfspace) _halfspaces[i-1];
				if (hs.hangle > hsprev.hangle){
					// New halfspace has wider angle than previous one
					// so we are done!
					break;
				} else { 
					// new halfspace needs to trade places with previous one
					o = hsprev;
					_halfspaces[i-1] = hs;
					_halfspaces[i] = o;
				}
			} // Done sorting, now update sign
			if(cnt == 1){
				this._sign = sign;
				return;
			}
			switch(this._sign){
				case Halfspace.Sign.Negative:
					if (sign == Halfspace.Sign.Positive) 
						this._sign = Halfspace.Sign.Mixed;
					break;
				case Halfspace.Sign.Positive:
					if (sign == Halfspace.Sign.Negative) 
						this._sign = Halfspace.Sign.Mixed;
					break;
				case Halfspace.Sign.Zero:
					this._sign = sign;
					break;
				case Halfspace.Sign.Mixed:
					// Mixed stays mixed
					break;
			}

		}
Example #2
0
		private void prune() {
			// NEW: Check if this halfspace is the whole sphere, if so, remove it.
			int clen = _halfspaces.Count;
			bool hasPositive = false;
			bool hasNegative = false;
			bool hasZero = false;
			bool[] removethese = new bool[clen];
			bool removeall = false;

			if (clen < 1)
				return;

			for (int i = 0; i < clen; i++) {
				Halfspace hi = (Halfspace)_halfspaces[i];
				removethese[i] = false;
				if (clen > 1 && hi.isUniversal()) {
					// _halfspaces.RemoveAt(i);
					removethese[i] = true;
				}
				if (hi.isNull()) {
					removeall = true;
					break;
				}
			}
			if (removeall) {
				_halfspaces.Clear();
				hasZero = true; // force consistency.
			} else {
				for (int i = clen - 1; i >= 0; i--) {
					if (removethese[i]) {
						_halfspaces.RemoveAt(i);
					} else {
						Halfspace hi = (Halfspace)_halfspaces[i];
						switch (hi.sign) {
							case Halfspace.Sign.Negative: hasNegative = true; break;
							case Halfspace.Sign.Positive: hasPositive = true; break;
							case Halfspace.Sign.Zero: hasZero = true; break;
						}
					}
				}
			}

			if (hasPositive && hasNegative) {
				_sign = Halfspace.Sign.Mixed;
			} else if (hasPositive) {
				_sign = Halfspace.Sign.Positive;
			} else if (hasNegative) {
				_sign = Halfspace.Sign.Negative;
			} else {
				_sign = Halfspace.Sign.Zero;
			} 
			if (_sign == Halfspace.Sign.Zero && !hasZero) {
				throw new Exception("Convex.prune() internal inconsistency");
			}
			// end new.
		}
Example #3
0
		private void init(){
			_halfspaces     = new ArrayList(); // will change
			_corners        = new ArrayList();
			_sign           = Halfspace.Sign.Zero;
			_boundingCircle = new Halfspace();
			_htm		    = new HtmTrixel();
		}
Example #4
0
		private  void clear(){
			_halfspaces     = null;
			_corners        = null;
			_sign           = Halfspace.Sign.Zero;
			_boundingCircle = null;
			_htm		    = new HtmTrixel();
		}
Example #5
0
		public void OLDsimplify() {

			prune();  // remove redundant halfspaces, adjust sign.
			if (_halfspaces.Count < 1)
				return;
			if (_sign == Halfspace.Sign.Zero) {
				simplify0();	// treat ZERO convexes separately
				return;
			}

			int i, j;
			int clen;
			bool redundancy = true;

			while (redundancy) {
				redundancy = false;
				clen = _halfspaces.Count;
				for (i = 0; i < clen; i++) {
					Halfspace hi = (Halfspace)_halfspaces[i];
					for (j = 0; j < i; j++) {
						Halfspace hj = (Halfspace)_halfspaces[j];
						Halfspace.Position iPosj;

						// don't bother with two zero constraints
						if (hi.sign == Halfspace.Sign.Zero &&
							hj.sign == Halfspace.Sign.Zero)
							continue;

						// both pos or zero
						if ((hi.sign == Halfspace.Sign.Positive
							|| hi.sign == Halfspace.Sign.Zero) &&
							(hj.sign == Halfspace.Sign.Positive ||
							hj.sign == Halfspace.Sign.Zero)) {

							// was: if ( (iPosj = testConstraints(i,j)) == 0 ) continue; // intersection
							if ((iPosj = hi.relativePosition(hj)) == Halfspace.Position.Intersecting) continue;
							if (iPosj == Halfspace.Position.Disjoint) {					// disjoint ! convex is empty
								_halfspaces.Clear();
								return;
							}
							// one is redundant
							if (iPosj == Halfspace.Position.Surrounds) {
								// was: constraints_.erase(constraints_.en d()-i-1);
								// was later:constraints_.erase(constraints_.begin()+i);
								_halfspaces.RemoveAt(i);
							} else if (iPosj == Halfspace.Position.Contained) {
								// was: constraints_.erase(constraints_.en d()-j-1);
								// later: was constraints_.erase(constraints_.begin()+j);
								_halfspaces.RemoveAt(j);
							} else
								continue;     // intersection
							redundancy = true; // we did cut out a constraint -> do the loop again
							break;
						}

						// both neg
						if ((hi.sign == Halfspace.Sign.Negative) &&
							(hj.sign == Halfspace.Sign.Negative)) {
							//was: if ( (iposj = testConstraints(i,j)) <= 0 ) continue; // ok
							iPosj = hi.relativePosition(hj);
							if (iPosj == Halfspace.Position.Intersecting || iPosj == Halfspace.Position.Disjoint)
								continue;
							// one is redundant
							if (iPosj == Halfspace.Position.Surrounds) {
								//was: constraints_.erase(constraints_.en d()-1-j);
								// later was:constraints_.erase(constraints_.begin()+j);
								_halfspaces.RemoveAt(j);
							} else if (iPosj == Halfspace.Position.Contained) {
								//was : constraints_.erase(constraints_.en d()-1-i);
								// later was: constraints_.erase(constraints_.begin()+i);
								_halfspaces.RemoveAt(i);
							} else
								continue; // intersection
							redundancy = true; // we did cut out a constraint -> do the loop again
							break;
						}

						// one neg, one pos/zero
						// was:if( (iposj = testConstraints(i,j)) == 0) continue; // ok: intersect
						if ((iPosj = hi.relativePosition(hj)) == Halfspace.Position.Intersecting)
							continue;
						if (iPosj == Halfspace.Position.Disjoint) { // neg is redundant
							if (hi.sign == Halfspace.Sign.Negative) {
								//was: constraints_.erase(constraints_.en d()-1-i);
								//was later:constraints_.erase(constraints_.begin()+i);
								_halfspaces.RemoveAt(i);
							} else {
								//was: constraints_.erase(constraints_.en d()-1-j);
								// was later: constraints_.erase(constraints_.begin()+j);
								_halfspaces.RemoveAt(j);
							}
							redundancy = true; // we did cut out a constraint -> do the loop again
							break;
						}
						// if the negative constraint is inside the positive: continue
						if ((hi.sign == Halfspace.Sign.Negative && iPosj == Halfspace.Position.Contained) ||
							(hj.sign == Halfspace.Sign.Negative && iPosj == Halfspace.Position.Surrounds))
							continue;

						// positive constraint in negative: convex is empty!
						_halfspaces.Clear();
						return;
					} // for (i...)
					if (redundancy) break;
				}
			}// while(redundancy)

			// reset the sign of the convex
			_sign = ((Halfspace)_halfspaces[0]).sign;
			for (i = 1; i < _halfspaces.Count; i++) {
				Halfspace hi = (Halfspace)_halfspaces[i];
				switch (_sign) {
					case Halfspace.Sign.Negative:
						if (hi.sign == Halfspace.Sign.Positive)
							_sign = Halfspace.Sign.Mixed;
						break;
					case Halfspace.Sign.Positive:
						if (hi.sign == Halfspace.Sign.Negative)
							_sign = Halfspace.Sign.Mixed;
						break;
					case Halfspace.Sign.Zero:
						_sign = hi.sign;
						break;
					case Halfspace.Sign.Mixed:
						break;
				}
			}

			if (_halfspaces.Count == 1) // for one constraint, it is itself the BC
				_boundingCircle.copy((Halfspace)_halfspaces[0]);
			else if (_sign == Halfspace.Sign.Positive)
				_boundingCircle.copy((Halfspace)_halfspaces[0]);

		}
Example #6
0
		//// ////////////////////////// SIMPLIFICATION /////////////////////
		//
		//
		
		// ///////////SIMPLIFY/////////////////////////////////////
		// simplify: 
		//

		/// <summary>
		/// We have the following decision tree for the
		///           simplification of convexes:
		///
		///  Always test two constraints against each other. We have
		///
		///  * If both halfspaces are Positive or Zero
		///    # If they intersect: keep both
		///     # If one lies inside the other: drop the *larger* one
		///     # Else: disjunct. Clear the convex, stop.
		///
		///  * If both constraints are Negative
		///     # If they intersect or are disjunct: ok
		///     # Else: one lies in the other, drop smaller 'hole'
		///
		///  * Mixed: one Positive one Negative
		///     # No intersection, disjunct: Positive is redundant
		///     # Intersection: keep both
		///     # POS inside NEG: empty convex, stop.
		///     # NEG inside POS: keep both.
		/// Eliminate reduntand Halfspaces
		///
		/// Simplification eliminates redundant Halfspaces.
		/// For example, a halfspace that completely surrounds
		/// another halfspace is eliminated. If two halfspaces
		/// in the Convex are disjoint, then the Convex is empty
		/// </summary>
		public void simplify() {

			prune();  // remove redundant halfspaces, adjust sign.
			if (_halfspaces.Count < 1)
				return;
			if(_sign == Halfspace.Sign.Zero) {
				simplify0();	// treat zERO convexes separately
				return;
			}

			int i,j;
			int clen;
			bool restart = true;

			while(restart) {
				restart = false;
				clen = _halfspaces.Count;
				for(i = 0; i < clen; i++) {
					Halfspace hi = (Halfspace) _halfspaces[i];
					for (j = 0; j < i; j++) {
						Halfspace hj = (Halfspace)_halfspaces[j];
						Halfspace.Position iPosj;

						// don't bother with two zero constraints
						if (hi.sign == Halfspace.Sign.Zero &&
							hj.sign == Halfspace.Sign.Zero)
							continue;

						// No longer need to look at sign of halfspace, relativeposition does the work
						iPosj = hi.relativePosition(hj);
						if (iPosj == Halfspace.Position.Intersecting)
							continue;
						if (iPosj == Halfspace.Position.Disjoint) {					// disjoint ! convex is empty
							_halfspaces.Clear();
							return;
						}
						if (iPosj == Halfspace.Position.Surrounds) {
							_halfspaces.RemoveAt(i);
							restart = true;
							break;
						} else if (iPosj == Halfspace.Position.Contained) {
							_halfspaces.RemoveAt(j);
							restart = true;
							break;
						}
					} // for j
					if(restart) break;
				} // for i
			}// while(redundancy)

			// reset the sign of the convex
			_sign = ((Halfspace) _halfspaces[0]).sign;
			for(i = 1; i < _halfspaces.Count; i++) {
				Halfspace hi = (Halfspace) _halfspaces[i];
				switch(_sign){
					case Halfspace.Sign.Negative:
						if(hi.sign == Halfspace.Sign.Positive)
							_sign = Halfspace.Sign.Mixed;
						break;
					case Halfspace.Sign.Positive:
						if(hi.sign == Halfspace.Sign.Negative)
							_sign = Halfspace.Sign.Mixed;
						break;
					case Halfspace.Sign.Zero:
						_sign = hi.sign;
						break;
					case Halfspace.Sign.Mixed:
						break;
				}
			}

			if (_halfspaces.Count == 1) // for one constraint, it is itself the BC
				_boundingCircle.copy((Halfspace) _halfspaces[0]);
			else if (_sign == Halfspace.Sign.Positive)
				_boundingCircle.copy((Halfspace) _halfspaces[0]);

		}