Example #1
0
bool
Surface_mesh::
is_collapse_ok(Halfedge v0v1)
{
    Halfedge  v1v0(opposite_halfedge(v0v1));
    Vertex    v0(to_vertex(v1v0));
    Vertex    v1(to_vertex(v0v1));
    Vertex    vv, vl, vr;
    Halfedge  h1, h2;


    // the edges v1-vl and vl-v0 must not be both boundary edges
    if (!is_boundary(v0v1))
    {
        vl = to_vertex(next_halfedge(v0v1));
        h1 = next_halfedge(v0v1);
        h2 = next_halfedge(h1);
        if (is_boundary(opposite_halfedge(h1)) && is_boundary(opposite_halfedge(h2)))
            return false;
    }


    // the edges v0-vr and vr-v1 must not be both boundary edges
    if (!is_boundary(v1v0))
    {
        vr = to_vertex(next_halfedge(v1v0));
        h1 = next_halfedge(v1v0);
        h2 = next_halfedge(h1);
        if (is_boundary(opposite_halfedge(h1)) && is_boundary(opposite_halfedge(h2)))
            return false;
    }


    // if vl and vr are equal or both invalid -> fail
    if (vl == vr) return false;


    // edge between two boundary vertices should be a boundary edge
    if ( is_boundary(v0) && is_boundary(v1) &&
        !is_boundary(v0v1) && !is_boundary(v1v0))
        return false;


    // test intersection of the one-rings of v0 and v1
    Vertex_around_vertex_circulator vv_it, vv_end;
    vv_it = vv_end = vertices(v0);
    do
    {
        vv = vv_it;
        if (vv != v1 && vv != vl && vv != vr)
            if (find_halfedge(vv, v1).is_valid())
                return false;
    }
    while (++vv_it != vv_end);


    // passed all tests
    return true;
}
Example #2
0
static void close_mime(struct mimestack **stack, int *iseof,
                       FILE *fpin, FILE *fpout)
{
    char buf[BUFSIZ];
    int is_closing;
    struct mimestack *b;

    for (;;)
    {
        if (fgets(buf, sizeof(buf), fpin) == NULL)
        {
            *iseof=1;
            break;
        }

        fprintf(fpout, "%s", buf);
        if (!(b=is_boundary(*stack, buf, &is_closing)))
            continue;
        if (!is_closing)
            continue;

        pop_mimestack_to(stack, b);
        break;
    }
}
Example #3
0
static void find_boundary(struct mimestack **stack, int *iseof,
                          FILE *fpin, FILE *fpout, int doappend)
{
    char buf[BUFSIZ];

    for (;;)
    {
        int is_closing;
        struct mimestack *b;

        if (fgets(buf, sizeof(buf), fpin) == NULL)
        {
            *iseof=1;
            return;
        }

        if (!(b=is_boundary(*stack, buf, &is_closing)))
        {
            if (fpout)
                fprintf(fpout, "%s", buf);
            if (strchr(buf, '\n') == 0)
            {
                int c;

                do
                {
                    if ((c=getc(fpin)) == EOF)
                    {
                        *iseof=1;
                        return;
                    }
                    if (fpout)
                        putc(c, fpout);
                } while (c != '\n');
            }
            continue;
        }

        if (fpout)
            fprintf(fpout, "--%s%s\n", b->boundary,
                    is_closing ? "--":"");
        if (is_closing)
        {
            pop_mimestack_to(stack, b);
            continue;
        }
        break;
    }
}
Example #4
0
Surface_mesh::Normal
Surface_mesh::
compute_vertex_normal(Vertex v) const
{
    Point     nn(0,0,0);
    Halfedge  h = halfedge(v);

    if (h.is_valid())
    {
        const Halfedge hend = h;
        const Point p0 = vpoint_[v];

        Point   n, p1, p2;
        Scalar  cosine, angle;

        do
        {
            if (!is_boundary(h))
            {
                p1 = vpoint_[to_vertex(h)];
                p1 -= p0;
                p1.normalize();

                p2 = vpoint_[from_vertex(prev_halfedge(h))];
                p2 -= p0;
                p2.normalize();

                cosine = p1.dot(p2) / sqrt(p1.dot(p1)*p2.dot(p2));
                if      (cosine < -1.0) cosine = -1.0;
                else if (cosine >  1.0) cosine =  1.0;
                angle = acos(cosine);

                n   = p1.cross(p2).normalized();
                n  *= angle;
                nn += n;
            }

            h  = cw_rotated_halfedge(h);
        }
        while (h != hend);

        nn.normalize();
    }

    return nn;
}
Example #5
0
    typename viennagrid::result_of::coord< MeshT >::type
    surface_meshsegment(MeshT const & mesh_obj)
    {
      typedef typename viennagrid::result_of::const_element_range<MeshT, ElementTypeOrTag>::type  ElementRange;
      typedef typename viennagrid::result_of::iterator<ElementRange>::type                        ElementIterator;

      typename viennagrid::result_of::coord<MeshT>::type result = 0;

      ElementRange facets(mesh_obj);
      for (ElementIterator fit = facets.begin();
                           fit != facets.end();
                         ++fit)
      {
        if (is_boundary(mesh_obj, *fit))
          result += viennagrid::volume(*fit);
      }
      return result;
    }
      static void detect(AccessorT accessor,
                        MeshT1 const & seg0,
                        MeshT2 const & seg1)
      {
        typedef typename viennagrid::result_of::cell_tag<MeshT1>::type CellTag;
        typedef typename viennagrid::result_of::element<MeshT1, typename CellTag::facet_tag>::type   FacetType;
        typedef typename viennagrid::result_of::const_handle<MeshT1, typename CellTag::facet_tag>::type   ConstFacetHandleType;

        typedef typename viennagrid::result_of::const_element_range<MeshT1, typename CellTag::facet_tag>::type      FacetRange;
        typedef typename viennagrid::result_of::iterator<FacetRange>::type                                           FacetIterator;

        std::set<ConstFacetHandleType>  facets_ptrs_seg0;

        //
        // Step 1: Write facets of segment 1 to a map:
        //
        FacetRange facets_seg0(seg0);
        for (FacetIterator fit = facets_seg0.begin();
              fit != facets_seg0.end();
              ++fit)
        {
          const FacetType & facet = *fit;

          if (is_boundary(seg0, facet))
            facets_ptrs_seg0.insert( fit.handle() );
        }

        //
        // Step 2: Compare facet in segment 2 with those stored in the map
        //
        FacetRange facets_seg1(seg1);
        for (FacetIterator fit = facets_seg1.begin();
              fit != facets_seg1.end();
              ++fit)
        {
          const FacetType & facet = *fit;

          if (facets_ptrs_seg0.find( fit.handle() ) != facets_ptrs_seg0.end()) accessor(facet) = true;
        }

      }
Example #7
0
void
Surface_mesh::
adjust_outgoing_halfedge(Vertex v)
{
    Halfedge h  = halfedge(v);
    const Halfedge hh = h;

    if (h.is_valid())
    {
        do
        {
            if (is_boundary(h))
            {
                set_halfedge(v, h);
                return;
            }
            h = cw_rotated_halfedge(h);
        }
        while (h != hh);
    }
}
Example #8
0
static int good_boundary(const char *boundary,
                         struct mimestack *m, const char *errmsg, FILE *fp)
{
    int dummy;
    int l=strlen(boundary);
    const char *p;
    char buf[BUFSIZ];

    if (is_boundary(m, boundary, &dummy))
        return (0);

    for (p=errmsg; *p; )
    {
        if (*p == '-' && p[1] == '-' && strncasecmp(p+2, boundary, l)
                == 0)
            return (0);

        while (*p)
            if (*p++ == '\n')
                break;
    }

    if (fp)
    {
        if (my_rewind(fp) < 0)
        {
            perror("fseek");
            exit(1);
        }

        while (fgets(buf, sizeof(buf), fp))
        {
            if (buf[0] == '-' && buf[1] == '-' &&
                    strncasecmp(buf+2, boundary, l) == 0)
                return (0);
        }
    }
    return (1);
}
Example #9
0
bool
Surface_mesh::
is_flip_ok(Edge e) const
{
    // boundary edges cannot be flipped
    if (is_boundary(e)) return false;

    // check if the flipped edge is already present in the mesh

    Halfedge h0 = halfedge(e, 0);
    Halfedge h1 = halfedge(e, 1);

    Vertex v0 = to_vertex(next_halfedge(h0));
    Vertex v1 = to_vertex(next_halfedge(h1));

    if (v0 == v1)   // this is generally a bad sign !!!
        return false;

    if (find_halfedge(v0, v1).is_valid())
        return false;

    return true;
}
Example #10
0
void cal_onePath(Location *cur)
{
	int min, i;
	Location buf[6];

	if(cur->type == STONE)
		min = 100;
	 else {
		 if(is_boundary((*cur)))
			min =  0;
		else {
			get_round((*cur), buf);
			min = 100;
			for(i = 0; i < 6; i++) {
				if(min > abs(buf[i].path)) {
					min = buf[i].path;				
				}
			}
			if(min != 100)
				min++;
		}
	 }
	cur->path = min;
}
Example #11
0
// Retriangulate a cavity formed when a constraint edge is inserted, following Shewchuck and Brown.
// The cavity is defined by a counterclockwise list of vertices v[0] to v[m-1] as in Shewchuck and Brown, Figure 5.
static void cavity_delaunay(MutableTriangleTopology& parent_mesh, RawField<const EV,VertexId> X,
                            RawArray<const VertexId> cavity, Random& random) {
  // Since the algorithm generates meshes which may be inconsistent with the outer mesh, and the cavity
  // array may have duplicate vertices, we use a temporary mesh and then copy the triangles over when done.
  // In the temporary, vertices are indexed consecutively from 0 to m-1.
  const int m = cavity.size();
  assert(m >= 3);
  const auto mesh = new_<MutableTriangleTopology>();
  Field<Perturbed2,VertexId> Xc(m,uninit);
  for (const int i : range(m))
    Xc.flat[i] = Perturbed2(cavity[i].id,X[cavity[i]]);
  mesh->add_vertices(m);
  const auto xs = Xc.flat[0],
             xe = Xc.flat[m-1];

  // Set up data structures for prev, next, pi in the paper
  const Field<VertexId,VertexId> prev(m,uninit),
                                 next(m,uninit);
  for (int i=0;i<m-1;i++) {
    next.flat[i] = VertexId(i+1);
    prev.flat[i+1] = VertexId(i);
  }
  const Array<VertexId> pi_(m-2,uninit);
  for (int i=1;i<=m-2;i++)
    pi_[i-1] = VertexId(i);
  #define PI(i) pi_[(i)-1]

  // Randomly shuffle [1,m-2], subject to vertices closer to xs-xe than both their neighbors occurring later
  for (int i=m-2;i>=2;i--) {
    int j;
    for (;;) {
      j = random.uniform<int>(0,i)+1;
      const auto pj = PI(j);
      if (!(   segment_directions_oriented(xe,xs,Xc[pj],Xc[prev[pj]])
            && segment_directions_oriented(xe,xs,Xc[pj],Xc[next[pj]])))
        break;
    }
    swap(PI(i),PI(j));
    // Remove PI(i) from the list
    const auto pi = PI(i);
    next[prev[pi]] = next[pi];
    prev[next[pi]] = prev[pi];
  }

  // Add the first triangle
  mesh->add_face(vec(VertexId(0),PI(1),VertexId(m-1)));

  // Add remaining triangles, flipping to ensure Delaunay
  const Field<bool,VertexId> marked(m);
  Array<HalfedgeId> fan;
  bool used_chew = false;
  for (int i=2;i<m-1;i++) {
    const auto pi = PI(i);
    insert_cavity_vertex(mesh,Xc,marked,pi,next[pi],prev[pi]);
    if (marked[pi]) {
      used_chew = true;
      marked[pi] = false;
      // Retriangulate the fans of triangles that have all three vertices marked
      auto e = mesh->reverse(mesh->halfedge(pi));
      auto v = mesh->src(e);
      bool mv = marked[v];
      marked[v] = false;
      fan.clear();
      do {
        const auto h = mesh->prev(e);
        e = mesh->reverse(mesh->next(e));
        v = mesh->src(e);
        const bool mv2 = marked[v];
        marked[v] = false;
        if (mv) {
          if (mv2)
            fan.append(h);
          if (!mv2 || mesh->is_boundary(e)) {
            chew_fan(mesh,Xc,pi,fan,random);
            fan.clear();
          }
        }
        mv = mv2;
      } while (!mesh->is_boundary(e));
    }
  }
  #undef PI

  // If we ran Chew's algorithm, validate the output.  I haven't tested this
  // case enough to be confident of its correctness.
  if (used_chew)
    assert_delaunay("Failure in extreme special case.  If this triggers, please email [email protected]: ",
                    mesh,Xc,Tuple<>(),false,false);

  // Copy triangles from temporary mesh to real mesh
  for (const auto f : mesh->faces()) {
    const auto v = mesh->vertices(f);
    parent_mesh.add_face(vec(cavity[v.x.id],cavity[v.y.id],cavity[v.z.id]));
  }
}
Example #12
0
static void checksign(struct mimestack **stack, int *iseof,
                      struct header *h,
                      FILE *fpin, FILE *fpout,
                      int argc, char **argv)
{
    char buf[BUFSIZ];
    struct header *h2;

    char signed_content[TEMPNAMEBUFSIZE];
    char signature[TEMPNAMEBUFSIZE];
    int signed_file, signature_file;
    FILE *signed_file_fp, *signature_file_fp;
    int clos_flag;
    int need_nl, check_boundary;
    struct mimestack *b=0;
    struct mime_header *mh;
    int qpdecode=0;

    signed_file=mimegpg_tempfile(signed_content);

    if (signed_file < 0 || (signed_file_fp=fdopen(signed_file, "w+")) == 0)
    {
        if (signed_file > 0)
        {
            close(signed_file);
            unlink(signed_content);
        }
        perror("open");
        exit(1);
    }
    noexec(signed_file_fp);

    find_boundary(stack, iseof, fpin, NULL, 0);
    if (*iseof)
        return;

    need_nl=0;
    check_boundary=1;

    while (!*iseof)
    {
        const char *p;

        if (fgets(buf, sizeof(buf), fpin) == NULL)
        {
            *iseof=1;
            continue;
        }

        if (check_boundary
                && (b=is_boundary(*stack, buf, &clos_flag)) != 0)
            break;
        if (need_nl)
            fprintf(signed_file_fp, "\r\n");

        for (p=buf; *p && *p != '\n'; p++)
            putc(*p, signed_file_fp);
        need_nl=check_boundary= *p != 0;
    }

    if (my_rewind(signed_file_fp) < 0)
    {
        perror(signed_content);
        fclose(signed_file_fp);
        unlink(signed_content);
        exit(1);
    }

    if (clos_flag)
    {
        fclose(signed_file_fp);
        unlink(signed_content);
        if (b)
            pop_mimestack_to(stack, b);
        find_boundary(stack, iseof, fpin, fpout, 1);
        return;
    }

    h=read_headers(stack, iseof, fpin, fpout, 0);

    if (!h || !(h2=find_header(h, "content-type:")))
    {
        fclose(signed_file_fp);
        unlink(signed_content);
        if (!*iseof)
            find_boundary(stack, iseof, fpin, fpout, 1);
        return;
    }

    mh=parse_mime_header(h2->header+sizeof("content-type:")-1);

    if (!mh)
    {
        perror("malloc");
        free_header(h);
        fclose(signed_file_fp);
        unlink(signed_content);
        exit(1);
    }

    if (!mh || strcasecmp(mh->header_name, "application/pgp-signature"))
    {
        if (!mh)
            free_mime_header(mh);
        free_header(h);
        fclose(signed_file_fp);
        unlink(signed_content);
        if (!*iseof)
            find_boundary(stack, iseof, fpin, fpout, 1);
        return;
    }
    free_mime_header(mh);

    /*
    ** In rare instances, the signature is qp-encoded.
    */

    if ((h2=find_header(h, "content-transfer-encoding:")) != NULL)
    {
        mh=parse_mime_header(h2->header
                             +sizeof("content-transfer-encoding:")-1);
        if (!mh)
        {
            perror("malloc");
            free_header(h);
            fclose(signed_file_fp);
            unlink(signed_content);
            exit(1);
        }

        if (strcasecmp(mh->header_name,
                       "quoted-printable") == 0)
            qpdecode=1;
        free_mime_header(mh);
    }
    free_header(h);

    signature_file=mimegpg_tempfile(signature);

    if (signature_file < 0
            || (signature_file_fp=fdopen(signature_file, "w+")) == 0)
    {
        if (signature_file > 0)
        {
            close(signature_file);
            unlink(signature);
        }
        fclose(signed_file_fp);
        unlink(signed_content);
        perror("open");
        exit(1);
    }

    while (!*iseof)
    {
        const char *p;

        if (fgets(buf, sizeof(buf), fpin) == NULL)
        {
            *iseof=1;
            continue;
        }

        if ((b=is_boundary(*stack, buf, &clos_flag)) != 0)
            break;

        for (p=buf; *p; p++)
        {
            int n;

            if (!qpdecode)
            {
                putc(*p, signature_file_fp);
                continue;
            }

            if (*p == '=' && p[1] == '\n')
                break;

            if (*p == '=' && p[1] && p[2])
            {
                n=nybble(p[1]) * 16 + nybble(p[2]);
                if ( (char)n )
                {
                    putc((char)n, signature_file_fp);
                    p += 2;
                }
                p += 2;
                continue;
            }
            putc(*p, signature_file_fp);

            /* If some spits out qp-lines > BUFSIZ, they deserve
            ** this crap.
            */
        }
    }

    fflush(signature_file_fp);
    if (ferror(signature_file_fp) || fclose(signature_file_fp))
    {
        unlink(signature);
        fclose(signed_file_fp);
        unlink(signed_content);
        perror("open");
        exit(1);
    }

    dochecksign(*stack, signed_file_fp, fpout, signed_content, signature,
                argc, argv);

    fclose(signed_file_fp);
    unlink(signature);
    unlink(signed_content);

    fprintf(fpout, "\n--%s--\n", b->boundary);

    while (!clos_flag)
    {
        if (fgets(buf, sizeof(buf), fpin) == NULL)
        {
            *iseof=1;
            break;
        }
        if (!(b=is_boundary(*stack, buf, &clos_flag)))
            clos_flag=0;
    }
    if (b)
        pop_mimestack_to(stack, b);

    if (iseof)
        return;
}
Example #13
0
static void dogpgsign(struct mimestack **stack, struct header *h, int *iseof,
                      FILE *fpin, FILE *fpout,
                      int argc,
                      char **argv)
{
    struct header *hp;
    char buf[BUFSIZ];
    struct gpgmime_forkinfo gpg;
    int clos_flag=0;
    struct mimestack *b=0;
    int rc;
    char signed_content_name[TEMPNAMEBUFSIZE];
    int signed_content;
    FILE *signed_content_fp;
    const char *boundary;
    int need_crlf;

    for (hp=h; hp; hp=hp->next)
    {
        if (encode_header(hp->header))
            continue;
        fprintf(fpout, "%s", hp->header);
    }

    signed_content=mimegpg_tempfile(signed_content_name);
    if (signed_content < 0 ||
            (signed_content_fp=fdopen(signed_content, "w+")) == NULL)
    {
        if (signed_content >= 0)
        {
            close(signed_content);
            unlink(signed_content_name);
        }
        perror("mktemp");
        exit(1);
    }
    noexec(signed_content_fp);
    unlink(signed_content_name);	/* UNIX semantics */

    for (hp=h; hp; hp=hp->next)
    {
        const char *p;

        if (!encode_header(hp->header))
            continue;

        for (p=hp->header; *p; p++)
        {
            if (*p == '\r')
                continue;

            if (*p == '\n')
                putc('\r', signed_content_fp);
            putc(*p, signed_content_fp);
        }
    }

    /*
    ** Chew the content until the next MIME boundary.
    */
    need_crlf=1;
    while (!*iseof)
    {
        const char *p;

        if (fgets(buf, sizeof(buf), fpin) == NULL)
        {
            *iseof=1;
            break;
        }

        if (need_crlf)
        {
            if ((b=is_boundary(*stack, buf, &clos_flag)) != NULL)
                break;

            fprintf(signed_content_fp, "\r\n");
        }

        need_crlf=0;
        for (;;)
        {
            for (p=buf; *p; p++)
            {
                if (*p == '\r')
                    continue;
                if (*p == '\n')
                {
                    need_crlf=1;
                    break;
                }

                putc(*p, signed_content_fp);
            }
            if (*p == '\n')
                break;

            if (fgets(buf, sizeof(buf), fpin) == NULL)
            {
                *iseof=1;
                break;
            }
        }
    }

    /*
    ** This needs some 'splainin.  Note that we spit out a newline at
    ** the BEGINNING of each line, above.  This generates the blank
    ** header->body separator line.  Now, if we're NOT doing multiline
    ** content, we need to follow the last line of the content with a
    ** newline.  If we're already doing multiline content, that extra
    ** newline (if it exists) is already there.
    */

    if (!*stack)
    {
        fprintf(signed_content_fp, "\r\n");
    }

    if (fflush(signed_content_fp) < 0 || ferror(signed_content_fp))
    {
        perror(signed_content_name);
        exit(1);
    }

    boundary=get_boundary(*stack, "", signed_content_fp);

    if (my_rewind(signed_content_fp) < 0)
    {
        perror(signed_content_name);
        exit(1);
    }

    if (gpgmime_fork_signencrypt(NULL, GPG_SE_SIGN,
                                 argc, argv,
                                 &dumpgpg, fpout,
                                 &gpg))
    {
        perror("fork");
        exit(1);
    }

    fprintf(fpout, "Content-Type: multipart/signed;\n"
            "    boundary=\"%s\";\n"
            "    micalg=pgp-sha1;"
            " protocol=\"application/pgp-signature\"\n"
            "\n"
            "This is a mimegpg-signed message.  If you see this text, it means that\n"
            "your E-mail software does not support MIME-formatted messages.\n"
            "\n--%s\n",
            boundary, boundary);

    while (fgets(buf, sizeof(buf), signed_content_fp) != NULL)
    {
        const char *p;

        gpgmime_write(&gpg, buf, strlen(buf));

        for (p=buf; *p; p++)
            if (*p != '\r')
                putc(*p, fpout);
    }

    fprintf(fpout, "\n--%s\n"
            "Content-Type: application/pgp-signature\n"
            "Content-Transfer-Encoding: 7bit\n\n", boundary);

    rc=gpgmime_finish(&gpg);

    if (rc)
    {
        fprintf(stderr, "%s",
                gpgmime_getoutput(&gpg));
        exit(1);
    }

    fprintf(fpout, "\n--%s--\n", boundary);

    fclose(signed_content_fp);
    if (*iseof)
        return;

    fprintf(fpout, "\n--%s%s\n", b->boundary, clos_flag ? "--":"");

    if (clos_flag)
    {
        pop_mimestack_to(stack, b);
        find_boundary(stack, iseof, fpin, fpout, 1);
    }
}
Example #14
0
static void dogpgencrypt(struct mimestack **stack,
                         struct header *h, int *iseof,
                         FILE *fpin, FILE *fpout,
                         int argc,
                         char **argv,
                         int dosign)
{
    struct header *hp;
    char buf[BUFSIZ];
    struct gpgmime_forkinfo gpg;
    int clos_flag=0;
    struct mimestack *b=0;
    int rc;
    const char *boundary;
    int need_crlf;

    boundary=get_boundary(*stack, "", NULL);

    if (gpgmime_fork_signencrypt(NULL,
                                 (dosign ? GPG_SE_SIGN:0) | GPG_SE_ENCRYPT,
                                 argc, argv,
                                 &dumpgpg, fpout,
                                 &gpg))
    {
        perror("fork");
        exit(1);
    }

    for (hp=h; hp; hp=hp->next)
    {
        if (encode_header(hp->header))
            continue;
        fprintf(fpout, "%s", hp->header);
    }

    fprintf(fpout, "Content-Type: multipart/encrypted;\n"
            "    boundary=\"%s\";\n"
            "    protocol=\"application/pgp-encrypted\"\n"
            "\n"
            "This is a mimegpg-encrypted message.  If you see this text, it means\n"
            "that your E-mail software does not support MIME formatted messages.\n"
            "\n--%s\n"
            "Content-Type: application/pgp-encrypted\n"
            "Content-Transfer-Encoding: 7bit\n"
            "\n"
            "Version: 1\n"
            "\n--%s\n"
            "Content-Type: application/octet-stream\n"
            "Content-Transfer-Encoding: 7bit\n\n",
            boundary, boundary, boundary);

    /* For Eudora compatiblity */
    gpgmime_write(&gpg, "Mime-Version: 1.0\r\n", 19);

    for (hp=h; hp; hp=hp->next)
    {
        const char *p;

        if (!encode_header(hp->header))
            continue;

        for (p=hp->header; *p; p++)
        {
            if (*p == '\r')
                continue;

            if (*p == '\n')
                gpgmime_write(&gpg, "\r\n", 2);
            else
                gpgmime_write(&gpg, p, 1);
        }
    }

    /*
    ** Chew the content until the next MIME boundary.
    */
    need_crlf=1;

    while (!*iseof)
    {
        const char *p;

        if (fgets(buf, sizeof(buf), fpin) == NULL)
        {
            *iseof=1;
            break;
        }

        if (need_crlf)
        {
            if ((b=is_boundary(*stack, buf, &clos_flag)) != NULL)
                break;

            gpgmime_write(&gpg, "\r\n", 2);
        }

        need_crlf=0;
        for (;;)
        {
            for (p=buf; *p; p++)
            {
                if (*p == '\r')
                    continue;
                if (*p == '\n')
                {
                    need_crlf=1;
                    break;
                }

                gpgmime_write(&gpg, p, 1);
            }
            if (*p == '\n')
                break;

            if (fgets(buf, sizeof(buf), fpin) == NULL)
            {
                *iseof=1;
                break;
            }
        }
    }

    /*
    ** This needs some 'splainin.  Note that we spit out a newline at
    ** the BEGINNING of each line, above.  This generates the blank
    ** header->body separator line.  Now, if we're NOT doing multiline
    ** content, we need to follow the last line of the content with a
    ** newline.  If we're already doing multiline content, that extra
    ** newline (if it exists) is already there.
    */

    if (!*stack)
    {
        gpgmime_write(&gpg, "\r\n", 2);
    }

    rc=gpgmime_finish(&gpg);

    if (rc)
    {
        fprintf(stderr, "%s",
                gpgmime_getoutput(&gpg));
        exit(1);
    }

    fprintf(fpout, "\n--%s--\n", boundary);

    if (*iseof)
        return;

    fprintf(fpout, "\n--%s%s\n", b->boundary, clos_flag ? "--":"");

    if (clos_flag)
    {
        pop_mimestack_to(stack, b);
        find_boundary(stack, iseof, fpin, fpout, 1);
    }
}
Example #15
0
static struct header *read_headers(struct mimestack **stack, int *iseof,
                                   FILE *fpin,
                                   FILE *fpout,
                                   int doappend)
{
    char buf[BUFSIZ];
    struct read_header_context rhc;
    struct header *h;

    init_read_header_context(&rhc);

    while (!*iseof)
    {
        if (fgets(buf, sizeof(buf), fpin) == NULL)
        {
            *iseof=1;
            break;
        }

        if (READ_START_OF_LINE(rhc))
        {
            struct mimestack *b;
            int is_closing;

            if (strcmp(buf, "\n") == 0
                    || strcmp(buf, "\r\n") == 0)
                break;

            b=is_boundary(*stack, buf, &is_closing);

            if (b)
            {
                /*
                ** Corrupted MIME message.  We should NOT
                ** see a MIME boundary in the middle of the
                ** headers!
                **
                ** Ignore this damage.
                */

                struct header *p;

                h=finish_header(&rhc);

                for (p=h; p; p=p->next)
                    fprintf(fpout, "%s", p->header);
                fprintf(fpout, "--%s%s", b->boundary,
                        is_closing ? "--":"");
                if (is_closing)
                {
                    pop_mimestack_to(stack, b);
                    find_boundary(stack, iseof,
                                  fpin, fpout, doappend);
                }
                free_header(h);

                init_read_header_context(&rhc);
                continue; /* From the top */
            }
        }
        read_header(&rhc, buf);
    }

    return (finish_header(&rhc));
}
Example #16
0
static void dodecrypt(struct mimestack **stack, int *iseof,
                      FILE *fpin, FILE *fpout, int argc, char **argv,
                      const char *temp_file, FILE *realout)
{
    struct gpgmime_forkinfo gpg;
    char buf[BUFSIZ];
    int is_closing;
    struct mimestack *b=NULL;
    int dowrite=1;
    int rc;
    const char *new_boundary;
    const char *output;

    if (gpgmime_forkdecrypt(NULL, argc, argv, &dumpdecrypt, fpout, &gpg))
    {
        perror("fork");
        exit(1);
    }

    for (;;)
    {
        if (fgets(buf, sizeof(buf), fpin) == NULL)
        {
            *iseof=1;
            break;
        }

        if (dowrite)
            gpgmime_write(&gpg, buf, strlen(buf));

        if (!(b=is_boundary(*stack, buf, &is_closing)))
            continue;
        dowrite=0;
        if (!is_closing)
            continue;
        break;
    }

    rc=gpgmime_finish(&gpg);
    if (fflush(fpout) || ferror(fpout) || my_rewind(fpout) < 0)
    {
        perror(temp_file);
        fclose(fpout);
        unlink(temp_file);
        exit(1);
    }

    if (*iseof)
        return;

    output=gpgmime_getoutput(&gpg),

    new_boundary=get_boundary(*stack, output, rc ? NULL:fpout);

    open_result_multipart(realout, rc, new_boundary,
                          output,
                          gpgmime_getcharset(&gpg));

    if (rc == 0)
    {
        int c;

        if (fseek(fpout, 0L, SEEK_SET) < 0)
        {
            perror(temp_file);
            fclose(fpout);
            unlink(temp_file);
            exit(1);
        }

        fprintf(realout, "\n--%s\n", new_boundary);

        while ((c=getc(fpout)) != EOF)
            if (c != '\r')
                putc(c, realout);
    }

    fprintf(realout, "\n--%s--\n", new_boundary);
    pop_mimestack_to(stack, b);
}
Example #17
0
void * motor_thread(void * arg)
{
	int iret;
	int a_bound=0,b_bound=0;
	unsigned char low_gpio[4]={0,0,0,0};
	unsigned char (*ptr)[4], *p;
	unsigned int	a_step_delay=0, b_step_delay=0;
	ptr = step_data;
	while(run_motor_thread)
	{

		set_step_motor(low_gpio,a_motor.gpio);
		set_step_motor( low_gpio,b_motor.gpio);
		iret = pthread_cond_wait(&motor_update,&motion_mutex);
		autostop_counter = 0;
		
		while ((a_motor.state != MOTOR_STOP || b_motor.state != MOTOR_STOP) && (autostop_counter < AUTOSTOP_COUNTER))
		{
			if(a_motor.state != MOTOR_STOP && a_step_delay ==0)
			{	
			
				if(is_boundary(a_motor.gpio[4]))
				{	
``````````````````````````````a_bound +=a_motor.state;
					if(a_bound > BOUNDARY_DETECT_NUM || a_bound < -BOUNDARY_DETECT_NUM)
					{
						a_motor.last_bound = a_motor.state;
						a_motor.state = MOTOR_STOP;
						a_bound = 0;
						printf("A motor boundary\n");
					}

				}
				
				set_index(&(a_motor.data_index), a_motor.state);
				set_index(&(a_motor.data_index), a_motor.state);

				p = *( ptr+ a_motor.data_index);
				set_step_motor(p,a_motor.gpio);				
			
				a_step_delay = a_motor.step_delay;
			}
			
			if(b_motor.state != MOTOR_STOP && b_step_delay == 0)
			{
				if(is_boundary(b_motor.gpio[4]))
				{
b_bound +=b_motor.state;
					if(b_bound > BOUNDARY_DETECT_NUM || b_bound < -BOUNDARY_DETECT_NUM)
					{
						b_motor.last_bound = b_motor.state;
						b_motor.state = MOTOR_STOP;
						b_bound =0;
						printf("B motor boundary\n");
					}
				}
				set_index(&(b_motor.data_index), b_motor.state);
				p=*(ptr+b_motor.data_index);
				set_step_motor( p,b_motor.gpio);				
				
				b_step_delay = b_motor.step_delay;
			}
			
			exit_motion:
				usleep(QUATUM_DLAY_STEP_MOTOR);
				autostop_counter++;
				if (autostop_counter >= AUTOSTOP_COUNTER)
				{

				}
				if(a_step_delay)
					a_step_delay--;
				if(b_step_delay)
					b_step_delay--;
		}
	}

	pthread_exit(NULL);
}
static apr_status_t upload_filter(ap_filter_t *f, apr_bucket_brigade *bbout,
	ap_input_mode_t mode, apr_read_type_e block, apr_off_t nbytes) {

  char* buf = 0 ;
  char* p = buf ;
  char* e ;
 
  int ret = APR_SUCCESS ;
 
  apr_size_t bytes = 0 ;
  apr_bucket* b ;
  apr_bucket_brigade* bbin ;
 
  upload_ctx* ctx = (upload_ctx*) f->ctx ;
  if ( ctx->parse_state == p_done ) {
    // send an EOS
    APR_BRIGADE_INSERT_TAIL(bbout, apr_bucket_eos_create(bbout->bucket_alloc) ) ;
    return APR_SUCCESS ;
  }

  /* should be more efficient to do this in-place without resorting
   * to a new brigade
   */
  bbin = apr_brigade_create(f->r->pool, f->r->connection->bucket_alloc) ;

  if ( ret = ap_get_brigade(f->next, bbin, mode, block, nbytes) ,
	ret != APR_SUCCESS )
     return ret ;


  for ( b = APR_BRIGADE_FIRST(bbin) ;
	b != APR_BRIGADE_SENTINEL(bbin) ;
	b = APR_BUCKET_NEXT(b) ) {
    const char* ptr = buf ;
    if ( APR_BUCKET_IS_EOS(b) ) {
      ctx->parse_state = p_done ;
      APR_BRIGADE_INSERT_TAIL(bbout,
	 apr_bucket_eos_create(bbout->bucket_alloc) ) ;
      apr_brigade_destroy(bbin) ;
      return APR_SUCCESS ;
    } else if ( apr_bucket_read(b, &ptr, &bytes, APR_BLOCK_READ)
		== APR_SUCCESS ) {
      const char* p = ptr ;
      while ( e = strchr(p, '\n'), ( e && ( e < (ptr+bytes) ) ) ) {
	const char* ptmp = p ;
	*e = 0 ;
	if ( ctx->leftover ) {
		// this'll be grossly inefficient if we get lots of
		// little buckets (we don't in my setup:-)
	  ptmp = apr_pstrcat(f->r->pool, ctx->leftover, p, NULL) ;
	  ctx->leftover = 0 ;
	}
	switch ( ctx->parse_state ) {
	  case p_none:
	    if ( is_boundary(ctx, ptmp) == boundary_part )
	      ctx->parse_state = p_head ;
	    break ;
	  case p_head:
	    if ( (! *ptmp) || ( *ptmp == '\r') )
	      ctx->parse_state = p_field ;
	    else
	      set_header(ctx, ptmp) ;
	    break ;
	  case p_field:
	    switch ( is_boundary(ctx, ptmp) ) {
	      case boundary_part:
		end_body(ctx) ;
		ctx->parse_state = p_head ;
		break ;
	      case boundary_end:
		end_body(ctx) ;
		ctx->parse_state = p_end ;
		break ;
	      case boundary_none:
		if ( ctx->is_file ) {
		  apr_brigade_puts(bbout, ap_filter_flush, f, ptmp) ;
		  apr_brigade_putc(bbout, ap_filter_flush, f, '\n') ;
		} else
		  set_body(ctx, ptmp) ;
		break ;
	    }
	    break ;
	  case p_end:
	    //APR_BRIGADE_INSERT_TAIL(bbout,
	//	apr_bucket_eos_create(bbout->bucket_alloc) ) ;
	    ctx->parse_state = p_done ;
	  case p_done:
	    break ;
	}
	if ( e - ptr >= bytes )
	  break ;
	p = e + 1 ;
      }
      if ( ( ctx->parse_state != p_end ) && ( ctx->parse_state != p_done ) ) {
	size_t bleft = bytes - (p-ptr) ;
	ctx->leftover = apr_pstrndup(f->r->pool, p, bleft ) ;
#ifdef DEBUG
  ap_log_rerror(APLOG_MARK,APLOG_DEBUG,0, f->r, "leftover %d bytes\n\t%s\n\t%s\n", bleft, ctx->leftover, p) ;
#endif
      }
    }
  }
  apr_brigade_destroy(bbin) ;
  return ret ;
}
Example #19
0
void
Surface_mesh::
split(Edge e, Vertex v)
{
    Halfedge h0 = halfedge(e, 0);
    Halfedge o0 = halfedge(e, 1);

    Vertex   v2 = to_vertex(o0);

    Halfedge e1 = new_edge(v, v2);
    Halfedge t1 = opposite_halfedge(e1);

    Face     f0 = face(h0);
    Face     f3 = face(o0);

    set_halfedge(v, h0);
    set_vertex(o0, v);

    if (!is_boundary(h0))
    {
        Halfedge h1 = next_halfedge(h0);
        Halfedge h2 = next_halfedge(h1);

        Vertex   v1 = to_vertex(h1);

        Halfedge e0 = new_edge(v, v1);
        Halfedge t0 = opposite_halfedge(e0);

        Face f1 = new_face();
        set_halfedge(f0, h0);
        set_halfedge(f1, h2);

        set_face(h1, f0);
        set_face(t0, f0);
        set_face(h0, f0);

        set_face(h2, f1);
        set_face(t1, f1);
        set_face(e0, f1);

        set_next_halfedge(h0, h1);
        set_next_halfedge(h1, t0);
        set_next_halfedge(t0, h0);

        set_next_halfedge(e0, h2);
        set_next_halfedge(h2, t1);
        set_next_halfedge(t1, e0);
    }
    else
    {
        set_next_halfedge(prev_halfedge(h0), t1);
        set_next_halfedge(t1, h0);
        // halfedge handle of _vh already is h0
    }


    if (!is_boundary(o0))
    {
        Halfedge o1 = next_halfedge(o0);
        Halfedge o2 = next_halfedge(o1);

        Vertex v3 = to_vertex(o1);

        Halfedge e2 = new_edge(v, v3);
        Halfedge t2 = opposite_halfedge(e2);

        Face f2 = new_face();
        set_halfedge(f2, o1);
        set_halfedge(f3, o0);

        set_face(o1, f2);
        set_face(t2, f2);
        set_face(e1, f2);

        set_face(o2, f3);
        set_face(o0, f3);
        set_face(e2, f3);

        set_next_halfedge(e1, o1);
        set_next_halfedge(o1, t2);
        set_next_halfedge(t2, e1);

        set_next_halfedge(o0, e2);
        set_next_halfedge(e2, o2);
        set_next_halfedge(o2, o0);
    }
    else
    {
        set_next_halfedge(e1, next_halfedge(o0));
        set_next_halfedge(o0, e1);
        set_halfedge(v, e1);
    }

    if (halfedge(v2) == h0)
        set_halfedge(v2, t1);
}
Example #20
0
void go_computer()
{
	int i;
	int oldx = computer.x;
    int	oldy = computer.y;
	Location buf[6];

	if(is_boundary(computer))
		who_win(COMPUTER);

	if(is_inCircle(computer)) {
		i = max_cost(computer);
		inCircle = 1;
	}
	else 
		i = min_path(computer);

	switch(i) {
		case 0:
			computer.y--;
			break;
		case 1:
			if((computer.x % 2) == 0) {
				computer.x--;
				computer.y--;
			}
			else {
				computer.x--;
			}
			break;
		case 2:
			if((computer.x % 2) == 0) {
				computer.x--;				
			}
			else {
				computer.x--;
				computer.y++;
			}
			break;			
		case 3:
			computer.y++;
			break;
		case 4:
			if((computer.x % 2) == 0) {
				computer.x++;
			}
			else {
				computer.x++;
				computer.y++;
			}
			break;
		case 5:
			if((computer.x % 2) == 0) {
				computer.x++;
				computer.y--;
			}
			else {
				computer.x++;
			}
			break;
	} //end switch

	if((oldx % 2) == 0)
		move(oldx, oldy*2);
	else
		move(oldx, oldy*2+1);
	draw_one(WAY);
	map[oldx][oldy].type = WAY;

	if((computer.x % 2) == 0)
		move(computer.x, computer.y*2);
	else
		move(computer.x, computer.y*2+1);
	draw_one(CAT);
	map[computer.x][computer.y].type = CAT;
}
Example #21
0
Surface_mesh::Face
Surface_mesh::
add_face(const std::vector<Vertex>& vertices)
{
    Vertex                   v;
    unsigned int             i, ii, n((int)vertices.size()), id;
    std::vector<Halfedge>    halfedges(n);
    std::vector<bool>        is_new(n), needs_adjust(n, false);
    Halfedge                 inner_next, inner_prev,
    outer_next, outer_prev,
    boundary_next, boundary_prev,
    patch_start, patch_end;

    // cache for set_next_halfedge and vertex' set_halfedge
    typedef std::pair<Halfedge, Halfedge>  NextCacheEntry;
    typedef std::vector<NextCacheEntry>    NextCache;

    NextCache    next_cache;
    next_cache.reserve(3*n);


    // don't allow degenerated faces
    assert (n > 2);


    // test for topological errors
    for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
    {
        if ( !is_boundary(vertices[i]) )
        {
            std::cerr << "Surface_meshT::add_face: complex vertex\n";
            return Face();
        }

        halfedges[i] = find_halfedge(vertices[i], vertices[ii]);
        is_new[i]    = !halfedges[i].is_valid();

        if (!is_new[i] && !is_boundary(halfedges[i]))
        {
            std::cerr << "Surface_meshT::add_face: complex edge\n";
            return Face();
        }
    }


    // re-link patches if necessary
    for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
    {
        if (!is_new[i] && !is_new[ii])
        {
            inner_prev = halfedges[i];
            inner_next = halfedges[ii];

            if (next_halfedge(inner_prev) != inner_next)
            {
                // here comes the ugly part... we have to relink a whole patch

                // search a free gap
                // free gap will be between boundary_prev and boundary_next
                outer_prev = opposite_halfedge(inner_next);
                outer_next = opposite_halfedge(inner_prev);
                boundary_prev = outer_prev;
                do
                    boundary_prev = opposite_halfedge(next_halfedge(boundary_prev));
                while (!is_boundary(boundary_prev) || boundary_prev==inner_prev);
                boundary_next = next_halfedge(boundary_prev);
                assert(is_boundary(boundary_prev));
                assert(is_boundary(boundary_next));


                // ok ?
                if (boundary_next == inner_next)
                {
                    std::cerr << "Surface_meshT::add_face: patch re-linking failed\n";
                    return Face();
                }

                // other halfedges' handles
                patch_start = next_halfedge(inner_prev);
                patch_end   = prev_halfedge(inner_next);

                // relink
                next_cache.push_back(NextCacheEntry(boundary_prev, patch_start));
                next_cache.push_back(NextCacheEntry(patch_end, boundary_next));
                next_cache.push_back(NextCacheEntry(inner_prev, inner_next));
            }
        }
    }



    // create missing edges
    for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
        if (is_new[i])
            halfedges[i] = new_edge(vertices[i], vertices[ii]);



    // create the face
    Face f(new_face());
    set_halfedge(f, halfedges[n-1]);



    // setup halfedges
    for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
    {
        v          = vertices[ii];
        inner_prev = halfedges[i];
        inner_next = halfedges[ii];

        id = 0;
        if (is_new[i])  id |= 1;
        if (is_new[ii]) id |= 2;

        if (id)
        {
            outer_prev = opposite_halfedge(inner_next);
            outer_next = opposite_halfedge(inner_prev);

            // set outer links
            switch (id)
            {
                case 1: // prev is new, next is old
                    boundary_prev = prev_halfedge(inner_next);
                    next_cache.push_back(NextCacheEntry(boundary_prev, outer_next));
                    set_halfedge(v, outer_next);
                    break;

                case 2: // next is new, prev is old
                    boundary_next = next_halfedge(inner_prev);
                    next_cache.push_back(NextCacheEntry(outer_prev, boundary_next));
                    set_halfedge(v, boundary_next);
                    break;

                case 3: // both are new
                    if (!halfedge(v).is_valid())
                    {
                        set_halfedge(v, outer_next);
                        next_cache.push_back(NextCacheEntry(outer_prev, outer_next));
                    }
                    else
                    {
                        boundary_next = halfedge(v);
                        boundary_prev = prev_halfedge(boundary_next);
                        next_cache.push_back(NextCacheEntry(boundary_prev, outer_next));
                        next_cache.push_back(NextCacheEntry(outer_prev, boundary_next));
                    }
                    break;
            }

            // set inner link
            next_cache.push_back(NextCacheEntry(inner_prev, inner_next));
        }
        else needs_adjust[ii] = (halfedge(v) == inner_next);


        // set face handle
        set_face(halfedges[i], f);
    }



    // process next halfedge cache
    NextCache::const_iterator ncIt(next_cache.begin()), ncEnd(next_cache.end());
    for (; ncIt != ncEnd; ++ncIt)
        set_next_halfedge(ncIt->first, ncIt->second);



    // adjust vertices' halfedge handle
    for (i=0; i<n; ++i)
        if (needs_adjust[i])
            adjust_outgoing_halfedge(vertices[i]);


    return f;
}
Example #22
0
// Delaunay retriangulate a triangle fan
static void chew_fan(MutableTriangleTopology& parent_mesh, RawField<const Perturbed2,VertexId> X,
                     const VertexId u, RawArray<HalfedgeId> fan, Random& random) {
  chew_fan_count_ += 1;
#ifndef NDEBUG
  for (const auto e : fan)
    assert(parent_mesh.opposite(e)==u);
  for (int i=0;i<fan.size()-1;i++)
    GEODE_ASSERT(parent_mesh.src(fan[i])==parent_mesh.dst(fan[i+1]));
#endif
  const int n = fan.size();
  if (n < 2)
    return;
  chew_fan_count_ += 1024*n;

  // Collect vertices
  const Field<VertexId,VertexId> vertices(n+2,uninit);
  vertices.flat[0] = u;
  vertices.flat[1] = parent_mesh.src(fan[n-1]);
  for (int i=0;i<n;i++)
    vertices.flat[i+2] = parent_mesh.dst(fan[n-1-i]);

  // Delete original vertices
  for (const auto e : fan)
    parent_mesh.erase(parent_mesh.face(e));

  // Make the vertices into a doubly linked list
  const Field<VertexId,VertexId> prev(n+2,uninit),
                                 next(n+2,uninit);
  prev.flat[0].id = n+1;
  next.flat[n+1].id = 0;
  for (int i=0;i<n+1;i++) {
    prev.flat[i+1].id = i;
    next.flat[i].id = i+1;
  }

  // Randomly shuffle the vertices, then pulling elements off the linked list in reverse order of our final shuffle.
  const Array<VertexId> pi(n+2,uninit);
  for (int i=0;i<n+2;i++)
    pi[i].id = i;
  random.shuffle(pi);
  for (int i=n+1;i>=0;i--) {
    const auto j = pi[i];
    prev[next[j]] = prev[j];
    next[prev[j]] = next[j];
  }

  // Make a new singleton mesh
  const auto mesh = new_<MutableTriangleTopology>();
  mesh->add_vertices(n+2);
  small_sort(pi[0],pi[1],pi[2]);
  mesh->add_face(vec(pi[0],pi[1],pi[2]));

  // Insert remaining vertices
  Array<HalfedgeId> work;
  for (int i=3;i<n+2;i++) {
    const auto j = pi[i];
    const auto f = mesh->add_face(vec(j,next[j],prev[j]));
    work.append(mesh->reverse(mesh->opposite(f,j)));
    while (work.size()) {
      auto e = work.pop();
      if (   !mesh->is_boundary(e)
          && incircle(X[vertices[mesh->src(e)]],
                      X[vertices[mesh->dst(e)]],
                      X[vertices[mesh->opposite(e)]],
                      X[vertices[mesh->opposite(mesh->reverse(e))]])) {
        work.append(mesh->reverse(mesh->next(e)));
        work.append(mesh->reverse(mesh->prev(e)));
        e = mesh->unsafe_flip_edge(e);
      }
    }
  }

  // Copy triangles back to parent
  for (const auto f : mesh->faces()) {
    const auto vs = mesh->vertices(f);
    parent_mesh.add_face(vec(vertices[vs.x],vertices[vs.y],vertices[vs.z]));
  }
}
Example #23
0
void
Surface_mesh::
garbage_collection()
{
    if (!garbage_) return;

    int  i, i0, i1,
    nV(vertices_size()),
    nE(edges_size()),
    nH(halfedges_size()),
    nF(faces_size());

    Vertex    v;
    Halfedge  h;
    Face      f;

    if (!vdeleted_) vdeleted_ = vertex_property<bool>("v:deleted", false);
    if (!edeleted_) edeleted_ = edge_property<bool>("e:deleted", false);
    if (!fdeleted_) fdeleted_ = face_property<bool>("f:deleted", false);


    // setup handle mapping
    Vertex_property<Vertex>      vmap = add_vertex_property<Vertex>("v:garbage-collection");
    Halfedge_property<Halfedge>  hmap = add_halfedge_property<Halfedge>("h:garbage-collection");
    Face_property<Face>          fmap = add_face_property<Face>("f:garbage-collection");
    for (i=0; i<nV; ++i)
        vmap[Vertex(i)] = Vertex(i);
    for (i=0; i<nH; ++i)
        hmap[Halfedge(i)] = Halfedge(i);
    for (i=0; i<nF; ++i)
        fmap[Face(i)] = Face(i);



    // remove deleted vertices
    if (nV > 0)
    {
        i0=0;  i1=nV-1;

        while (1)
        {
            // find first deleted and last un-deleted
            while (!vdeleted_[Vertex(i0)] && i0 < i1)  ++i0;
            while ( vdeleted_[Vertex(i1)] && i0 < i1)  --i1;
            if (i0 >= i1) break;

            // swap
            vprops_.swap(i0, i1);

            //add
            for(unsigned int j = 0;j<map_2skel.size();j++)
            {
                if(map_2skel[j] == i0)
                    map_2skel[j] = i1;
                else if(map_2skel[j] == i1)
                    map_2skel[j] = i0;
            }
            //end
        };

        // remember new size
        nV = vdeleted_[Vertex(i0)] ? i0 : i0+1;
    }


    // remove deleted edges
    if (nE > 0)
    {
        i0=0;  i1=nE-1;

        while (1)
        {
            // find first deleted and last un-deleted
            while (!edeleted_[Edge(i0)] && i0 < i1)  ++i0;
            while ( edeleted_[Edge(i1)] && i0 < i1)  --i1;
            if (i0 >= i1) break;

            // swap
            eprops_.swap(i0, i1);
            hprops_.swap(2*i0,   2*i1);
            hprops_.swap(2*i0+1, 2*i1+1);
        };

        // remember new size
        nE = edeleted_[Edge(i0)] ? i0 : i0+1;
        nH = 2*nE;
    }


    // remove deleted faces
    if (nF > 0)
    {
        i0=0;  i1=nF-1;

        while (1)
        {
            // find 1st deleted and last un-deleted
            while (!fdeleted_[Face(i0)] && i0 < i1)  ++i0;
            while ( fdeleted_[Face(i1)] && i0 < i1)  --i1;
            if (i0 >= i1) break;

            // swap
            fprops_.swap(i0, i1);
        };

        // remember new size
        nF = fdeleted_[Face(i0)] ? i0 : i0+1;
    }


    // update vertex connectivity
    for (i=0; i<nV; ++i)
    {
        v = Vertex(i);
        if (!is_isolated(v))
            set_halfedge(v, hmap[halfedge(v)]);
    }


    // update halfedge connectivity
    for (i=0; i<nH; ++i)
    {
        h = Halfedge(i);
        set_vertex(h, vmap[to_vertex(h)]);
        set_next_halfedge(h, hmap[next_halfedge(h)]);
        if (!is_boundary(h))
            set_face(h, fmap[face(h)]);
    }


    // update handles of faces
    for (i=0; i<nF; ++i)
    {
        f = Face(i);
        set_halfedge(f, hmap[halfedge(f)]);
    }


    // remove handle maps
    remove_vertex_property(vmap);
    remove_halfedge_property(hmap);
    remove_face_property(fmap);


    // finally resize arrays
    vprops_.resize(nV); vprops_.free_memory();
    hprops_.resize(nH); hprops_.free_memory();
    eprops_.resize(nE); eprops_.free_memory();
    fprops_.resize(nF); fprops_.free_memory();

    deleted_vertices_ = deleted_edges_ = deleted_faces_ = 0;
    garbage_ = false;
}