static char *SccsId = "@(#)enumTile.c 4.10 (TU-Delft) 05/14/93";
/**********************************************************

Name/Version      : space/4.10

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Author(s)         : A.J. van Genderen
		  : N.P. van der Meijs
Creation date     : 15-Mar-1988
Modified by       :
Modification date :


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1988. All rights reserved.
**********************************************************/
#include <math.h>
#include <stdio.h>
#include "include/config.h"
#include "include/type.h"
#include "aux/aux.h"
#include "aux/plot.h"
#include "extract/define.h"
#include "extract/extern.h"
#include "lump/lump.h"

extern PLOT_KEY * cirPK;

#define  IsRectangle(blP,brP,tlP,trP)  ((brP -> y != blP -> y             \
				         || trP -> y != tlP -> y          \
                                         || brP -> x != trP -> x          \
                                         || blP -> x != tlP -> x) ? 0 : 1)

#define  TriArea2(x1,y1,x2,y2,x3,y3)  \
				(Abs((double)x1 * ((double)y2 - (double)y3) \
				  - (double)x2 * ((double)y1 - (double)y3)  \
				  + (double)x3 * ((double)y1 - (double)y2)))

				      /* area of a triangle * 2 */
    

coor_t currX;
coor_t currY;
static tile_t * currTile;

/* local operations */
private void    resEnumTile ();
private void    rmUnfixedPoints ();
private void    rmPoint ();
private void    triangular ();
private int onSameLine ();
private double  edgeLength ();
private void    tryTriangle ();
private void    flushTryTriangle ();
private void    doRectangle ();
private void    doTriangle ();
private void    parPlateCap ();
private void    makeContact ();

/* enumTile (tile)
 *
 * will update the network description for the influence
 * of the surface of 'tile'.
 *
 * actions performed :
 *
 * - A list of recognized elements is fetched for 'tile'.
 *
 * - For each contact element that is present in 'tile',
 *   joins are made between the subnodes of the 
 *   corresponding conductor layers that are connected
 *   by the contact.
 *
 * - For a transistor that is present in 'tile', a subnode
 *   in the gate (conductor) layer is used as gate node.
 *   Also, surface information for the transistor is 
 *   updated.
 *
 * - For each surface capacitance that is present in 'tile',
 *   capacitance values are calculated and assigned to
 *   the subnodes of the corresponding conductor layers.
 *
 * - When a resistance extraction is performed, 
 *   a triangularization is done for 'tile' and resistances 
 *   are calculated and assigned between the subnodes of each
 *   relevant conductor layer.
 */

void enumTile (tile)
tile_t * tile;
{
    register elemDef_t * el;
    register subnode_t * sn1;
    register subnode_t * sn2;

    int cx;
    double surface;
    double capacitance;
    elemDef_t ** elem;
    elemDef_t ** recognizeElements ();



    if (! HasConduc (tile))
	return;

    currTile = tile;
    currX = tile -> xl;
    currY = tile -> bl;



    surface = meters * meters
	      * (((tile -> xr) - (tile -> xl)) 
	         * ((tile -> tl) + (tile -> tr) 
	            - (tile -> bl) - (tile -> br))) / 2.0;

    for (elem = RecogS (tile -> color); *elem; elem++) {

	switch ((el = *elem) -> type) {

	    case CONTELEM:

		sn1 = tile -> cons[el -> s.cont.con1];
		sn2 = tile -> cons[el -> s.cont.con2];
		if (sn1 && sn2)
		    subnodeJoin (sn1, sn2);
		break;

	    case TORELEM:
		
		ASSERT (el == tile -> tor -> type);

		cx = tile -> tor -> type -> s.tor.gCon;
		if ((sn1 = tile -> cons[cx]) == NULL)
		    missingCon (tile -> tor -> type -> s.tor.gMask, 
				SURFACE, tile, (tile_t *) NULL, (tile_t *) NULL,
				el, tile -> xl, tile -> bl);

		if (tile -> tor -> gate == NULL) {
		    portAdd (sn1, tile, 'g');

		    /* the right top node is used as gate (see also lump.c) */
		}

		tile -> tor -> surface += surface;
		break;

	    case SURFCAPELEM:

		if (optNoCore && HasCore (tile))
		    break;

		cx = el -> s.cap.pCon;
		if ((sn1 = tile -> cons[cx]) == NULL) {
		    missingCon (el -> s.cap.pMask,
				el -> s.cap.pOccurrence,
				tile, (tile_t *) NULL, (tile_t *) NULL,
				el, tile -> xl, tile -> bl);
		}

		if ((cx = el -> s.cap.nCon) < 0) {
		    sn2 = subnGND;
		}
		else if ((sn2 = tile -> cons[cx]) == NULL) {
		    missingCon (el -> s.cap.nMask,
				el -> s.cap.nOccurrence,
				tile, (tile_t *) NULL, (tile_t *) NULL,
				el, tile -> xl, tile -> bl);
		}

		capacitance = el -> s.cap.val * surface;

		{
		    GndCapAdd (sn1, capacitance);
		    if (sn2 != subnGND)
		        GndCapAdd (sn2, capacitance);
		}
		break;

	    case RESELEM:
		break;

	    default:
		ASSERT (0);
		break;
	} /* switch */
    } /* for */
}

