Exemple #1
0
void QtWin::loadWorkpiece() {
  if (project->getAutomaticWorkpiece()) on_automaticCuboidRadioButton_clicked();
  else on_manualCuboidRadioButton_clicked();

  LOCK_UI_UPDATES;
  ui->marginDoubleSpinBox->setValue(project->getWorkpieceMargin());

  ToolUnits units = project->getUnits();

  // Bounds
  real scale = units == ToolUnits::UNITS_MM ? 1 : 1 / 25.4;
  Rectangle3R bounds = project->getWorkpieceBounds();
  ui->xDimDoubleSpinBox->setValue(bounds.getDimensions().x() * scale);
  ui->yDimDoubleSpinBox->setValue(bounds.getDimensions().y() * scale);
  ui->zDimDoubleSpinBox->setValue(bounds.getDimensions().z() * scale);
  ui->xOffsetDoubleSpinBox->setValue(bounds.getMin().x() * scale);
  ui->yOffsetDoubleSpinBox->setValue(bounds.getMin().y() * scale);
  ui->zOffsetDoubleSpinBox->setValue(bounds.getMin().z() * scale);

  // Update Workpiece steps
  real step = units == ToolUnits::UNITS_MM ? 1 : 0.125;
  ui->xDimDoubleSpinBox->setSingleStep(step);
  ui->yDimDoubleSpinBox->setSingleStep(step);
  ui->zDimDoubleSpinBox->setSingleStep(step);
  ui->xOffsetDoubleSpinBox->setSingleStep(step);
  ui->yOffsetDoubleSpinBox->setSingleStep(step);
  ui->zOffsetDoubleSpinBox->setSingleStep(step);

  // Update visual
  view->setWorkpiece(bounds);
  redraw();
}
Exemple #2
0
void QtWin::setWorkpieceOffset(unsigned dim, real value) {
  real scale = project->getUnits() == ToolUnits::UNITS_MM ? 1 : 25.4;
  Rectangle3R bounds = project->getWorkpieceBounds();
  bounds.rmax[dim] = bounds.getDimension(dim) + value * scale;
  bounds.rmin[dim] = value * scale;
  project->setWorkpieceBounds(bounds);
  loadWorkpiece();

  redraw(true);
}
Exemple #3
0
void Project::updateResolution() {
  if (getResolutionMode() == ResolutionMode::RESOLUTION_MANUAL) return;

  Rectangle3R wpBounds = getWorkpieceBounds();
  if (wpBounds == Rectangle3R()) return;

  double divisor;
  switch (getResolutionMode()) {
  case ResolutionMode::RESOLUTION_LOW: divisor = 100000; break;
  case ResolutionMode::RESOLUTION_HIGH: divisor = 5000000; break;
  case ResolutionMode::RESOLUTION_VERY_HIGH: divisor = 10000000; break;
  default: divisor = 250000; break; // Medium
  }

  setResolution(pow(wpBounds.getVolume() / divisor, 1.0 / 3.0));
}
Exemple #4
0
void QtWin::updateToolPathBounds() {
  Rectangle3R bounds = *toolPath;
  Vector3R bMin = bounds.getMin();
  Vector3R bMax = bounds.getMax();
  Vector3R bDim = bounds.getDimensions();

  setUnitLabel(ui->toolPathBoundsXMinLabel, bMin.x());
  setUnitLabel(ui->toolPathBoundsXMaxLabel, bMax.x());
  setUnitLabel(ui->toolPathBoundsXDimLabel, bDim.x());

  setUnitLabel(ui->toolPathBoundsYMinLabel, bMin.y());
  setUnitLabel(ui->toolPathBoundsYMaxLabel, bMax.y());
  setUnitLabel(ui->toolPathBoundsYDimLabel, bDim.y());

  setUnitLabel(ui->toolPathBoundsZMinLabel, bMin.z());
  setUnitLabel(ui->toolPathBoundsZMaxLabel, bMax.z());
  setUnitLabel(ui->toolPathBoundsZDimLabel, bDim.z());
}
Exemple #5
0
void QtWin::updateWorkpieceBounds() {
  if (project.isNull()) return;

  Rectangle3R bounds = project->getWorkpieceBounds();
  Vector3R bMin = bounds.getMin();
  Vector3R bMax = bounds.getMax();
  Vector3R bDim = bounds.getDimensions();

  setUnitLabel(ui->workpieceBoundsXMinLabel, bMin.x());
  setUnitLabel(ui->workpieceBoundsXMaxLabel, bMax.x());
  setUnitLabel(ui->workpieceBoundsXDimLabel, bDim.x());

  setUnitLabel(ui->workpieceBoundsYMinLabel, bMin.y());
  setUnitLabel(ui->workpieceBoundsYMaxLabel, bMax.y());
  setUnitLabel(ui->workpieceBoundsYDimLabel, bDim.y());

  setUnitLabel(ui->workpieceBoundsZMinLabel, bMin.z());
  setUnitLabel(ui->workpieceBoundsZMaxLabel, bMax.z());
  setUnitLabel(ui->workpieceBoundsZDimLabel, bDim.z());
}
Exemple #6
0
double Project::computeResolution(ResolutionMode mode, Rectangle3R bounds) {
  if (mode == ResolutionMode::RESOLUTION_MANUAL || bounds == Rectangle3R())
    return 1;

  double divisor;
  switch (mode) {
  case ResolutionMode::RESOLUTION_LOW: divisor = 100000; break;
  case ResolutionMode::RESOLUTION_HIGH: divisor = 5000000; break;
  case ResolutionMode::RESOLUTION_VERY_HIGH: divisor = 10000000; break;
  default: divisor = 250000; break; // Medium
  }

  return pow(bounds.getVolume() / divisor, 1.0 / 3.0);
}
static void boxSplit(vector<Rectangle3R> &boxes, Rectangle3R box,
                     unsigned count) {
  if (count < 2) {
    boxes.push_back(box);
    return;
  }

  Rectangle3R left(box);
  Rectangle3R right(box);

  // Split on largest dimension (reduces overlap)
  if (box.getLength() <= box.getWidth() && box.getHeight() <= box.getWidth())
    right.rmin.x() = left.rmax.x() = (box.rmin.x() + box.rmax.x()) / 2;

  else if (box.getWidth() <= box.getLength() &&
           box.getHeight() <= box.getLength())
    right.rmin.y() = left.rmax.y() = (box.rmin.y() + box.rmax.y()) / 2;

  else right.rmin.z() = left.rmax.z() = (box.rmin.z() + box.rmax.z()) / 2;

  boxSplit(boxes, left, count - 2);
  boxSplit(boxes, right, count - 2);
}
Rectangle3R CompositeSurface::getBounds() const {
  Rectangle3R bounds;
  for (unsigned i = 0; i < surfaces.size(); i++)
    bounds.add(surfaces[i]->getBounds());
  return bounds;
}
void Viewer::draw(const View &view) {
  init();

  SmartPointer<Surface> surface = view.surface;

  // Setup view port
  Rectangle3R bounds = view.path->getBounds();
  if (!surface.isNull()) bounds.add(surface->getBounds());
  bounds.add(view.workpiece->getBounds());
  view.glDraw(bounds);

  // Workpiece bounds
  if (!view.isFlagSet(View::SHOW_WORKPIECE_FLAG) &&
      view.isFlagSet(View::SHOW_WORKPIECE_BOUNDS_FLAG)) {
    glEnable(GL_DEPTH_TEST);
    glLineWidth(1);
    glColor4f(1, 1, 1, 0.5); // White

    BoundsView(view.workpiece->getBounds()).draw();
  }

  // Enable Lighting
  view.setLighting(true);

  // Tool path
  if (view.isFlagSet(View::SHOW_PATH_FLAG)) view.path->draw();
  else view.path->update();

  // Model
  if (view.isFlagSet(View::SHOW_WORKPIECE_FLAG | View::SHOW_SURFACE_FLAG)) {
    const float ambient[] = {12.0 / 255, 45.0 / 255,  83.0 / 255, 1.00};
    const float diffuse[] = {16.0 / 255, 59.0 / 255, 108.0 / 255, 1.00};

    glDisable(GL_COLOR_MATERIAL);
    glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);

    view.setWire(view.isFlagSet(View::WIRE_FLAG));

    if (!surface.isNull() && view.isFlagSet(View::SHOW_SURFACE_FLAG))
      surface->draw();

    if (view.isFlagSet(View::SHOW_WORKPIECE_FLAG)) view.workpiece->draw();

    glEnable(GL_COLOR_MATERIAL);

    view.setWire(false);

    if (view.isFlagSet(View::SHOW_NORMALS_FLAG)) {
      glColor4f(1.0, 1.0, 0, 0.6);
      surface->drawNormals();
    }
  }

  // Bounding box tree
  // TODO revive this
  //if (view.isFlagSet(View::SHOW_BBTREE_FLAG)) cutWP->drawBB();

  // Tool
  if (view.isFlagSet(View::SHOW_TOOL_FLAG) && !view.path->getPath().isNull()) {
    Vector3R currentPosition = view.path->getPosition();
    glTranslatef(currentPosition.x(), currentPosition.y(),
                 currentPosition.z());

    ToolTable &tools = *view.path->getPath()->getTools();
    const Move &move = view.path->getMove();
    const Tool &tool = *tools.get(move.getTool());
    double diameter = tool.getDiameter();
    double radius = tool.getRadius();
    double length = tool.getLength();
    ToolShape shape = tool.getShape();

    if (radius <= 0) {
      // Default tool specs
      radius = 25.4 / 8;
      shape = ToolShape::TS_CONICAL;

      glColor4f(1, 0, 0, 1); // Red

    } else glColor4f(1, 0.5, 0, 1); // Orange

    if (length <= 0) length = 50;

    switch (shape) {
    case ToolShape::TS_SPHEROID: {
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix();
      glTranslatef(0, 0, length / 2);
      glScaled(1, 1, length / diameter);
      gluSphere((GLUquadric *)toolQuad, radius, 100, 100);
      glPopMatrix();
      break;
    }

    case ToolShape::TS_BALLNOSE:
      glPushMatrix();
      glTranslatef(0, 0, radius);
      gluSphere((GLUquadric *)toolQuad, radius, 100, 100);
      drawCylinder((GLUquadric *)toolQuad, radius, radius, length - radius);
      glPopMatrix();
      break;

    case ToolShape::TS_SNUBNOSE:
      drawCylinder((GLUquadric *)toolQuad, tool.getSnubDiameter() / 2, radius,
                   length);
      break;

    case ToolShape::TS_CONICAL:
      drawCylinder((GLUquadric *)toolQuad, 0, radius, length);
      break;

    case ToolShape::TS_CYLINDRICAL:
    default:
      drawCylinder((GLUquadric *)toolQuad, radius, radius, length);
      break;
    }
  }

  // Disable Lighting
  view.setLighting(false);

  CHECK_GL_ERROR("");
}
Exemple #10
0
void Project::setWorkpieceBounds(const Rectangle3R &bounds) {
  options["workpiece-min"].set(bounds.getMin().toString());
  options["workpiece-max"].set(bounds.getMax().toString());
  updateResolution();
  if (!getAutomaticWorkpiece()) markDirty();
}
Exemple #11
0
void Project::updateAutomaticWorkpiece(ToolPath &path) {
  if (!getAutomaticWorkpiece()) return;
  setAutomaticWorkpiece(true);
  Rectangle3R wpBounds;

  // Guess workpiece bounds from cutting moves
  vector<SmartPointer<Sweep> > sweeps;
  vector<Rectangle3R> bboxes;

  for (unsigned i = 0; i < path.size(); i++) {
    const Move &move = path.at(i);

    if (move.getType() != MoveType::MOVE_RAPID) {
      unsigned tool = move.getTool();

      if (sweeps.size() <= tool) sweeps.resize(tool + 1);
      if (sweeps[tool].isNull()) sweeps[tool] = tools.get(tool).getSweep();

      sweeps[tool]->getBBoxes(move.getStartPt(), move.getEndPt(), bboxes, 0);
    }
  }

  for (unsigned i = 0; i < bboxes.size(); i++) wpBounds.add(bboxes[i]);

  if (wpBounds == Rectangle3R()) return;

  // Start from z = 0
  Vector3R bMin = wpBounds.getMin();
  Vector3R bMax = wpBounds.getMax();
  wpBounds = Rectangle3R(bMin, Vector3R(bMax.x(), bMax.y(), 0));

  // At least 2mm thick
  if (wpBounds.getHeight() < 2)
    wpBounds.add(Vector3R(bMin.x(), bMin.y(), bMin.z() - 2));

  if (wpBounds.isReal()) {
    // Margin
    Vector3R margin =
      wpBounds.getDimensions() * getWorkpieceMargin() / 100.0;
    wpBounds.add(wpBounds.getMin() - margin);
    wpBounds.add(wpBounds.getMax() + Vector3R(margin.x(), margin.y(), 0));

    setWorkpieceBounds(wpBounds);
  }
}
Exemple #12
0
void ViewPort::glDraw(const Rectangle3R &bbox) const {
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  // Background
  glBegin(GL_QUADS);
  glColor3ub(0x25, 0x30, 0x40);
  glVertex2f(-1, -1);
  glVertex2f(1, -1);
  glColor3ub(0x5, 0x5, 0x5);
  glVertex2f(1, 1);
  glVertex2f(-1, 1);
  glEnd();

  // Compute "radius"
  Vector3R dims = bbox.getDimensions();
  real radius = dims.x() < dims.y() ? dims.y() : dims.x();
  radius = dims.z() < radius ? radius : dims.z();

  // Perspective
  gluPerspective(45, (float)width / height, 1, 100000);

  // Translate
  glTranslatef(translation.x() * radius / zoom,
               translation.y() * radius / zoom, 0);

  // Scale
  gluLookAt(0, 0, radius / zoom, 0, 0, 0, 0, 1, 0);

  glMatrixMode(GL_MODELVIEW);

  // Rotate
  glRotated(rotation[0], rotation[1], rotation[2], rotation[3]);

  // Center
  Vector3R center = bbox.getCenter();
  glTranslatef(-center.x(), -center.y(), -center.z());

  // Axes
  if (axes) {
    double length = (bbox.getWidth() + bbox.getLength() + bbox.getHeight()) / 3;
    length *= 0.1;
    double radius = length / 20;

    setLighting(true);

    for (int axis = 0; axis < 3; axis++)
      for (int up = 0; up < 2; up++)
        drawAxis(axis, up, length, radius);

    setLighting(false);
  }
  
  // Bounds
  if (bounds) {
    glEnable(GL_LINE_STIPPLE);
    glLineStipple(1, 0x5555);
    glLineWidth(1);
    glColor4f(1, 1, 1, 0.5); // White

    BoundsView(bbox).draw();

    glDisable(GL_LINE_STIPPLE);
  }
}
cb::SmartPointer<Surface>
Renderer::render(CutWorkpiece &cutWorkpiece, unsigned threads,
                 double resolution, RenderMode mode) {
  // Setup
  task->begin();

  cutWorkpiece.clearSampleCount();
  cutWorkpiece.getToolSweep()->clearHitTests();

  // Increase bounds a little
  Rectangle3R bbox = cutWorkpiece.getBounds();
  real off = 2 * resolution - 0.00001;
  bbox = bbox.grow(Vector3R(off, off, off));

  // Divide work
  vector<Rectangle3R> jobBoxes;
  boxSplit(jobBoxes, bbox, threads);
  unsigned totalJobCount = jobBoxes.size();

  LOG_INFO(1, "Computing surface bounded by " << bbox << " at "
           << resolution << " grid resolution in " << jobBoxes.size()
           << " boxes");


  // Run jobs
  SmartPointer<CompositeSurface> surface = new CompositeSurface;
  typedef list<SmartPointer<RenderJob> > jobs_t;
  jobs_t jobs;
  while (!task->shouldQuit() && !(jobBoxes.empty() && jobs.empty())) {

    // Start new jobs
    while (!jobBoxes.empty() && jobs.size() < threads) {
      Rectangle3R jobBox = jobBoxes.back();
      jobBoxes.pop_back();

      SmartPointer<RenderJob> job =
        new RenderJob(cutWorkpiece, mode, resolution, jobBox);
      job->start();
      jobs.push_back(job);
    }


    // Reap completed jobs
    jobs_t::iterator it;
    for (it = jobs.begin(); it != jobs.end() && !task->shouldQuit();)
      if ((*it)->getState() == Thread::THREAD_DONE) {
        (*it)->join();
        surface->add((*it)->getSurface());
        it = jobs.erase(it);
      } else it++;


    // Update Progress
    double progress = 0;

    // Add running jobs
    for (it = jobs.begin(); it != jobs.end() && !task->shouldQuit(); it++)
      progress += (*it)->getProgress();

    // Add completed jobs
    progress += totalJobCount - jobBoxes.size() - jobs.size();
    progress /= totalJobCount;

    task->update(progress, "Rendering surface");


    // Sleep
    Timer::sleep(0.1);
  }


  // Clean up remaining jobs in case of an early exit
  for (jobs_t::iterator it = jobs.begin(); it != jobs.end(); it++)
    (*it)->join();

  if (shouldQuit()) {
    task->end();
    LOG_INFO(1, "Render aborted");
    return 0;
  }

  // Done
  double delta = task->end();
  LOG_INFO(1, "Time: " << TimeInterval(delta)
           << " Triangles: " << surface->getCount()
           << " Triangles/sec: "
           << String::printf("%0.2f", surface->getCount() / delta)
           << " Resolution: " << resolution);


  return surface;
}
Exemple #14
0
Workpiece::Workpiece(const Rectangle3R &r) :
  Rectangle3R(r), center(r.getCenter()) {
  Vector3R halfDim = r.getDimensions() / 2;
  halfDim2 = halfDim * halfDim;
}