
/*
  
  FACILITY:  NMMTL
  
  MODULE DESCRIPTION:
  
  Contains nmmtl_evaluate_rectangles function.
  
  AUTHORS:
  
  Kevin J. Buchs
  
  CREATION DATE:  Thu Jan  2 11:14:27 1992
  
  COPYRIGHT:   Copyright (C) 1992 by Mayo Foundation. All rights reserved.
  
  
  */


/*
 *******************************************************************
 **  INCLUDE FILES
 *******************************************************************
 */

#include "nmmtl.h"


/*
 *******************************************************************
 **  STRUCTURE AND TYPE DEFINITIONS
 *******************************************************************
 */
/*
 *******************************************************************
 **  MACRO DEFINITIONS
 *******************************************************************
 */
/*
 *******************************************************************
 **  PREPROCESSOR CONSTANTS
 *******************************************************************
 */
/*
 *******************************************************************
 **  GLOBALS
 *******************************************************************
 */
/*
 *******************************************************************
 **  FUNCTION DECLARATIONS
 *******************************************************************
 */
/*
 *******************************************************************
 **  FUNCTION DEFINITIONS
 *******************************************************************
 */


/*
  
  FUNCTION NAME:  nmmtl_evaluate_rectangles
  
  FUNCTIONAL DESCRIPTION:
  
  Takes a rectangle contour and processes it into a series of line
  segments, with appropriate angle information.
  
  
  FORMAL PARAMETERS:
  
  int cntr_seg
  number of segments to break a contour into
  
  -- NOT USED --
  float half_minimum_dimension
  half of the smallest geometric dimension - used to determine if
  segments are broken small enough.
  -- --

  int conductor_counter
  keep count of the conductors
  
  CONTOURS_P contour:
  Conductor or groundwire contour.
  
  LINE_SEGMENTS_P *segments:
  output list of line segments generated by fracturing the 
  rectangle found.
  
  EXTENT_DATA_P extent_data:
  structure of extents of conductor region


  RETURN VALUE:
  
  SUCCESS or FAIL
  
  DESIGN:
  
  Traverse the rectangle in the order of bottom, right, top and left,
  with each edge originating where the previous one terminated.  As far
  as edge angles go, theta[0] and theta[1] are both 270 degress.
  
  The algorithm to determine the number of elements this should be
  broken into: take the ratio of the length of the side to the total
  perimeter of the rectangle and multiply by the number of segments to
  break each contour into.  Round up to the next higher integer.  Is
  this element size too large?  Check to see if it is greater than half
  of the smallest conductor edge as given by half_minimum_dimension.
  
  CALLING SEQUENCE:
  
  status = nmmtl_evaluate_rectangles(cntr_seg,
  conductor_counter,contours,&segments,extent_data)
  
  
  */


int nmmtl_evaluate_rectangles(int cntr_seg,
#ifndef NO_HALF_MIN_CHECKING
					  float half_minimum_dimension,
#endif
					  int conductor_counter,
					  CONTOURS_P contour,
					  LINE_SEGMENTS_P *segments,
					  EXTENT_DATA_P extent_data)
{
  int side;
  int save_divisions[2];
  double perimeter, save_length[2];
  LINE_SEGMENTS_P new_segment, last_segment, leading_segment;
  
  /* find the end of the segment list */
  last_segment = *segments;
  if(last_segment != NULL)
  {
    while(last_segment->next != NULL)
      last_segment = last_segment->next;
  }
  
  perimeter = 2 * (ABS(contour->x1 - contour->x0) +
		   ABS(contour->y1 - contour->y0));
  
  
  for(side = 1; side <= 4; side++)
  {
    
    /* for each edge of the rectangle, set up a new line segment */
    /* with the appropriate parameters */
    
    new_segment = (LINE_SEGMENTS_P)malloc(sizeof(LINE_SEGMENTS));
    new_segment->theta2[0] = 3*PI/2;
    new_segment->theta2[1] = 3*PI/2;
    new_segment->nu[0] = 2.0/3.0;
    new_segment->nu[1] = 2.0/3.0;
    new_segment->free_space_nu[0] = 2.0/3.0;
    new_segment->free_space_nu[1] = 2.0/3.0;
    new_segment->conductor = conductor_counter;
    new_segment->epsilon[0] = 0.0;
    new_segment->epsilon[1] = 0.0;
    
    switch(side)
    {
    case 1:
      new_segment->startx = contour->x0;
      new_segment->endx = contour->x1;
      new_segment->starty = contour->y0;
      new_segment->endy = contour->y0;
      save_length[0] = 
	sqrt((new_segment->endx - new_segment->startx)*
	     (new_segment->endx - new_segment->startx) +
	     (new_segment->endy - new_segment->starty)*
	     (new_segment->endy - new_segment->starty));
      new_segment->length = save_length[0];
      /* straight calculation of number of divisions */
      save_divisions[0] = (int)(.99 + cntr_seg * new_segment->length / 
				perimeter);

      /* force 2 divisions per side, minimum */
      if(save_divisions[0] < 2) save_divisions[0] = 2;
      
#ifndef NO_HALF_MIN_CHECKING
      
      /* is the number of divisions too small ? */
      if(new_segment->length/save_divisions[0] > half_minimum_dimension)
      {
	save_divisions[0] = .99 + new_segment->length / half_minimum_dimension;
      }
      
#endif
      
      new_segment->divisions = save_divisions[0];
      leading_segment = new_segment;
      break;
    case 2:
      new_segment->startx = contour->x1;
      new_segment->endx = contour->x1;
      new_segment->starty = contour->y0;
      new_segment->endy = contour->y1;
      save_length[1] = 
	sqrt((new_segment->endx - new_segment->startx)*
	     (new_segment->endx - new_segment->startx) +
	     (new_segment->endy - new_segment->starty)*
	     (new_segment->endy - new_segment->starty));
      new_segment->length = save_length[1];
      /* straight calculation of number of divisions */
      save_divisions[1] = (int)(.99 + cntr_seg * new_segment->length / 
				perimeter);
      
      /* force 2 divisions per side, minimum */
      if(save_divisions[1] < 2) save_divisions[1] = 2;

#ifndef NO_HALF_MIN_CHECKING
      
      /* is the number of divisions too small ? */
      if(new_segment->length/save_divisions[1] > half_minimum_dimension)
      {
	save_divisions[1] = .99 + new_segment->length / half_minimum_dimension;
      }
      
#endif
      
      new_segment->divisions = save_divisions[1];
      break;
    case 3:
      new_segment->startx = contour->x1;
      new_segment->endx = contour->x0;
      new_segment->starty = contour->y1;
      new_segment->endy = contour->y1;
      /* use symmetry */
      new_segment->length = save_length[0];
      new_segment->divisions = save_divisions[0];
      break;
    case 4:
      new_segment->startx = contour->x0;
      new_segment->endx = contour->x0;
      new_segment->starty = contour->y1;
      new_segment->endy = contour->y0;
      /* use symmetry */
      new_segment->length = save_length[1];
      new_segment->divisions = save_divisions[1];
      break;
    }
    
    
    /* which way do you turn to get to the interior of rectangle -  */
    /* LEFT, since we traverse in counterclockwise. */
    new_segment->interior = 1;
    
    
    /* associate edge pairs, first side must wait till list is complete */
    if(side != 1)
    {
      last_segment->edge_pair[1] = new_segment;
      new_segment->edge_pair[0] = last_segment;
    }
    
    /* hook up to end of the list */
    if(last_segment == NULL)
    {
      *segments = new_segment;
      last_segment = new_segment;
      /* edge pair association will need to wait till the list is done */
    }
    else
    {
      last_segment->next = new_segment;
      last_segment = new_segment;
    }
    
  }

  /* final segment is complete: */
  
  /* terminate list */
  new_segment->next = NULL;
  
  /* make last edge pair assocation */
  new_segment->edge_pair[1] = leading_segment;
  leading_segment->edge_pair[0] = new_segment;

  /* set up the new extent data */

  /* left conductor extent */
  if(extent_data->left_cond_extent > contour->x0)
    extent_data->left_cond_extent = contour->x0;

  /* right conductor extent */
  if(extent_data->right_cond_extent < contour->x1)
    extent_data->right_cond_extent = contour->x1;

  /* minimum conductor height above ground plane */
  if(extent_data->min_cond_height > contour->y0)
    extent_data->min_cond_height = contour->y0;
  
  return(SUCCESS);
}
