Logo Search packages:      
Sourcecode: zinnia version File versions

character.cpp

//
//  Zinnia: Online hand recognition system with machine learning
//
//  $Id: character.cpp 12 2009-03-08 02:03:17Z taku-ku $;
//
//  Copyright(C) 2008 Taku Kudo <taku@chasen.org>
//
#include <cmath>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <cctype>
#include "common.h"
#include "zinnia.h"
#include "sexp.h"
#include "scoped_ptr.h"

namespace zinnia {

  class CharacterImpl: public Character {
  public:
    void set_value(const char *str) {
      value_.assign(str, std::strlen(str));
    }

    void set_value(const char *str, size_t length) {
      value_.assign(str, length);
    }

    const char *value() const {
      return value_.c_str();
    }

    void set_width(size_t width) {
      width_ = width;
    }

    void set_height(size_t height) {
      height_ = height;
    }

    size_t width() const { return width_; }
    size_t height() const { return height_; }
    void clear() { strokes_.clear(); }
    bool add(size_t id, int x, int y);

    size_t strokes_size() const {
      return strokes_.size();
    }

    size_t stroke_size(size_t id) const {
      return (strokes_.size() <= id) ?
        static_cast<size_t>(-1) : strokes_[id].size();
    }

    int x(size_t id, size_t i) const {
      return (id >= strokes_.size() || i >= strokes_[id].size()) ?
        -1 : strokes_[id][i].x;
    }

    int y(size_t id, size_t i) const {
      return (id >= strokes_.size() || i >= strokes_[id].size()) ?
        -1 : strokes_[id][i].y;
    }

    bool parse(const char *str, size_t length);

    bool parse(const char *str) {
      return parse(str, std::strlen(str));
    }

    bool toString(char *buf, size_t length) const;

    const char *what() { return what_.str(); }

    CharacterImpl(): width_(300), height_(300) {}
    virtual ~CharacterImpl() { clear(); }

  private:
    struct Dot {
      int x;
      int y;
    };
    std::vector<std::vector<Dot> > strokes_;
    std::string value_;
    size_t width_;
    size_t height_;
    whatlog what_;
    scoped_ptr<Sexp> sexp_;
  };

  bool CharacterImpl::add(size_t id, int x, int y) {
    strokes_.resize(id + 1);
    Dot d;
    d.x = x;
    d.y = y;
    strokes_[id].push_back(d);
    return true;
  }

  // parse S-expression
  // (character
  //   (value A)
  //   (width 100)
  //   (height 100)
  //   (strokes ( (0 1) (1 2) ) ( (0 1) (1 2) ) ) )
  bool CharacterImpl::parse(const char *str, size_t length) {
    clear();
    if (!sexp_.get()) {
      sexp_.reset(new Sexp);
    }
    sexp_->free();
    char *begin = const_cast<char *>(str);
    const char *end = str + length;
    const Sexp::Cell *root_cell = sexp_->read(&begin, end);

    if (!root_cell) {
      sexp_->free();
      return false;
    }
    const Sexp::Cell *ccel = root_cell->car();
    if (!ccel->is_atom() || std::strcmp("character", ccel->atom()) != 0) {
      sexp_->free();
      return false;
    }

    for (const Sexp::Cell *it = root_cell->cdr(); it; it = it->cdr()) {
      const Sexp::Cell *cell= it->car();
      if (cell->car() && cell->car()->is_atom() &&
          cell->cdr() && cell->cdr()->car() &&
          cell->cdr()->car()->is_atom()) {
        const char *name = cell->car()->atom();
        const char *value = cell->cdr()->car()->atom();
        if (std::strcmp("value", name) == 0) {
          set_value(value);
        } else if (std::strcmp("width", name) == 0) {
          set_width(std::atoi(value));
        } else if (std::strcmp("height", name) == 0)  {
          set_height(std::atoi(value));
        }
      }

      if (cell->car() && cell->car()->is_atom() &&
          cell->cdr() && cell->cdr()->car() &&
          cell->cdr()->car()->is_cons() &&
          std::strcmp("strokes", cell->car()->atom()) == 0) {
        int id = 0;
        for (const Sexp::Cell *st = cell->cdr(); st; st = st->cdr()) {
          for (const Sexp::Cell *dot = st->car(); dot; dot = dot->cdr()) {
            if (dot->car() && dot->car()->car() &&
                dot->car()->car()->is_atom() &&
                dot->car()->cdr() &&
                dot->car()->cdr()->car() &&
                dot->car()->cdr()->car()->is_atom()) {
              const int x = std::atoi(dot->car()->car()->atom());
              const int y = std::atoi(dot->car()->cdr()->car()->atom());
              add(id, x, y);
            }
          }
          ++id;
        }
      }
    }

    return true;
  }

  bool CharacterImpl::toString(char *str, size_t length) const {
    std::ostringstream os;
    os << "(character (value " << value() << ")";
    os << "(width " << width() << ")";
    os << "(height " << height() << ")";
    os << "(stroeks ";
    for (size_t id = 0; id < strokes_size(); ++id) {
      os << "(";
      for (size_t s = 0; s < stroke_size(id); ++s) {
        os << "(" << x(id, s) << " " << y(id, s) << ")";
      }
      os << ")";
    }
    os << ")";
    const std::string &buf = os.str();
    if (buf.size() < length) {
      memcpy(str, buf.data(), buf.size());
      str[buf.size()] = '\0';
    }
    return true;
  }

  Character *Character::create() {
    return new CharacterImpl;
  }

  Character *createCharacter() {
    return new CharacterImpl;
  }
}

Generated by  Doxygen 1.6.0   Back to index