static Relation CompressCSGTreeWithOppo(CSGTreeOld* tree, uint32_t Id) { auto leaf = tree->Leaves[Id]; CSGTreeNode *curPtr = leaf, *parent = leaf->Parent, *neib; while (true) { if (!parent) { delete tree->pRoot; tree->pRoot = nullptr; tree->Leaves.clear(); return REL_OPPOSITE; } if (LeftOrRight(curPtr) < 0.0) neib = parent->pRight; else neib = parent->pLeft; if (neib->relation == REL_OPPOSITE) { curPtr = parent; parent = parent->Parent; } else if (neib->relation == REL_SAME) { if (parent->Type == TYPE_UNION) return CompressCSGTreeWithInside(tree, Id); else if (parent->Type == TYPE_INTERSECT) return CompressCSGTreeWithOutside(tree, Id); else assert(0); } else break; } curPtr->relation = REL_OPPOSITE; SAFE_DELETE(curPtr->pLeft); SAFE_DELETE(curPtr->pRight); GetLeafList(tree); return REL_NOT_AVAILABLE; }
static Relation CompressCSGTreeWithOutside(CSGTreeOld* tree, uint32_t Id) { auto leaf = tree->Leaves[Id]; CSGTreeNode *curPtr = leaf, *parent = leaf->Parent; while (parent && parent->Type == TYPE_INTERSECT) { curPtr = parent; parent = parent->Parent; } if (!parent) { delete tree->pRoot; tree->pRoot = nullptr; tree->Leaves.clear(); return REL_OUTSIDE; } assert(parent->Type == TYPE_UNION); int resCur = LeftOrRight(curPtr); int resPar = LeftOrRight(parent); if (resPar == 0) // root { if (resCur < 0) { tree->pRoot = parent->pRight; parent->pRight = nullptr; delete parent; } else { assert(resCur); tree->pRoot = parent->pLeft; parent->pLeft = nullptr; delete parent; } tree->pRoot->Parent = nullptr; } else if (resPar < 0) { if (resCur < 0) { parent->pRight->Parent = parent->Parent; parent->Parent->pLeft = parent->pRight; parent->pRight = nullptr; delete parent; } else { assert(resCur); parent->pLeft->Parent = parent->Parent; parent->Parent->pLeft = parent->pLeft; parent->pLeft = nullptr; delete parent; } } else { if (resCur < 0) { parent->pRight->Parent = parent->Parent; parent->Parent->pRight = parent->pRight; parent->pRight = nullptr; delete parent; } else { assert(resCur); parent->pLeft->Parent = parent->Parent; parent->Parent->pRight = parent->pLeft; parent->pLeft = nullptr; delete parent; } } GetLeafList(tree); return REL_UNKNOWN; }
// result is the last node (if any... which is a peekstack) PLAYER_PATH_NODE LAYER::UnlayPath( int nLayers ) { // unwind to, and including this current spot. // this is to handle when the line intersects itself. // other conditions of unlaying via pathways may require // other functionality. int n; PLAYER_PATH_NODE node;// = (PLAYER_PATH_NODE)PopData( &pds_path ); lprintf( WIDE("overlapped self at path segment %d"), nLayers ); for( n = nLayers; (n && (node = (PLAYER_PATH_NODE)PopData( &pds_path ))), n; n-- ) { lprintf( WIDE("Popped node %d(%p)"), n, node ); // grab the NEXT node... // if it has bForced set... then this node must exist. PLAYER_PATH_NODE next = (PLAYER_PATH_NODE)PeekData( &pds_path ); if( next && next->flags.bForced ) { DebugBreak(); node->flags.ForeDir = NOWHERE; return node; } if( node && node->flags.bForced ) { DebugBreak(); // this is SO bad. } //if( node->x == dest_x && node->y == dest_y ) { //lprintf( WIDE("And then we find the node we overlaped...") ); } } lprintf( WIDE("Okay done popping... %d, %p"), n, node ); if( node ) { PLAYER_PATH_NODE next = (PLAYER_PATH_NODE)PeekData( &pds_path ); // set this as nowhere, so that we can easily just step forward here.. if( !next ) { if( !node->flags.bForced ) { node->flags.ForeDir = NOWHERE; } PushData( &pds_path, node ); return node; } if( !nLayers && next->flags.bForced && next->flags.BackDir != NOWHERE ) { // if it was forced, then this MUST be here. There is a reason. // there is also a way to end this reason, and unlay 0 path. This // releases the foredir to anything. This may be used for error correction path // assumptions? DebugBreak(); if( next->flags.bTry ) { node = (PLAYER_PATH_NODE)PopData(&pds_path ); // this is the second attempt if( !node->flags.bFlopped ) { node->flags.bFlopped = 1; node->flags.ForeDir = LeftOrRight( Opposite( node->flags.BackDir ), 1 ); return node; } } next->flags.bForced = 0; } else { next->flags.ForeDir = NOWHERE; lprintf( WIDE("this node itself is okay...") ); } return next; } return NULL; }
void LAYER::LayPath( int32_t wX, int32_t wY ) { int DeltaDir; LOGICAL bLoop = FALSE, bIsRetry; // no looping.... int tx, ty; int nPathLayed = 0; int nDir, nNewDir; LOGICAL bBackTrace = FALSE, bFailed = FALSE; PLAYER_PATH_NODE node; lprintf( WIDE("Laying path %p to %d,%d"), this, wX, wY ); node = (PLAYER_PATH_NODE)PeekData( &pds_path ); // sanity validations... // being done already, etc... wX -= LAYER::x; wY -= LAYER::y; if( node ) { if( node->x == wX && node->y == wY ) { lprintf( WIDE("Already at this end point, why are you telling me to end where I already did?") ); return; } // should range check wX and wY to sane limits // but for now we'll trust the programmer... if( abs( node->x - wX ) > 100 || abs( node->y - wY ) > 100 ) { DebugBreak(); lprintf( WIDE("Laying a LONG path - is this okay?!") ); } } #ifdef DEBUG_BACKTRACE Log( WIDE("Enter...") ); #endif //------------ FORWARD DRAWING NOW ..... bIsRetry = FALSE; DeltaDir = 0; { PLAYER_PATH_NODE node; // get the last node in the path. node = (PLAYER_PATH_NODE)PeekData( &pds_path ); while( node ) { nNewDir = FindDirection( node->x , node->y , wX, wY ); if( nNewDir == NOWHERE ) { // already have this node at the current spot... lprintf( WIDE("Node has ended here...") ); break; } nDir = NOWHERE; // intialize this, in case we missed a path below... if( node->flags.BackDir == NOWHERE ) { // if it is newdir, we're okay to go ahead with this plan. if( node->flags.ForeDir != nNewDir && flags.bForced ) { lprintf( WIDE("Have a forced begin point, and no way to get there from here....") ); DebugBreak(); if( NearDir( node->flags.ForeDir, nNewDir ) == 10 ) { lprintf( WIDE("MUST go %d , have to go %d from here. Go nowhere."), node->flags.ForeDir, nNewDir ); lprintf( WIDE("Okay - consider a arbitrary jump to go forward... until we can go backward.") ); } else { lprintf( WIDE("It's just not quite right... return, a less radical assumption may be made.") ); } return; } // else, just go ahead, we returned above here. node->flags.ForeDir = nNewDir; } else { // need to determine a valid foredir based on nNewDir desire, and nBackDir given. lprintf( WIDE("%d, %d = %d") , Opposite( node->flags.BackDir ) , nNewDir , NearDir(Opposite( node->flags.BackDir ) , nNewDir ) ); lprintf( WIDE("newdir = %d backdir = %d"), nNewDir, node->flags.BackDir ); //pold->TopLayer->ForeDir; if( NearDir( nNewDir, Opposite( node->flags.BackDir ) ) != 10 ) { // this is a valid direction to go. node->flags.ForeDir = nNewDir; } else { lprintf( WIDE("Unlay path cause we can't get there from here.") ); node = UnlayPath( nPathLayed + 1 ); // at this point always unlay at least one more than we put down. nPathLayed = 1; continue; #if 0 int nBase = Opposite( node->flags.BackDir ); nDir = ( node->flags.BackDir + 2 ) & 7; if( NearDir( nNewDir, nDir ) != 10 ) { //node->flags.ForeDir = (nBase + 6) &7; node->flags.ForeDir = Right( nBase ); } else if( NearDir( nNewDir, Opposite( nDir ) ) != 10 ) { node->flags.ForeDir = Left(nBase); } else { // this should be a random chance to go left or right... // maybe tend to the lower x or higher x ? lprintf( WIDE("Choosing an arbitrary directino of 1, and only on1") ); //node->flags.ForeDir = Right( nBase + 1 ); node->flags.bFlopped = 0; node->flags.bTry = 1; node->flags.bForced = 1; node->flags.ForeDir = LeftOrRight( nBase, node->flags.bFlopped ); // set a flag in this node for which way to go... // but a left/right node needs the ability // to remain forced for a single unlay, and move in a direction... } #endif } } { int n; tx = node->x + DirDeltaMap[node->flags.ForeDir].x; ty = node->y + DirDeltaMap[node->flags.ForeDir].y; lprintf( WIDE("New coordinate will be %d,%d"), tx, ty ); if( n = Overlaps( tx, ty ) ) // aleady drew something here... // the distance of the overlap is n layers, including Nth layer // for( ; n; PopData(&pds_stack), n-- ) // and some fixups which unlay path does. { lprintf( WIDE("Unlaying path %d steps to overlap") , n ); node = UnlayPath( n ); // at an unlay point of forced, unlay path should be 'smart' and 'wait' // otherwise we may unwind to our tail and be confused... specially when moving away // and coming back to reside at the center. // if the force direction to go from a forced node is excessive, that definatly // breaks force, and releases the path node. // there may be board conditions which also determine the pathing. // okay try this again from the top do { // startin laying path again. continue; } // otherwise we're good to go foreward. // at least we won't add this node if it would have // already been there, heck, other than that via's // don't exist, sometimes we'll even get the exact node // that this should be.... { LAYER_PATH_NODE newnode; // this may be set intrinsically by being an excessive force // causing a large direction delta newnode.flags.bForced = FALSE; newnode.flags.ForeDir = NOWHERE; // this of course must start(?) exactly how the other ended(?)... newnode.flags.BackDir = Opposite( node->flags.ForeDir ); newnode.x = tx; newnode.y = ty; { int xx = tx + x; int yy = ty + y; if( xx < min_x ) { w += min_x - xx; min_x = xx; } if( xx >= ( min_x + (int32_t)w ) ) w = xx - min_x + 1; if( yy < min_y ) { h += min_y - yy; min_y = yy; } if( yy >= ( min_y + (int32_t)h ) ) h = yy - min_y + 1; } lprintf( WIDE("Push path %d,%d min=%d,%d size=%d,%d"), newnode.x, newnode.y, min_x, min_y, w, h ); PushData( &pds_path, &newnode ); nPathLayed++; node = (PLAYER_PATH_NODE)PeekData( &pds_path ); // okay this is now where we are. } } } } }
void dedtype(RING * gbl, char *name, int inlist, int binary, int stripped, int isdir) { int had_eof; int c; int count, /* ...and repeat-count */ y, /* current line-in-screen */ shift = COLS / 4, /* amount of left/right shift */ done = FALSE, shown = FALSE, infile = -1; /* # of lines processed */ OFF_T skip = 0; tabstop = 8; Shift = 0; UsePattern = FALSE; OptBinary = binary; OptStripped = stripped; if (isdir && !OptBinary) { DIR *dp; DirentT *de; char bfr[MAXPATHLEN]; # define INO_FMT "%5lu" if ((InFile = tmpfile()) == 0) { warn(gbl, "tmp-file"); return; } if ((dp = opendir(name)) != 0) { while ((de = readdir(dp)) != NULL) { (void) ded2string(gbl, bfr, (int) NAMLEN(de), de->d_name, FALSE); FPRINTF(InFile, INO_FMT, (unsigned long) de->d_ino); FPRINTF(InFile, " %s\n", bfr); } (void) closedir(dp); rewind(InFile); } else { warn(gbl, "opendir"); FCLOSE(InFile); return; } } else InFile = fopen(name, "r"); in_dedtype = TRUE; /* disable clearing of workspace via A/a cmd */ if (InFile) { int jump = 0; dlog_comment("type \"%s\" (%s %s)\n", name, OptBinary ? "binary" : "text", isdir ? "directory" : "file"); to_work(gbl, FALSE); dyn_init(&my_text, BUFSIZ); dyn_init(&my_over, BUFSIZ); max_lines = -1; MarkLine(&infile); while (!done) { if (jump) { #if defined(HAVE_WSCRL) && defined(HAVE_WSETSCRREG) /* * If we're doing single-line scrolling past * the point we've read in the file, try to * cache pointers so that the scrolling logic * will go more smoothly. */ if (jump > 0 && jump < NumP(1) && infile + NumP(1) >= max_lines) { int line = infile; (void) StartPage(&line, TRUE, &had_eof); } #endif (void) JumpBackwards(&infile, jump); jump = 0; } markC(gbl, TRUE); y = StartPage(&infile, (int) skip, &had_eof); if (skip && !was_interrupted) { if (feof(InFile)) { skip = 0; jump = NumP(1); } else { IgnorePage(infile); skip--; } continue; } if (had_eof) { int blank; infile = TopOfPage(infile, &blank); (void) JumpToLine(infile); y = StartPage(&infile, 0, &had_eof); } shown |= FinishPage(gbl, inlist, infile, y); jump = NumP(1); reset_catcher(); switch (c = dlog_char(gbl, &count, 1)) { case CTL('K'): deddump(gbl); break; case 'w': retouch(gbl, 0); break; case '\t': if (OptBinary) { beep(); } else { tabstop = (count <= 1) ? (tabstop == 8 ? 4 : 8) : count; } break; case 'q': done = TRUE; break; case KEY_HOME: case '^': jump = infile; break; case KEY_END: case '$': infile = max_lines; skip = MaxP(); break; case KEY_PPAGE: case '\b': case 'b': if (AtTop(infile)) { beep(); } else { jump += NumP(count); } break; case KEY_NPAGE: case '\n': case ' ': case 'f': jump = 0; skip = count - 1; break; case '<': case CTL('L'): LeftOrRight(-shift * count); break; case '>': case CTL('R'): LeftOrRight(shift * count); break; case KEY_LEFT: case 'h': LeftOrRight(-count); break; case KEY_DOWN: case 'j': jump = NumP(1) - count; if ((infile - jump) > max_lines) { skip = (-jump + NumP(1) - 1) / NumP(1); jump = 0; } break; case KEY_UP: case 'k': if (AtTop(infile)) { beep(); } else { jump += count; } break; case KEY_RIGHT: case 'l': LeftOrRight(count); break; /* move work-area marker */ case 'A': count = -count; jump -= count; /*FALLTHRU */ case 'a': markset(gbl, (unsigned) (mark_W + count)); break; case '/': case '?': case 'n': case 'N': FindPattern(gbl, &infile, c); break; default: beep(); } } FCLOSE(InFile); if (shown) (void) reshow(gbl, (unsigned) inlist); showMARK(gbl->Xbase); showC(gbl); } else warn(gbl, name); in_dedtype = FALSE; }