Пример #1
0
double reg_calc_area_complex_polygon( regShape* shape ) {
    
    regRegion *temp;
    regShape *copy;
    double area;

    fprintf(stderr, "WARNING: Calculating area of a complex polygon ");
    fprintf(stderr,"using brute force method. This may take a long time.\n");

    // Create a new region with just the polygon
    temp = regCreateRegion(NULL, NULL);
    copy = shape->copy(shape);

    // Analytic area calculations always computes the area of the interior
    // of the shape.    
    copy->include = regInclude;
    regAddShape(temp, regAND, copy);
    
    // Calc the extent of the polygon then trim the bounds to fit within
    // the original region if available
    regCalcExtentPolygon(shape, temp->xregbounds, temp->yregbounds);
    if (shape->region) {
        reg_trim_extent(temp->xregbounds, 
                        temp->yregbounds,
                        shape->region->xregbounds,
                        shape->region->yregbounds, 0);
    }

    area = regComputePixellatedArea(temp, temp->xregbounds, temp->yregbounds, 1);

    // Free and return
    regFree(temp);
    return area;
}
Пример #2
0
/* Invert a region

   We come here with a region structure containing a linked list of "shapes"

   Region->shapeA->shapeB->shapeC->shapeD etc

   Each shape has a flag which indicates its relation to the previous shape,
   whether AND or OR.  AND operations take precedence over OR, so we can
   view the shape list as a series of AND terms separated by OR operations:

	P*Q+R*S*T+W*Z = (P*Q)+(R*S*T)+(W*Z)

   This inversion function has two stages.  First it creates a linked
   list of terms.  A term is a set of shapes grouped by AND.  Successive
   entries in the term list are joined by OR.


   From DeMorgan's laws:

   ___________________     _ _ _   _ _ _   _ _ _   _ _ _   _ _ _   _ _ _
   (P*Q)+(R*S*T)+(W*Z)  =  P*R*W + P*R*Z + P*S*W + P*S*Z + P*T*W + P*T*Z +
                           _ _ _   _ _ _   _ _ _   _ _ _   _ _ _   _ _ _
   			   Q*R*W + Q*R*Z + Q*S*W + Q*S*Z + Q*T*W + Q*T*Z 

   Stated more simply, the left hand side is composed of all combinations
   of one shape chosen from each term, with each shape negated.  This is NOT
   the most compact way to write the results of DeMorgan's transformation,
   but is a representation which requires no explicit grouping syntax: AND 
   over OR precedence being adequate.

   The second stage of this function cycles through the term list, pulling
   shapes out, negating them, and adding them to the inverted region shape
   list.
*/
regRegion* regInvert( regRegion* inRegion )
{
    double fx[2] ={ -DBL_MAX, DBL_MAX };
    double fy[2] ={ -DBL_MAX, DBL_MAX };
    regRegion* Region;
    regShape* Shape;
    regShape* inShape;
    struct regTerm *term;
    struct regTerm *nextTerm;
    struct regTerm *firstTerm;
    struct regTerm *safeTerm;
    #ifndef TRUE
    #define TRUE 1
    #define FALSE 0
    typedef int boolean;
    #endif

    boolean done;

    // Copy shapes
    if ( !inRegion ) {
        return NULL;
    }

    Region = regCreateRegion(NULL, NULL);

    if (inRegion->shape == NULL) {
        return Region;
    }

    inShape = inRegion->shape;

    // parse the region shapes in "terms" connected by OR 
    term = (struct regTerm *) (malloc(sizeof(struct regTerm)));
    term->next = NULL;
    term->prev = NULL;
			  
    firstTerm = term;

    // initialize first term
    term->first = inShape;
    term->current = inShape;
    term->last = inShape;

    // add shapes to the current term
    while (inShape->next != NULL) 
    {
        // look for OR glue 
        if (inShape->component != inShape->next->component) {
	        // found it - finish off current term, and start new one
	        term->last = inShape;  // remember this shape as "last'

	        // malloc new term
	        nextTerm = (struct regTerm *) (malloc(sizeof(struct regTerm)));

	        // init new term
	        nextTerm->first = inShape->next;
	        nextTerm->current = inShape->next;
	        term->next = nextTerm;
	        nextTerm->prev = term;
	        nextTerm->next = NULL;

	        // new term is current term */
	        term = nextTerm;
        }
        inShape = inShape->next;
    }
    term->last = inShape;

    // now do the inversion math
    done = FALSE;
    while (!done)
    {
        // get a shape from each term 
        term = firstTerm;
        do {
	        // remember our current term (we will advance past it)
	        safeTerm = term;
	        Shape = regCopyShape(term->current );
	        Shape->include = Shape->include ? regExclude : regInclude;

	        // first shape in term is "joined" to predecessor (nothing) by OR
	        if (term == firstTerm) {
	            regAddShape( Region, regOR, Shape );
            }
	        else {
	            // all other terms join shapes by AND
	            regAddShape( Region, regAND, Shape );
            }
	 
            term = term->next;
        
        } while (term != NULL);

        // we have now got a shape from each term
        term = safeTerm;

        // advance to next shape in last term */
        if (term->current != term->last) {
            term->current = term->current->next;
        }
        else {
	        // already at last shape, reset current term to first
	        if (term != firstTerm) {
	            term->current = term->first;
            }
	        else {
	            done = TRUE;
            }

	        while (term != firstTerm)
	        {
	            // go to previous term and advance or reset as appropriate
	            term = term->prev;

	            // any shapes left?
	            if (term->current != term->last)
	            {
		            // yes advance and break out of loop 
		            term->current = term->current->next;
		            break;
	            }
	            else {
	                // no - reset to first shape...*/
	                if (term != firstTerm) {
		                term->current = term->first;
                    }
	                else {
		                // ...unless this is the first term,
		                //   in which case we are done
		                done = TRUE;
                    }
                }
	        }
       }
   }


    // dispose of our parsing structures
    term = firstTerm;
    do {
        nextTerm = term->next;
        free(term);
        term = nextTerm;
    } while (term != NULL);

    regExtent(Region, fx, fy, Region->xregbounds, Region->yregbounds);
 
    return Region;
}
Пример #3
0
regRegion* regUnionRegion( regRegion* Region1, regRegion* Region2 )
{
    double fx[2] ={ -DBL_MAX, DBL_MAX };
    double fy[2] ={ -DBL_MAX, DBL_MAX };

    regRegion* region;
    regShape*  shape;
    regShape*  inShape;
    regMath    glue;
  
    long lastComponent;
    int  haveMore;
  
    /* Copy shapes */
    if ( !Region1 )
    {
        if ( !Region2 ) {
            return NULL;
        }
        return regCopyRegion( Region2 );
    }
  
    /* If regions are equal just return copy of one */
    if ( regCompareRegion( Region1, Region2 )) {
         return regCopyRegion( Region1 );
    }
  
    /* Make a new region with all the combined components of the input regions */
    /*  - Put USER defined shapes first in the series.                         */
    region = regCreateRegion(NULL, NULL); 

    /* Transfer Region components with USER shapes.                            */
    /*   NOTE: expectation is that USER shapes are first on the component      */
    haveMore = 1;
    inShape = Region1->shape;
    
    while ( inShape != NULL )
    {
        if ( inShape->type == regMASK )
        {
            glue = regOR;
            lastComponent = inShape->component;
            while ( inShape && inShape->component == lastComponent )
            {
                shape = regCopyShape(inShape);
                regAddShape( region, glue, shape );
                glue = regAND;
                inShape = inShape->next;
            }
        }
        else
        {
            inShape = reg_next_component( inShape );
        }
        
        if ( (inShape == NULL) && haveMore )
        {
            /* scan second region components */
            inShape = Region2->shape;
            haveMore = 0;
        }
    }
  
    /* Transfer Region components Non-USER shapes.*/
    haveMore = 1;
    inShape = Region1->shape;
    while ( inShape != NULL )
    {
        if ( inShape->type == regMASK )
        {
            inShape = reg_next_component( inShape );
        } 
        else 
        {
            glue = regOR;
            lastComponent = inShape->component;
            while ( inShape && inShape->component == lastComponent )
            {
                shape = regCopyShape(inShape);
                regAddShape( region, glue, shape );
                glue = regAND;
                inShape = inShape->next;
            }
        }

        if ( (inShape == NULL) && haveMore )
        {
            /* scan second region components */
            inShape = Region2->shape;
            haveMore = 0;
        }
    }

    /* re-calculate the region extent */
    regExtent(region, fx, fy, region->xregbounds, region->yregbounds);

    return region;
}