//following is at least half the algorithm
//transforms each point locally
//and computes numDist distances out to localLevel away
void calcAppAniDel(double *vort, double *dist)
  {
  //big for loop. means do everything for every vector in vort.
  for (int x = 0; x < nx; x++)
    {
    for (int y = 0; y < ny; y++)
      {
      for (int z = 0; z < nz; z++)
        {
        //fprintf(stderr, "%d %d %d\n", x, y, z);
        //find transform based on this vector.
	double vX = GetArray(vort, x, y, z, 0);
	double vY = GetArray(vort, x, y, z, 1);
	double vZ = GetArray(vort, x, y, z, 2);
        double vNormSqr = vX*vX + vY*vY + vZ*vZ;  //used alot
	double alpha = calcAlpha(sqrt(vNormSqr)); //used equally alot
        //fprintf(stderr, "%e %f\n", vNormSqr, alpha);
        //fprintf(stderr, "%f %f %f\n", vX, vY, vZ);
	double *metricTensor = calcMetricTensor(vX, vY, vZ, vNormSqr, alpha);
	
        //calc distance and save in each point
	for (int boxX = 0; boxX < numDist; boxX++)
          {
	  for (int boxY = 0; boxY < numDist; boxY++)
            {  
            for (int boxZ = 0; boxZ < numDist; boxZ++)
              {
              //gridDist is global variable that determines grid spacing
              //void SetDist(double *a, double v, int i, int j, int k, int l) is function to set each distance
              double thisDist = 0.0;
              if (!((0 == boxX - localLevel) && (0 == boxY - localLevel) && (0 == boxZ - localLevel))) 
                {
                // we don't set the distance to this point, just to all surrounding.
                // treat current vector tail as origin, compute distances with metricTensor
                // and put total in thisDist
                
                //first compute the array representing the difference between this point and the one 
                //the distance to which is being calculated
                double *point = (double *)malloc(3 * sizeof(double));
                point[0] = (boxX - localLevel) * gridDist;
                point[1] = (boxY - localLevel) * gridDist;
                point[2] = (boxZ - localLevel) * gridDist;
                //fprintf(stderr, "%f %f %f \n", point[0], point[1], point[2]);
                //first step is metric (3x3) times the point (3x1) resulting in a 3x1 matrix
                double *firstStep = (double *)malloc(3 * sizeof(double));
                firstStep[0] = point[0] * metricTensor[0] + 
                               point[1] * metricTensor[1] + 
                               point[2] * metricTensor[2];
                firstStep[1] = point[0] * metricTensor[3] + 
                               point[1] * metricTensor[4] + 
                               point[2] * metricTensor[5];
                firstStep[2] = point[0] * metricTensor[6] + 
                               point[1] * metricTensor[7] + 
                               point[2] * metricTensor[8];
                //fprintf(stderr, "%f %f %f \n", firstStep[0], firstStep[1], firstStep[2]);
                //now take the point as a 1x3 matrix times this 3x1 resulting in a 1x1 (scalar) value.
                thisDist =       firstStep[0] * point[0] +
                                 firstStep[1] * point[1] +                 
                                 firstStep[2] * point[2] ;
                if (thisDist < 0.0)
                  {
                  thisDist = sqrt(-thisDist);
                  }
                else
                  {
                  thisDist = sqrt(thisDist);
                  }
                //the following lines transforms the dist in L2-norm to L(infinity)-norm
                //this cheap trick is only going to work for localLevel == 1
                //since in that case all 26 points have the same L(infinite)-distance
                double normalDist = sqrt( point[0] * point[0] +
                                          point[1] * point[1] +
                                          point[2] * point[2] );
                double infDist = abs(boxX - localLevel);
		if (infDist < abs(boxY - localLevel))
                  {
                  infDist = abs(boxY - localLevel);
                  }
		if (infDist < abs(boxZ - localLevel))
                  {
                  infDist = abs(boxZ - localLevel);
                  }
                //fprintf(stderr, "%f\n", infDist);
                thisDist = infDist*thisDist/normalDist;
                //end L(infinity)-norm conversion
                free(firstStep);
                free(point);
                //fprintf(stderr, "%e \n", thisDist);
                }
              SetDist(dist, thisDist, x, y, z, (boxZ + numDist * (boxY + numDist * boxX)) );
              }
            }
          }
	//that should be it for this step.
        free(metricTensor);
        }
      }
    }
  }
//put into arrays, check orientation... then sort.
int  averageStoreDistances(double *dists, int *aSegs, double *aDists, double *vort)
  {
  //okay, go through the whole big array of distances, setting each on the first pass, then adding, then /2
  //also store the distances and the point indices they connect
  int countStore = 0;
  for (int x = 0; x < nx; x++)
    {
    for (int y = 0; y < ny; y++)
      {
      for (int z = 0; z < nz; z++)
        {
        //fprintf(stderr, "another point %d %d %d\n", x, y, z);
	for (int boxX = 0; boxX < numDist; boxX++)
          {
	  for (int boxY = 0; boxY < numDist; boxY++)
            {  
            for (int boxZ = 0; boxZ < numDist; boxZ++)
              {
              if (!((0==boxX - localLevel)&&(0==boxY - localLevel)&&(0==boxZ - localLevel)))
                {
                double thisDist =  GetDist(dists, x, y, z, (boxZ + numDist * (boxY + numDist * boxX)) );
                //now find other distance this is to.
                int otherX = (nx + x + boxX - localLevel) % nx;
                int otherY = (ny + y + boxY - localLevel) % ny;
                int otherZ = (nz + z + boxZ - localLevel) % nz;
                int otherBoxX = numDist - boxX - 1;
                int otherBoxY = numDist - boxY - 1;
                int otherBoxZ = numDist - boxZ - 1;
                double otherDist =  GetDist(dists, otherX, otherY, otherZ, 
                                            (otherBoxZ + numDist * (otherBoxY + numDist * otherBoxX)) );
                double newDist = (thisDist + otherDist)/2.0;
                SetDist(dists, newDist, x, y, z, (boxZ + numDist * (boxY + numDist * boxX)));
                SetDist(dists, newDist, otherX, otherY, otherZ,
                                            (otherBoxZ + numDist * (otherBoxY + numDist * otherBoxX)) );
                
                if ((z + nz * (y + ny * x)) < (otherZ + nz * (otherY + ny * otherX)) )
                  {
                  //fprintf(stderr, "(%d %d %d) (%d %d %d) %e\n", x, y, z, otherX, otherY, otherZ, newDist); 
                  //determine orientation now instead of later
                  //throw out poorly defined orientations as well
 	          double vX = GetArray(vort, x, y, z, 0);
 	          double vY = GetArray(vort, x, y, z, 1);
	          double vZ = GetArray(vort, x, y, z, 2);
                  double signOrient = orientation(x,y,z,otherX,otherY,otherZ,vX,vY,vZ);
 	          vX = GetArray(vort, otherX, otherY, otherZ, 0);
 	          vY = GetArray(vort, otherX, otherY, otherZ, 1);
 	          vZ = GetArray(vort, otherX, otherY, otherZ, 2);
                  double signBackOrient = orientation(otherX,otherY,otherZ,x,y,z,vX,vY,vZ);
                  //fprintf(stderr, "%f %f \n", signOrient,signBackOrient);
                  if (signOrient > 0.0 && signBackOrient < 0.0)
                    {
                    SetAlphaDist(aDists, newDist, countStore);
                    SetAlphaSeg(aSegs, x, countStore, 0, 0);
                    SetAlphaSeg(aSegs, y, countStore, 1, 0);
                    SetAlphaSeg(aSegs, z, countStore, 2, 0);
                    SetAlphaSeg(aSegs, otherX, countStore, 0, 1);
                    SetAlphaSeg(aSegs, otherY, countStore, 1, 1);
                    SetAlphaSeg(aSegs, otherZ, countStore, 2, 1);
                    countStore++;
                    }
                  else if (signOrient < 0.0 && signBackOrient > 0.0)
                    {
                    SetAlphaDist(aDists, newDist, countStore);
                    SetAlphaSeg(aSegs, otherX, countStore, 0, 0);
                    SetAlphaSeg(aSegs, otherY, countStore, 1, 0);
                    SetAlphaSeg(aSegs, otherZ, countStore, 2, 0);
                    SetAlphaSeg(aSegs, x, countStore, 0, 1);
                    SetAlphaSeg(aSegs, y, countStore, 1, 1);
                    SetAlphaSeg(aSegs, z, countStore, 2, 1);
                    countStore++;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  return countStore;
  }
Esempio n. 3
0
/* Route une piste du BOARD.
	Parametres:
		1 face / 2 faces ( 0 / 1)
		coord source (row,col)
		coord destination (row,col)
		net_code
		pointeur sur le chevelu de reference

	Retourne :
		SUCCESS si route trouvee
		TRIVIAL_SUCCESS si pads connectes par superposition ( pas de piste a tirer)
		NOSUCCESS si echec
		STOP_FROM_ESC si Escape demande
		ERR_MEMORY defaut alloc RAM
*/
static int Route_1_Trace(WinEDA_PcbFrame * pcbframe, wxDC * DC,
				int two_sides, int row_source,int col_source,
				int row_target,int col_target, CHEVELU * pt_chevelu )
{
int  r, c, side , d, apx_dist, nr, nc;
int result, skip;
int i;
LISTE_PAD * ptr;
long curcell, newcell, buddy, lastopen, lastclos, lastmove;
int newdist, olddir, _self;
int current_net_code;
int marge, via_marge;
int pad_masque_layer_s; /* Masque des couches appartenant au pad de depart */
int pad_masque_layer_e; /* Masque des couches appartenant au pad d'arrivee */
int masque_layer_TOP = g_TabOneLayerMask[Route_Layer_TOP];
int masque_layer_BOTTOM = g_TabOneLayerMask[Route_Layer_BOTTOM];
int masque_layers;		/* Masque des 2 couches de routage */
int tab_mask[2];		/* permet le calcul du Masque de la couche en cours
							de tst (side = TOP ou BOTTOM)*/
int start_mask_layer = 0;
wxString msg;
	
	result = NOSUCCESS;

	marge = g_DesignSettings.m_TrackClearence + (g_DesignSettings.m_CurrentTrackWidth / 2);
	via_marge = g_DesignSettings.m_TrackClearence + (g_DesignSettings.m_CurrentViaSize / 2);

	/* clear direction flags */
	i = Nrows * Ncols * sizeof(char);
	memset(Board.m_DirSide[TOP], FROM_NOWHERE, i );
	memset(Board.m_DirSide[BOTTOM], FROM_NOWHERE, i );

	lastopen = lastclos = lastmove = 0;

	/* Init tab_masque[side] pour tests de fin de routage */
	tab_mask[TOP] = masque_layer_TOP;
	tab_mask[BOTTOM] = masque_layer_BOTTOM;
	/* Init masque des couches actives */
	masque_layers = masque_layer_TOP | masque_layer_BOTTOM;

	pt_cur_ch = pt_chevelu;
	current_net_code = pt_chevelu->m_NetCode;
	pad_masque_layer_s = pt_cur_ch->pad_start->m_Masque_Layer;
	pad_masque_layer_e = pt_cur_ch->pad_end->m_Masque_Layer;

	/* Test 1 Si routage possible c.a.d si les pads sont accessibles
			sur les couches de routage */

	if( (masque_layers & pad_masque_layer_s) == 0 ) goto end_of_route;
	if( (masque_layers & pad_masque_layer_e) == 0 ) goto end_of_route;

	/* Test 2 Si routage possible c.a.d si les pads sont accessibles
		sur la grille de routage ( 1 point de grille doit etre dans le pad)*/
	{
	int cX = (pas_route * col_source) + pcbframe->m_Pcb->m_BoundaryBox.m_Pos.x;
	int cY = (pas_route * row_source) + pcbframe->m_Pcb->m_BoundaryBox.m_Pos.y;
	int dx = pt_cur_ch->pad_start->m_Size.x / 2;
	int dy = pt_cur_ch->pad_start->m_Size.y / 2;
	int px = pt_cur_ch->pad_start->m_Pos.x;
	int py = pt_cur_ch->pad_start->m_Pos.y;

	if ( ((pt_cur_ch->pad_start->m_Orient/900)&1) != 0 ) EXCHG(dx,dy) ;
	if ( (abs(cX - px) > dx ) || (abs(cY - py) > dy) ) goto end_of_route;

	cX = (pas_route * col_target) + pcbframe->m_Pcb->m_BoundaryBox.m_Pos.x;
	cY = (pas_route * row_target) + pcbframe->m_Pcb->m_BoundaryBox.m_Pos.y;
	dx = pt_cur_ch->pad_end->m_Size.x / 2;
	dy = pt_cur_ch->pad_end->m_Size.y / 2;
	px = pt_cur_ch->pad_end->m_Pos.x;
	py = pt_cur_ch->pad_end->m_Pos.y;
	if ( ((pt_cur_ch->pad_end->m_Orient/900)&1) != 0 ) EXCHG(dx,dy) ;

	if ( (abs(cX - px) > dx ) || (abs(cY - py) > dy) ) goto end_of_route;
	}

	/* Test du cas trivial: connection directe par superposition des pads */
	if( (row_source == row_target) && (col_source == col_target)
		&& ( pad_masque_layer_e & pad_masque_layer_s & g_TabAllCopperLayerMask[g_DesignSettings.m_CopperLayerCount-1]) )
	{
		result = TRIVIAL_SUCCESS;
		goto end_of_route;
	}



	/* Placement du bit de suppression d'obstacle relative aux 2 pads a relier */
	pcbframe->Affiche_Message( wxT("Gen Cells") );

	Place_1_Pad_Board(pcbframe->m_Pcb, pt_cur_ch->pad_start,CURRENT_PAD ,marge,WRITE_OR_CELL);
	Place_1_Pad_Board(pcbframe->m_Pcb, pt_cur_ch->pad_end, CURRENT_PAD ,marge,WRITE_OR_CELL);

	/* Regenere les barrieres restantes (qui peuvent empieter sur le placement
		des bits precedents) */
	ptr = (LISTE_PAD*) pcbframe->m_Pcb->m_Pads; i = pcbframe->m_Pcb->m_NbPads;
	for( ; i > 0 ; i-- , ptr++)
		{
		if((pt_cur_ch->pad_start != *ptr) && (pt_cur_ch->pad_end != *ptr) )
			{
			Place_1_Pad_Board(pcbframe->m_Pcb, *ptr, ~CURRENT_PAD,marge,WRITE_AND_CELL);
			}
		}

	InitQueue(); /* initialize the search queue */
	apx_dist = GetApxDist( row_source, col_source, row_target, col_target );

	/* Init 1ere recherche */
	if(two_sides)	/* orientation preferentielle */
		{
		if( abs(row_target-row_source) > abs(col_target-col_source) )
			{
			if( pad_masque_layer_s & masque_layer_TOP )
				{
				start_mask_layer = 2;
				if(SetQueue( row_source, col_source, TOP, 0, apx_dist,
							row_target, col_target ) == 0)
 					{
					return(ERR_MEMORY);
					}
				}
			if( pad_masque_layer_s & masque_layer_BOTTOM )
				{
				start_mask_layer |= 1;

				if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
							row_target, col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}
			}
		else
			{
			if( pad_masque_layer_s & masque_layer_BOTTOM )
				{
				start_mask_layer = 1;
				if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
							row_target, col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}
			if( pad_masque_layer_s & masque_layer_TOP )
				{
				start_mask_layer |= 2;

				if (SetQueue( row_source, col_source, TOP, 0, apx_dist,
							row_target, col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}
			}
		}

	else
		if( pad_masque_layer_s & masque_layer_BOTTOM )
			{
			start_mask_layer = 1;

			if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
							row_target, col_target ) == 0 )
				{
				return(ERR_MEMORY);
				}
			}

	/* search until success or we exhaust all possibilities */
	GetQueue( &r, &c, &side, &d, &apx_dist );
	for ( ; r != ILLEGAL; GetQueue( &r, &c, &side, &d, &apx_dist ) )
		{
		curcell = GetCell( r, c, side );
		if(curcell & CURRENT_PAD) curcell &= ~HOLE ;
		if( (r == row_target) && (c == col_target)  /* success si layer OK */
			&& ( tab_mask[side] & pad_masque_layer_e) )
			{
			/* Efface Liaison */
			GRSetDrawMode(DC, GR_XOR);
			GRLine(&pcbframe->DrawPanel->m_ClipBox, DC, segm_oX, segm_oY, segm_fX, segm_fY, WHITE);

			/* Generation de la trace */
			if( Retrace(pcbframe, DC, row_source, col_source,
						 row_target, col_target, side, current_net_code) )
				{
				result = SUCCESS;	/* Success : Route OK */
				}
			break;	/* Fin du routage */
			}
		/* report every 300 new nodes or so */
		if( (OpenNodes-lastopen > 300) || (ClosNodes-lastclos > 300) || (MoveNodes - lastmove > 300))
			{
			lastopen = (OpenNodes/300)*300; lastclos = (ClosNodes/300)*300;
			lastmove = (MoveNodes/300)*300;

			if( pcbframe->DrawPanel->m_AbortRequest )
				{
				result = STOP_FROM_ESC; break;
				}
			AFFICHE_ACTIVITE_ROUTE;
			}

		_self = 0;
		if (curcell & HOLE)
			{
			_self = 5;
			/* set 'present' bits */
			for (i = 0; i < 8; i++)
				{
				selfok2[i].present = 0;
				if( (curcell & selfok2[i].trace) ) selfok2[i].present = 1;
				}
			}

		for (i = 0; i < 8; i++) /* consider neighbors */
			{
			nr = r+delta[i][0]; nc = c+delta[i][1];

			/* off the edge? */
			if( nr < 0 || nr >= Nrows || nc < 0 || nc >= Ncols)
				continue; /* off the edge */

			if (_self == 5 && selfok2[i].present) continue;
			newcell = GetCell( nr, nc, side );
			if(newcell & CURRENT_PAD) newcell &= ~HOLE;

			/* check for non-target hole */
			if (newcell & HOLE)
				{
				if (nr != row_target || nc != col_target) continue;
				}

			/* check for traces */
			else if (newcell & HOLE & ~(newmask[i])) continue;

			/* check blocking on corner neighbors */
			if (delta[i][0] && delta[i][1])
				{
				/* check first buddy */
				buddy = GetCell( r+blocking[i].r1, c+blocking[i].c1, side );
				if(buddy & CURRENT_PAD) buddy &= ~HOLE;
				if (buddy & HOLE) continue;
//				if (buddy & (blocking[i].b1)) continue;
				/* check second buddy */
				buddy = GetCell( r+blocking[i].r2, c+blocking[i].c2, side );
				if(buddy & CURRENT_PAD) buddy &= ~HOLE;
				if (buddy & HOLE) continue;
//				if (buddy & (blocking[i].b2)) continue;
				}

			olddir = GetDir( r, c, side );
			newdist = d + CalcDist( ndir[i], olddir,
				(olddir == FROM_OTHERSIDE) ? GetDir( r, c, 1-side ) : 0 , side);

			/* if (a) not visited yet, or (b) we have */
			/* found a better path, add it to queue */
			if (!GetDir( nr, nc, side ))
				{
				SetDir( nr, nc, side, ndir[i] );
				SetDist( nr, nc, side, newdist );
				if( SetQueue( nr, nc, side, newdist,
					GetApxDist( nr, nc, row_target, col_target ),
						row_target, col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}

			else if (newdist < GetDist( nr, nc, side ))
				{
				SetDir( nr, nc, side, ndir[i] );
				SetDist( nr, nc, side, newdist );
				ReSetQueue( nr, nc, side, newdist,
					GetApxDist( nr, nc, row_target, col_target ),
					row_target, col_target );
				}
			}

		/** etude de l'autre couche **/
		if( (two_sides) && ! g_No_Via_Route )
			{
			olddir = GetDir( r, c, side );
			if (olddir == FROM_OTHERSIDE)
				continue; /* useless move, so don't bother */
			if (curcell) /* can't drill via if anything here */
				continue;
			/* check for holes or traces on other side */
			if( (newcell = GetCell( r, c, 1-side )) != 0 )
				continue;
			/* check for nearby holes or traces on both sides */
			for (skip = 0, i = 0; i < 8; i++)
				{
				nr = r + delta[i][0]; nc = c + delta[i][1];

				if (nr < 0 || nr >= Nrows || nc < 0 || nc >= Ncols)
					continue;  /* off the edge !! */

				if (GetCell( nr, nc, side )/* & blocking2[i]*/)
					{
					skip = 1; /* can't drill via here */
					break;
					}

				if (GetCell( nr, nc, 1-side )/* & blocking2[i]*/)
					{
					skip = 1; /* can't drill via here */
					break;
					}
				}

			if (skip) /* neighboring hole or trace? */
				continue; /* yes, can't drill via here */

			newdist = d + CalcDist( FROM_OTHERSIDE, olddir, 0 , side);

			/*  if (a) not visited yet,
				or (b) we have found a better path,
				add it to queue */
			if (!GetDir( r, c, 1-side ))
				{
				SetDir( r, c, 1-side, FROM_OTHERSIDE );
				SetDist( r, c, 1-side, newdist );
				if( SetQueue( r, c, 1-side, newdist, apx_dist, row_target,
								 col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}
			else if (newdist < GetDist( r, c, 1-side ))
				{
				SetDir( r, c, 1-side, FROM_OTHERSIDE );
				SetDist( r, c, 1-side, newdist );
				ReSetQueue( r, c, 1-side, newdist, apx_dist, row_target, col_target );
				}
			} /* Fin de l'exploration de l'autre couche */
		}

end_of_route:
	Place_1_Pad_Board(pcbframe->m_Pcb, pt_cur_ch->pad_start,~CURRENT_PAD ,marge,WRITE_AND_CELL);
	Place_1_Pad_Board(pcbframe->m_Pcb, pt_cur_ch->pad_end, ~CURRENT_PAD ,marge,WRITE_AND_CELL);

	AFFICHE_ACTIVITE_ROUTE;
	return(result);
}