예제 #1
0
        void Preferences::applyDefaults() {
            fl::Engine* engine = Model::Default()->engine();

            if (engine->numberOfRuleBlocks() == 0) {
                QMessageBox::critical(this, "Error",
                        "Current engine has no rule blocks. "
                        "At least one ruleblock was expected.",
                        QMessageBox::Ok);
                return;
            }
            std::string tnorm = Minimum().className();
            std::string snorm = Maximum().className();
            std::string activation = Minimum().className();

            RuleBlock* ruleblock = engine->getRuleBlock(0);
            if (ruleblock->getTnorm()) tnorm = ruleblock->getTnorm()->className();
            if (ruleblock->getSnorm()) snorm = ruleblock->getSnorm()->className();
            if (ruleblock->getActivation()) activation = ruleblock->getActivation()->className();

            std::string defuzzifier = Centroid().className();
            int divisions = fl::fuzzylite::defaultDivisions();
            std::string accumulation = Maximum().className();

            if (engine->numberOfOutputVariables() > 0) {
                OutputVariable* variable = engine->getOutputVariable(0);
                if (variable->getDefuzzifier()) {
                    defuzzifier = variable->getDefuzzifier()->className();
                    divisions = variable->getDefuzzifier()->getDivisions();
                }
                if (variable->output()->getAccumulation())
                    accumulation = variable->output()->getAccumulation()->className();
            }
            engine->configure(tnorm, snorm, activation, accumulation, defuzzifier, divisions);
        }
예제 #2
0
int main(int, const char * []) {
  IloEnv env;
  try {
    IloIntVarArray x(env);
    for (IloInt i = 0; i < 10; i++) {
      char name[6];
      sprintf(name, "X%ld", i);
      x.add(IloIntVar(env, 0, 100 - 2*(i / 2), name));
    }
    IloModel mdl(env);
    mdl.add(IloAllDiff(env, x));
    mdl.add(x);

    IloIntVarChooser varChooser   = ChooseSmallestCentroid(env);
    IloIntValueChooser valChooser = ChooseSmallestDistanceFromCentroid(env);
    IloSearchPhase sp1(env, x, varChooser, valChooser);

    IloIntVarEval   varEval       = Centroid(env);
    IloIntValueEval valEval       = DistanceFromCentroid(env);
    IloSearchPhase sp2(env, x, IloSelectSmallest(varEval),
                               IloSelectSmallest(valEval));

    // sp2 can have ties as two variable or values could evaluate
    // to the same values.  sp3 shows how to break these ties
    // choosing, for equivalent centroid and distance-to-centroid
    // evaluations, the lowest indexed variable in x and the
    // lowest value.
    IloVarSelectorArray selVar(env);
    selVar.add(IloSelectSmallest(varEval));
    selVar.add(IloSelectSmallest(IloVarIndex(env, x))); // break ties on index

    IloValueSelectorArray selValue(env);
    selValue.add(IloSelectSmallest(valEval));
    selValue.add(IloSelectSmallest(IloValue(env))); // break ties on smallest

    IloSearchPhase sp3(env, x, selVar, selValue);

    IloCP cp(mdl);
    cp.setParameter(IloCP::Workers, 1);
    cp.setParameter(IloCP::SearchType, IloCP::DepthFirst);
    cp.setParameter(IloCP::LogPeriod, 1);
    cp.out() << "Choosers" << std::endl;
    cp.solve(sp1);
    cp.out() << cp.domain(x) << std::endl;

    cp.out() << "Evaluators" << std::endl;
    cp.solve(sp2);
    cp.out() << cp.domain(x) << std::endl;
    cp.out() << "Evaluators (with tie-break)" << std::endl;
    cp.solve(sp3);
    cp.out() << cp.domain(x) << std::endl;

    cp.end();
  } catch (IloException & ex) {
    env.out() << "Caught: " << ex << std::endl;
  }
  env.end();
  return 0;
}
예제 #3
0
파일: R3Triangle.C 프로젝트: acplus/peptalk
const R3Sphere R3Triangle::
BSphere(void) const
{
    // Return bounding sphere (is this right???)
    R3Point centroid = Centroid();
    RNLength radius = R3Distance(centroid, v[0]->Position());
    return R3Sphere(centroid, radius);
}
예제 #4
0
파일: polygon.cpp 프로젝트: Piping/ECS175
void Polygon::ScaleCenter(Vector3 scale_amount)
{
	if(vertices.empty()) return;
	Vector3 centroid = Centroid();
	Translate(-centroid);
	Scale(scale_amount);
	Translate(centroid);
}
예제 #5
0
파일: R3Box.C 프로젝트: acplus/peptalk
void R3Box::
Inflate (RNScalar fraction) 
{
    // Scale box around centroid by fraction
  if (IsEmpty()) return;
  R3Point centroid = Centroid();
  R3Vector diagonal = Max() - centroid;
  Reset(centroid - fraction * diagonal, centroid + fraction * diagonal);
}
예제 #6
0
float IndicativeAngle(Array* points)
{
    Vec2 centroid = Centroid(points);
    PointObject* firstPoint = (PointObject*)points->getObjectAtIndex(0);
    float x = (centroid.x - firstPoint->x);
    float y = (centroid.y - firstPoint->y);
    
    return atan2f(y, x);
}
예제 #7
0
DefuzzifierFactory::DefuzzifierFactory() {
    registerClass(Bisector().className(), &(Bisector::constructor));
    registerClass(Centroid().className(), &(Centroid::constructor));
    registerClass(LargestOfMaximum().className(), &(LargestOfMaximum::constructor));
    registerClass(MeanOfMaximum().className(), &(MeanOfMaximum::constructor));
    registerClass(SmallestOfMaximum().className(), &(SmallestOfMaximum::constructor));
    registerClass(WeightedAverage().className(), &(WeightedAverage::constructor));
    registerClass(WeightedSum().className(), &(WeightedSum::constructor));
}
예제 #8
0
void BinarySpaceTree<BoundType, StatisticType, MatType, SplitType>::SplitNode(
    MatType& data,
    std::vector<size_t>& oldFromNew,
    const size_t maxLeafSize,
    SplitType& splitter)
{
  // This should be a single function for Bound.
  // We need to expand the bounds of this node properly.
  bound |= data.cols(begin, begin + count - 1);

  // Calculate the furthest descendant distance.
  furthestDescendantDistance = 0.5 * bound.Diameter();

  // First, check if we need to split at all.
  if (count <= maxLeafSize)
    return; // We can't split this.

  // splitCol denotes the two partitions of the dataset after the split. The
  // points on its left go to the left child and the others go to the right
  // child.
  size_t splitCol;

  // Split the node. The elements of 'data' are reordered by the splitting
  // algorithm. This function call updates splitCol and oldFromNew.
  const bool split = splitter.SplitNode(bound, data, begin, count, splitCol,
      oldFromNew);

  // The node may not be always split. For instance, if all the points are the
  // same, we can't split them.
  if (!split)
    return;

  // Now that we know the split column, we will recursively split the children
  // by calling their constructors (which perform this splitting process).
  left = new BinarySpaceTree<BoundType, StatisticType, MatType>(data, begin,
      splitCol - begin, oldFromNew, splitter, this, maxLeafSize);
  right = new BinarySpaceTree<BoundType, StatisticType, MatType>(data, splitCol,
      begin + count - splitCol, oldFromNew, splitter, this, maxLeafSize);

  // Calculate parent distances for those two nodes.
  arma::vec centroid, leftCentroid, rightCentroid;
  Centroid(centroid);
  left->Centroid(leftCentroid);
  right->Centroid(rightCentroid);

  const double leftParentDistance = bound.Metric().Evaluate(centroid,
      leftCentroid);
  const double rightParentDistance = bound.Metric().Evaluate(centroid,
      rightCentroid);

  left->ParentDistance() = leftParentDistance;
  right->ParentDistance() = rightParentDistance;
}
 void TranslateToOrigin(PointVector& points)
 {
     PointPtr c = Centroid(points);
     PointVector newpoints;
     for (size_t i = 0; i < points.size(); ++i)
     {
         double qx = points[i]->X - c->X;
         double qy = points[i]->Y - c->Y;
         newpoints.push_back(PointPtr(new Point(qx, qy)));
     }
     points.clear();
     points.insert(points.begin(), newpoints.begin(), newpoints.end());
 }
예제 #10
0
/**--------------------------------------------------------------------------<BR>
C2DPolyArc::GetCentroid <BR>
\brief Calculates the centroid of the shape by calculating the centroid of the simple
polygon then shifting it by the area weighted centroids of the segments defined
by the arcs.
<P>---------------------------------------------------------------------------*/
C2DPoint C2DPolyArc::GetCentroid(void) const
{
	// Find the centroid and area of the straight line polygon.
	C2DPoint Centroid(0, 0);
	C2DPoint pti;
	C2DPoint ptii;
	double dArea = 0;

	for (unsigned int i = 0; i < m_Lines.size(); i++)
	{
		pti = m_Lines[i].GetPointFrom();
		ptii = m_Lines[i].GetPointTo();

		Centroid.x += (pti.x + ptii.x) * (pti.x * ptii.y - ptii.x * pti.y);
		Centroid.y += (pti.y + ptii.y) * (pti.x * ptii.y - ptii.x * pti.y);

		dArea += pti.x * ptii.y - ptii.x * pti.y;
	}
	dArea = dArea / 2.0;

	Centroid.x = Centroid.x / (6.0 * dArea);
	Centroid.y = Centroid.y / (6.0 * dArea);

	std::vector<double> dSegAreas;
	double dTotalArea = dArea;
	std::vector<C2DPoint> SegCentroids;

	for (unsigned int i = 0; i < m_Lines.size(); i++)
	{
		if (m_Lines[i].GetType() == C2DLineBase::ArcedLine)
		{
			C2DSegment Seg( dynamic_cast<const C2DArc&>( m_Lines[i] ) );
			double dSegArea = Seg.GetAreaSigned();
			dTotalArea += dSegArea;
			dSegAreas.push_back( dSegArea );
			SegCentroids.push_back( Seg.GetCentroid() );
		}
	}

	Centroid = Centroid * dArea;

	for (unsigned int i = 0; i < dSegAreas.size(); i++)
	{
		Centroid += SegCentroids[i] * dSegAreas[i];
	}

	Centroid = Centroid / dTotalArea;

	return Centroid;

}
예제 #11
0
const Vector & 
QuadCell::getCentroidPosition(void)
{
   int i, i1;
   double yi, zi, yi1, zi1, dyi, dzi;
   double area, integ;
   double CGy = 0.0, CGz = 0.0;

   area = this->getArea();

   for (i = 0; i < 4; i++)
   {
      i1 = (i+1)%4;
        
      yi  = vertCoord(i,0);
      zi  = vertCoord(i,1);
      yi1 = vertCoord(i1,0);
      zi1 = vertCoord(i1,1);

      dyi = yi1 - yi;
      dzi = zi1 - zi;
   
      integ = yi*zi + (yi*dzi + zi*dyi)/2.0 + dyi*dzi/3.0;

      CGy -= dyi * integ;
      CGz += dzi * integ;
   }
   
   CGy /= area;
   CGz /= area;

   Centroid(0) = CGy;
   Centroid(1) = CGz;

//   opserr << "\narea : " << area << " centroid: " << Centroid;
 
   return Centroid;
}
예제 #12
0
파일: R3Box.C 프로젝트: acplus/peptalk
const R3Box R3Box::
Octant (RNDirection xdir, RNDirection ydir, RNDirection zdir) const
{
    // Return box in octant (xdir, ydir, zdir)
    R3Box result;
    R3Point centroid = Centroid();
    if (xdir == RN_HI) { result[RN_LO][RN_X] = centroid[RN_X]; result[RN_HI][RN_X] = maxpt[RN_X]; }
    else { result[RN_LO][RN_X] = minpt[RN_X]; result[RN_HI][RN_X] = centroid[RN_X]; }
    if (ydir == RN_HI) { result[RN_LO][RN_Y] = centroid[RN_Y]; result[RN_HI][RN_Y] = maxpt[RN_Y]; }
    else { result[RN_LO][RN_Y] = minpt[RN_Y]; result[RN_HI][RN_Y] = centroid[RN_Y]; }
    if (zdir == RN_HI) { result[RN_LO][RN_Z] = centroid[RN_Z]; result[RN_HI][RN_Z] = maxpt[RN_Z]; }
    else { result[RN_LO][RN_Z] = minpt[RN_Z]; result[RN_HI][RN_Z] = centroid[RN_Z]; }
    return result;
}
예제 #13
0
float Fuzzy(int** regle, int TAILLE, float** MF_X, float A_norm, float B_norm, char* And, char* Or)
{

	// Initialisation des variables utilisées dans le main
		
		// Compteurs
	int i = 0;
	int j = 0;

		// Variables d'échanges entre fonctions
	int MF_And[4] = {-1, -1, -1, -1};
	float Y_And[4] = {-1, -1, -1, -1};
	int N_And = 0;

	float Y_Or[14] = {0};
	float X_Or[14] = {0};
	int N_Or = 0;

	float Centroide = 0.0;

		// Variables de test
	int test_And;
	int test_Or; 

	// On appele la fonction choisie pour le And pour commencer
	if ( strcmp(And, "Min") == 0)
		test_And = Min_Fun(TAILLE, regle, A_norm, B_norm, MF_X, MF_And, Y_And, &N_And);
	else if ( strcmp(And, "Product") == 0)
		test_And = ProdFun(TAILLE, regle, A_norm, B_norm, MF_X, MF_And, Y_And, &N_And);
	else 
		return -2; // TO DO : définir les valeurs de sorties suivant les erreurs
	
	if (test_And != 0)
		return -1;
	
	// Ensuite, on appele la fonction pour le Or
	if ( strcmp(Or, "Max") == 0)
		test_Or = MaxFun(TAILLE, MF_X, MF_And, Y_And, N_And, X_Or, Y_Or, &N_Or);
	else if ( strcmp(Or, "ProbSum") == 0)
		i = 1;// à écrire
	else 
		return -3;	// cf. line 48

	// Ensuite on calcule le centroide de tout ca
	Centroide = Centroid(X_Or, Y_Or, N_Or);

	// On a fini, on retourne le centroide
	return Centroide;
}
예제 #14
0
Array* TranslateToOrigin(Array* points)
{
    Array* translated = Array::create();
    Vec2 centroid = Centroid(points);
    float qx;
    float qy;
    
    for (int i = 0; i < points->count(); i++) {
        PointObject* point = (PointObject*)points->getObjectAtIndex(i);
        qx = point->x - centroid.x;
        qy = point->y - centroid.y;
        translated->addObject(PointObject::create(qx, qy));
    }
    return translated;
}
    void RotateBy(PointVector& points, double theta)
    {
        PointPtr c = Centroid(points);
        double cosine = cos(theta);
        double sine = sin(theta);

        PointVector newpoints;
        for (size_t i = 0; i < points.size(); ++i)
        {
            double qx = (points[i]->X - c->X) * cosine - (points[i]->Y - c->Y) * sine + c->X;
            double qy = (points[i]->X - c->X) * sine + (points[i]->Y - c->Y) * cosine + c->Y;
            newpoints.push_back(PointPtr(new Point(qx, qy)));
        }

        points.clear();
        points.insert(points.begin(), newpoints.begin(), newpoints.end());
    }
예제 #16
0
/*----------------------------------------------------------------------*
 |  make a triangulization of a polygon (private)             mwgee 10/05|
 *----------------------------------------------------------------------*/
bool MOERTEL::Overlap::Triangulation()
{
  // we have a polygon that is in clockwise order at this moment

  // if more than 3 points, find a center point
  int np = SizePointPolygon();
  if (np<3)
  {
	std::cout << "***ERR*** MOERTEL::Overlap::Triangulization:\n"
         << "***ERR*** # point in polygon < 3 ... very strange!!!\n"
         << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
    exit(EXIT_FAILURE);
  }
  if (np>3) // we have to add a center point
  {
    double xi[2];
	std::vector<Teuchos::RCP<MOERTEL::Point> > points; PointView(points);

#if 1 // compute center point xi as centroid
    Centroid(xi,points,np);    
    //std::cout << "Centroid xi : " << xi[0] << " / " << xi[1] << endl; fflush(stdout);
#endif
    
#if 0 // compute center point as nodal avergage
    xi[0] = xi[1] = 0.0;
    for (int i=0; i<np; ++i)
    {
      const double* pxi = points[i]->Xi();
      xi[0] += pxi[0];
      xi[1] += pxi[1];
    }
    xi[0] /= np;
    xi[1] /= np;
    //std::cout << "Nodal    xi : " << xi[0] << " / " << xi[1] << endl << endl; fflush(stdout);
#endif
    
    // create a point -1 as center point and add it to the polygon
    AddPointtoPolygon(-1,xi);
    points.clear();
  } // if (np>3)
  
  np = SizePointPolygon();
  std::vector<Teuchos::RCP<MOERTEL::Point> >  points; PointView(points);

  // create a MOERTEL::Node for every point
  int dof[3]; dof[0] = dof[1] = dof[2] = -1;
  
  // find real world coords for all points
  // find real world normal for all points
  // note that the polygon is in slave segment parameter space and is
  // completely contained in the slave segment. we can therefore use
  // slave segment values to interpolate polgon point values
  for (int i=0; i<np; ++i)
  {
    double x[3]; x[0] = x[1] = x[2] = 0.0;
    double n[3]; n[0] = n[1] = n[2] = 0.0;
    double val[20];
    sseg_.EvaluateFunction(0,points[i]->Xi(),val,sseg_.Nnode(),NULL);
    MOERTEL::Node** snodes = sseg_.Nodes();
    for (int j=0; j<sseg_.Nnode(); ++j)
      for (int k=0; k<3; ++k)
      {
        x[k] += val[j]*snodes[j]->X()[k];
        n[k] += val[j]*snodes[j]->N()[k];
      }
    const double length = MOERTEL::length(n,3);
    for (int j=0; j<3; ++j) n[j] /= length;
    // create a node with this coords and normal;
    MOERTEL::Node* node = new MOERTEL::Node(points[i]->Id(),x,3,dof,false,OutLevel());
    node->SetN(n);
    // set node in point
    points[i]->SetNode(node);
#if 0
	std::cout << *points[i];
#endif
  }  

  // find projection values for all points in polygon on mseg
  {
    double mxi[2];
	double gap;
    MOERTEL::Projector projector(inter_.IsOneDimensional(),OutLevel());
    for (int i=0; i<np; ++i)
    {
	  Teuchos::RCP<MOERTEL::Node> node = points[i]->Node();
      projector.ProjectNodetoSegment_NodalNormal(*node,mseg_,mxi,gap);
      // create a projected node and set it in node
      MOERTEL::ProjectedNode* pnode = new MOERTEL::ProjectedNode(*node,mxi,&mseg_);
      node->SetProjectedNode(pnode);
	  node->SetGap(gap);
#if 0
	  std::cout << "-------------------------------------------------------\n";
      if (mseg_.Nnode()==3)
      {
        if (mxi[0]<=1. && mxi[1]<=abs(1.-mxi[0]) && mxi[0]>=0. && mxi[1]>=0.)
          std::cout << "OVERLAP: point " << points[i]->Id() << " is in mseg, mxi " << mxi[0] << " / " << mxi[1] << endl;
        else
          std::cout << "OVERLAP: point " << points[i]->Id() << " is NOT in mseg, mxi " << mxi[0] << " / " << mxi[1] << endl;
      }
      else if (mseg_.Nnode()==4)
      {
        if (mxi[0]<=1.001 && mxi[0]>=-1.001 && mxi[1]<=1.001 && mxi[1]>=-1.001)
          std::cout << "OVERLAP: point " << points[i]->Id() << " is in mseg, mxi " << mxi[0] << " / " << mxi[1] << endl;
        else
          std::cout << "OVERLAP: point " << points[i]->Id() << " is NOT in mseg, mxi " << mxi[0] << " / " << mxi[1] << endl;
      }
      else
      {
		std::cout << "***ERR*** MOERTEL::Overlap::Triangulization:\n"
             << "***ERR*** # nodes " << mseg_.Nnode() << " of master segment is unknown\n"
             << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
        exit(EXIT_FAILURE);
      }
	  std::cout << "-------------------------------------------------------\n";
#endif

    }
  }

  // if we plan to interpolate function values at the gaussian points we need the
  // function values at the points
  if (exactvalues_==false)
  {
    // every point has 3 values of the 3 shape functions of the elements:
    // max 4 values from function 0 from sseg
    // max 4 values from function 1 from sseg
    // max 4 values from function 0 from mseg
    for (int i=0; i<np; ++i)
    {
      double val[20];
      int nmval = mseg_.Nnode();
      int nsval = sseg_.Nnode();
      // evaluate function 0 from sseg
      sseg_.EvaluateFunction(0,points[i]->Xi(),val,nsval,NULL);
      points[i]->StoreFunctionValues(0,val,nsval);
      // evaluate function 1 from sseg
      sseg_.EvaluateFunction(1,points[i]->Xi(),val,nsval,NULL);
      points[i]->StoreFunctionValues(1,val,nsval);
      // evaluate function 0 from mseg
      mseg_.EvaluateFunction(0,points[i]->Node()->GetProjectedNode()->Xi(),val,nmval,NULL);
      points[i]->StoreFunctionValues(2,val,nmval);
    }
  }
  
  // create the triangle elements from polygon with centerpoint
  // In case of np==3, there is no centerpoint
  if (np>3)
  {
    // the polygon is in clockwise order, center point is points[0] and has
    // id = -1
    if (points[0]->Id() != -1)
    {
	  std::cout << "***ERR*** MOERTEL::Overlap::Triangulization:\n"
           << "***ERR*** points[0]->Id() is not -1\n"
           << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
      exit(EXIT_FAILURE);
    }
    int nodeid[3];
    MOERTEL::Segment_BiLinearTri* tmp;
    MOERTEL::Function_LinearTri* func = new Function_LinearTri(OutLevel());
    for (int i=2; i<np; ++i)
    {
      // there are np-1 triangles
      // triangle ids go from 0 to np-2
      // a triangle is defined by nodes 0, i, i-1
      // *this class takes ownership of triangle
      nodeid[0]   = points[0]->Id();
      nodeid[1]   = points[i]->Id();
      nodeid[2]   = points[i-1]->Id();
      tmp = new MOERTEL::Segment_BiLinearTri(i-2,3,nodeid,OutLevel());
      // set a linear shape function to this triangle
      tmp->SetFunction(0,func);
      // add triangle to the *this class
      AddSegment(tmp->Id(),tmp);
    }
    // add the last triangle defined by nodes 0, 1, np-1 separately
    // *this class takes ownership of triangle
    nodeid[0]   = points[0]->Id();
    nodeid[1]   = points[1]->Id();
    nodeid[2]   = points[np-1]->Id();
    tmp = new MOERTEL::Segment_BiLinearTri(np-2,3,nodeid,OutLevel());
    // set a linear shape function to this triangle
    tmp->SetFunction(0,func);
    // add triangle to the *this class
    AddSegment(tmp->Id(),tmp);
    if (func) delete func; func = NULL;
  }
  else if (np==3) // single triangle without centerpoint
  {
    int nodeid[3];
    MOERTEL::Segment_BiLinearTri* tmp;
    MOERTEL::Function_LinearTri* func = new Function_LinearTri(OutLevel());
    nodeid[0] = points[0]->Id();
    nodeid[1] = points[2]->Id();
    nodeid[2] = points[1]->Id();
    // *this class takes ownership of triangle
    tmp = new MOERTEL::Segment_BiLinearTri(0,3,nodeid,OutLevel());
    // set a linear shape function to this triangle
    tmp->SetFunction(0,func);
    // add triangle the *this class
    AddSegment(tmp->Id(),tmp);
    if (func) delete func; func = NULL;
  }
  else
  {
	std::cout << "***ERR*** MOERTEL::Overlap::Triangulization:\n"
         << "***ERR*** # point in polygon < 3 ... very strange!!!\n"
         << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
    exit(EXIT_FAILURE);
  }
  
  // create ptr topology between triangle and nodes in points
  std::vector<MOERTEL::Node*> nodes(np);
  for (int i=0; i<np; ++i) nodes[i] = points[i]->Node().get();
  
  // loop segments and set ptr to nodes in them
  std::map<int,Teuchos::RCP<MOERTEL::Segment> >::iterator curr;
  for (curr=s_.begin(); curr != s_.end(); ++curr)
    curr->second->GetPtrstoNodes(nodes);
  
  nodes.clear();
  
  points.clear();
  
  return true;
}
예제 #17
0
//---------------------------------------------------------
bool CMultiBand_Variation::Get_Variation(int x, int y)
{
	if( !m_Mask.is_NoData(x, y) )
	{
		int			iBand, iCell, ix, iy;
		double		iDistance, iWeight, Weights, Distance;
		CSG_Vector	Centroid(m_pBands->Get_Count());

		//-------------------------------------------------
		for(iCell=0, Weights=0.0; iCell<m_Cells.Get_Count(); iCell++)
		{
			if( m_Cells.Get_Values(iCell, ix = x, iy = y, iDistance, iWeight, true) && m_Mask.is_InGrid(ix, iy) )
			{
				for(iBand=0; iBand<m_pBands->Get_Count(); iBand++)
				{
					Centroid[iBand]	+= iWeight * m_pBands->asGrid(iBand)->asDouble(ix, iy);
				}

				Weights			+= iWeight;
			}
		}

		//-------------------------------------------------
		if( Weights > 0.0 )
		{
			CSG_Simple_Statistics	s;

			Centroid	*= 1.0 / Weights;

			for(iCell=0; iCell<m_Cells.Get_Count(); iCell++)
			{
				if( m_Cells.Get_Values(iCell, ix = x, iy = y, iDistance, iWeight, true) && m_Mask.is_InGrid(ix, iy) )
				{
					for(iBand=0, Distance=0.0; iBand<m_pBands->Get_Count(); iBand++)
					{
						Distance	+= SG_Get_Square(Centroid[iBand] - m_pBands->asGrid(iBand)->asDouble(ix, iy));
					}

					s.Add_Value(sqrt(Distance), iWeight);

					if( ix == x && iy == y )
					{
						if( m_pDiff )	m_pDiff->Set_Value(x, y, sqrt(Distance));
					}
				}
			}

			if( m_pMean   )	m_pMean  ->Set_Value(x, y, s.Get_Mean());
			if( m_pStdDev )	m_pStdDev->Set_Value(x, y, s.Get_StdDev());

			return( true );
		}
	}

	//-----------------------------------------------------
	if( m_pMean     )	m_pMean		->Set_NoData(x, y);
	if( m_pStdDev   )	m_pStdDev	->Set_NoData(x, y);
	if( m_pDiff     )	m_pDiff		->Set_NoData(x, y);

	return( false );
}
예제 #18
0
void CTexturedLineRData::Update(const SOverlayTexturedLine& line)
{
	if (m_VB)
	{
		g_VBMan.Release(m_VB);
		m_VB = NULL;
	}
	if (m_VBIndices)
	{
		g_VBMan.Release(m_VBIndices);
		m_VBIndices = NULL;
	}

	if (!line.m_SimContext)
	{
		debug_warn(L"[TexturedLineRData] No SimContext set for textured overlay line, cannot render (no terrain data)");
		return;
	}

	const CTerrain& terrain = line.m_SimContext->GetTerrain();
	CmpPtr<ICmpWaterManager> cmpWaterManager(*line.m_SimContext, SYSTEM_ENTITY);

	float v = 0.f;
	std::vector<SVertex> vertices;
	std::vector<u16> indices;

	size_t n = line.m_Coords.size() / 2; // number of line points
	bool closed = line.m_Closed;

	ENSURE(n >= 2); // minimum needed to avoid errors (also minimum value to make sense, can't draw a line between 1 point)

	// In each iteration, p1 is the position of vertex i, p0 is i-1, p2 is i+1.
	// To avoid slightly expensive terrain computations we cycle these around and
	// recompute p2 at the end of each iteration.

	CVector3D p0;
	CVector3D p1(line.m_Coords[0], 0, line.m_Coords[1]);
	CVector3D p2(line.m_Coords[(1 % n)*2], 0, line.m_Coords[(1 % n)*2+1]);

	if (closed)
		// grab the ending point so as to close the loop
		p0 = CVector3D(line.m_Coords[(n-1)*2], 0, line.m_Coords[(n-1)*2+1]);
	else
		// we don't want to loop around and use the direction towards the other end of the line, so create an artificial p0 that 
		// extends the p2 -> p1 direction, and use that point instead
		p0 = p1 + (p1 - p2);

	bool p1floating = false;
	bool p2floating = false;

	// Compute terrain heights, clamped to the water height (and remember whether
	// each point was floating on water, for normal computation later)

	// TODO: if we ever support more than one water level per map, recompute this per point
	float w = cmpWaterManager->GetExactWaterLevel(p0.X, p0.Z);

	p0.Y = terrain.GetExactGroundLevel(p0.X, p0.Z);
	if (p0.Y < w)
		p0.Y = w;

	p1.Y = terrain.GetExactGroundLevel(p1.X, p1.Z);
	if (p1.Y < w)
	{
		p1.Y = w;
		p1floating = true;
	}

	p2.Y = terrain.GetExactGroundLevel(p2.X, p2.Z);
	if (p2.Y < w)
	{
		p2.Y = w;
		p2floating = true;
	}

	for (size_t i = 0; i < n; ++i)
	{
		// For vertex i, compute bisector of lines (i-1)..(i) and (i)..(i+1)
		// perpendicular to terrain normal

		// Normal is vertical if on water, else computed from terrain
		CVector3D norm;
		if (p1floating)
			norm = CVector3D(0, 1, 0);
		else
			norm = terrain.CalcExactNormal(p1.X, p1.Z);

		CVector3D b = ((p1 - p0).Normalized() + (p2 - p1).Normalized()).Cross(norm);

		// Adjust bisector length to match the line thickness, along the line's width
		float l = b.Dot((p2 - p1).Normalized().Cross(norm));
		if (fabs(l) > 0.000001f) // avoid unlikely divide-by-zero
			b *= line.m_Thickness / l;

		// Push vertices and indices for each quad in GL_TRIANGLES order. The two triangles of each quad are indexed using
		// the winding orders (BR, BL, TR) and (TR, BL, TR) (where BR is bottom-right of this iteration's quad, TR top-right etc).
		SVertex vertex1(p1 + b + norm*OverlayRenderer::OVERLAY_VOFFSET, 0.f, v);
		SVertex vertex2(p1 - b + norm*OverlayRenderer::OVERLAY_VOFFSET, 1.f, v);
		vertices.push_back(vertex1);
		vertices.push_back(vertex2);

		u16 index1 = vertices.size() - 2; // index of vertex1 in this iteration (TR of this quad)
		u16 index2 = vertices.size() - 1; // index of the vertex2 in this iteration (TL of this quad)

		if (i == 0)
		{
			// initial two vertices to continue building triangles from (n must be >= 2 for this to work)
			indices.push_back(index1);
			indices.push_back(index2);
		}
		else 
		{
			u16 index1Prev = vertices.size() - 4; // index of the vertex1 in the previous iteration (BR of this quad)
			u16 index2Prev = vertices.size() - 3; // index of the vertex2 in the previous iteration (BL of this quad)
			ENSURE(index1Prev < vertices.size());
			ENSURE(index2Prev < vertices.size());
			// Add two corner points from last iteration and join with one of our own corners to create triangle 1
			// (don't need to do this if i == 1 because i == 0 are the first two ones, they don't need to be copied)
			if (i > 1)
			{
				indices.push_back(index1Prev);
				indices.push_back(index2Prev);
			}
			indices.push_back(index1); // complete triangle 1

			// create triangle 2, specifying the adjacent side's vertices in the opposite order from triangle 1
			indices.push_back(index1);
			indices.push_back(index2Prev);
			indices.push_back(index2);
		}

		// alternate V coordinate for debugging
		v = 1 - v;

		// cycle the p's and compute the new p2
		p0 = p1;
		p1 = p2;
		p1floating = p2floating;

		// if in closed mode, wrap around the coordinate array for p2 -- otherwise, extend linearly
		if (!closed && i == n-2)
			// next iteration is the last point of the line, so create an artificial p2 that extends the p0 -> p1 direction
			p2 = p1 + (p1 - p0);
		else
			p2 = CVector3D(line.m_Coords[((i+2) % n)*2], 0, line.m_Coords[((i+2) % n)*2+1]);

		p2.Y = terrain.GetExactGroundLevel(p2.X, p2.Z);
		if (p2.Y < w)
		{
			p2.Y = w;
			p2floating = true;
		}
		else
			p2floating = false;
	}

	if (closed)
	{
		// close the path
		indices.push_back(vertices.size()-2);
		indices.push_back(vertices.size()-1);
		indices.push_back(0);

		indices.push_back(0);
		indices.push_back(vertices.size()-1);
		indices.push_back(1);
	}
	else
	{
		// Create start and end caps. On either end, this is done by taking the centroid between the last and second-to-last pair of
		// vertices that was generated along the path (i.e. the vertex1's and vertex2's from above), taking a directional vector 
		// between them, and drawing the line cap in the plane given by the two butt-end corner points plus said vector.
		std::vector<u16> capIndices;
		std::vector<SVertex> capVertices;

		// create end cap
		CreateLineCap(
			line,
			// the order of these vertices is important here, swapping them produces caps at the wrong side
			vertices[vertices.size()-2].m_Position, // top-right vertex of last quad
			vertices[vertices.size()-1].m_Position, // top-left vertex of last quad
			// directional vector between centroids of last vertex pair and second-to-last vertex pair
			(Centroid(vertices[vertices.size()-2], vertices[vertices.size()-1]) - Centroid(vertices[vertices.size()-4], vertices[vertices.size()-3])).Normalized(),
			line.m_EndCapType,
			capVertices,
			capIndices
		);

		for (unsigned i = 0; i < capIndices.size(); i++)
			capIndices[i] += vertices.size();

		vertices.insert(vertices.end(), capVertices.begin(), capVertices.end());
		indices.insert(indices.end(), capIndices.begin(), capIndices.end());

		capIndices.clear();
		capVertices.clear();

		// create start cap
		CreateLineCap(
			line,
			// the order of these vertices is important here, swapping them produces caps at the wrong side
			vertices[1].m_Position,
			vertices[0].m_Position,
			// directional vector between centroids of first vertex pair and second vertex pair
			(Centroid(vertices[1], vertices[0]) - Centroid(vertices[3], vertices[2])).Normalized(),
			line.m_StartCapType,
			capVertices,
			capIndices
		);

		for (unsigned i = 0; i < capIndices.size(); i++)
			capIndices[i] += vertices.size();

		vertices.insert(vertices.end(), capVertices.begin(), capVertices.end());
		indices.insert(indices.end(), capIndices.begin(), capIndices.end());
	}

	ENSURE(indices.size() % 3 == 0); // GL_TRIANGLES indices, so must be multiple of 3

	m_VB = g_VBMan.Allocate(sizeof(SVertex), vertices.size(), GL_STATIC_DRAW, GL_ARRAY_BUFFER);
	if (m_VB) // allocation might fail (e.g. due to too many vertices)
	{
		m_VB->m_Owner->UpdateChunkVertices(m_VB, &vertices[0]); // copy data into VBO

		for (size_t k = 0; k < indices.size(); ++k)
			indices[k] += m_VB->m_Index;

		m_VBIndices = g_VBMan.Allocate(sizeof(u16), indices.size(), GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER);
		if (m_VBIndices)
			m_VBIndices->m_Owner->UpdateChunkVertices(m_VBIndices, &indices[0]);
	}

}
 void RotateToZero(PointVector& points)
 {
     PointPtr c = Centroid(points);
     double theta = atan2(c->Y - points[0]->Y, c->X - points[0]->X);
     RotateBy(points, -theta);
 }
예제 #20
0
파일: R3Box.C 프로젝트: acplus/peptalk
const R3Sphere R3Box::
BSphere (void) const
{
    // Return bounding sphere 
    return R3Sphere(Centroid(), DiagonalRadius());
}