// ============================================================================= NOX::Abstract::Group::ReturnType Ginla::FDM::Constraint::MinDist:: computeConstraints() { if (!isValidConstraints_) { // the dot() method is indeed smart enough to compute // conjugate the first complex vector psiRef_ constraints_(0,0) = std::imag( psiRef_->dot(*psi_) ); isValidConstraints_ = true; } return NOX::Abstract::Group::Ok; }
// ============================================================================= // The first column of dgdp should be filled with the constraint // residuals g if isValidG is false. // If isValidG is true, then the dgdp contains g on input. NOX::Abstract::Group::ReturnType Ginla::FDM::Constraint::MinDist:: computeDP( const vector<int> & paramIDs, NOX::Abstract::MultiVector::DenseMatrix & dgdp, bool isValidG ) { if (!isValidG) dgdp(0,0) = constraints_(0,0); for (unsigned int i=0; i<paramIDs.size(); i++) dgdp(0,i+1) = 0.0; // no dependence on constraints in the phase condition return NOX::Abstract::Group::Ok; }
void SpatialConvex::simplify() { if(sign_ == zERO) { simplify0(); // treat zERO convexes separately return; } size_t i,j; size_t clen; bool redundancy = true; while(redundancy) { redundancy = false; clen = constraints_.length(); for(i = 0; i < clen; i++) { for(j = 0; j < i; j++) { int test; // don't bother with two zero constraints if( constraints_[i].sign_ == zERO && constraints_[j].sign_ == zERO) continue; // both pos or zero if( ( constraints_[i].sign_ == pOS || constraints_[i].sign_ == zERO ) && ( constraints_[j].sign_ == pOS || constraints_[j].sign_ == zERO ) ) { if ( (test = testConstraints(i,j)) == 0 ) continue; // intersection if ( test < 0 ) { // disjoint ! convex is empty constraints_.cut(constraints_.length()); return; } // one is redundant if(test == 1) constraints_.cut(1, clen - 1 - i); else if(test==2)constraints_.cut(1, clen - 1 - j); else continue; // intersection redundancy = true; // we did cut out a constraint -> do the loop again break; } // both neg or zero if( ( constraints_[i].sign_ == nEG ) && ( constraints_[j].sign_ == nEG ) ) { if ( (test = testConstraints(i,j)) <= 0 ) continue; // ok // one is redundant if(test == 1) constraints_.cut(1, clen - 1 - j); else if(test==2)constraints_.cut(1, clen - 1 - i); else continue; // intersection redundancy = true; // we did cut out a constraint -> do the loop again break; } // one neg, one pos/zero if( (test = testConstraints(i,j)) == 0) continue; // ok: intersect if( test < 0 ) { // neg is redundant if ( constraints_[i].sign_ == nEG ) constraints_.cut(1, clen - 1 - i); else constraints_.cut(1, clen - 1 - j); redundancy = true; // we did cut out a constraint -> do the loop again break; } // if the negative constraint is inside the positive: continue if ( (constraints_[i].sign_ == nEG && test == 2) || (constraints_[j].sign_ == nEG && test == 1) )continue; // positive constraint in negative: convex is empty! constraints_.cut(constraints_.length()); return; } if(redundancy)break; } } // reset the sign of the convex sign_ = constraints_[0].sign_; for(i = 1; i < constraints_.length(); i++) { switch (sign_) { case nEG: if(constraints_[i].sign_ == pOS) sign_ = mIXED; break; case pOS: if(constraints_[i].sign_ == nEG) sign_ = mIXED; break; case zERO: sign_ = constraints_[i].sign_; break; } } if (constraints_.length() == 1) // for one constraint, it is itself the BC boundingCircle_ = constraints_(0); else if (sign_ == pOS) boundingCircle_ = constraints_(0); }
void SpatialConvex::simplify0() { size_t i,j,k; SpatialVector vi1, vi2; ValVec<size_t> cornerConstr1, cornerConstr2, removeConstr; ValVec<SpatialVector> corner; if (constraints_.length() == 1) { // for one constraint, it is itself the BC boundingCircle_ = constraints_(0); return; // 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. } else if(constraints_.length() == 2) { // test for constraints being identical - rule 1 out if(constraints_.vector_[0].a_ == constraints_.vector_[1].a_){ constraints_.cut(1); boundingCircle_ = constraints_(0); return; } // test for constraints being two disjoint half spheres - empty convex! if(constraints_.vector_[0].a_ == (-1.0)*constraints_.vector_[1].a_){ constraints_.cut(constraints_.length()); return; } boundingCircle_ = SpatialConstraint(constraints_(0).v() + constraints_(1).v(),0); return; } // Go over all pairs of constraints for(i = 0; i < constraints_.length() - 1; i++) { bool ruledout = true; for(j = i+1; j < constraints_.length(); j ++) { // test for constraints being identical - rule i out if(constraints_.vector_[i].a_ == constraints_.vector_[j].a_)break; // test for constraints being two disjoint half spheres - empty convex! if(constraints_.vector_[i].a_ == (-1.0)*constraints_.vector_[j].a_){ constraints_.cut(constraints_.length()); return; } // vi1 and vi2 are their intersection points vi1 = constraints_.vector_[i].a_ ^ constraints_.vector_[j].a_ ; vi1.normalize(); vi2 = (-1.0) * vi1; bool vi1ok = true, vi2ok = true; // now test whether vi1 or vi2 or both are inside every other constraint. // if yes, store them in the corner array. for(k = 0; k < constraints_.length(); k++) { if(k == i || k == j) continue; if(vi1ok && vi1 * constraints_.vector_[k].a_ <= 0.0) vi1ok = false; if(vi2ok && vi2 * constraints_.vector_[k].a_ <= 0.0) vi2ok = false; if(!vi1ok && !vi2ok)break; } if(vi1ok) { corner.append(vi1); cornerConstr1.append(i); cornerConstr2.append(j); ruledout = false; } if(vi2ok) { corner.append(vi2); cornerConstr1.append(i); cornerConstr2.append(j); ruledout = false; } } // is this constraint ruled out? i.e. none of its intersections // with other constraints are corners... remove it from constraints_ list. if(ruledout) removeConstr.append(i); } // 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. corners_.cut(corners_.length()); corners_.append(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 = cornerConstr1(0); // the i'th constraint and j'th constraint j = cornerConstr2(0); // intersect at 0'th corner size_t c1=0,c2=0,k1=0,k2=0; // 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. for( k = 1; k < cornerConstr1.length(); k ++) { if(cornerConstr1(k) == i) { vi1 = corner(k); c1 = cornerConstr2(k); k1 = k; } if(cornerConstr2(k) == i) { vi1 = corner(k); c1 = cornerConstr1(k); k1 = k; } if(cornerConstr1(k) == j) { vi2 = corner(k); c2 = cornerConstr2(k); k2 = k; } if(cornerConstr2(k) == j) { vi2 = corner(k); c2 = 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... // size_t c,currentCorner; if( ((vi1 - corner(0)) ^ constraints_(i).a_) * corner(0) > 0 ) { corners_.append(vi1); c = c1; currentCorner = k1; } else { corners_.append(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 ) { for (k = 0; k < cornerConstr1.length(); k++) { if(k == currentCorner)continue; if(cornerConstr1(k) == c) { if( (currentCorner = k) == 0) break; corners_.append(corner(k)); c = cornerConstr2(k); break; } if(cornerConstr2(k) == c) { if( (currentCorner = k) == 0) break; corners_.append(corner(k)); c = cornerConstr1(k); break; } } } // Remove all redundant constraints for ( i = 0; i < removeConstr.length(); i++) constraints_.remove(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 (constraints_.length() >=3 ) { for(i = 0; i < corners_.length(); i++) for(j = i+1; j < corners_.length(); j++) for(k = j+1; k < corners_.length(); k++) { 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 float64 d = v * corners_(i); if(boundingCircle_.d_ > d) boundingCircle_ = SpatialConstraint(v,d); } } #ifdef DIAGNOSE for(i = 0; i < corners_.length(); i++) { //cout << corners_(i).ra() << "," << corners_(i).dec() << ":" << corners_(i) << "\n"; } #endif }