Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

edge_strip.C

Go to the documentation of this file.
00001 /**********************************************************************
00002  * edge_strip.C:
00003  **********************************************************************/
00004 #include "bfilters.H"
00005 #include "stripcb.H"
00006 #include "mi.H"
00007 
00008 /**********************************************************************
00009  * EdgeStrip:
00010  **********************************************************************/
00011 void
00012 EdgeStrip::draw(StripCB* cb)
00013 {
00014    // Draw the strip -- e.g. by making calls to OpenGL or some
00015    // other graphics API, or by writing a description of the
00016    // strip to a text file. Which of these is done depends on the
00017    // implementation of the StripCB.
00018 
00019    // Stop now if nothing is going on
00020    if (empty())
00021       return;
00022 
00023    // Iterate over the strip. Keep in mind _verts[i] is the
00024    // leading vertex (with respect to this strip) of _edges[i].
00025    // Whenever _edges[i]->other_vertex(_verts[i]) is different
00026    // from _verts[i+1], the line strip is broken at that point.
00027    // So a single EdgeStrip encodes 1 or more GL_LINE_STRIPs.
00028    // The following loop checks for these breaks.
00029 
00030    bool started = 0;
00031    for (int i=0; i<_verts.num(); i++) {
00032 
00033       // start new line strip if needed:
00034       if (!started) {
00035          cb->begin_edges(this);
00036          cb->edgeCB(_verts[i], _edges[i]);
00037          started = 1;
00038       }
00039 
00040       // Get next vert:
00041       Bvert* next = next_vert(i);  // _edges[i]->other_vertex(_verts[i])
00042 
00043       // Continue line strip ("finish" this edge):
00044       cb->edgeCB(next, _edges[i]);
00045 
00046       // If we got to the end of the array or if _verts[i+1]
00047       // isn't part of current edge, then break the strip here.
00048       if ((i == _verts.num()-1) || (_verts[i+1] != next)) {
00049          cb->end_edges(this);
00050          started = 0;
00051       }
00052    }
00053 }
00054 
00055 Bedge*
00056 EdgeStrip::next_edge(
00057    Bvert*               v,
00058    Bvert_list&          stack,
00059    CSimplexFilter&      filter
00060    )
00061 {
00062    // Used in EdgeStrip::build() below.  Return an edge of the
00063    // given 'type'; if not all edges have been checked, then push
00064    // the vertex on the stack so remaining edges can be checked
00065    // next time.
00066 
00067    // The filter should accept edges of the desired type only the
00068    // *first* time it checks an edge. Examples are NewSilEdgeFilter,
00069    // UnreachedEdgeFilter() + CreaseEdgeFilter(), etc.
00070 
00071    // Check all adjacent edges:
00072    for (int i=v->degree()-1; i>=0; i--) {
00073       if (filter.accept(v->e(i))) { // if we find a good edge
00074          if (i > 0)                 //  and not all edges have been checked
00075             stack += v;             //  remember this vertex to come back to it
00076          return v->e(i);            // return the good edge
00077       }
00078    }
00079    return 0;
00080 }
00081 
00082 void
00083 EdgeStrip::build(CBedge_list& edges, CSimplexFilter& filter)
00084 {
00085    // Given a list of edges to search, build the strip from edges
00086    // that satisfy a given property.
00087 
00088    reset();
00089 
00090    for (int k=0; k<edges.num(); k++)
00091       build(0, edges[k], filter);
00092 }
00093 
00094 void
00095 EdgeStrip::build_line_strip(
00096    Bvert*          v,           // leading vertex
00097    Bedge*          e,           // contains v, satisfied filter
00098    CSimplexFilter& filter,      // selects desired edges
00099    Bvert_list&     stack        // vertices to check later
00100    )
00101 {
00102    // Run a strip from v thru e and continuing on to other edges
00103    // accepted by the filter. Incompletely explored vertices are
00104    // pushed on the stack so they can be revisited another time.
00105    //
00106    // Note: e has already satisfied the filter, and e contains v.
00107 
00108    assert(e && e->contains(v));
00109 
00110    while (e) {
00111       add(v,e);
00112       e = next_edge(v = e->other_vertex(v), stack, filter);
00113    }
00114 }
00115 
00116 void
00117 EdgeStrip::build(Bvert* v, Bedge* e, CSimplexFilter& filter)
00118 {
00119    // continue building the edge strip, starting with the
00120    // given edge e. if v is not null, e must contain v.
00121    // in that case v will be the leading vertex of the strip.
00122 
00123    // must have an edge to proceed,
00124    // and the edge must be accepted by the filter.
00125    if (!(e && filter.accept(e))) // someone has to punch its ticket
00126       return;
00127 
00128    assert(!v || e->contains(v));
00129 
00130    static Bvert_list stack(64);
00131    stack.clear();
00132 
00133    // first loop:
00134    build_line_strip(v ? v : e->v1(), e, filter, stack);
00135 
00136    // get the rest of them
00137    while (!stack.empty()) {
00138       if ((v = stack.pop()) && (e = next_edge(v, stack, filter))) 
00139          build_line_strip(v, e, filter, stack);
00140    }
00141 }
00142 
00143 void
00144 EdgeStrip::build_with_tips(CBedge_list& edges, CSimplexFilter& filter)
00145 {
00146    // Build the strip from the given pool of edges, with the
00147    // given filter.  Try to start the edge strip at the "tips" of
00148    // chains of edges of the desired type. The given filter
00149    // should just screen for edges of the desired kind;
00150    // internally this method also screens for edges that have not
00151    // yet been reached (added to the strip).
00152 
00153    // Clear edge flags to screen for unreached edges:
00154    set_adjacent_edges(edges.get_verts(), 1);
00155    edges.clear_flags();
00156 
00157    // Pull out the edge tips:
00158    Bedge_list tips = edges.filter(ChainTipEdgeFilter(filter));
00159 
00160    // Construct the filter that screens out previously reached
00161    // edges:
00162    UnreachedSimplexFilter unreached;
00163    AndFilter       wanted = unreached + filter;
00164 
00165    int k;
00166 
00167    // Start from all the tips first:
00168    for (k=0; k<tips.num(); k++) {
00169       Bedge* e = tips[k];
00170       Bvert* v = (e->v2()->degree(filter) != 2) ? e->v2() : e->v1();
00171       build(v, e, wanted);
00172    }
00173 
00174    // Now check the rest:
00175    for (k=0; k<edges.num(); k++)
00176       build(0, edges[k], wanted);
00177 }
00178 
00179 void
00180 EdgeStrip::build_ccw_boundaries(
00181    CBedge_list& edges,
00182    CSimplexFilter& face_filter
00183    )
00184 {
00185    // Similar to previous...
00186    //
00187    // XXX - needs comments
00188 
00189    // Clear edge flags to screen for unreached edges:
00190    // set edge flags to 1 in 1-ring of verts,
00191    // then clear edge flags of internal edges
00192    set_adjacent_edges(edges.get_verts(), 1);
00193    edges.clear_flags();
00194 
00195    // get an edge filter that accepts "boundary" edges WRT the
00196    // given face filter
00197    BoundaryEdgeFilter boundary(face_filter);
00198 
00199    // Pull out the edge tips:
00200    Bedge_list tips = edges.filter(ChainTipEdgeFilter(boundary));
00201 
00202    // Construct the filter that screens out previously reached
00203    // edges:
00204    UnreachedSimplexFilter unreached;
00205    AndFilter       wanted = unreached + boundary;
00206 
00207    int k;
00208 
00209    // Start from all the tips first:
00210    for (k=0; k<tips.num(); k++) {
00211       Bedge* e = tips[k];
00212       Bvert* v = (e->v2()->degree(boundary) != 2) ? e->v2() : e->v1();
00213       Bface* f = e->screen_face(face_filter);
00214       assert(f); // e must have 1 face satisfying the filter
00215 
00216       // If this will start out running ccw, take it.
00217       // otherwise skip:
00218       if (f->next_vert_ccw(v) == e->other_vertex(v))
00219          build(v, e, wanted);
00220    }
00221 
00222    // Now check the rest:
00223    for (k=0; k<edges.num(); k++) {
00224       Bedge* e = edges[k];
00225       Bface* f = e->screen_face(face_filter);
00226       assert(f); // e must have 1 face satisfying the filter
00227 
00228       // Go CCW around faces
00229       build(f->leading_vert_ccw(e), e, wanted);
00230    }
00231 }
00232 
00233 bool
00234 EdgeStrip::has_break(int i) const
00235 {
00236    // Returns true if the line strip is broken at vert i
00237    // (or if it's the first or last vert):
00238 
00239    // For bogus input say it's not broken:
00240    if (empty() || (i < 0) || (i > _verts.num()))
00241       return false;
00242 
00243    // For the first or last vertex say it is broken:
00244    // Note: last vert is the one *after* _verts.last()
00245    if ((i == 0) || (i == _verts.num()))
00246       return true;
00247 
00248    // Just check the vertex:
00249    return (_verts[i] != next_vert(i-1));
00250 }
00251 
00252 int 
00253 EdgeStrip::num_line_strips() const
00254 {
00255    // Returns number of distinct (disconnected) line strips:
00256 
00257    if (empty())
00258       return 0;
00259 
00260    int ret = 1; // last edge has a break
00261 
00262    // check all edges but the last:
00263    for (int i=0; i<_edges.num()-1; i++)
00264       if (next_vert(i) != _verts[i+1])
00265          ret++;
00266    return ret;
00267 }
00268 
00269 bool
00270 EdgeStrip::get_chain(int& k, Bvert_list& chain) const
00271 {
00272    // Return the chain starting at index k,
00273    // and advance k to the start of the next chain.
00274 
00275    chain.clear();               // get set...
00276 
00277    if (k < 0 || k >= num())     // if out of range, reject
00278       return false;
00279 
00280    if (!has_break(k))           // if k is not a chain endpoint, reject
00281       return false;             
00282 
00283    chain += vert(k);            // add leading vertex
00284    do {
00285       chain.add(next_vert(k));  // add subsequent vertex
00286    } while (!has_break(++k));   // advance k, break at chain end
00287 
00288    return true;
00289 }
00290 
00291 void
00292 EdgeStrip::get_chains(ARRAY<Bvert_list>& chains) const
00293 {
00294    // Return a list of distinct chains of edges, in the form
00295    // of a set of Bvert_lists. 
00296 
00297    chains.clear();
00298 
00299    Bvert_list chain;
00300    for (int k=0; get_chain(k, chain); )
00301       chains += chain;
00302 }
00303 
00304 EdgeStrip 
00305 EdgeStrip::get_reverse() const
00306 {
00307    // Generate the reversed edge strip:
00308 
00309    EdgeStrip ret = *this;
00310    if (!empty()) {
00311       ret._edges.reverse();
00312       ret._verts += last();
00313       ret._verts.reverse();
00314       ret._verts.pop();
00315    }
00316    return ret;
00317 }
00318 
00319 EdgeStrip 
00320 EdgeStrip::get_filtered(CSimplexFilter& filter) const
00321 {
00322    EdgeStrip ret;
00323    for (int i=0; i<num(); i++)
00324       if (filter.accept(edge(i)))
00325          ret.add(vert(i), edge(i));
00326    return ret;
00327 }
00328 
00329 inline Bvert*
00330 get_leading_vert(CEdgeStrip& source)
00331 {
00332    CBvert_list& verts = source.verts();
00333    CBedge_list& edges = source.edges();
00334    for (int i=0; i<verts.num(); i++)
00335       if (verts[i]->degree(SimplexFlagFilter(1)) == 1 && edges[i]->flag())
00336          return verts[i];
00337    for (int j=0; j<verts.num(); j++)
00338       if (edges[j]->flag())
00339          return verts[j];
00340    return 0;
00341 }
00342 
00343 inline void
00344 add_to_strip(Bvert* v, CEdgeStrip& source, EdgeStrip& ret)
00345 {
00346    assert(v);
00347    CBvert_list& verts = source.verts();
00348    CBedge_list& edges = source.edges();
00349    int k = verts.get_index(v);
00350    assert(verts.valid_index(k) && edges[k]->flag());
00351    while (verts.valid_index(k) && edges[k]->flag()) {
00352       edges[k]->clear_flag();
00353       ret.add(verts[k], edges[k]);
00354       if (source.has_break(k+1)) {
00355          k = verts.get_index(source.next_vert(k));
00356       } else {
00357          k++;
00358       }
00359    }
00360 }
00361 
00362 EdgeStrip 
00363 EdgeStrip::get_unified() const
00364 {
00365    _edges.get_verts().clear_flag02();
00366    _edges.set_flags(1);
00367    EdgeStrip ret;
00368    Bvert* v = 0;
00369    while ((v = get_leading_vert(*this))) {
00370       add_to_strip(v, *this, ret);
00371    }
00372    return ret;
00373 }
00374 
00375 // end of file edge_strip.C

Generated on Mon Sep 18 11:39:29 2006 for jot by  doxygen 1.4.4