Added a new selection command option "select intersect" that selects

the area of intersection between any number of types.
This commit is contained in:
Tim Edwards 2021-03-24 14:52:17 -04:00
parent e152deb97b
commit 7cb88ffceb
3 changed files with 245 additions and 102 deletions

View File

@ -528,6 +528,26 @@ CmdSee(w, cmd)
return; return;
} }
#define SEL_AREA 0
#define SEL_VISIBLE 1
#define SEL_CELL 2
#define SEL_LABELS 3
#define SEL_INTERSECT 4
#define SEL_CLEAR 5
#define SEL_FLAT 6
#define SEL_HELP 7
#define SEL_KEEP 8
#define SEL_MOVE 9
#define SEL_PICK 10
#define SEL_SAVE 11
#define SEL_FEEDBACK 12
#define SEL_BBOX 13
#define SEL_BOX 14
#define SEL_CHUNK 15
#define SEL_REGION 16
#define SEL_NET 17
#define SEL_SHORT 18
#define SEL_DEFAULT 19
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
@ -550,86 +570,10 @@ CmdSee(w, cmd)
/* ARGSUSED */ /* ARGSUSED */
void void
cmdSelectArea(layers, less) cmdSelectArea(layers, less, option)
char *layers; /* Which layers are to be selected. */
bool less;
{
SearchContext scx;
TileTypeBitMask mask;
int windowMask, xMask;
DBWclientRec *crec;
MagWindow *window;
bzero(&scx, sizeof(SearchContext));
window = ToolGetBoxWindow(&scx.scx_area, &windowMask);
if (window == NULL)
{
TxPrintf("The box isn't in a window.\n");
return;
}
/* Since the box may actually be in multiple windows, we have to
* be a bit careful. If the box is only in one window, then there's
* no problem. If it's in more than window, the cursor must
* disambiguate the windows.
*/
xMask = ((DBWclientRec *) window->w_clientData)->dbw_bitmask;
if ((windowMask & ~xMask) != 0)
{
window = CmdGetRootPoint((Point *) NULL, (Rect *) NULL);
xMask = ((DBWclientRec *) window->w_clientData)->dbw_bitmask;
if ((windowMask & xMask) == 0)
{
TxPrintf("The box is in more than one window; use the cursor\n");
TxPrintf("to select the one you want to select from.\n");
return;
}
}
if (CmdParseLayers(layers, &mask))
{
if (TTMaskEqual(&mask, &DBSpaceBits))
(void) CmdParseLayers("*,label", &mask);
TTMaskClearType(&mask, TT_SPACE);
}
else return;
if (less)
{
(void) SelRemoveArea(&scx.scx_area, &mask);
return;
}
scx.scx_use = (CellUse *) window->w_surfaceID;
scx.scx_trans = GeoIdentityTransform;
crec = (DBWclientRec *) window->w_clientData;
SelectArea(&scx, &mask, crec->dbw_bitmask);
}
/*
* ----------------------------------------------------------------------------
*
* cmdSelectVisible --
*
* This is a utility procedure used by CmdSelect to do area
* selection of visible paint.
*
* Results:
* None.
*
* Side effects:
* The selection is augmented to contain all the information on
* layers that is visible under the box, including paint, labels,
* and expanded subcells.
*
* ----------------------------------------------------------------------------
*/
/* ARGSUSED */
void
cmdSelectVisible(layers, less)
char *layers; /* Which layers are to be selected. */ char *layers; /* Which layers are to be selected. */
bool less; bool less;
int option; /* Option from defined list above */
{ {
SearchContext scx; SearchContext scx;
TileTypeBitMask mask; TileTypeBitMask mask;
@ -680,6 +624,7 @@ cmdSelectVisible(layers, less)
scx.scx_use = (CellUse *) window->w_surfaceID; scx.scx_use = (CellUse *) window->w_surfaceID;
scx.scx_trans = GeoIdentityTransform; scx.scx_trans = GeoIdentityTransform;
crec = (DBWclientRec *) window->w_clientData; crec = (DBWclientRec *) window->w_clientData;
if (option == SEL_VISIBLE)
{ {
int i; int i;
for (i = 0; i < DBNumUserLayers; i++) for (i = 0; i < DBNumUserLayers; i++)
@ -688,7 +633,10 @@ cmdSelectVisible(layers, less)
TTMaskClearType(&mask, i); TTMaskClearType(&mask, i);
} }
} }
SelectArea(&scx, &mask, crec->dbw_bitmask); if (option == SEL_INTERSECT)
SelectIntersect(&scx, &mask, crec->dbw_bitmask);
else
SelectArea(&scx, &mask, crec->dbw_bitmask);
} }
/* /*
@ -728,32 +676,13 @@ CmdSelect(w, cmd)
* second table, due to a help message for ":select" with no arguments. * second table, due to a help message for ":select" with no arguments.
*/ */
#define SEL_AREA 0
#define SEL_VISIBLE 1
#define SEL_CELL 2
#define SEL_LABELS 3
#define SEL_CLEAR 4
#define SEL_FLAT 5
#define SEL_HELP 6
#define SEL_KEEP 7
#define SEL_MOVE 8
#define SEL_PICK 9
#define SEL_SAVE 10
#define SEL_FEEDBACK 11
#define SEL_BBOX 12
#define SEL_BOX 13
#define SEL_CHUNK 14
#define SEL_REGION 15
#define SEL_NET 16
#define SEL_SHORT 17
#define SEL_DEFAULT 18
static char *cmdSelectOption[] = static char *cmdSelectOption[] =
{ {
"area", "area",
"visible", "visible",
"cell", "cell",
"labels", "labels",
"intersection",
"clear", "clear",
"flat", "flat",
"help", "help",
@ -780,6 +709,7 @@ CmdSelect(w, cmd)
"[more | less] visible [layers] [de]select all visible info under box in layers", "[more | less] visible [layers] [de]select all visible info under box in layers",
"[more | less | top] cell [name] [de]select cell under cursor, or \"name\"", "[more | less | top] cell [name] [de]select cell under cursor, or \"name\"",
"[do | no] labels [do not] select subcell labels", "[do | no] labels [do not] select subcell labels",
"[more | less] intersection [layers] [de]select intersection of layers",
"clear clear selection", "clear clear selection",
"flat flatten the contents of the selection", "flat flatten the contents of the selection",
"help print this message", "help print this message",
@ -980,7 +910,7 @@ CmdSelect(w, cmd)
} }
if (!(more || less)) SelectClear(); if (!(more || less)) SelectClear();
if (cmd->tx_argc == 3) if (cmd->tx_argc == 3)
cmdSelectArea(optionArgs[1], less); cmdSelectArea(optionArgs[1], less, option);
else cmdSelectArea("*,label,subcell", less); else cmdSelectArea("*,label,subcell", less);
return; return;
@ -994,8 +924,21 @@ CmdSelect(w, cmd)
if (cmd->tx_argc > 3) goto usageError; if (cmd->tx_argc > 3) goto usageError;
if (!(more || less)) SelectClear(); if (!(more || less)) SelectClear();
if (cmd->tx_argc == 3) if (cmd->tx_argc == 3)
cmdSelectVisible(optionArgs[1], less); cmdSelectArea(optionArgs[1], less, option);
else cmdSelectVisible("*,label,subcell", less); else cmdSelectArea("*,label,subcell", less, option);
return;
/*--------------------------------------------------------------------
* Select area that is the intersection of all the specified layers
*--------------------------------------------------------------------
*/
case SEL_INTERSECT:
if (cmd->tx_argc > 3) goto usageError;
if (!(more || less)) SelectClear();
if (cmd->tx_argc == 3)
cmdSelectArea(optionArgs[1], less, option);
else cmdSelectArea("*,label,subcell", less, option);
return; return;
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------

View File

@ -253,6 +253,205 @@ selClearFunc(scx)
else return 2; else return 2;
} }
/* Structure used by selIntersectPaintFunc() */
struct selIntersectData {
Rect *sid_rect;
TileType sid_type;
};
/*
* ----------------------------------------------------------------------------
*
* selDupPaintFunc --
*
* Copy paint from tile area in Select2Def into SelectDef as all types
* in rMask.
*
* ----------------------------------------------------------------------------
*/
int
selDupPaintFunc(tile, rMask)
Tile *tile; /* The tile to get the area to copy paint. */
TileTypeBitMask *rMask; /* Paint types to copy to. */
{
Rect r;
TiToRect(tile, &r);
DBPaintMask(SelectDef, &r, rMask);
return 0; /* Keep the search going. */
}
/*
* ----------------------------------------------------------------------------
*
* selIntersectPaintFunc2 ---
*
* ----------------------------------------------------------------------------
*/
int
selIntersectPaintFunc2(tile, sid)
Tile *tile; /* The tile to copy paint from. */
struct selIntersectData *sid;
{
Rect r;
int p;
TiToRect(tile, &r);
GEOCLIP(&r, sid->sid_rect); /* Clip out the intersection area */
DBPaint(Select2Def, &r, sid->sid_type); /* Paint back into Select2Def */
return 0; /* Keep the search going. */
}
/*
* ----------------------------------------------------------------------------
*
* selIntersectPaintFunc --
*
* Erase paint of types in rMask from the area of the tile.
*
* ----------------------------------------------------------------------------
*/
int
selIntersectPaintFunc(tile, type)
Tile *tile; /* The tile to copy paint from. */
TileType type; /* The type of tile to keep */
{
TileTypeBitMask tMask;
Rect r;
int plane;
struct selIntersectData sid;
TiToRect(tile, &r);
TTMaskSetOnlyType(&tMask, type);
plane = DBPlane(type);
sid.sid_type = TiGetTypeExact(tile);
sid.sid_rect = &r;
DBSrPaintArea((Tile *)NULL, Select2Def->cd_planes[plane], &r,
&tMask, selIntersectPaintFunc2, (ClientData)&sid);
return 0; /* Keep the search going. */
}
/*
* ----------------------------------------------------------------------------
*
* SelectIntersect --
*
* This procedure selects all information that falls in a given area
* and contains the intersection of all the supplied types.
*
* Results:
* None.
*
* Side effects:
* The indicated information is added to the select cell, and
* outlined on the screen. Only information of particular
* types, and in expanded cells (according to xMask) is
* selected.
*
* ----------------------------------------------------------------------------
*/
void
SelectIntersect(scx, types, xMask)
SearchContext *scx; /* Describes the area in which material
* is to be selected. The resulting
* coordinates should map to the coordinates
* of EditRootDef. The cell use should be
* the root of a window.
*/
TileTypeBitMask *types; /* Indicates which intersecting layers to
* select. May not include labels or cells.
*/
int xMask; /* Indicates window (or windows) where cells
* must be expanded for their contents to be
* considered. 0 means treat everything as
* expanded.
*/
{
TileTypeBitMask tMask, rMask;
TileType s, t;
int plane;
/* If the source definition is changing, clear the old selection. */
if (SelectRootDef != scx->scx_use->cu_def)
{
if (SelectRootDef != NULL)
SelectClear();
SelectRootDef = scx->scx_use->cu_def;
SelSetDisplay(SelectUse, SelectRootDef);
}
SelRememberForUndo(TRUE, (CellDef *) NULL, (Rect *) NULL);
/* Select all paint of types in "types" mask and copy into Select2Def */
DBCellClearDef(Select2Def);
(void) DBCellCopyAllPaint(scx, types, xMask, Select2Use);
/* Find the first type in the list. This will be used as the reference */
for (t = 0; t < DBNumUserLayers; t++)
if (TTMaskHasType(types, t))
break;
if (t == DBNumUserLayers) return;
/* Compute the type mask of the reference type */
TTMaskSetOnlyType(&tMask, t);
plane = DBPlane(t);
/* For each other type in "types", do the following */
for (s = t + 1; s < DBNumUserLayers; s++)
{
if (TTMaskHasType(types, s))
{
/* Copy the reference paint type from Select2Def into SelectDef */
DBSrPaintArea((Tile *)NULL, Select2Def->cd_planes[plane], &scx->scx_area,
&tMask, selDupPaintFunc, (ClientData)&tMask);
/* Erase the reference paint type from Select2Def */
DBEraseMask(Select2Def, &TiPlaneRect, &tMask);
/* Scan Select2Def for all geometry of type s inside the areas of */
/* the reference type, and copy back to Select2Def as the reference */
/* type */
DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[plane],
&scx->scx_area, &tMask, selIntersectPaintFunc, (ClientData)s);
/* Erase the reference paint type from SelectDef */
DBEraseMask(SelectDef, &TiPlaneRect, &tMask);
}
}
/* Copy any remaining paint in the reference layer in Select2Def to */
/* SelectDef as all the intersection types. */
DBSrPaintArea((Tile *)NULL, Select2Def->cd_planes[plane], &scx->scx_area,
&tMask, selDupPaintFunc, (ClientData)types);
SelectDef->cd_types = *types; /* Remember what types were requested */
/* Display the new selection. */
SelRememberForUndo(FALSE, SelectRootDef, &scx->scx_area);
DBReComputeBbox(SelectDef);
DBWHLRedraw(SelectRootDef, &scx->scx_area, TRUE);
DBWAreaChanged(SelectDef, &SelectDef->cd_extended, DBW_ALLWINDOWS,
&DBAllButSpaceBits);
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------

View File

@ -35,6 +35,7 @@ extern void SelectRegion();
extern void SelectInit(); extern void SelectInit();
extern void SelectClear(); extern void SelectClear();
extern void SelectCell(); extern void SelectCell();
extern void SelectIntersect();
extern void SelRemoveArea(); extern void SelRemoveArea();
extern int SelRemoveSel2(); extern int SelRemoveSel2();
extern int SelectRemoveCellUse(); extern int SelectRemoveCellUse();