Пример #1
0
/*
 * Sets up the polygons, runs the overlap computation, and returns the area of overlap.
 */
double computeOverlap(double *ilon, double *ilat, double *olon, double *olat,
                      int energyMode, double refArea, double *areaRatio) {
  int i;
  double thisPixelArea;

  *areaRatio = 1.;

  if (energyMode) {
    nv = 0;

    for (i = 0; i < 4; ++i)
      SaveVertex(&P[i]);

    thisPixelArea = Girard();

    *areaRatio = thisPixelArea / refArea;
  }

  nv = 0;

  if (DEBUG >= 4) {
    printf("Input (P):\n");
    for (i = 0; i < 4; ++i)
      printf("%10.6f %10.6f\n", ilon[i], ilat[i]);

    printf("\nOutput (Q):\n");
    for (i = 0; i < 4; ++i)
      printf("%10.6f %10.6f\n", olon[i], olat[i]);

    printf("\n");
    fflush(stdout);
  }

  for (i = 0; i < 4; ++i) {
    P[i].x = cos(ilon[i]) * cos(ilat[i]);
    P[i].y = sin(ilon[i]) * cos(ilat[i]);
    P[i].z = sin(ilat[i]);
  }

  for (i = 0; i < 4; ++i) {
    Q[i].x = cos(olon[i]) * cos(olat[i]);
    Q[i].y = sin(olon[i]) * cos(olat[i]);
    Q[i].z = sin(olat[i]);
  }

  ComputeIntersection(P, Q);

  return (Girard());
}
int PointInPolyhedron(const Real p[restrict], const Polyhedron *poly, int fid[restrict])
{
    const Real zero = 0.0;
    RealVec v0 = {zero}; /* vertices */
    RealVec v1 = {zero};
    RealVec v2 = {zero};
    RealVec e01 = {zero}; /* edges */
    RealVec e02 = {zero};
    RealVec pi = {zero}; /* closest point */
    RealVec N = {zero}; /* normal of the closest point */
    /*
     * Parametric equation of triangle defined plane 
     * T(s,t) = v0 + s(v1-v0) + t(v2-v0) = v0 + s*e01 + t*e02
     * s, t: real numbers. v0, v1, v2: vertices. e01, e02: edge vectors. 
     * A point pi = T(s,t) is in the triangle T when s>=0, t>=0, and s+t<=1.
     * Further, pi is on an edge of T if one of the conditions s=0; t=0; 
     * s+t=1 is true with each condition corresponds to one edge. Each 
     * s=0, t=0; s=1, t=0; s=0, t=1 corresponds to v0, v1, and v2.
     */
    RealVec para = {zero}; /* parametric coordinates */
    Real distSquare = zero; /* store computed squared distance */
    Real distSquareMin = FLT_MAX; /* store minimum squared distance */
    int cid = 0; /* closest face identifier */
    for (int n = 0; n < poly->faceN; ++n) {
        BuildTriangle(n, poly, v0, v1, v2, e01, e02);
        distSquare = PointTriangleDistance(p, v0, e01, e02, para);
        if (distSquareMin > distSquare) {
            distSquareMin = distSquare;
            cid = n;
        }
    }
    *fid = cid;
    ComputeIntersection(p, cid, poly, pi, N);
    pi[X] = p[X] - pi[X];
    pi[Y] = p[Y] - pi[Y];
    pi[Z] = p[Z] - pi[Z];
    if (zero < Dot(pi, N)) {
        /* outside polyhedron */
        return 0;
    } else {
        /* inside or on polyhedron */
        return 1;
    }
}
Пример #3
0
/**
@def This function move a particle over the mesh
*/
void MoveParticle(Particle<CMeshO> &info,CMeshO::VertexPointer p,float l,int t,Point3f dir,Point3f g,float a){
    if(CheckFallPosition(info.face,g,a)){
        p->SetS();
        return;
    }
    float time=t;
    if(dir.Norm()==0) dir=getRandomDirection();
    Point3f new_pos;
    Point3f current_pos;
    Point3f int_pos;
    CMeshO::FacePointer current_face=info.face;
    CMeshO::FacePointer new_face;
    new_face=current_face;
    current_pos=p->P();
    new_pos=StepForward(current_pos,info.v,info.mass,current_face,g+dir,l,time);
    while(!IsOnFace(new_pos,current_face)){
        int edge=ComputeIntersection(current_pos,new_pos,current_face,new_face,int_pos);
        if(edge!=-1){
            Point3f n = new_face->N();
            if(CheckFallPosition(new_face,g,a))  p->SetS();
            float elapsed_time=GetElapsedTime(current_pos,int_pos,new_pos,time);
            info.v=GetNewVelocity(info.v,current_face,new_face,g+dir,g,info.mass,elapsed_time);
            time=time-elapsed_time;
            current_pos=int_pos;
            current_face->Q()+=elapsed_time*5;
            current_face=new_face;
            new_pos=int_pos;
            if(time>0){
                if(p->IsS()) break;
                new_pos=StepForward(current_pos,info.v,info.mass,current_face,g+dir,l,time);
            }
            current_face->C()=Color4b::Green;//Just Debug!!!!
        }else{
            //We are on a border
            new_pos=int_pos;
            current_face=new_face;
            p->SetS();
            break;
        }
    }
    p->P()=new_pos;
    info.face=current_face;
}
//----------------------------------------------------------------------------
bool IntersectConvexPolyhedra::OnKeyDown (unsigned char key, int x, int y)
{
    switch (key)
    {
    case 's':
    case 'S':
        InitializeObjectMotion(mScene);
        return true;
    case '0':
        InitializeObjectMotion(mMeshPoly0);
        return true;
    case '1':
        InitializeObjectMotion(mMeshPoly1);
        return true;
    case 'r':
    case 'R':
        ComputeIntersection();
        mScene->Update();
        mCuller.ComputeVisibleSet(mScene);
        return true;
    }

    return WindowApplication3::OnKeyDown(key, x, y);
}
Пример #5
0
//
// DivideOneSeg
//
// Apply the partition line to the given seg, taking the necessary
// action (moving it into either the left list, right list, or
// splitting it).
//
// -AJA- I have rewritten this routine based on the EvalPartition
//       routine above (which I've also reworked, heavily).  I think
//       it is important that both these routines follow the exact
//       same logic when determining which segs should go left, right
//       or be split.
//
void DivideOneSeg(seg_t *cur, seg_t *part, 
    superblock_t *left_list, superblock_t *right_list,
    intersection_t ** cut_list)
{
  seg_t *new_seg;

  float_g x, y;

  /* get state of lines' relation to each other */
  float_g a = UtilPerpDist(part, cur->psx, cur->psy);
  float_g b = UtilPerpDist(part, cur->pex, cur->pey);

  boolean_g self_ref = cur->linedef ? cur->linedef->self_ref : FALSE;

  if (cur->source_line == part->source_line)
    a = b = 0;

  /* check for being on the same line */
  if (fabs(a) <= DIST_EPSILON && fabs(b) <= DIST_EPSILON)
  {
    AddIntersection(cut_list, cur->start, part, self_ref);
    AddIntersection(cut_list, cur->end,   part, self_ref);

    // this seg runs along the same line as the partition.  check
    // whether it goes in the same direction or the opposite.

    if (cur->pdx*part->pdx + cur->pdy*part->pdy < 0)
    {
      AddSegToSuper(left_list, cur);
    }
    else
    {
      AddSegToSuper(right_list, cur);
    }

    return;
  }

  /* check for right side */
  if (a > -DIST_EPSILON && b > -DIST_EPSILON)
  {
    if (a < DIST_EPSILON)
      AddIntersection(cut_list, cur->start, part, self_ref);
    else if (b < DIST_EPSILON)
      AddIntersection(cut_list, cur->end, part, self_ref);

    AddSegToSuper(right_list, cur);
    return;
  }
 
  /* check for left side */
  if (a < DIST_EPSILON && b < DIST_EPSILON)
  {
    if (a > -DIST_EPSILON)
      AddIntersection(cut_list, cur->start, part, self_ref);
    else if (b > -DIST_EPSILON)
      AddIntersection(cut_list, cur->end, part, self_ref);

    AddSegToSuper(left_list, cur);
    return;
  }
 
  // when we reach here, we have a and b non-zero and opposite sign,
  // hence this seg will be split by the partition line.
  
  ComputeIntersection(cur, part, a, b, &x, &y);

  new_seg = SplitSeg(cur, x, y);

  AddIntersection(cut_list, cur->end, part, self_ref);

  if (a < 0)
  {
    AddSegToSuper(left_list,  cur);
    AddSegToSuper(right_list, new_seg);
  }
  else
  {
    AddSegToSuper(right_list, cur);
    AddSegToSuper(left_list,  new_seg);
  }
}
//----------------------------------------------------------------------------
void IntersectConvexPolyhedra::CreateScene ()
{
    mScene = new0 Node();
    mMotionObject = mScene;

    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    // Attach a dummy intersection mesh.  If the intersection is nonempty,
    // the Culling flag will be modified to CULL_DYNAMIC.  The intersection
    // is drawn as a solid.
    mMeshIntersection = StandardMesh(vformat).Tetrahedron();
    VertexBufferAccessor vba(mMeshIntersection);
    Float3 green(0.0f, 1.0f, 0.0f);
    int i, j;
    for (i = 0; i < vba.GetNumVertices(); ++i)
    {
        vba.Color<Float3>(0, i) = green;
    }
    mMeshIntersection->SetEffectInstance(
        VertexColor3Effect::CreateUniqueInstance());
    mMeshIntersection->Culling = Spatial::CULL_ALWAYS;
    mScene->AttachChild(mMeshIntersection);

    // The first polyhedron is an ellipsoid.
    ConvexPolyhedronf::CreateEggShape(Vector3f::ZERO, 1.0f, 1.0f, 2.0f, 2.0f,
        4.0f, 4.0f, 3, mWorldPoly0);

    // Build the corresponding mesh.
    int numVertices = mWorldPoly0.GetNumVertices();
    int numTriangles = mWorldPoly0.GetNumTriangles();
    int numIndices = 3*numTriangles;
    VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride);
    IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int));
    Float3 red(1.0f, 0.0f, 0.0f);
    vba.ApplyTo(vformat, vbuffer);
    for (i = 0; i < numVertices; ++i)
    {
        vba.Position<Vector3f>(i) = mWorldPoly0.Point(i);
        vba.Color<Float3>(0,i) = red;
    }
    int* indices = (int*)ibuffer->GetData();
    for (i = 0; i < numTriangles; ++i)
    {
        const MTTriangle& triangle = mWorldPoly0.GetTriangle(i);
        for (j = 0; j < 3; ++j)
        {
            indices[3*i + j] = mWorldPoly0.GetVLabel(triangle.GetVertex(j));
        }
    }

    mMeshPoly0 = new0 TriMesh(vformat, vbuffer, ibuffer);
    VisualEffectInstance* instance =
        VertexColor3Effect::CreateUniqueInstance();
    instance->GetEffect()->GetWireState(0, 0)->Enabled = true;
    mMeshPoly0->SetEffectInstance(instance);
    mMeshPoly0->LocalTransform.SetTranslate(APoint(0.0f, 2.0f, 0.0f));
    mScene->AttachChild(mMeshPoly0);

    // The second polyhedron is egg shaped.
    ConvexPolyhedronf::CreateEggShape(Vector3f::ZERO, 2.0f, 2.0f, 4.0f, 4.0f,
        5.0f, 3.0f, 4, mWorldPoly1);

    // Build the corresponding mesh.
    numVertices = mWorldPoly1.GetNumVertices();
    numTriangles = mWorldPoly1.GetNumTriangles();
    numIndices = 3*numTriangles;
    vbuffer = new0 VertexBuffer(numVertices, vstride);
    ibuffer = new0 IndexBuffer(numIndices, sizeof(int));
    Float3 blue(0.0f, 0.0f, 1.0f);
    vba.ApplyTo(vformat, vbuffer);
    for (i = 0; i < numVertices; ++i)
    {
        vba.Position<Vector3f>(i) = mWorldPoly1.Point(i);
        vba.Color<Float3>(0, i) = blue;
    }
    indices = (int*)ibuffer->GetData();
    for (i = 0; i < numTriangles; ++i)
    {
        const MTTriangle& triangle = mWorldPoly1.GetTriangle(i);
        for (j = 0; j < 3; ++j)
        {
            indices[3*i + j] = mWorldPoly1.GetVLabel(triangle.GetVertex(j));
        }
    }

    mMeshPoly1 = new0 TriMesh(vformat, vbuffer, ibuffer);
    instance = VertexColor3Effect::CreateUniqueInstance();
    instance->GetEffect()->GetWireState(0, 0)->Enabled = true;
    mMeshPoly1->SetEffectInstance(instance);
    mMeshPoly1->LocalTransform.SetTranslate(APoint(0.0f, -2.0f, 0.0f));
    mScene->AttachChild(mMeshPoly1);

    ComputeIntersection();
}
Пример #7
0
double computeOverlap(double *ilon, double *ilat,
                      double *olon, double *olat, 
		      int energyMode, double refArea, double *areaRatio)
{
   int    i;
   double thisPixelArea;

   pi  = atan(1.0) * 4.;
   dtr = pi / 180.;


   *areaRatio = 1.;

   if(energyMode)
   {
      nv = 0;

      for(i=0; i<4; ++i)
      SaveVertex(&P[i]);

      thisPixelArea = Girard();

      *areaRatio = thisPixelArea / refArea;
   }


   nv = 0;

   if(debug >= 4)
   {
      printf("\n-----------------------------------------------\n\nAdding pixel (%d,%d) to pixel (%d,%d)\n\n",
         inRow, inColumn, outRow, outColumn);

      printf("Input (P):\n");
      for(i=0; i<4; ++i)
         printf("%10.6f %10.6f\n", ilon[i], ilat[i]);

      printf("\nOutput (Q):\n");
      for(i=0; i<4; ++i)
         printf("%10.6f %10.6f\n", olon[i], olat[i]);

      printf("\n");
      fflush(stdout);
   }

   for(i=0; i<4; ++i)
   {
      P[i].x = cos(ilon[i]*dtr) * cos(ilat[i]*dtr);
      P[i].y = sin(ilon[i]*dtr) * cos(ilat[i]*dtr);
      P[i].z = sin(ilat[i]*dtr);
   }

   for(i=0; i<4; ++i)
   {
      Q[i].x = cos(olon[i]*dtr) * cos(olat[i]*dtr);
      Q[i].y = sin(olon[i]*dtr) * cos(olat[i]*dtr);
      Q[i].z = sin(olat[i]*dtr);
   }

   ComputeIntersection(P, Q);

   return(Girard());
}
Пример #8
0
static inline void 
DivideSegs(struct Seg *ts, struct Seg **rs, struct Seg **ls, const bbox_t bbox)
{
	struct Seg *rights,*lefts;
	struct Seg *tmps,*best,*news,*prev;
	struct Seg *add_to_rs,*add_to_ls;
  	struct Seg *new_best=NULL,*new_rs,*new_ls;

	struct Seg *strights,*stlefts;
        int num_new=0;
	short int x,y,val;

	best = PickNode(ts,bbox);			/* Pick best node to use.*/

	if(best == NULL) ProgError("Couldn't pick nodeline!");

	node_x = vertices[best->start].x;
	node_y = vertices[best->start].y;
	node_dx = vertices[best->end].x-vertices[best->start].x;
	node_dy = vertices[best->end].y-vertices[best->start].y;

/* When we get to here, best is a pointer to the partition seg.
	Using this partition line, we must split any lines that are intersected
	into a left and right half, flagging them to be put their respective sides
	Ok, now we have the best line to use as a partitioning line, we must
   split all of the segs into two lists (rightside & leftside).				 */

	rights = NULL;									/* Start off with empty*/
	lefts = NULL;									/* lists.*/
	strights = NULL;								/* Start off with empty*/
	stlefts = NULL;								/* lists.*/

	psx = vertices[best->start].x;			/* Partition line coords*/
	psy = vertices[best->start].y;
	pex = vertices[best->end].x;
	pey = vertices[best->end].y;
	pdx = psx - pex;								/* Partition line DX,DY*/
	pdy = psy - pey;

	for(tmps=ts;tmps;tmps=tmps->next)
		{
		progress();									/* Something for the user to look at.*/
		add_to_rs = NULL;
		add_to_ls = NULL;
		if(tmps != best)
			{
			lsx = vertices[tmps->start].x;	/* Calculate this here, cos it doesn't*/
			lsy = vertices[tmps->start].y;	/* change for all the interations of*/
			lex = vertices[tmps->end].x;		/* the inner loop!*/
			ley = vertices[tmps->end].y;
			val = DoLinesIntersect();
			if((val&2 && val&64) || (val&4 && val&32))	/* If intersecting !!*/
				{
				ComputeIntersection(&x,&y);
/*				printf("Splitting Linedef %d at %d,%d\n",tmps->linedef,x,y);*/
 			        vertices = ResizeMemory(vertices, sizeof(struct Vertex) * (num_verts+1));
				vertices[num_verts].x = x;
				vertices[num_verts].y = y;

				news = GetMemory(sizeof( struct Seg));
				*news = *tmps;
				tmps->next = news;
				news->start = num_verts;
				tmps->end = num_verts;
				news->dist = SplitDist(news);
/*				printf("splitting dist = %d\n",news->dist);*/
/*				printf("splitting vertices = %d,%d,%d,%d\n",tmps->start,tmps->end,news->start,news->end);*/
				if(val&32) add_to_ls = tmps;
				if(val&64) add_to_rs = tmps;
				if(val&2) add_to_ls = news;
				if(val&4) add_to_rs = news;
				tmps = news;
				num_verts++;
				num_new++;
				}
			else
				{											/* Not split, which side ?*/
				if(val&34) add_to_ls = tmps;
				if(val&68) add_to_rs = tmps;
				if(val&1 && val&16)					/* On same line*/
					{
/* 06/01/97 Lee Killough: this fixes a bug ever since 1.2x,
   probably 1.0, of BSP: when partitioning a parallel seg,
   you must take its vertices' orientation into account, NOT the
   flip bits, to determine which side of the partitioning line a
   parallel seg should go on. If you simply flip the linedef in
   question, you will be flipping both its vertices and sidedefs,
   and the flip bits as well, even though the basic geometry has
   not changed. Thus you need to use the vertices' orientation
   (whether the seg is in the same direction or not, regardless
   of its original linedef's being flipped or not), into account.

   Originally, some segs were partitioned backwards, and if
   it happened that there were different sectors on either
   side of the seg being partitioned, it could leave holes
   in space, causing either invisible barriers or disappearing
   Things, because the ssector would be associated with the
   wrong sector.

   The old logic of tmps->flip != best->flip seems to rest on
   the assumption that if two segs are parallel, they came
   from the same linedef. This is clearly not always true.   */

              /*  if (tmps->flip != best->flip)   old logic -- wrong!!! */

              /* We know the segs are parallel or nearly so, so take their
                 dot product to determine their relative orientation. */

		if ( (lsx-lex)*pdx + (lsy-ley)*pdy < 0)
  	         add_to_ls = tmps;
	 	else
		 add_to_rs = tmps;
					}
				}
			}
		else add_to_rs = tmps;						/* This is the partition line*/

/*		printf("Val = %X\n",val);*/

		if(add_to_rs)							/* CHECK IF SHOULD ADD RIGHT ONE */
			{
			new_rs = GetMemory(sizeof(struct Seg));
			*new_rs = *add_to_rs;
			if(add_to_rs == best) new_best = new_rs;
			new_rs->next = NULL;
			if(!rights) strights = rights = new_rs;
			else
				{
				rights->next = new_rs;
				rights = new_rs;
				}
			}
				
		if(add_to_ls)							/* CHECK IF SHOULD ADD LEFT ONE */
			{
			new_ls = GetMemory(sizeof(struct Seg));
			*new_ls = *add_to_ls;
			if(add_to_ls == best) new_best = new_ls;
			new_ls->next = NULL;
			if(!lefts) stlefts = lefts = new_ls;
			else
				{
				lefts->next = new_ls;
				lefts = new_ls;
				}
			}
		}

	if(strights == NULL)
		{
/*		printf("No right side, moving partition into right side\n");*/
		strights = rights = new_best;
		prev = NULL;
		for(tmps=stlefts;tmps;tmps=tmps->next)
			{
			if(tmps == new_best)
				{
				if(prev != NULL) prev->next=tmps->next;
				else stlefts=tmps->next;
				}
			prev=tmps;
			}
		prev->next = NULL;
		}
	
	if(stlefts == NULL)
		{
/*		printf("No left side, moving partition into left side\n");*/
		stlefts = lefts = new_best;
		prev = NULL;
		for(tmps=strights;tmps;tmps=tmps->next)
			{
			if(tmps == new_best)
				{
				if(prev != NULL) prev->next=tmps->next;
				else strights=tmps->next;
				}
			prev=tmps;
			}
		stlefts->next = NULL;
		prev->next = NULL;								/* Make sure end of list = NULL*/
		}

	if(rights->next != NULL) rights->next = NULL;
	if(lefts->next != NULL) lefts->next = NULL;

	for(tmps=ts;tmps;tmps=best)
		{
		best=tmps->next;
		free(tmps);
		}

/*	printf("Made %d new Vertices and Segs\n",num_new);*/

	*rs = strights ; *ls = stlefts;
}