<commit_before>#include <PCU.h>
#include "phRestart.h"
#include <apf.h>
#include "phIO.h"
#include "ph.h"
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <cassert>
#include <cstring>

namespace ph {

/* in_size is the number of dofs for the data array
   and out_size is the number of dofs in the field.
   they are unequal when we read a restart file
   and want to add more dofs for the next restart files */

void attachField(
    apf::Mesh* m,
    const char* fieldname,
    double* data,
    int in_size,
    int out_size)
{
  if (!(in_size <= out_size))
    fprintf(stderr, "field \"%s\" in_size %d out_size %d\n", fieldname, in_size, out_size);
  assert(in_size <= out_size);
  apf::Field* f = apf::createPackedField(m, fieldname, out_size);
  size_t n = m->count(0);
  apf::NewArray<double> c(out_size);
  apf::MeshEntity* e;
  size_t i = 0;
  apf::MeshIterator* it = m->begin(0);
  while ((e = m->iterate(it))) {
    for (int j = 0; j < in_size; ++j)
      c[j] = data[j * n + i];
    apf::setComponents(f, e, 0, &c[0]);
    ++i;
  }
  m->end(it);
  assert(i == n);
}

/* convenience wrapper, in most cases in_size=out_size */
void attachField(
    apf::Mesh* m,
    const char* fieldname,
    double* data,
    int size)
{
  attachField(m, fieldname, data, size, size);
}

void detachField(
    apf::Field* f,
    double*& data,
    int& size)
{
  apf::Mesh* m = apf::getMesh(f);
  size = apf::countComponents(f);
  size_t n = m->count(0);
  apf::NewArray<double> c(size);
  data = (double*)malloc(sizeof(double) * size * m->count(0));
  apf::MeshEntity* e;
  size_t i = 0;
  apf::MeshIterator* it = m->begin(0);
  while ((e = m->iterate(it))) {
    apf::getComponents(f, e, 0, &c[0]);
    for (int j = 0; j < size; ++j)
      data[j * n + i] = c[j];
    ++i;
  }
  m->end(it);
  assert(i == n);
  apf::destroyField(f);
}

void detachField(
    apf::Mesh* m,
    const char* fieldname,
    double*& data,
    int& size)
{
  apf::Field* f = m->findField(fieldname);
  assert(f);
  detachField(f, data, size);
}

static bool isNodalField(const char* fieldname, int nnodes, apf::Mesh* m)
{
  static char const* const known_nodal_fields[] = {
    "solution",
    "displacement",
    "dwal",
    "mapping_partid",
    "mapping_vtxid",
    "errors",
    "time derivative of solution"
  };
  static char const* const known_cell_fields[] = {
    "VOF solution",
  };
  int known_nodal_field_count =
    sizeof(known_nodal_fields) / sizeof(known_nodal_fields[0]);
  int known_cell_field_count =
    sizeof(known_cell_fields) / sizeof(known_cell_fields[0]);
  for (int i = 0; i < known_nodal_field_count; ++i)
    if (!strcmp(fieldname, known_nodal_fields[i])) {
      assert(static_cast<size_t>(nnodes) == m->count(0));
      return true;
    }
  for (int i = 0; i < known_cell_field_count; ++i)
    if (!strcmp(fieldname, known_cell_fields[i]))
      return false;
  fprintf(stderr, "unknown restart field name \"%s\"\n", fieldname);
  fprintf(stderr, "please add \"%s\" to isNodalField above line %d of %s\n",
      fieldname, __LINE__, __FILE__);
  if (static_cast<size_t>(nnodes) == m->count(0)) {
    fprintf(stderr, "assuming \"%s\" is a nodal field,\n"
                    "it is the right size...\n", fieldname);
    return true;
  }
  return false;
}

int readAndAttachField(
    Input& in,
    FILE* f,
    apf::Mesh* m,
    int swap)
{
  double* data;
  int nodes, vars, step;
  char hname[1024];
  const char* anyfield = "";
  int ret = ph_read_field(f, anyfield, swap,
      &data, &nodes, &vars, &step, hname);
  /* no field was found or the field has an empty data block */
  if(ret==0 || ret==1)
    return ret;
  if (!isNodalField(hname, nodes, m)) {
    free(data);
    return 1;
  }
  assert(step == in.timeStepNumber);
  int out_size = vars;
  if ( std::string(hname) == std::string("solution") )
    out_size = in.ensa_dof;
  if (m->findField(hname)) {
    if (!PCU_Comm_Self())
      fprintf(stderr, "field \"%s\" listed twice in restart files, ignoring...\n",
          hname);
  } else {
    attachField(m, hname, data, vars, out_size);
  }
  free(data);
  return 1;
}

void detachAndWriteField(
    Input& in,
    apf::Mesh* m,
    FILE* f,
    const char* fieldname)
{
  double* data;
  int size;
  detachField(m, fieldname, data, size);
  ph_write_field(f, fieldname, data, m->count(0), size, in.timeStepNumber);
  free(data);
}

/* silliest darn fields I ever did see */
static double* buildMappingPartId(apf::Mesh* m)
{
  int n = m->count(0);
  /* malloc instead of new[] for consistency with ph_read_field */
  double* data = (double*)malloc(sizeof(double) * n);
  int self = PCU_Comm_Self();
  for (int i = 0; i < n; ++i)
    data[i] = self;
  return data;
}
static double* buildMappingVtxId(apf::Mesh* m)
{
  int n = m->count(0);
  /* malloc instead of new[] for consistency with ph_read_field */
  double* data = (double*)malloc(sizeof(double) * n);
  for (int i = 0; i < n; ++i)
    data[i] = i;
  return data;
}

static std::string buildRestartFileName(std::string prefix, int step)
{
  std::stringstream ss;
  int rank = PCU_Comm_Self() + 1;
  ss << prefix << '.' << step << '.' << rank;
  return ss.str();
}

void readAndAttachFields(Input& in, apf::Mesh* m) {
  double t0 = PCU_Time();
  setupInputSubdir(in.restartFileName);
  std::string filename = buildRestartFileName(in.restartFileName, in.timeStepNumber);
  FILE* f = in.openfile_read(in, filename.c_str());
  if (!f) {
    fprintf(stderr,"failed to open \"%s\"!\n", filename.c_str());
    abort();
  }
  int swap = ph_should_swap(f);
  /* stops when ph_read_field returns 0 */
  while( readAndAttachField(in,f,m,swap) );
  fclose(f);
  double t1 = PCU_Time();
  if (!PCU_Comm_Self())
    printf("fields read and attached in %f seconds\n", t1 - t0);
}

void buildMapping(apf::Mesh* m)
{
  double* mapping = buildMappingPartId(m);
  attachField(m, "mapping_partid", mapping, 1);
  free(mapping);
  mapping = buildMappingVtxId(m);
  attachField(m, "mapping_vtxid", mapping, 1);
  free(mapping);
}

void attachZeroSolution(Input& in, apf::Mesh* m)
{
  int vars = in.ensa_dof;
  int nodes = m->count(0);
  double* data = new double[nodes * vars]();
  attachField(m, "solution", data, vars);
  delete [] data;
}

void detachAndWriteSolution(Input& in, Output& out, apf::Mesh* m, std::string path)
{
  double t0 = PCU_Time();
  path += buildRestartFileName("restart", in.timeStepNumber);
  FILE* f = out.openfile_write(out, path.c_str());
  if (!f) {
    fprintf(stderr,"failed to open \"%s\"!\n", path.c_str());
    abort();
  }
  ph_write_preamble(f);
  int nodes = m->count(0);
  ph_write_header(f, "number of modes", 0, 1, &nodes);
  ph_write_header(f, "number of variables", 0, 1, &in.ensa_dof);
  apf::Field* errField = m->findField("errors");
  if (errField)
    apf::destroyField(errField);
  if (m->findField("solution"))
    detachAndWriteField(in, m, f, "solution");
  if (in.displacementMigration)
    detachAndWriteField(in, m, f, "displacement");
  if (in.dwalMigration)
    detachAndWriteField(in, m, f, "dwal");
  if (in.buildMapping) {
    detachAndWriteField(in, m, f, "mapping_partid");
    detachAndWriteField(in, m, f, "mapping_vtxid");
  }
  /* detach any remaining fields */
  while(m->countFields())
    apf::destroyField( m->getField(0) );
  fclose(f);
  double t1 = PCU_Time();
  if (!PCU_Comm_Self())
    printf("solution written in %f seconds\n", t1 - t0);
}

}
<commit_msg>Try to fix #22<commit_after>#include <PCU.h>
#include "phRestart.h"
#include <apf.h>
#include "phIO.h"
#include "ph.h"
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <cassert>
#include <cstring>

namespace ph {

/* in_size is the number of dofs for the data array
   and out_size is the number of dofs in the field.
   they are unequal when we read a restart file
   and want to add more dofs for the next restart files */

void attachField(
    apf::Mesh* m,
    const char* fieldname,
    double* data,
    int in_size,
    int out_size)
{
  if (!(in_size <= out_size))
    fprintf(stderr, "field \"%s\" in_size %d out_size %d\n", fieldname, in_size, out_size);
  assert(in_size <= out_size);
  apf::Field* f = apf::createPackedField(m, fieldname, out_size);
  size_t n = m->count(0);
  apf::NewArray<double> c(out_size);
  apf::MeshEntity* e;
  size_t i = 0;
  apf::MeshIterator* it = m->begin(0);
  while ((e = m->iterate(it))) {
    for (int j = 0; j < in_size; ++j)
      c[j] = data[j * n + i];
    apf::setComponents(f, e, 0, &c[0]);
    ++i;
  }
  m->end(it);
  assert(i == n);
}

/* convenience wrapper, in most cases in_size=out_size */
void attachField(
    apf::Mesh* m,
    const char* fieldname,
    double* data,
    int size)
{
  attachField(m, fieldname, data, size, size);
}

void detachField(
    apf::Field* f,
    double*& data,
    int& size)
{
  apf::Mesh* m = apf::getMesh(f);
  size = apf::countComponents(f);
  size_t n = m->count(0);
  apf::NewArray<double> c(size);
  data = (double*)malloc(sizeof(double) * size * m->count(0));
  apf::MeshEntity* e;
  size_t i = 0;
  apf::MeshIterator* it = m->begin(0);
  while ((e = m->iterate(it))) {
    apf::getComponents(f, e, 0, &c[0]);
    for (int j = 0; j < size; ++j)
      data[j * n + i] = c[j];
    ++i;
  }
  m->end(it);
  assert(i == n);
  apf::destroyField(f);
}

void detachField(
    apf::Mesh* m,
    const char* fieldname,
    double*& data,
    int& size)
{
  apf::Field* f = m->findField(fieldname);
  assert(f);
  detachField(f, data, size);
}

static bool isNodalField(const char* fieldname, int nnodes, apf::Mesh* m)
{
  static char const* const known_nodal_fields[] = {
    "solution",
    "displacement",
    "dwal",
    "mapping_partid",
    "mapping_vtxid",
    "errors",
    "time derivative of solution"
  };
  static char const* const known_cell_fields[] = {
    "VOF solution",
  };
  int known_nodal_field_count =
    sizeof(known_nodal_fields) / sizeof(known_nodal_fields[0]);
  int known_cell_field_count =
    sizeof(known_cell_fields) / sizeof(known_cell_fields[0]);
  for (int i = 0; i < known_nodal_field_count; ++i)
    if (!strcmp(fieldname, known_nodal_fields[i])) {
      assert(static_cast<size_t>(nnodes) == m->count(0));
      return true;
    }
  for (int i = 0; i < known_cell_field_count; ++i)
    if (!strcmp(fieldname, known_cell_fields[i]))
      return false;
  fprintf(stderr, "unknown restart field name \"%s\"\n", fieldname);
  fprintf(stderr, "please add \"%s\" to isNodalField above line %d of %s\n",
      fieldname, __LINE__, __FILE__);
  if (static_cast<size_t>(nnodes) == m->count(0)) {
    fprintf(stderr, "assuming \"%s\" is a nodal field,\n"
                    "it is the right size...\n", fieldname);
    return true;
  }
  return false;
}

int readAndAttachField(
    Input& in,
    FILE* f,
    apf::Mesh* m,
    int swap)
{
  double* data;
  int nodes, vars, step;
  char hname[1024];
  const char* anyfield = "";
  int ret = ph_read_field(f, anyfield, swap,
      &data, &nodes, &vars, &step, hname);
  /* no field was found or the field has an empty data block */
  if(ret==0 || ret==1)
    return ret;
  if (!isNodalField(hname, nodes, m)) {
    free(data);
    return 1;
  }
  assert(step == in.timeStepNumber);
  int out_size = vars;
  if ( std::string(hname) == std::string("solution") )
    out_size = in.ensa_dof;
  if (m->findField(hname)) {
    if (!PCU_Comm_Self())
      fprintf(stderr, "field \"%s\" listed twice in restart files, ignoring...\n",
          hname);
  } else {
    attachField(m, hname, data, vars, out_size);
  }
  free(data);
  return 1;
}

void detachAndWriteField(
    Input& in,
    apf::Mesh* m,
    FILE* f,
    const char* fieldname)
{
  double* data;
  int size;
  detachField(m, fieldname, data, size);
  ph_write_field(f, fieldname, data, m->count(0), size, in.timeStepNumber);
  free(data);
}

/* silliest darn fields I ever did see */
static double* buildMappingPartId(apf::Mesh* m)
{
  int n = m->count(0);
  /* malloc instead of new[] for consistency with ph_read_field */
  double* data = (double*)malloc(sizeof(double) * n);
  int self = PCU_Comm_Self();
  for (int i = 0; i < n; ++i)
    data[i] = self;
  return data;
}
static double* buildMappingVtxId(apf::Mesh* m)
{
  int n = m->count(0);
  /* malloc instead of new[] for consistency with ph_read_field */
  double* data = (double*)malloc(sizeof(double) * n);
  for (int i = 0; i < n; ++i)
    data[i] = i;
  return data;
}

static std::string buildRestartFileName(std::string prefix, int step)
{
  std::stringstream ss;
  int rank = PCU_Comm_Self() + 1;
  ss << prefix << '.' << step << '.' << rank;
  return ss.str();
}

void readAndAttachFields(Input& in, apf::Mesh* m) {
  double t0 = PCU_Time();
  setupInputSubdir(in.restartFileName);
  std::string filename = buildRestartFileName(in.restartFileName, in.timeStepNumber);
  FILE* f = in.openfile_read(in, filename.c_str());
  if (!f) {
    fprintf(stderr,"failed to open \"%s\"!\n", filename.c_str());
    abort();
  }
  int swap = ph_should_swap(f);
  /* stops when ph_read_field returns 0 */
  while( readAndAttachField(in,f,m,swap) );
  fclose(f);
  double t1 = PCU_Time();
  if (!PCU_Comm_Self())
    printf("fields read and attached in %f seconds\n", t1 - t0);
}

static void destroyIfExists(apf::Mesh* m, const char* name)
{
  apf::Field* f = m->findField(name);
  if (f)
    apf::destroyField(f);
}

void buildMapping(apf::Mesh* m)
{
  destroyIfExists(m, "mapping_partid");
  double* mapping = buildMappingPartId(m);
  attachField(m, "mapping_partid", mapping, 1);
  free(mapping);
  destroyIfExists(m, "mapping_vtxid");
  mapping = buildMappingVtxId(m);
  attachField(m, "mapping_vtxid", mapping, 1);
  free(mapping);
}

void attachZeroSolution(Input& in, apf::Mesh* m)
{
  int vars = in.ensa_dof;
  int nodes = m->count(0);
  double* data = new double[nodes * vars]();
  attachField(m, "solution", data, vars);
  delete [] data;
}

void detachAndWriteSolution(Input& in, Output& out, apf::Mesh* m, std::string path)
{
  double t0 = PCU_Time();
  path += buildRestartFileName("restart", in.timeStepNumber);
  FILE* f = out.openfile_write(out, path.c_str());
  if (!f) {
    fprintf(stderr,"failed to open \"%s\"!\n", path.c_str());
    abort();
  }
  ph_write_preamble(f);
  int nodes = m->count(0);
  ph_write_header(f, "number of modes", 0, 1, &nodes);
  ph_write_header(f, "number of variables", 0, 1, &in.ensa_dof);
  apf::Field* errField = m->findField("errors");
  if (errField)
    apf::destroyField(errField);
  if (m->findField("solution"))
    detachAndWriteField(in, m, f, "solution");
  if (in.displacementMigration)
    detachAndWriteField(in, m, f, "displacement");
  if (in.dwalMigration)
    detachAndWriteField(in, m, f, "dwal");
  if (in.buildMapping) {
    detachAndWriteField(in, m, f, "mapping_partid");
    detachAndWriteField(in, m, f, "mapping_vtxid");
  }
  /* detach any remaining fields */
  while(m->countFields())
    apf::destroyField( m->getField(0) );
  fclose(f);
  double t1 = PCU_Time();
  if (!PCU_Comm_Self())
    printf("solution written in %f seconds\n", t1 - t0);
}

}
<|endoftext|>


<commit_before>#include "core/argparse.h"

#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>

#include "core/generator_maze.h"
#include "core/generator_cell.h"
#include "core/random.h"
#include "core/imageops.h"
#include "core/stringutils.h"
#include "core/io.h"
#include "core/knuthshuffle.h"

// later when doing floodfill
// #include "core/colorbrewer.h"

using namespace euphoria::core;

struct Difference
{
    int x;
    int y;
    bool new_value;
};

std::vector<Difference>
FindDifferences(const Table<bool>& src, const Table<bool>& dst)
{
    std::vector<Difference> ret;
    for(int y = 0; y < src.GetHeight(); y += 1)
    {
        for(int x = 0; x < src.GetWidth(); x += 1)
        {
            const auto lhs = src(x, y);
            const auto rhs = dst(x, y);
            if(lhs != rhs)
            {
                ret.push_back({x, y, lhs});
            }
        }
    }
    return ret;
}

void
PrintMazeToConsole(const generator::Drawer& drawer)
{
    const auto table = ImageToStringTable
    (
        drawer.image,
        {
            {'#', drawer.wall_color},
            {'/', drawer.cell_color},
            {' ', drawer.wall_color},
            {' ', drawer.cell_visited_color},
            {'O', drawer.unit_color}
        }
    );

    const auto strings = ToStrings(table);
    for(const auto& s: strings)
    {
        std::cout << s << "\n";
    }
}

enum class MazeAlgorithm
{
    RecursiveBacktracker,
    RandomTraversal
};

void
HandleMazeCommand
(
    MazeAlgorithm algo,
    int world_width,
    int world_height,
    int cell_size,
    int wall_size,
    const std::string& f,
    bool console
)
{
    auto output = argparse::FileOutput {f};
    auto random = Random{};
    auto maze = generator::Maze::FromWidthHeight(world_width, world_height);

    auto drawer = generator::Drawer {};

    std::unique_ptr<generator::Algorithm> gen;

    switch(algo)
    {
    case MazeAlgorithm::RecursiveBacktracker:
        {
            auto g = std::make_unique<generator::RecursiveBacktracker>();
            g->maze = &maze;
            g->random = &random;
            drawer.tracker = g.get();
            gen.reset(g.release());
        }
        break;
    case MazeAlgorithm::RandomTraversal:
        {
            auto g = std::make_unique<generator::RandomTraversal>();
            g->maze = &maze;
            g->random = &random;
            drawer.traversal = g.get();
            gen.reset(g.release());
        }
        break;
    default:
        DIE("Unhandled");
    }

    gen->Setup();

    drawer.maze = &maze;
    drawer.cell_size = cell_size;
    drawer.wall_size = wall_size;

    auto draw_frame = [&]()
    {
        if(!output.single)
        {
            drawer.Draw();
            io::ChunkToFile
            (
                drawer.image.Write(ImageWriteFormat::PNG),
                output.NextFile()
            );
        }
    };

    draw_frame();

    while(gen->HasMoreWork())
    {
        gen->Work();
        draw_frame();
    }

    drawer.Draw();

    if(console)
    {
        PrintMazeToConsole(drawer);
    }
    else
    {
        if(output.single)
        {
            io::ChunkToFile
            (
                drawer.image.Write(ImageWriteFormat::PNG),
                output.file
            );
        }
        else
        {
            for(int i = 0; i < 5; i += 1)
            {
                io::ChunkToFile
                (
                    drawer.image.Write(ImageWriteFormat::PNG),
                    output.NextFile()
                );
            }
        }
    }
}

struct Cellwriter
{
    bool debug;
    argparse::FileOutput output;
    generator::World* world;
    int world_scale;

    Random shuffle_random;
    generator::World world_copy;

    explicit Cellwriter
    (
        bool d,
        const std::string& f,
        generator::World* w,
        int ws
    )
        : debug(d)
        , output{f}
        , world(w)
        , world_scale(ws)
    {
    }

    Image
    GenerateWorldImage(const generator::World& w)
    {
        return Draw(w, Color::Black, Color::White, world_scale);
    }

    void
    FirstState()
    {
        if(!output.single)
        {
            auto img = GenerateWorldImage(*world);
            io::ChunkToFile(img.Write(ImageWriteFormat::PNG), output.NextFile());
        }

        world_copy = *world;
        DrawStep();
    }

    void
    Done()
    {
        if(output.single)
        {
            auto img = GenerateWorldImage(*world);
            io::ChunkToFile(img.Write(ImageWriteFormat::PNG), output.file);
        }
        else
        {
            DrawStep();
        }
    }

    void
    DrawStep()
    {
        if(output.single) { return; }
        if (debug)
        {
            const auto img = GenerateWorldImage(*world);
            io::ChunkToFile
            (
                img.Write(ImageWriteFormat::PNG),
                output.NextFile()
            );
        }
        else
        {
            ShuffleDraw();
        }
    }

    void
    ShuffleDraw()
    {
        auto diffs = FindDifferences(*world, world_copy);
        KnuthShuffle(&diffs, &shuffle_random);
        const auto diffs_per_write = std::max<decltype(diffs.size())>
        (
            2,
            diffs.size() / 25
        );
        int write_index = 0;
        for (const auto d : diffs)
        {
            world_copy(d.x, d.y) = d.new_value;
            if ((write_index % diffs_per_write) == 0)
            {
                const auto img = GenerateWorldImage(world_copy);
                io::ChunkToFile
                (
                    img.Write(ImageWriteFormat::PNG),
                    output.NextFile()
                );
            }
            write_index += 1;
        }

        for (int i = 0; i < 5; i += 1)
        {
            const auto img = GenerateWorldImage(world_copy);
            io::ChunkToFile
            (
                img.Write(ImageWriteFormat::PNG),
                output.NextFile()
            );
        }
    }
};

struct MazeArguments
{
    Sizei size = Sizei::FromWidthHeight(10, 10);
    std::string output = "maze.png";

    int cell_size = 1;
    int wall_size = 1;
    bool console = false;

    void
    Add(argparse::ParserBase* base)
    {
        base->Add("--size", &size).Help("set the size");
        base->Add("-o, --output", &output).Help("specify output");

        base->Add("--cell", &cell_size).Help("set the cell size");
        base->Add("--wall", &wall_size).Help("set the wall size");
        base->SetTrue("-c,--console", &console).Help("foce console");
    }
};

int
main(int argc, char* argv[])
{
    auto parser = argparse::Parser{"Generate worlds"};
    auto sub = parser.AddSubParsers();

    sub->Add
    (
        "recursive",
        "maze generation using recursive backtracker algorithm",
        [&](argparse::SubParser* sub)
        {
            auto args = MazeArguments{};
            args.Add(sub);

            return sub->OnComplete
            (
                [&]
                {
                    HandleMazeCommand
                    (
                        MazeAlgorithm::RecursiveBacktracker,
                        args.size.width,
                        args.size.height,
                        args.cell_size,
                        args.wall_size,
                        args.output,
                        args.console
                    );
                    return argparse::ParseResult::Ok;
                }
            );
        }
    );

    sub->Add
    (
        "random",
        "maze generation using random traversal algorithm",
        [&](argparse::SubParser* sub)
        {
            auto args = MazeArguments{};
            args.Add(sub);

            return sub->OnComplete
            (
                [&]
                {
                    HandleMazeCommand
                    (
                        MazeAlgorithm::RandomTraversal,
                        args.size.width,
                        args.size.height,
                        args.cell_size,
                        args.wall_size,
                        args.output,
                        args.console
                    );
                    return argparse::ParseResult::Ok;
                }
            );
        }
    );

    sub->Add
    (
        "cell",
        "world generation using cellular automata algorithm",
        [&](argparse::SubParser* sub)
        {
            int world_scale = 5;
            Fourway<BorderSetupRule> border_control = Fourway{BorderSetupRule::AlwaysWall};
            float random_fill = 0.5;
            bool debug = false;
            Sizei size = Sizei::FromWidthHeight(100, 70);
            std::string output = "cell.png";

            sub->Add("--size", &size).Help("set the size");
            sub->Add("-o, --output", &output).Help("specify output");
            sub->Add("--scale", &world_scale).Help("set the scale");
            sub->Add("--fill", &random_fill).Help("How much to fill");
            sub->Add("-bc", &border_control)
                .Help("Change how the border is generated")
                ;
            sub->SetTrue("--debug", &debug);

            return sub->OnComplete
            (
                [&]
                {
                    auto random = Random {};

                    auto world = generator::World::FromWidthHeight(size.width, size.height);
                    world.Clear(false);

                    auto rules = generator::Rules{};
                    generator::AddRandomFill(&rules, &random, random_fill, border_control);
                    generator::AddSimpleRules(&rules, 5, 4);

                    auto cell = generator::CellularAutomata{&rules, &world, Fourway{OutsideRule::Wall}};

                    auto writer = Cellwriter{debug, output, &world, world_scale};
                    writer.FirstState();

                    while(cell.HasMoreWork())
                    {
                        cell.Work();
                        writer.DrawStep();
                    }

                    writer.Done();

                    return argparse::ParseResult::Ok;
                }
            );
        }
    );

    return argparse::ParseFromMain(&parser, argc, argv);
}

<commit_msg>rules are now specifed as commands<commit_after>#include "core/argparse.h"

#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>

#include "core/generator_maze.h"
#include "core/generator_cell.h"
#include "core/random.h"
#include "core/imageops.h"
#include "core/stringutils.h"
#include "core/io.h"
#include "core/knuthshuffle.h"

// later when doing floodfill
// #include "core/colorbrewer.h"

using namespace euphoria::core;

struct Difference
{
    int x;
    int y;
    bool new_value;
};

std::vector<Difference>
FindDifferences(const Table<bool>& src, const Table<bool>& dst)
{
    std::vector<Difference> ret;
    for(int y = 0; y < src.GetHeight(); y += 1)
    {
        for(int x = 0; x < src.GetWidth(); x += 1)
        {
            const auto lhs = src(x, y);
            const auto rhs = dst(x, y);
            if(lhs != rhs)
            {
                ret.push_back({x, y, lhs});
            }
        }
    }
    return ret;
}

void
PrintMazeToConsole(const generator::Drawer& drawer)
{
    const auto table = ImageToStringTable
    (
        drawer.image,
        {
            {'#', drawer.wall_color},
            {'/', drawer.cell_color},
            {' ', drawer.wall_color},
            {' ', drawer.cell_visited_color},
            {'O', drawer.unit_color}
        }
    );

    const auto strings = ToStrings(table);
    for(const auto& s: strings)
    {
        std::cout << s << "\n";
    }
}

enum class MazeAlgorithm
{
    RecursiveBacktracker,
    RandomTraversal
};

void
HandleMazeCommand
(
    MazeAlgorithm algo,
    int world_width,
    int world_height,
    int cell_size,
    int wall_size,
    const std::string& f,
    bool console
)
{
    auto output = argparse::FileOutput {f};
    auto random = Random{};
    auto maze = generator::Maze::FromWidthHeight(world_width, world_height);

    auto drawer = generator::Drawer {};

    std::unique_ptr<generator::Algorithm> gen;

    switch(algo)
    {
    case MazeAlgorithm::RecursiveBacktracker:
        {
            auto g = std::make_unique<generator::RecursiveBacktracker>();
            g->maze = &maze;
            g->random = &random;
            drawer.tracker = g.get();
            gen.reset(g.release());
        }
        break;
    case MazeAlgorithm::RandomTraversal:
        {
            auto g = std::make_unique<generator::RandomTraversal>();
            g->maze = &maze;
            g->random = &random;
            drawer.traversal = g.get();
            gen.reset(g.release());
        }
        break;
    default:
        DIE("Unhandled");
    }

    gen->Setup();

    drawer.maze = &maze;
    drawer.cell_size = cell_size;
    drawer.wall_size = wall_size;

    auto draw_frame = [&]()
    {
        if(!output.single)
        {
            drawer.Draw();
            io::ChunkToFile
            (
                drawer.image.Write(ImageWriteFormat::PNG),
                output.NextFile()
            );
        }
    };

    draw_frame();

    while(gen->HasMoreWork())
    {
        gen->Work();
        draw_frame();
    }

    drawer.Draw();

    if(console)
    {
        PrintMazeToConsole(drawer);
    }
    else
    {
        if(output.single)
        {
            io::ChunkToFile
            (
                drawer.image.Write(ImageWriteFormat::PNG),
                output.file
            );
        }
        else
        {
            for(int i = 0; i < 5; i += 1)
            {
                io::ChunkToFile
                (
                    drawer.image.Write(ImageWriteFormat::PNG),
                    output.NextFile()
                );
            }
        }
    }
}

struct Cellwriter
{
    bool debug;
    argparse::FileOutput output;
    generator::World* world;
    int world_scale;

    Random shuffle_random;
    generator::World world_copy;

    explicit Cellwriter
    (
        bool d,
        const std::string& f,
        generator::World* w,
        int ws
    )
        : debug(d)
        , output{f}
        , world(w)
        , world_scale(ws)
    {
    }

    Image
    GenerateWorldImage(const generator::World& w)
    {
        return Draw(w, Color::Black, Color::White, world_scale);
    }

    void
    FirstState()
    {
        if(!output.single)
        {
            auto img = GenerateWorldImage(*world);
            io::ChunkToFile(img.Write(ImageWriteFormat::PNG), output.NextFile());
        }

        world_copy = *world;
        DrawStep();
    }

    void
    Done()
    {
        if(output.single)
        {
            auto img = GenerateWorldImage(*world);
            io::ChunkToFile(img.Write(ImageWriteFormat::PNG), output.file);
        }
        else
        {
            DrawStep();
        }
    }

    void
    DrawStep()
    {
        if(output.single) { return; }
        if (debug)
        {
            const auto img = GenerateWorldImage(*world);
            io::ChunkToFile
            (
                img.Write(ImageWriteFormat::PNG),
                output.NextFile()
            );
        }
        else
        {
            ShuffleDraw();
        }
    }

    void
    ShuffleDraw()
    {
        auto diffs = FindDifferences(*world, world_copy);
        KnuthShuffle(&diffs, &shuffle_random);
        const auto diffs_per_write = std::max<decltype(diffs.size())>
        (
            2,
            diffs.size() / 25
        );
        int write_index = 0;
        for (const auto d : diffs)
        {
            world_copy(d.x, d.y) = d.new_value;
            if ((write_index % diffs_per_write) == 0)
            {
                const auto img = GenerateWorldImage(world_copy);
                io::ChunkToFile
                (
                    img.Write(ImageWriteFormat::PNG),
                    output.NextFile()
                );
            }
            write_index += 1;
        }

        for (int i = 0; i < 5; i += 1)
        {
            const auto img = GenerateWorldImage(world_copy);
            io::ChunkToFile
            (
                img.Write(ImageWriteFormat::PNG),
                output.NextFile()
            );
        }
    }
};

struct MazeArguments
{
    Sizei size = Sizei::FromWidthHeight(10, 10);
    std::string output = "maze.png";

    int cell_size = 1;
    int wall_size = 1;
    bool console = false;

    void
    Add(argparse::ParserBase* base)
    {
        base->Add("--size", &size).Help("set the size");
        base->Add("-o, --output", &output).Help("specify output");

        base->Add("--cell", &cell_size).Help("set the cell size");
        base->Add("--wall", &wall_size).Help("set the wall size");
        base->SetTrue("-c,--console", &console).Help("foce console");
    }
};

int
main(int argc, char* argv[])
{
    auto parser = argparse::Parser{"Generate worlds"};
    auto sub = parser.AddSubParsers();

    sub->Add
    (
        "recursive",
        "maze generation using recursive backtracker algorithm",
        [&](argparse::SubParser* sub)
        {
            auto args = MazeArguments{};
            args.Add(sub);

            return sub->OnComplete
            (
                [&]
                {
                    HandleMazeCommand
                    (
                        MazeAlgorithm::RecursiveBacktracker,
                        args.size.width,
                        args.size.height,
                        args.cell_size,
                        args.wall_size,
                        args.output,
                        args.console
                    );
                    return argparse::ParseResult::Ok;
                }
            );
        }
    );

    sub->Add
    (
        "random",
        "maze generation using random traversal algorithm",
        [&](argparse::SubParser* sub)
        {
            auto args = MazeArguments{};
            args.Add(sub);

            return sub->OnComplete
            (
                [&]
                {
                    HandleMazeCommand
                    (
                        MazeAlgorithm::RandomTraversal,
                        args.size.width,
                        args.size.height,
                        args.cell_size,
                        args.wall_size,
                        args.output,
                        args.console
                    );
                    return argparse::ParseResult::Ok;
                }
            );
        }
    );

    sub->Add
    (
        "cell",
        "world generation using cellular automata algorithm",
        [&](argparse::SubParser* sub)
        {
            int world_scale = 5;
            bool debug = false;
            Sizei size = Sizei::FromWidthHeight(100, 70);
            std::string output = "cell.png";
            auto random = Random {};
            auto rules = generator::Rules{};

            sub->Add("--size", &size).Help("set the size");
            sub->Add("-o, --output", &output).Help("specify output");
            sub->Add("--scale", &world_scale).Help("set the scale");
            sub->SetTrue("--debug", &debug);

            auto commands = sub->AddSubParsers("commands");

            commands->Add("random", "random fill", [&](argparse::SubParser* cmd)
            {
                cmd->parser_style = argparse::SubParserStyle::Fallback;
                Fourway<BorderSetupRule> border_control = Fourway{BorderSetupRule::AlwaysWall};
                float random_fill = 0.5;
                cmd->Add("--fill", &random_fill).Help("How much to fill");
                cmd->Add("-bc", &border_control)
                    .Help("Change how the border is generated")
                    ;
                return cmd->OnComplete([&]{
                    generator::AddRandomFill(&rules, &random, random_fill, border_control);
                    return argparse::ParseResult::Ok;
                });
            });
            commands->Add("smooth", "smooth map", [&](argparse::SubParser* cmd)
            {
                cmd->parser_style = argparse::SubParserStyle::Fallback;
                int times = 5;
                int count = 4;
                cmd->Add("--times", &times).Help("How many to run");
                cmd->Add("--count", &count).Help("neighbour count");
                return cmd->OnComplete([&]{
                    generator::AddSimpleRules(&rules, times, count);
                    return argparse::ParseResult::Ok;
                });
            });

            return sub->OnComplete
            (
                [&]
                {

                    auto world = generator::World::FromWidthHeight(size.width, size.height);
                    world.Clear(false);

                    if(rules.rules.empty())
                    {
                        std::cerr << "no rules specified";
                        return argparse::ParseResult::Ok;
                    }

                    auto cell = generator::CellularAutomata{&rules, &world, Fourway{OutsideRule::Wall}};

                    auto writer = Cellwriter{debug, output, &world, world_scale};
                    writer.FirstState();

                    while(cell.HasMoreWork())
                    {
                        cell.Work();
                        writer.DrawStep();
                    }

                    writer.Done();

                    return argparse::ParseResult::Ok;
                }
            );
        }
    );

    return argparse::ParseFromMain(&parser, argc, argv);
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011, Paul Tagliamonte <tag@pault.ag>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <malloc.h>
#include <iostream>
#include <pty.h>
#include <stdlib.h>
#include <string.h>

#include "Shibuya.hh"
#include "Terminal.hh"

#include "conf/term.hh"

void Terminal::_init_Terminal(int width, int height) {
	this->width  = width;
	this->height = height;

	this->cX     = 0;
	this->cY     = 0;

	this->cMode  = 0x70;
	/* 11100000 = 0x70 (112)
	   FFF BBB */

	this->scroll_frame_bottom = this->height;
	this->scroll_frame_top   = 0;

	this->pty    = -1;

	this->chars = (TerminalCell*)
		malloc(sizeof(TerminalCell) * (width * height));

	for ( int i = 0; i < ( height * width ); ++i ) {
		this->chars[i].ch   = ' ';
		this->chars[i].attr = this->cMode;
	}
}

Terminal::~Terminal() {
	free( this->chars );
}

Terminal::Terminal() {
	this->_init_Terminal(80, 25);
}

Terminal::Terminal( int width, int height ) {
	this->_init_Terminal(width, height);
}

void Terminal::erase_to_from( int iX, int iY, int tX, int tY ) {
	iY--;
	tY--;
	int from = GET_OFFSET(iX, iY);
	int to   = GET_OFFSET(tX, tY);
	for ( int i = from - 1; i < to; ++i ) {
		this->chars[i].ch   = ' ';
		this->chars[i].attr = 0x70;
	}
}

void Terminal::scroll_up() {
	for (
		int iy = this->scroll_frame_top + 1;
		iy < this->scroll_frame_bottom;
		iy++
	) {
		for ( int ix = 0; ix < this->width; ++ix ) {
			int thisChar = GET_OFFSET(ix, iy);
			int lastChar = GET_OFFSET(ix, (iy - 1));
			this->chars[lastChar].ch   = this->chars[thisChar].ch;
			this->chars[lastChar].attr = this->chars[thisChar].attr;
		}
	}
	for ( int ix = 0; ix < this->width; ++ix ) {
		int offset = GET_OFFSET( ix, (this->scroll_frame_bottom - 1) );
		this->chars[offset].ch = ' ';
		this->chars[offset].attr = 0x70;
	}
}

pid_t Terminal::fork( const char * command ) {

	struct winsize ws;

	ws.ws_row    = this->height;
	ws.ws_col    = this->width;
	ws.ws_xpixel = 0;
	ws.ws_ypixel = 0;

	pid_t childpid = forkpty(&this->pty, NULL, NULL, &ws);
	if (childpid < 0) return -1;

	if (childpid == 0) {
		setenv("TERM", TERMINAL_ENV_NAME, 1);
		execl("/bin/sh", "/bin/sh", "-c", command, NULL); // XXX: Choose shell better
		std::cerr << "Failed to fork." << std::endl;
		exit(127);
	}
	/* if we got here we are the parent process */
	this->childpid = childpid;
	return childpid;
}

void Terminal::poke() {
	/* This is ripped off from librote */

	fd_set         ifs;
	struct timeval tvzero;

	char  buf[512];
	int   bytesread;
	int   n = 5; // XXX: Fix?

	if (this->pty < 0)
		return;

	while (n--) {
		FD_ZERO(&ifs);
		FD_SET(this->pty, &ifs);

		tvzero.tv_sec  = 0;
		tvzero.tv_usec = 0;

		if (select(this->pty + 1, &ifs, NULL, NULL, &tvzero) <= 0)
			return;

		bytesread = read(this->pty, buf, 512);
		if (bytesread <= 0)
			return;

		for ( int i = 0; i < bytesread; ++i )
			this->insert( buf[i] );
	}
}

void Terminal::insert( unsigned char c ) {

	if ( c == '\n' ) {
		this->cX = 0;
		this->cY++;
		return;
	}

	int ix = this->cX;
	int iy = this->cY;
	/*
	 * XXX: Why was the math using this->cX failing?
	 * for some reason we have to bring it into the local
	 * scope...
	 */
	int offset = GET_OFFSET(ix, iy);

	this->chars[offset].ch   = c;
	this->chars[offset].attr = this->cMode;
	this->advance_curs();
}

void Terminal::type( char c ) {
	write(this->pty, &c, 1);
}

void Terminal::advance_curs() {
	this->cX++;

	if ( this->width <= this->cX ) {
		this->cX = 0;
		this->cY++;
	}

	if ( this->height <= this->cY ) {
		this->cY = (this->height - 1);
		this->scroll_up();
	}
}

int Terminal::get_width() {
	return this->width;
}

int Terminal::get_height() {
	return this->height;
}
<commit_msg>Adding in a skitch of tabular things<commit_after>/*
 * Copyright (C) 2011, Paul Tagliamonte <tag@pault.ag>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <malloc.h>
#include <iostream>
#include <pty.h>
#include <stdlib.h>
#include <string.h>

#include "Shibuya.hh"
#include "Terminal.hh"

#include "conf/term.hh"

void Terminal::_init_Terminal(int width, int height) {
	this->width  = width;
	this->height = height;

	this->cX     = 0;
	this->cY     = 0;

	this->cMode  = 0x70;
	/* 11100000 = 0x70 (112)
	   FFF BBB */

	this->scroll_frame_bottom = this->height;
	this->scroll_frame_top   = 0;

	this->pty    = -1;

	this->chars = (TerminalCell*)
		malloc(sizeof(TerminalCell) * (width * height));

	for ( int i = 0; i < ( height * width ); ++i ) {
		this->chars[i].ch   = ' ';
		this->chars[i].attr = this->cMode;
	}
}

Terminal::~Terminal() {
	free( this->chars );
}

Terminal::Terminal() {
	this->_init_Terminal(80, 25);
}

Terminal::Terminal( int width, int height ) {
	this->_init_Terminal(width, height);
}

void Terminal::erase_to_from( int iX, int iY, int tX, int tY ) {
	iY--;
	tY--;
	int from = GET_OFFSET(iX, iY);
	int to   = GET_OFFSET(tX, tY);
	for ( int i = from - 1; i < to; ++i ) {
		this->chars[i].ch   = ' ';
		this->chars[i].attr = 0x70;
	}
}

void Terminal::scroll_up() {
	for (
		int iy = this->scroll_frame_top + 1;
		iy < this->scroll_frame_bottom;
		iy++
	) {
		for ( int ix = 0; ix < this->width; ++ix ) {
			int thisChar = GET_OFFSET(ix, iy);
			int lastChar = GET_OFFSET(ix, (iy - 1));
			this->chars[lastChar].ch   = this->chars[thisChar].ch;
			this->chars[lastChar].attr = this->chars[thisChar].attr;
		}
	}
	for ( int ix = 0; ix < this->width; ++ix ) {
		int offset = GET_OFFSET( ix, (this->scroll_frame_bottom - 1) );
		this->chars[offset].ch = ' ';
		this->chars[offset].attr = 0x70;
	}
}

pid_t Terminal::fork( const char * command ) {

	struct winsize ws;

	ws.ws_row    = this->height;
	ws.ws_col    = this->width;
	ws.ws_xpixel = 0;
	ws.ws_ypixel = 0;

	pid_t childpid = forkpty(&this->pty, NULL, NULL, &ws);
	if (childpid < 0) return -1;

	if (childpid == 0) {
		setenv("TERM", TERMINAL_ENV_NAME, 1);
		execl("/bin/sh", "/bin/sh", "-c", command, NULL); // XXX: Choose shell better
		std::cerr << "Failed to fork." << std::endl;
		exit(127);
	}
	/* if we got here we are the parent process */
	this->childpid = childpid;
	return childpid;
}

void Terminal::poke() {
	/* This is ripped off from librote */

	fd_set         ifs;
	struct timeval tvzero;

	char  buf[512];
	int   bytesread;
	int   n = 5; // XXX: Fix?

	if (this->pty < 0)
		return;

	while (n--) {
		FD_ZERO(&ifs);
		FD_SET(this->pty, &ifs);

		tvzero.tv_sec  = 0;
		tvzero.tv_usec = 0;

		if (select(this->pty + 1, &ifs, NULL, NULL, &tvzero) <= 0)
			return;

		bytesread = read(this->pty, buf, 512);
		if (bytesread <= 0)
			return;

		for ( int i = 0; i < bytesread; ++i )
			this->insert( buf[i] );
	}
}

void Terminal::insert( unsigned char c ) {

	if ( c == '\n' ) {
		this->cX = 0;
		this->cY++;
		return;
	}

	if ( c == 8 ) {
		/* Backspace */
		this->cX--;
	}

	if ( c == 9 ) {
		/* Tab */
		this->insert(' ');

		while ( ( this->cX % 8 ) != 0 ) {
			this->insert(' ');
		}
		return;
	}

	if ( c < 32 )
		return;

	int ix = this->cX;
	int iy = this->cY;
	/*
	 * XXX: Why was the math using this->cX failing?
	 * for some reason we have to bring it into the local
	 * scope...
	 */
	int offset = GET_OFFSET(ix, iy);

	this->chars[offset].ch   = c;
	this->chars[offset].attr = this->cMode;
	this->advance_curs();
}

void Terminal::type( char c ) {
	write(this->pty, &c, 1);
}

void Terminal::advance_curs() {
	this->cX++;

	if ( this->width <= this->cX ) {
		this->cX = 0;
		this->cY++;
	}

	if ( this->height <= this->cY ) {
		this->cY = (this->height - 1);
		this->scroll_up();
	}
}

int Terminal::get_width() {
	return this->width;
}

int Terminal::get_height() {
	return this->height;
}
<|endoftext|>


<commit_before>/*
 * Netlist Generator Helper
 * Checks validity of vias and buried contacts
 *
 * Copyright (c) 2011-2012 QMT Productions
 * All rights reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include "polygon.h"

int main (int argc, char **argv)
{
	vector<node *> nodes, vias;
	node *cur, *sub;
	int i, j;

	int metal_start, metal_end;
	int poly_start, poly_end;
	int diff_start, diff_end;

	metal_start = nodes.size();
	readnodes<node>("metal_vcc.dat", nodes, LAYER_METAL);
	if (nodes.size() != 1)
	{
		fprintf(stderr, "Error: metal_vcc.dat contains more than one node (found %i)!\n", nodes.size());
		return 1;
	}
	readnodes<node>("metal_gnd.dat", nodes, LAYER_METAL);
	if (nodes.size() != 2)
	{
		fprintf(stderr, "Error: metal_gnd.dat contains more than one node (found %i)!\n", nodes.size() - 1);
		return 1;
	}
	readnodes<node>("metal.dat", nodes, LAYER_METAL);
	metal_end = nodes.size();

	printf("Checking for hollow metal segments (%i-%i)\n", metal_start, metal_end - 1);
	for (i = metal_start; i < metal_end; i++)
	{
		cur = nodes[i];
		for (j = metal_start; j < metal_end; j++)
		{
			if (i == j)
				continue;
			sub = nodes[j];
			if (cur->collide(sub))
				printf("Metal segments %i (%s) and %i (%s) collide!\n", i, cur->poly.toString().c_str(), j, sub->poly.toString().c_str());
		}
	}

	poly_start = nodes.size();
	readnodes<node>("polysilicon.dat", nodes, LAYER_POLY);
	poly_end = nodes.size();

	printf("Checking for hollow polysilicon segments (%i-%i)\n", poly_start, poly_end - 1);
	for (i = poly_start; i < poly_end; i++)
	{
		cur = nodes[i];
		for (j = poly_start; j < poly_end; j++)
		{
			if (i == j)
				continue;
			sub = nodes[j];
			if (cur->collide(sub))
				printf("Polysilicon segments %i (%s) and %i (%s) collide!\n", i, cur->poly.toString().c_str(), j, sub->poly.toString().c_str());
		}
	}

	diff_start = nodes.size();
	readnodes<node>("diffusion.dat", nodes, LAYER_DIFF);
	diff_end = nodes.size();

	printf("Checking for hollow diffusion segments (%i-%i)\n", diff_start, diff_end - 1);
	for (i = diff_start; i < diff_end; i++)
	{
		cur = nodes[i];
		for (j = diff_start; j < diff_end; j++)
		{
			if (i == j)
				continue;
			sub = nodes[j];
			if (cur->collide(sub))
				printf("Diffusion segments %i (%s) and %i (%s) collide!\n", i, cur->poly.toString().c_str(), j, sub->poly.toString().c_str());
		}
	}
	readnodes<node>("vias.dat", vias, LAYER_SPECIAL);

	printf("Checking for bad vias (%i total)\n", vias.size());
	for (i = 0; i < vias.size(); i++)
	{
		int hits = 0;
		sub = vias[i];
		for (j = metal_start; j < diff_end; j++)
		{
			cur = nodes[j];
			if (cur->collide(sub))
				hits++;
		}
		if (hits != 2)
			printf("Invalid number of connections %i for via %i (%s)\n", hits, i, sub->poly.toString().c_str());
	}
	vias.clear();

	readnodes<node>("buried_contacts.dat", vias, LAYER_SPECIAL);

	printf("Checking for bad buried contacts (%i total)\n", vias.size());
	for (i = 0; i < vias.size(); i++)
	{
		int hits = 0;
		sub = vias[i];
		for (j = poly_start; j < diff_end; j++)
		{
			cur = nodes[j];
			if (cur->collide(sub))
				hits++;
		}
		if (hits != 2)
			printf("Invalid number of connections %i for buried contact %i (%s)\n", hits, i, sub->poly.toString().c_str());
	}
	vias.clear();

	printf("Done!\n");
}
<commit_msg>In check, skip hollowness checks on vcc/gnd - if they wre hollow, there'd be more than one node and it'd be rejected<commit_after>/*
 * Netlist Generator Helper
 * Checks validity of vias and buried contacts
 *
 * Copyright (c) 2011-2012 QMT Productions
 * All rights reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include "polygon.h"

int main (int argc, char **argv)
{
	vector<node *> nodes, vias;
	node *cur, *sub;
	int i, j;

	int metal_start, metal_end;
	int poly_start, poly_end;
	int diff_start, diff_end;

	metal_start = nodes.size();
	readnodes<node>("metal_vcc.dat", nodes, LAYER_METAL);
	if (nodes.size() != 1)
	{
		fprintf(stderr, "Error: metal_vcc.dat contains more than one node (found %i)!\n", nodes.size());
		return 1;
	}
	readnodes<node>("metal_gnd.dat", nodes, LAYER_METAL);
	if (nodes.size() != 2)
	{
		fprintf(stderr, "Error: metal_gnd.dat contains more than one node (found %i)!\n", nodes.size() - 1);
		return 1;
	}
	readnodes<node>("metal.dat", nodes, LAYER_METAL);
	metal_end = nodes.size();

	printf("Checking for hollow metal segments (%i-%i)\n", metal_start + 2, metal_end - 1);
	for (i = metal_start + 2; i < metal_end; i++)
	{
		cur = nodes[i];
		for (j = metal_start + 2; j < metal_end; j++)
		{
			if (i == j)
				continue;
			sub = nodes[j];
			if (cur->collide(sub))
				printf("Metal segments %i (%s) and %i (%s) collide!\n", i, cur->poly.toString().c_str(), j, sub->poly.toString().c_str());
		}
	}

	poly_start = nodes.size();
	readnodes<node>("polysilicon.dat", nodes, LAYER_POLY);
	poly_end = nodes.size();

	printf("Checking for hollow polysilicon segments (%i-%i)\n", poly_start, poly_end - 1);
	for (i = poly_start; i < poly_end; i++)
	{
		cur = nodes[i];
		for (j = poly_start; j < poly_end; j++)
		{
			if (i == j)
				continue;
			sub = nodes[j];
			if (cur->collide(sub))
				printf("Polysilicon segments %i (%s) and %i (%s) collide!\n", i, cur->poly.toString().c_str(), j, sub->poly.toString().c_str());
		}
	}

	diff_start = nodes.size();
	readnodes<node>("diffusion.dat", nodes, LAYER_DIFF);
	diff_end = nodes.size();

	printf("Checking for hollow diffusion segments (%i-%i)\n", diff_start, diff_end - 1);
	for (i = diff_start; i < diff_end; i++)
	{
		cur = nodes[i];
		for (j = diff_start; j < diff_end; j++)
		{
			if (i == j)
				continue;
			sub = nodes[j];
			if (cur->collide(sub))
				printf("Diffusion segments %i (%s) and %i (%s) collide!\n", i, cur->poly.toString().c_str(), j, sub->poly.toString().c_str());
		}
	}
	readnodes<node>("vias.dat", vias, LAYER_SPECIAL);

	printf("Checking for bad vias (%i total)\n", vias.size());
	for (i = 0; i < vias.size(); i++)
	{
		int hits = 0;
		sub = vias[i];
		for (j = metal_start; j < diff_end; j++)
		{
			cur = nodes[j];
			if (cur->collide(sub))
				hits++;
		}
		if (hits != 2)
			printf("Invalid number of connections %i for via %i (%s)\n", hits, i, sub->poly.toString().c_str());
	}
	vias.clear();

	readnodes<node>("buried_contacts.dat", vias, LAYER_SPECIAL);

	printf("Checking for bad buried contacts (%i total)\n", vias.size());
	for (i = 0; i < vias.size(); i++)
	{
		int hits = 0;
		sub = vias[i];
		for (j = poly_start; j < diff_end; j++)
		{
			cur = nodes[j];
			if (cur->collide(sub))
				hits++;
		}
		if (hits != 2)
			printf("Invalid number of connections %i for buried contact %i (%s)\n", hits, i, sub->poly.toString().c_str());
	}
	vias.clear();

	printf("Done!\n");
}
<|endoftext|>


<commit_before>/*
===========================================================================

Daemon GPL Source Code
Copyright (C) 2012 Unvanquished Developers

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Daemon Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Daemon Source Code is also subject to certain additional terms.
You should have received a copy of these additional terms immediately following the
terms and conditions of the GNU General Public License which accompanied the Daemon
Source Code.  If not, please request a copy in writing from id Software at the address
below.

If you have questions concerning this license or the applicable additional terms, you
may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
Maryland 20850 USA.

===========================================================================
*/

// Code to deal with libRocket's loading and handling of documents and elements

#include <Rocket/Core.h>

extern "C"
{
#include "client.h"
}

void Rocket_LoadDocument( const char *path )
{
	Rocket::Core::ElementDocument* document = context->LoadDocument( path );
	if( document )
	{
		document->Hide();
		document->RemoveReference();
	}
	else
	{
		Com_Printf( "Document is NULL\n");
	}
}

void Rocket_LoadCursor( const char *path )
{
	Rocket::Core::ElementDocument* document = context->LoadMouseCursor( path );
	if( document )
	{
		document->RemoveReference();
	}
	else
	{
		Com_Printf( "Cursor is NULL\n");
	}
}

void Rocket_DocumentAction( const char *name, const char *action )
{
	if ( !Q_stricmp( action, "show" ) || !Q_stricmp( action, "open" ) )
	{
		Rocket::Core::ElementDocument* document = context->GetDocument( name );
		if ( document )
		{
			document->Show();
		}
	}
	else if ( !Q_stricmp( "close", action ) )
	{
		if ( !*name ) // If name is empty, hide active
		{
			if ( context->GetFocusElement() &&
				context->GetFocusElement()->GetOwnerDocument() &&
				context->GetFocusElement()->GetOwnerDocument() != context->GetDocument( "main" ) )
			{
				context->GetFocusElement()->GetOwnerDocument()->Close();
			}

			return;
		}

		Rocket::Core::ElementDocument* document = context->GetDocument( name );
		if ( document )
		{
			document->Close();
		}
	}
	else if ( !Q_stricmp( "goto", action ) )
	{
		Rocket::Core::ElementDocument* document = context->GetDocument( name );
		if ( document )
		{
			Rocket::Core::ElementDocument *owner = context->GetFocusElement()->GetOwnerDocument();
			if ( owner )
			{
				owner->Close();
			}
			document->Show();
		}
	}
	else if ( !Q_stricmp( "load", action ) )
	{
		Rocket_LoadDocument( name );
	}
}
<commit_msg>Add a blur event to hide documents<commit_after>/*
===========================================================================

Daemon GPL Source Code
Copyright (C) 2012 Unvanquished Developers

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Daemon Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Daemon Source Code is also subject to certain additional terms.
You should have received a copy of these additional terms immediately following the
terms and conditions of the GNU General Public License which accompanied the Daemon
Source Code.  If not, please request a copy in writing from id Software at the address
below.

If you have questions concerning this license or the applicable additional terms, you
may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
Maryland 20850 USA.

===========================================================================
*/

// Code to deal with libRocket's loading and handling of documents and elements

#include <Rocket/Core.h>

extern "C"
{
#include "client.h"
}

void Rocket_LoadDocument( const char *path )
{
	Rocket::Core::ElementDocument* document = context->LoadDocument( path );
	if( document )
	{
		document->Hide();
		document->RemoveReference();
	}
	else
	{
		Com_Printf( "Document is NULL\n");
	}
}

void Rocket_LoadCursor( const char *path )
{
	Rocket::Core::ElementDocument* document = context->LoadMouseCursor( path );
	if( document )
	{
		document->RemoveReference();
	}
	else
	{
		Com_Printf( "Cursor is NULL\n");
	}
}

void Rocket_DocumentAction( const char *name, const char *action )
{
	if ( !Q_stricmp( action, "show" ) || !Q_stricmp( action, "open" ) )
	{
		Rocket::Core::ElementDocument* document = context->GetDocument( name );
		if ( document )
		{
			document->Show();
		}
	}
	else if ( !Q_stricmp( "close", action ) )
	{
		if ( !*name ) // If name is empty, hide active
		{
			if ( context->GetFocusElement() &&
				context->GetFocusElement()->GetOwnerDocument() &&
				context->GetFocusElement()->GetOwnerDocument() != context->GetDocument( "main" ) )
			{
				context->GetFocusElement()->GetOwnerDocument()->Close();
			}

			return;
		}

		Rocket::Core::ElementDocument* document = context->GetDocument( name );
		if ( document )
		{
			document->Close();
		}
	}
	else if ( !Q_stricmp( "goto", action ) )
	{
		Rocket::Core::ElementDocument* document = context->GetDocument( name );
		if ( document )
		{
			Rocket::Core::ElementDocument *owner = context->GetFocusElement()->GetOwnerDocument();
			if ( owner )
			{
				owner->Close();
			}
			document->Show();
		}
	}
	else if ( !Q_stricmp( "load", action ) )
	{
		Rocket_LoadDocument( name );
	}
	else if ( !Q_stricmp( "blur", action ) || !Q_stricmp( "hide", action ) )
	{
		Rocket::Core::ElementDocument* document = context->GetDocument( name );
		if ( document )
		{
			document->Blur();
		}
	}
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    Threshld.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Toolkit. No part of this file
or its contents may be copied, reproduced or altered in any way
without the express written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
#include "Threshld.hh"

// Construct with lower threshold=0, upper threshold=1, and threshold
// function=upper.
vtkThreshold::vtkThreshold()
{
  this->LowerThreshold = 0.0;
  this->UpperThreshold = 1.0;

  this->ThresholdFunction = &vtkThreshold::Upper;
}

// Description:
// Criterion is cells whose scalars are less than lower threshold.
void vtkThreshold::ThresholdByLower(float lower)
{
  if ( this->LowerThreshold != lower )
    {
    this->LowerThreshold = lower;
    this->ThresholdFunction = &vtkThreshold::Lower;
    this->Modified();
    }
}

// Description:
// Criterion is cells whose scalars are less than upper threshold.
void vtkThreshold::ThresholdByUpper(float upper)
{
  if ( this->UpperThreshold != upper )
    {
    this->UpperThreshold = upper;
    this->ThresholdFunction = &vtkThreshold::Upper;
    this->Modified();
    }
}

// Description:
// Criterion is cells whose scalars are between lower and upper thresholds.
void vtkThreshold::ThresholdBetween(float lower, float upper)
{
  if ( this->LowerThreshold != lower || this->UpperThreshold != upper )
    {
    this->LowerThreshold = lower;
    this->UpperThreshold = upper;
    this->ThresholdFunction = vtkThreshold::Between;
    this->Modified();
    }
}

void vtkThreshold::Execute()
{
  int cellId;
  vtkIdList *cellPts, *pointMap;
  vtkIdList newCellPts(MAX_CELL_SIZE);
  vtkScalars *inScalars;
  vtkFloatScalars cellScalars(MAX_CELL_SIZE);
  vtkCell *cell;
  vtkFloatPoints *newPoints;
  vtkPointData *pd;
  int i, ptId, newId, numPts, numCellPts;
  float *x;

  vtkDebugMacro(<< "Executing threshold filter");
  this->Initialize();

  if ( ! (inScalars = this->Input->GetPointData()->GetScalars()) )
    {
    vtkErrorMacro(<<"No scalar data to threshold");
    return;
    }

  numPts = this->Input->GetNumberOfPoints();

  this->Allocate(this->Input->GetNumberOfCells());
  newPoints = new vtkFloatPoints(numPts);
  pd = this->Input->GetPointData();
  this->PointData.CopyAllocate(pd);

  pointMap = new vtkIdList(numPts); // maps old point ids into new
  for (i=0; i < numPts; i++) pointMap->SetId(i,-1);

  // Check that the scalars of each cell satisfy the threshold criterion
  for (cellId=0; cellId < this->Input->GetNumberOfCells(); cellId++)
    {
    cell = this->Input->GetCell(cellId);
    cellPts = cell->GetPointIds();
    inScalars->GetScalars(*cellPts,cellScalars);
    numCellPts = cell->GetNumberOfPoints();

    for ( i=0; i < numCellPts; i++)
      {
      ptId = cellPts->GetId(i);
      if ( ! ((this->*(this->ThresholdFunction))(cellScalars.GetScalar(ptId))) ) break;
      }

    if ( i >= numCellPts ) // satisfied thresholding
      {
      for (i=0; i < numCellPts; i++)
        {
        ptId = cellPts->GetId(i);
        if ( (newId = pointMap->GetId(ptId)) < 0 )
          {
          x = this->Input->GetPoint(ptId);
          newId = newPoints->InsertNextPoint(x);
          pointMap->SetId(ptId,newId);
          this->PointData.CopyData(pd,ptId,newId);
          }
        newCellPts.SetId(i,newId);
        }
      this->InsertNextCell(cell->GetCellType(),newCellPts);
      } // satisfied thresholding
    } // for all cells

  vtkDebugMacro(<< "Extracted " << this->GetNumberOfCells()
               << " number of cells.");

  // now clean up / update ourselves
  delete pointMap;
  this->Squeeze();
  newPoints->Squeeze();

  this->SetPoints(newPoints);
}

void vtkThreshold::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToUnstructuredGridFilter::PrintSelf(os,indent);

  if ( this->ThresholdFunction == &vtkThreshold::Upper )
    os << indent << "Threshold By Upper\n";

  else if ( this->ThresholdFunction == &vtkThreshold::Lower )
    os << indent << "Threshold By Lower\n";

  else if ( this->ThresholdFunction == &vtkThreshold::Between )
    os << indent << "Threshold Between\n";

  os << indent << "Lower Threshold: " << this->LowerThreshold << "\n";;
  os << indent << "Upper Threshold: " << this->UpperThreshold << "\n";;
}
<commit_msg>*** empty log message ***<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    Threshld.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Toolkit. No part of this file
or its contents may be copied, reproduced or altered in any way
without the express written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
#include "Threshld.hh"

// Construct with lower threshold=0, upper threshold=1, and threshold
// function=upper.
vtkThreshold::vtkThreshold()
{
  this->LowerThreshold = 0.0;
  this->UpperThreshold = 1.0;

  this->ThresholdFunction = &vtkThreshold::Upper;
}

// Description:
// Criterion is cells whose scalars are less than lower threshold.
void vtkThreshold::ThresholdByLower(float lower)
{
  if ( this->LowerThreshold != lower )
    {
    this->LowerThreshold = lower;
    this->ThresholdFunction = &vtkThreshold::Lower;
    this->Modified();
    }
}

// Description:
// Criterion is cells whose scalars are less than upper threshold.
void vtkThreshold::ThresholdByUpper(float upper)
{
  if ( this->UpperThreshold != upper )
    {
    this->UpperThreshold = upper;
    this->ThresholdFunction = &vtkThreshold::Upper;
    this->Modified();
    }
}

// Description:
// Criterion is cells whose scalars are between lower and upper thresholds.
void vtkThreshold::ThresholdBetween(float lower, float upper)
{
  if ( this->LowerThreshold != lower || this->UpperThreshold != upper )
    {
    this->LowerThreshold = lower;
    this->UpperThreshold = upper;
    this->ThresholdFunction = vtkThreshold::Between;
    this->Modified();
    }
}

void vtkThreshold::Execute()
{
  int cellId;
  vtkIdList *cellPts, *pointMap;
  vtkIdList newCellPts(MAX_CELL_SIZE);
  vtkScalars *inScalars;
  vtkFloatScalars cellScalars(MAX_CELL_SIZE);
  vtkCell *cell;
  vtkFloatPoints *newPoints;
  vtkPointData *pd;
  int i, ptId, newId, numPts, numCellPts;
  float *x;

  vtkDebugMacro(<< "Executing threshold filter");
  this->Initialize();

  if ( ! (inScalars = this->Input->GetPointData()->GetScalars()) )
    {
    vtkErrorMacro(<<"No scalar data to threshold");
    return;
    }

  numPts = this->Input->GetNumberOfPoints();

  this->Allocate(this->Input->GetNumberOfCells());
  newPoints = new vtkFloatPoints(numPts);
  pd = this->Input->GetPointData();
  this->PointData.CopyAllocate(pd);

  pointMap = new vtkIdList(numPts); // maps old point ids into new
  for (i=0; i < numPts; i++) pointMap->SetId(i,-1);

  // Check that the scalars of each cell satisfy the threshold criterion
  for (cellId=0; cellId < this->Input->GetNumberOfCells(); cellId++)
    {
    cell = this->Input->GetCell(cellId);
    cellPts = cell->GetPointIds();
    inScalars->GetScalars(*cellPts,cellScalars);
    numCellPts = cell->GetNumberOfPoints();

    for ( i=0; i < numCellPts; i++)
      {
      ptId = cellPts->GetId(i);
      if ( ! ((this->*(this->ThresholdFunction))(cellScalars.GetScalar(ptId))) ) break;
      }

    if ( i >= numCellPts ) // satisfied thresholding
      {
      for (i=0; i < numCellPts; i++)
        {
        ptId = cellPts->GetId(i);
        if ( (newId = pointMap->GetId(ptId)) < 0 )
          {
          x = this->Input->GetPoint(ptId);
          newId = newPoints->InsertNextPoint(x);
          pointMap->SetId(ptId,newId);
          this->PointData.CopyData(pd,ptId,newId);
          }
        newCellPts.SetId(i,newId);
        }
      this->InsertNextCell(cell->GetCellType(),newCellPts);
      } // satisfied thresholding
    } // for all cells

  vtkDebugMacro(<< "Extracted " << this->GetNumberOfCells()
               << " number of cells.");

  // now clean up / update ourselves
  pointMap->Delete();

  this->SetPoints(newPoints);
  newPoints->Delete();

  this->Squeeze();
}

void vtkThreshold::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToUnstructuredGridFilter::PrintSelf(os,indent);

  if ( this->ThresholdFunction == &vtkThreshold::Upper )
    os << indent << "Threshold By Upper\n";

  else if ( this->ThresholdFunction == &vtkThreshold::Lower )
    os << indent << "Threshold By Lower\n";

  else if ( this->ThresholdFunction == &vtkThreshold::Between )
    os << indent << "Threshold Between\n";

  os << indent << "Lower Threshold: " << this->LowerThreshold << "\n";;
  os << indent << "Upper Threshold: " << this->UpperThreshold << "\n";;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011 Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <cxxtools/jsonformatter.h>
#include <cxxtools/convert.h>
#include <cxxtools/log.h>
#include <limits>

log_define("cxxtools.jsonformatter")

namespace cxxtools
{

namespace
{

    void checkTs(std::basic_ostream<Char>* _ts)
    {
        if (_ts == 0)
            throw std::logic_error("textstream is not set in JsonFormatter");

    }

    bool isplain(const std::string& str)
    {
        if (str.empty())
            return false;

        if (!std::isalpha(str[0]))
            return false;

        for (std::string::size_type n = 1; n < str.size(); ++n)
            if (!std::isalnum(str[n]))
                return false;

        return true;
    }

}

void JsonFormatter::begin(std::basic_ostream<Char>& ts)
{
    _ts = &ts;
    _level = 0;
    _lastLevel = std::numeric_limits<unsigned>::max();
}

void JsonFormatter::finish()
{
    log_trace("finish");
    if (_beautify)
        *_ts << L'\n';
    _level = 0;
    _lastLevel = std::numeric_limits<unsigned>::max();
}

void JsonFormatter::addValueString(const std::string& name, const std::string& type,
                      const String& value)
{
    log_trace("addValueString name=\"" << name << "\", type=\"" << type << "\", value=\"" << value << '"');

    if (type == "bool")
    {
        addValueBool(name, type, convert<bool>(value));
    }
    else
    {
        beginValue(name);

        if (type == "int" || type == "double")
        {
            stringOut(value);
        }
        else if (type == "json")
        {
            *_ts << value;
        }
        else if (type == "null")
        {
            *_ts << L"null";
        }
        else
        {
            *_ts << L'"';
            stringOut(value);
            *_ts << L'"';
        }

        finishValue();
    }
}

void JsonFormatter::addValueStdString(const std::string& name, const std::string& type,
                      const std::string& value)
{
    log_trace("addValueStdString name=\"" << name << "\", type=\"" << type << "\", \" value=\"" << value << '"');

    if (type == "bool")
    {
        addValueBool(name, type, convert<bool>(value));
    }
    else
    {
        beginValue(name);

        if (type == "int" || type == "double")
        {
            stringOut(value);
        }
        else if (type == "json")
        {
            for (std::string::const_iterator it = value.begin(); it != value.end(); ++it)
                *_ts << Char(*it);
        }
        else if (type == "null")
        {
            *_ts << L"null";
        }
        else
        {
            *_ts << L'"';
            stringOut(value);
            *_ts << L'"';
        }

        finishValue();
    }
}

void JsonFormatter::addValueBool(const std::string& name, const std::string& type,
                      bool value)
{
    log_trace("addValueBool name=\"" << name << "\", type=\"" << type << "\", \" value=\"" << value << '"');

    beginValue(name);

    *_ts << (value ? L"true" : L"false");

    finishValue();
}

void JsonFormatter::addValueInt(const std::string& name, const std::string& type,
                      int_type value)
{
    log_trace("addValueInt name=\"" << name << "\", type=\"" << type << "\", \" value=" << value);

    beginValue(name);

    if (type == "bool")
        *_ts << (value ? L"true" : L"false");
    else
        *_ts << value;

    finishValue();
}

void JsonFormatter::addValueUnsigned(const std::string& name, const std::string& type,
                      unsigned_type value)
{
    log_trace("addValueUnsigned name=\"" << name << "\", type=\"" << type << "\", \" value=" << value);

    beginValue(name);

    if (type == "bool")
        *_ts << (value ? L"true" : L"false");
    else
        *_ts << value;

    finishValue();
}

void JsonFormatter::addValueFloat(const std::string& name, const std::string& type,
                      long double value)
{
    log_trace("addValueFloat name=\"" << name << "\", type=\"" << type << "\", \" value=" << value);

    beginValue(name);

    if (value != value  // check for nan
        || value == std::numeric_limits<long double>::infinity()
        || value == -std::numeric_limits<long double>::infinity())
    {
        *_ts << L"null";
    }
    else
    {
        *_ts << convert<String>(value);
    }

    finishValue();
}

void JsonFormatter::addNull(const std::string& name, const std::string& /*type*/)
{
    beginValue(name);
    *_ts << L"null";
    finishValue();
}

void JsonFormatter::beginArray(const std::string& name, const std::string& /*type*/)
{
    checkTs(_ts);

    if (_level == _lastLevel)
    {
        *_ts << L',';
        if (_beautify)
            *_ts << L'\n';
    }
    else
        _lastLevel = _level;

    if (_beautify)
        indent();

    ++_level;

    if (!name.empty())
    {
        if (_plainkey && isplain(name))
        {
            for (std::string::size_type n = 0; n < name.size(); ++n)
                *_ts << Char(name[n]);
        }
        else
        {
          *_ts << L'"';
          stringOut(name);
          *_ts << L'"';
        }

        *_ts << L':';

        if (_beautify)
            *_ts << L' ';
    }

    *_ts << L'[';
    if (_beautify)
        *_ts << L'\n';
}

void JsonFormatter::finishArray()
{
    checkTs(_ts);

    --_level;
    _lastLevel = _level;
    if (_beautify)
    {
        *_ts << L'\n';
        indent();
    }
    *_ts << L']';
}

void JsonFormatter::beginObject(const std::string& name, const std::string& /*type*/)
{
    checkTs(_ts);

    log_trace("beginObject name=\"" << name << '"');

    if (_level == _lastLevel)
    {
        *_ts << L',';
        if (_beautify)
            *_ts << L'\n';
    }
    else
        _lastLevel = _level;

    if (_beautify)
        indent();

    ++_level;

    if (!name.empty())
    {
        if (_plainkey && isplain(name))
        {
            for (std::string::size_type n = 0; n < name.size(); ++n)
                *_ts << Char(name[n]);
        }
        else
        {
          *_ts << L'"';
          stringOut(name);
          *_ts << L'"';
        }

        *_ts << L':';

        if (_beautify)
            *_ts << L' ';
    }

    *_ts << L'{';
    if (_beautify)
        *_ts << L'\n';
}

void JsonFormatter::beginMember(const std::string& /*name*/)
{
}

void JsonFormatter::finishMember()
{
}

void JsonFormatter::finishObject()
{
    checkTs(_ts);

    log_trace("finishObject");

    --_level;
    _lastLevel = _level;
    if (_beautify)
    {
        *_ts << L'\n';
        indent();
    }
    *_ts << L'}';
}

void JsonFormatter::indent()
{
    for (unsigned n = 0; n < _level; ++n)
        *_ts << L'\t';
}

void JsonFormatter::stringOut(const std::string& str)
{
    for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
    {
        if (*it == '"')
            *_ts << L'\\'
                << L'\"';
        else if (*it == '\\')
            *_ts << L'\\'
                << L'\\';
        else if (*it == '\b')
            *_ts << L'\\'
                << L'b';
        else if (*it == '\f')
            *_ts << L'\\'
                << L'f';
        else if (*it == '\n')
            *_ts << L'\\'
                << L'n';
        else if (*it == '\r')
            *_ts << L'\\'
                << L'r';
        else if (*it == '\t')
            *_ts << L'\\'
                << L't';
        else if (static_cast<unsigned char>(*it) >= 0x80 || static_cast<unsigned char>(*it) < 0x20)
        {
            *_ts << L'\\'
                 << L'u';
            static const char hex[] = "0123456789abcdef";
            uint32_t v = static_cast<unsigned char>(*it);
            for (uint32_t s = 16; s > 0; s -= 4)
            {
                *_ts << Char(hex[(v >> (s - 4)) & 0xf]);
            }
        }
        else
            *_ts << Char(*it);
    }
}

void JsonFormatter::stringOut(const cxxtools::String& str)
{
    for (cxxtools::String::const_iterator it = str.begin(); it != str.end(); ++it)
    {
        if (*it == L'"')
            *_ts << L'\\'
                << L'\"';
        else if (*it == L'\\')
            *_ts << L'\\'
                << L'\\';
        else if (*it == L'\b')
            *_ts << L'\\'
                << L'b';
        else if (*it == L'\f')
            *_ts << L'\\'
                << L'f';
        else if (*it == L'\n')
            *_ts << L'\\'
                << L'n';
        else if (*it == L'\r')
            *_ts << L'\\'
                << L'r';
        else if (*it == L'\t')
            *_ts << L'\\'
                << L't';
        else if (it->value() >= 0x80 || it->value() < 0x20)
        {
            *_ts << L'\\'
                 << L'u';
            static const char hex[] = "0123456789abcdef";
            uint32_t v = it->value();
            for (uint32_t s = 16; s > 0; s -= 4)
            {
                *_ts << Char(hex[(v >> (s - 4)) & 0xf]);
            }
        }
        else
            *_ts << *it;
    }
}

void JsonFormatter::beginValue(const std::string& name)
{
    checkTs(_ts);

    if (_level == _lastLevel)
    {
        *_ts << L',';
        if (_beautify)
        {
            *_ts << L'\n';
            indent();
        }
    }
    else
    {
        _lastLevel = _level;
        if (_beautify)
            indent();
    }

    if (!name.empty())
    {
        if (_plainkey && isplain(name))
        {
            for (std::string::size_type n = 0; n < name.size(); ++n)
                *_ts << Char(name[n]);
        }
        else
        {
            *_ts << L'"';
            stringOut(name);
            *_ts << L'"';
        }

        *_ts << L':';
        if (_beautify)
            *_ts << L' ';
    }

    ++_level;
}

void JsonFormatter::finishValue()
{
    --_level;
}

}
<commit_msg>change logging category for json formatter to match other json objects<commit_after>/*
 * Copyright (C) 2011 Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <cxxtools/jsonformatter.h>
#include <cxxtools/convert.h>
#include <cxxtools/log.h>
#include <limits>

log_define("cxxtools.json.formatter")

namespace cxxtools
{

namespace
{

    void checkTs(std::basic_ostream<Char>* _ts)
    {
        if (_ts == 0)
            throw std::logic_error("textstream is not set in JsonFormatter");

    }

    bool isplain(const std::string& str)
    {
        if (str.empty())
            return false;

        if (!std::isalpha(str[0]))
            return false;

        for (std::string::size_type n = 1; n < str.size(); ++n)
            if (!std::isalnum(str[n]))
                return false;

        return true;
    }

}

void JsonFormatter::begin(std::basic_ostream<Char>& ts)
{
    _ts = &ts;
    _level = 0;
    _lastLevel = std::numeric_limits<unsigned>::max();
}

void JsonFormatter::finish()
{
    log_trace("finish");
    if (_beautify)
        *_ts << L'\n';
    _level = 0;
    _lastLevel = std::numeric_limits<unsigned>::max();
}

void JsonFormatter::addValueString(const std::string& name, const std::string& type,
                      const String& value)
{
    log_trace("addValueString name=\"" << name << "\", type=\"" << type << "\", value=\"" << value << '"');

    if (type == "bool")
    {
        addValueBool(name, type, convert<bool>(value));
    }
    else
    {
        beginValue(name);

        if (type == "int" || type == "double")
        {
            stringOut(value);
        }
        else if (type == "json")
        {
            *_ts << value;
        }
        else if (type == "null")
        {
            *_ts << L"null";
        }
        else
        {
            *_ts << L'"';
            stringOut(value);
            *_ts << L'"';
        }

        finishValue();
    }
}

void JsonFormatter::addValueStdString(const std::string& name, const std::string& type,
                      const std::string& value)
{
    log_trace("addValueStdString name=\"" << name << "\", type=\"" << type << "\", \" value=\"" << value << '"');

    if (type == "bool")
    {
        addValueBool(name, type, convert<bool>(value));
    }
    else
    {
        beginValue(name);

        if (type == "int" || type == "double")
        {
            stringOut(value);
        }
        else if (type == "json")
        {
            for (std::string::const_iterator it = value.begin(); it != value.end(); ++it)
                *_ts << Char(*it);
        }
        else if (type == "null")
        {
            *_ts << L"null";
        }
        else
        {
            *_ts << L'"';
            stringOut(value);
            *_ts << L'"';
        }

        finishValue();
    }
}

void JsonFormatter::addValueBool(const std::string& name, const std::string& type,
                      bool value)
{
    log_trace("addValueBool name=\"" << name << "\", type=\"" << type << "\", \" value=\"" << value << '"');

    beginValue(name);

    *_ts << (value ? L"true" : L"false");

    finishValue();
}

void JsonFormatter::addValueInt(const std::string& name, const std::string& type,
                      int_type value)
{
    log_trace("addValueInt name=\"" << name << "\", type=\"" << type << "\", \" value=" << value);

    beginValue(name);

    if (type == "bool")
        *_ts << (value ? L"true" : L"false");
    else
        *_ts << value;

    finishValue();
}

void JsonFormatter::addValueUnsigned(const std::string& name, const std::string& type,
                      unsigned_type value)
{
    log_trace("addValueUnsigned name=\"" << name << "\", type=\"" << type << "\", \" value=" << value);

    beginValue(name);

    if (type == "bool")
        *_ts << (value ? L"true" : L"false");
    else
        *_ts << value;

    finishValue();
}

void JsonFormatter::addValueFloat(const std::string& name, const std::string& type,
                      long double value)
{
    log_trace("addValueFloat name=\"" << name << "\", type=\"" << type << "\", \" value=" << value);

    beginValue(name);

    if (value != value  // check for nan
        || value == std::numeric_limits<long double>::infinity()
        || value == -std::numeric_limits<long double>::infinity())
    {
        *_ts << L"null";
    }
    else
    {
        *_ts << convert<String>(value);
    }

    finishValue();
}

void JsonFormatter::addNull(const std::string& name, const std::string& /*type*/)
{
    beginValue(name);
    *_ts << L"null";
    finishValue();
}

void JsonFormatter::beginArray(const std::string& name, const std::string& /*type*/)
{
    checkTs(_ts);

    if (_level == _lastLevel)
    {
        *_ts << L',';
        if (_beautify)
            *_ts << L'\n';
    }
    else
        _lastLevel = _level;

    if (_beautify)
        indent();

    ++_level;

    if (!name.empty())
    {
        if (_plainkey && isplain(name))
        {
            for (std::string::size_type n = 0; n < name.size(); ++n)
                *_ts << Char(name[n]);
        }
        else
        {
          *_ts << L'"';
          stringOut(name);
          *_ts << L'"';
        }

        *_ts << L':';

        if (_beautify)
            *_ts << L' ';
    }

    *_ts << L'[';
    if (_beautify)
        *_ts << L'\n';
}

void JsonFormatter::finishArray()
{
    checkTs(_ts);

    --_level;
    _lastLevel = _level;
    if (_beautify)
    {
        *_ts << L'\n';
        indent();
    }
    *_ts << L']';
}

void JsonFormatter::beginObject(const std::string& name, const std::string& /*type*/)
{
    checkTs(_ts);

    log_trace("beginObject name=\"" << name << '"');

    if (_level == _lastLevel)
    {
        *_ts << L',';
        if (_beautify)
            *_ts << L'\n';
    }
    else
        _lastLevel = _level;

    if (_beautify)
        indent();

    ++_level;

    if (!name.empty())
    {
        if (_plainkey && isplain(name))
        {
            for (std::string::size_type n = 0; n < name.size(); ++n)
                *_ts << Char(name[n]);
        }
        else
        {
          *_ts << L'"';
          stringOut(name);
          *_ts << L'"';
        }

        *_ts << L':';

        if (_beautify)
            *_ts << L' ';
    }

    *_ts << L'{';
    if (_beautify)
        *_ts << L'\n';
}

void JsonFormatter::beginMember(const std::string& /*name*/)
{
}

void JsonFormatter::finishMember()
{
}

void JsonFormatter::finishObject()
{
    checkTs(_ts);

    log_trace("finishObject");

    --_level;
    _lastLevel = _level;
    if (_beautify)
    {
        *_ts << L'\n';
        indent();
    }
    *_ts << L'}';
}

void JsonFormatter::indent()
{
    for (unsigned n = 0; n < _level; ++n)
        *_ts << L'\t';
}

void JsonFormatter::stringOut(const std::string& str)
{
    for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
    {
        if (*it == '"')
            *_ts << L'\\'
                << L'\"';
        else if (*it == '\\')
            *_ts << L'\\'
                << L'\\';
        else if (*it == '\b')
            *_ts << L'\\'
                << L'b';
        else if (*it == '\f')
            *_ts << L'\\'
                << L'f';
        else if (*it == '\n')
            *_ts << L'\\'
                << L'n';
        else if (*it == '\r')
            *_ts << L'\\'
                << L'r';
        else if (*it == '\t')
            *_ts << L'\\'
                << L't';
        else if (static_cast<unsigned char>(*it) >= 0x80 || static_cast<unsigned char>(*it) < 0x20)
        {
            *_ts << L'\\'
                 << L'u';
            static const char hex[] = "0123456789abcdef";
            uint32_t v = static_cast<unsigned char>(*it);
            for (uint32_t s = 16; s > 0; s -= 4)
            {
                *_ts << Char(hex[(v >> (s - 4)) & 0xf]);
            }
        }
        else
            *_ts << Char(*it);
    }
}

void JsonFormatter::stringOut(const cxxtools::String& str)
{
    for (cxxtools::String::const_iterator it = str.begin(); it != str.end(); ++it)
    {
        if (*it == L'"')
            *_ts << L'\\'
                << L'\"';
        else if (*it == L'\\')
            *_ts << L'\\'
                << L'\\';
        else if (*it == L'\b')
            *_ts << L'\\'
                << L'b';
        else if (*it == L'\f')
            *_ts << L'\\'
                << L'f';
        else if (*it == L'\n')
            *_ts << L'\\'
                << L'n';
        else if (*it == L'\r')
            *_ts << L'\\'
                << L'r';
        else if (*it == L'\t')
            *_ts << L'\\'
                << L't';
        else if (it->value() >= 0x80 || it->value() < 0x20)
        {
            *_ts << L'\\'
                 << L'u';
            static const char hex[] = "0123456789abcdef";
            uint32_t v = it->value();
            for (uint32_t s = 16; s > 0; s -= 4)
            {
                *_ts << Char(hex[(v >> (s - 4)) & 0xf]);
            }
        }
        else
            *_ts << *it;
    }
}

void JsonFormatter::beginValue(const std::string& name)
{
    checkTs(_ts);

    if (_level == _lastLevel)
    {
        *_ts << L',';
        if (_beautify)
        {
            *_ts << L'\n';
            indent();
        }
    }
    else
    {
        _lastLevel = _level;
        if (_beautify)
            indent();
    }

    if (!name.empty())
    {
        if (_plainkey && isplain(name))
        {
            for (std::string::size_type n = 0; n < name.size(); ++n)
                *_ts << Char(name[n]);
        }
        else
        {
            *_ts << L'"';
            stringOut(name);
            *_ts << L'"';
        }

        *_ts << L':';
        if (_beautify)
            *_ts << L' ';
    }

    ++_level;
}

void JsonFormatter::finishValue()
{
    --_level;
}

}
<|endoftext|>