#pragma ident "@(#)edges.c	1.2 98/08/25 SMI"

/*
 * edges.c
 *
 *	@(#)edges.c 1.4 96/07/04 14:59:17
 *
 * Copyright (c) 1996, Sun Microsystems Computer Company, Mountain View, CA
 *
 *			All Rights Reserved
 *
 *	This is a program for manipulating 3D objects.  It is currently being
 *	developed by Mike M. Chow and Scott R. Nelson.
 *
 *      This module contains edge algorithms.
 */


#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "types.h"
#include "zdebug.h"



/*
 * findEdge
 *
 *      Either create a new edge or find a previous edge between point1 
 *      and point2. 
 *      
 *      Note: This search algorithm is adopted from leotool's do_all_edges 
 *          go through each facet sharing v1
 *             if f share the same edge, e2 as e 
 *	        then if e2 is NULL 
 *		     then create a new edge and assign it to e2 and e.
 *		     else check e2.
 *	    if e is still NULL then create new edge.	
 */

Edge *
findEdge (Part *part, Facet *fptr, int vindex1, int vindex2)
{ 
    FacetList *flptr;
    int foundEdge;
    Vertex *v1, *v2; /* Actual vertex pointers for point1 and point2 */
    Edge *eptr;
    int point1, point2;  


    eptr = NULL;  /* Assume edge is NULL */
    /* See if this edge exists, if not, create it */
    foundEdge = 0;		/* Haven't found it yet */

    point1 = fptr->vindex[vindex1];
    point2 = fptr->vindex[vindex2];

    zdo fprintf(stderr, "\n\n finding edge %d %d for facet %d\n", point1, point2, fptr);
    v1 = &part->obj->varray[point1];
    v2 = &part->obj->varray[point2];

    flptr = v1->facets;
    if (flptr == NULL)
	fprintf(stderr, "Point has no facets\n");
    
    while ((flptr != NULL) && !foundEdge) {
	int i; /* Counter */

	if ((flptr->current->owner == part) && (flptr->current != fptr)) {
	    /* Only check for this same part, but not same facet */
	    zdo fprintf(stderr, "checking facet %d and %d\n", fptr, flptr->current);
	    for (i = 0; i < flptr->current->numVerts; i++) {
		int f2p2; /* 2nd Facet's point */

		if (flptr->current->vindex[i] == point1) {
		    f2p2 = (flptr->current->numVerts + i - 1)
			 % flptr->current->numVerts;

				/* Found a match! */
		    if (flptr->current->vindex
			[f2p2] == point2) {
				/* This is the edge */
			if (flptr->current->edges[f2p2] == NULL) {
				/* Create a new edge */
			    
			    eptr = edgeNew(part, v1, v2);
			    eptr->vid1 = point1;
			    eptr->vid2 = point2;
			    eptr->f1 = fptr;
			    eptr->f2 = flptr->current;
  
			    /* Remember facet indices */
			    eptr->f1p1 = vindex1;
			    eptr->f1p2 = vindex2;
			    eptr->f2p1 = f2p2;
			    eptr->f2p2 = i;
			    
			    zdo fprintf(stderr, "Creating2 new edge %d for fptr:%x \n",
				       eptr, fptr);
			    zdo fprintf(stderr, " %d %d", vindex1, vindex2);
		
			    zdo fprintf(stderr, "edge f2p1,2 are %d %d\n", vindex1, vindex2);
			    /* get_edge_angle(eptr);*/
			    eptr->owner = part;
			    foundEdge = 1;
			    break;
			}
			else {
			    
			    zdo fprintf(stderr, "edge already exists.\n");
			    zdo fprintf(stderr, "facet:%d edge[%d]:%x\n", 
				       flptr->current, f2p2);
				/* Already done, check it */
			    eptr = flptr->current->edges[f2p2];
			    zdo fprintf(stderr, "edge %d has facets %d %d\n",eptr,  eptr->f1, 
				       eptr->f2);
			    zdo fprintf(stderr, "edge f1p1,2 are %d %d\n", eptr->f1p1, 
				       eptr->f1p2);
			    zdo fprintf(stderr, "edge f2p1,2 are %d %d\n", eptr->f2p1, 
				       eptr->f2p2);
			    
			    if (eptr->f1 != flptr->current) {
				fprintf(stderr, "Facet 1 doesn't match\n");
			    }
			    foundEdge = 1;
			    break;	/* Exit for loop */
			}
		    } /* End of if both points match */
		    
		    else if (flptr->current->vindex[(flptr->current->numVerts + 1) % flptr->current->numVerts] == point2) {
				/* This is the edge, but backwards from expected */
			fprintf(stderr, "Edge is backwards from expected\n");
		    } /* End of backwards match */
		    else {
				/* Doesn't share a common edge */
		    }
		} /* End of if this point matches */
		
	    } /* End of for each point of this facet */
	    
	} /* End of if this is in the same part */
	
	flptr = flptr->next;	/* Get to next facet */
    } /* End of while there is another facet */
    
    /* No edge is found, make one*/
    if (eptr == NULL) 
	{
	    eptr = edgeNew(part, v1, v2);
	    eptr->vid1 = point1;
	    eptr->vid2 = point2;
	    eptr->f1 = fptr;
	    eptr->f2 = NULL;

	    zdo fprintf(stderr, "Creating new edge %d for fptr:%x \n", eptr, fptr);
	    zdo fprintf(stderr, " %d %d", vindex1, vindex2);
	    
	    
	    /* Remember facet indices */
	    eptr->f1p1 = vindex1;
	    eptr->f1p2 = vindex2;
	    zdo fprintf(stderr, "edge f1p1,2 are %d %d\n", vindex1, vindex2);
	    eptr->f2p1 = -1;
	    eptr->f2p2 = -1;
	    
	    /* get_edge_angle(eptr);*/
	    eptr->owner = part;	    /* Make a new edge */
	}

    return (eptr);
}  /* End of findEdge */




/*
 * printEdges
 *
 *      Pretty print edges.      
 */

void
printEdges(Part *part)
{
    Facet *fptr2;
    int i;

    zdo6 fprintf(stderr, "\nedges \n");
    /* Create edges */
    for (fptr2 = part->facets; fptr2 != NULL; fptr2 = fptr2->next){
      zdo fprintf(stderr, "for facet:%d \n", fptr2);
      facetNewEdges(fptr2); 
    }
    zdo fprintf(stderr, "that was edges \n");
}  /* End of printEdges */



int
isHardEdge(Edge *eptr)
{
  
  if ((eptr->f1 == NULL) ||
      (eptr->f2 == NULL)){
    eptr->hard = 1;
    return 1;
  }
  else 
    eptr->hard = 0;

  return 0;
}
  

void
findHardEdges(Part *part)
{
    Facet     *fptr, *fptr2; /* Current facet ptr */
    Edge      *eptr; /* Temp edge ptr */
    int        i;
    int hardEdgeCnt = 0;
  
    /*Go through each facet */
    for (fptr = part->facets; fptr != NULL; fptr = fptr->next){

      zdo6 fprintf(stderr, "looking at facet %x\n", fptr);
	/* Go through each point */
	for (i = 0; i < fptr->numVerts; i++) {
	    eptr = fptr->edges[i];
	    isHardEdge(eptr);
	    if (eptr->hard) {
	      fptr->hasHardEdge = 1;
	      eptr->v1->boundaryVertex = 1;
	      eptr->v2->boundaryVertex = 1;
	      hardEdgeCnt++;
	    }
	} /*Go through each point. */

    } /*Go through each facet. */
    part->hardEdgeCount = hardEdgeCnt;
    zdo6 printf("part %s hard edges %d\n", part->name, hardEdgeCnt); 
}

/*
 * findPartEdges 
 *
 *      Find the edges (used in wireframe mode) for each facet of a part.
 *
 * Algorithm Notes:
 *  a. Redundant Edges,
 * For each facet do
 *    Go through each two consecutive verticies of facet 
 *       and make a new edge and store it.
 *    
 *  b. Unique Edges,
 * For each facet do
 *     Go through each two consecutive verticies of the facet
 *        If some facet containing the vertex already has the edge
 * 	    then break;
 *        Otherwise, create a new edge and store it.
 *    
 *   
 * Note: Later, in display list mode
 *    For each facet,
 * 	For each edge in facet
 * 	  Draw edge segment 
 * 	     
 */

void
findPartEdges (Part *part)
{
    Facet     *fptr, *fptr2; /* Current facet ptr */
    Edge      *eptr; /* Temp edge ptr */
    int        i;
    int hardEdgeCnt = 0;

    for (fptr2 = part->facets; fptr2 != NULL; fptr2 = fptr2->next){
	facetNewEdges(fptr2); 
    }

    /*Go through each facet */
    for (fptr = part->facets; fptr != NULL; fptr = fptr->next){

      zdo6 fprintf(stderr, "looking at facet %x\n", fptr);
	/* Go through each point */
	for (i = 0; i < fptr->numVerts; i++) {
	    eptr = findEdge(part, fptr, i, (i + 1) % fptr->numVerts);
	    edgeListAddEdge(&(part->obj->varray[fptr->vindex[i]].elist),
			    (void *) eptr);
	    assert (eptr != NULL);
	    facetAddEdge(fptr, i, eptr);
	} /*Go through each point. */

    } /*Go through each facet. */
    

    findHardEdges(part);
}  /* End of findPartEdges */





/* 
 * findObjEdges
 *             
 *      Find the unique edges for all the parts of an object.
 * 
 */

void 
findObjEdges(ModelObject *obj)
{
    int i;

    zdebugOff( 
    zdo fprintf(stderr, "findObj object \n");
 
    for (i = 0; i < obj->partCnt; i++){

	zdo fprintf(stderr, "findObjing part %d\n", i);
	findPartEdges(obj->parts[i]);
    }
  )
}  /* End of findPartEdges*/

 /* End of edges.c */




