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;
}
#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 */
void
cmdSelectArea(layers, less)
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)
cmdSelectArea(layers, less, option)
char *layers; /* Which layers are to be selected. */
bool less;
int option; /* Option from defined list above */
{
SearchContext scx;
TileTypeBitMask mask;
@ -680,6 +624,7 @@ cmdSelectVisible(layers, less)
scx.scx_use = (CellUse *) window->w_surfaceID;
scx.scx_trans = GeoIdentityTransform;
crec = (DBWclientRec *) window->w_clientData;
if (option == SEL_VISIBLE)
{
int i;
for (i = 0; i < DBNumUserLayers; i++)
@ -688,7 +633,10 @@ cmdSelectVisible(layers, less)
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.
*/
#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[] =
{
"area",
"visible",
"cell",
"labels",
"intersection",
"clear",
"flat",
"help",
@ -780,6 +709,7 @@ CmdSelect(w, cmd)
"[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\"",
"[do | no] labels [do not] select subcell labels",
"[more | less] intersection [layers] [de]select intersection of layers",
"clear clear selection",
"flat flatten the contents of the selection",
"help print this message",
@ -980,7 +910,7 @@ CmdSelect(w, cmd)
}
if (!(more || less)) SelectClear();
if (cmd->tx_argc == 3)
cmdSelectArea(optionArgs[1], less);
cmdSelectArea(optionArgs[1], less, option);
else cmdSelectArea("*,label,subcell", less);
return;
@ -994,8 +924,21 @@ CmdSelect(w, cmd)
if (cmd->tx_argc > 3) goto usageError;
if (!(more || less)) SelectClear();
if (cmd->tx_argc == 3)
cmdSelectVisible(optionArgs[1], less);
else cmdSelectVisible("*,label,subcell", less);
cmdSelectArea(optionArgs[1], less, option);
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;
/*--------------------------------------------------------------------

View File

@ -253,6 +253,205 @@ selClearFunc(scx)
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 SelectClear();
extern void SelectCell();
extern void SelectIntersect();
extern void SelRemoveArea();
extern int SelRemoveSel2();
extern int SelectRemoveCellUse();