Added a new "orthogonal" operator to cifoutput to allow non-

manhattan shapes (especially minimum-sized ones) to be eliminated,
as these can survive a shrink-grow operation intended to get rid
of such shapes.  This implementation may not be in its final form
but should suffice for now.
This commit is contained in:
R. Timothy Edwards 2025-03-28 10:11:17 -04:00
parent dde7144966
commit 6b9efefc02
4 changed files with 116 additions and 13 deletions

View File

@ -1 +1 @@
8.3.523
8.3.524

View File

@ -2082,6 +2082,53 @@ cifBridgeCheckFunc(
return 0; /* Nothing found here, so keep going */
}
/*
* ----------------------------------------------------------------------------
*
* cifOrthogonalFunc --
*
* Called for each relevant tile during "orthogonal" operations.
*
* Results:
* Always returns 0 to keep the search alive.
*
* Side effects:
* Paints into cifNewPlane. Tiles in old plane are copied as-is
* if they are not split tiles. Split tiles are either replaced
* with a rectangle of type "1" or "0" depending on whether the
* option is "fill" or "remove", respectively.
* ----------------------------------------------------------------------------
*/
int
cifOrthogonalFunc(
Tile *tile,
const PaintResultType *table) /* Table to be used for painting. */
{
Rect area;
TileType oldType = TiGetTypeExact(tile);
TiToRect(tile, &area);
/* In scaling the tile, watch out for infinities!! If something
* is already infinity, don't change it. */
if (area.r_xbot > TiPlaneRect.r_xbot) area.r_xbot *= cifScale;
if (area.r_ybot > TiPlaneRect.r_ybot) area.r_ybot *= cifScale;
if (area.r_xtop < TiPlaneRect.r_xtop) area.r_xtop *= cifScale;
if (area.r_ytop < TiPlaneRect.r_ytop) area.r_ytop *= cifScale;
/* Diagonal tiles get replaced with non-diagonal tiles */
if (oldType & TT_DIAGONAL)
DBPaintPlane(cifPlane, &area, table, (PaintUndoInfo *) NULL);
else
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
CIFTileOps += 1;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -2117,16 +2164,18 @@ cifCloseFunc(
atotal = 0;
/* Search all sides for connected space tiles, and accumulate the total */
/* area. If any connected tile borders infinity, then stop searching */
/* because the area is not enclosed. */
/* Search all sides for connected space tiles, and accumulate the */
/* total area. If any connected tile borders infinity, then stop */
/* searching because the area is not enclosed. */
cifGatherFunc(tile, &atotal, CLOSE_SEARCH);
/* If the total area is smaller than the rule area, then paint all the */
/* tile areas into the destination plane. */
/* If the total area is smaller than the rule area, then paint all */
/* the tile areas into the destination plane. A rule area of zero */
/* indicates that any enclosed area, no matter how large, should be */
/* filled. */
if ((atotal != INFINITY) && (atotal < growDistance))
if ((atotal != INFINITY) && ((atotal < growDistance) || (growDistance == 0)))
{
cifGatherFunc(tile, &atotal, CLOSE_FILL);
}
@ -2134,7 +2183,6 @@ cifCloseFunc(
{
cifGatherFunc(tile, &atotal, CLOSE_DONE);
}
return 0;
}
@ -5264,6 +5312,22 @@ CIFGenLayer(
}
break;
case CIFOP_MANHATTAN:
DBClearPaintPlane(nextPlane);
cifPlane = nextPlane;
cifScale = 1;
DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
&CIFSolidBits, cifOrthogonalFunc,
(op->co_client == (ClientData)1) ?
(ClientData) CIFPaintTable :
(ClientData) CIFEraseTable);
temp = curPlane;
curPlane = nextPlane;
nextPlane = temp;
break;
case CIFOP_MAXRECT:
cifPlane = curPlane;

View File

@ -141,6 +141,7 @@ typedef struct cifop
* which will be painted into parent cells instead of the
* current cell. This replaces the "fault" method.
* CIFOP_CLOSE - Added 11/25/19---close up areas smaller than indicated
* CIFOP_MANHATTAN - Added 3/27/25---remove or fill nonmanhattan areas
* CIFOP_BRIDGE - Added 6/11/20---Bridge across catecorner gaps
* CIFOP_BRIDGELIM - Added 27/07/20---Bridge across catecorner gaps, but with limiting layers
* CIFOP_MASKHINTS - Added 12/14/20---Add geometry from cell properties, if any.
@ -167,9 +168,10 @@ typedef struct cifop
#define CIFOP_INTERACT 19
#define CIFOP_COPYUP 20
#define CIFOP_CLOSE 21
#define CIFOP_BRIDGE 22
#define CIFOP_BRIDGELIM 23
#define CIFOP_MASKHINTS 24
#define CIFOP_MANHATTAN 22
#define CIFOP_BRIDGE 23
#define CIFOP_BRIDGELIM 24
#define CIFOP_MASKHINTS 25
/* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */

View File

@ -111,6 +111,7 @@ cifTechFreeStyle(void)
case CIFOP_MAXRECT:
case CIFOP_BOUNDARY:
case CIFOP_INTERACT:
case CIFOP_MANHATTAN:
/* These options use co_client to hold a single */
/* integer value, so it is not allocated. */
break;
@ -1091,6 +1092,8 @@ CIFTechLine(
newOp->co_opcode = CIFOP_MASKHINTS;
else if (strcmp(argv[0], "close") == 0)
newOp->co_opcode = CIFOP_CLOSE;
else if (strcmp(argv[0], "orthogonal") == 0)
newOp->co_opcode = CIFOP_MANHATTAN;
else if (strcmp(argv[0], "bridge") == 0)
newOp->co_opcode = CIFOP_BRIDGE;
else if (strcmp(argv[0], "bridge-lim") == 0)
@ -1133,7 +1136,6 @@ CIFTechLine(
case CIFOP_GROWMIN:
case CIFOP_GROW_G:
case CIFOP_SHRINK:
case CIFOP_CLOSE:
if (argc != 2) goto wrongNumArgs;
newOp->co_distance = atoi(argv[1]);
if (newOp->co_distance <= 0)
@ -1143,6 +1145,26 @@ CIFTechLine(
}
break;
case CIFOP_CLOSE:
/* "close" is like "grow" and "shrink" except that it can have
* no argument, in which case any closed shape of any size
* will be closed (useful for finding enclosed areas).
*/
if (argc == 1)
newOp->co_distance = 0;
else if (argc != 2)
goto wrongNumArgs;
else
{
newOp->co_distance = atoi(argv[1]);
if (newOp->co_distance <= 0)
{
TechError("Grow/shrink distance must be greater than zero.\n");
goto errorReturn;
}
}
break;
case CIFOP_BRIDGE:
if (argc != 3) goto wrongNumArgs;
newOp->co_distance = atoi(argv[1]);
@ -1334,6 +1356,19 @@ bloatCheck:
goto wrongNumArgs;
break;
case CIFOP_MANHATTAN:
if (argc == 2)
{
if (!strcmp(argv[1], "fill"))
newOp->co_client = (ClientData)1;
else if (strcmp(argv[1], "remove"))
TechError("Orthogonal takes only one optional argument "
"\"fill\" or \"remove\" (default).\n");
}
else if (argc != 1)
goto wrongNumArgs;
break;
case CIFOP_BBOX:
if (argc == 2)
{
@ -1925,7 +1960,7 @@ CIFTechFinal(void)
}
}
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */
/* of the SquaresData pointer from a following operator */
/* of the SquaresData pointer from a following operator. */
/* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
/* as a flag field, while CIFOP_NET and CIFOP_MASKHINTS */
/* uses it for a string. */
@ -1938,6 +1973,7 @@ CIFTechFinal(void)
case CIFOP_MASKHINTS:
case CIFOP_BOUNDARY:
case CIFOP_MAXRECT:
case CIFOP_MANHATTAN:
case CIFOP_NET:
break;
case CIFOP_BRIDGELIM:
@ -2472,6 +2508,7 @@ CIFTechOutputScale(
case CIFOP_BOUNDARY:
case CIFOP_MASKHINTS:
case CIFOP_MAXRECT:
case CIFOP_MANHATTAN:
case CIFOP_NET:
case CIFOP_INTERACT:
break;