<commit_before>//
// Coypright (c) 2022 Singular Inversions Inc. (facegen.com)
// Use, modification and distribution is subject to the MIT License,
// see accompanying file LICENSE.txt or facegen.com/base_library_license.txt
//
// Command to software-render meshes to image files.
//

#include "stdafx.h"

#include "FgCommand.hpp"
#include "FgFileSystem.hpp"
#include "Fg3dMeshIo.hpp"
#include "Fg3dCamera.hpp"
#include "FgSoftRender.hpp"
#include "FgTime.hpp"
#include "FgSyntax.hpp"
#include "FgMetaFormat.hpp"
#include "FgImgDisplay.hpp"
#include "FgParse.hpp"
#include "FgTestUtils.hpp"
#include "FgBuild.hpp"
#include "FgGridTriangles.hpp"

using namespace std;

namespace Fg {

namespace {

struct      ModelFile
{
    String              meshFilename;
    Strings             imgFilenames;
    bool                shiny = false;
    FG_SERIALIZE3(meshFilename,imgFilenames,shiny)
};
typedef Svec<ModelFile>     ModelFiles;

struct      RenderArgs
{
    ModelFiles              models;
    double                  roll = 0,       // Z axis rotation, radians, in order:
                            tilt = 0,       // X axis rotation
                            pan = 0;        // Y axis rotation
    SimilarityD             modelview;      // Transform world to openGL eye coordinate system (OECS)
    // transform from projected coordinates (image tangent CS) to image unit CS (x,y in [0,1]):
    AffineEw2D              itcsToIucs;
    Vec2UI                  imagePixelSize = Vec2UI(512,512);
    RenderOptions           options;

    FG_SERIALIZE8(models,roll,tilt,pan,modelview,itcsToIucs,imagePixelSize,options);
};

Meshes              loadMeshes(ModelFiles const & mfs)
{
    Meshes          meshes;
    for (ModelFile const & mf : mfs) {
        meshes.push_back(loadMesh(mf.meshFilename));
        for (size_t ss=0; ss<mf.imgFilenames.size(); ++ss) {
            if (ss < meshes.back().surfaces.size()) {
                meshes.back().surfaces[ss].setAlbedoMap(loadImage(mf.imgFilenames[ss]));
                meshes.back().surfaces[ss].material.shiny = mf.shiny;
            }
            else
                fgout << "WARNING: more images specified than surfaces for mesh " << mf.meshFilename;
        }
    }
    return meshes;
}

void                cmdRenderSetup(CLArgs const & args)
{
    Syntax              syn {args,
        R"(<name>.xml (-<option> <value>)* (<mesh>.<ext> [<albedo>.])*
    <option>        - (roll | tilt | pan) - specify object pose, with <value> given in degrees
    <ext>           - )" + getMeshLoadExtsCLDescription() + R"(
               - )" + getImageFileExtCLDescriptions() + R"(
OUTPUT:
    <name>.xml      - render configuration file
NOTES:
    * creates default rendering parameters for the given models
    * fields in <name>.xml can be modified as long as the XML structure remains valid
    <name>.xml description:
        <models>
            The list of mesh and related albedo map files to be rendered.
        <roll>,<tilt>,<pan>
            Euler angle rotations in radians applied to the models, in this order, before
            application of <modelview> below. Can be used to orient your meshes for proper viewing
            (FG head coordinate system is X - head's left, Y - head's up, Z - head's forward),
            or to orient the head as desired. Defaults are 0.
        <modelview>
            The similarity transform from mesh coordinates to openGL eye coordinates,
            consisting of scale, rotation (as a quaternion) and translation, applied in that order.
            Default places subject at a viewing distance from the camera to mostly fill the frame.
        <itcsToIucs>
            The 2D transform from projected coordinates ("image tangent CS") to the
            "image unit CS" in which x,y are in [0,1] with origin at top left of image.
        <imagePixelSize>
            Pixel width, height
        <options>
            <lighting> all color component values below are in the range [0,1]:
                <ambient> light coming from all directions.
                <lights>
                    <colour> RGB order
                    <direction> in order of X,Y,Z in OpenGL Eye Coordinates.
            <backgroundColor> RGBA order, values in [0,1].
            <antiAliasBitDepth> 3 is high quality (equivalent to 8x FSAA) without running too slowly
            <renderSurfPoints> 0 - don't, 1 - when visible, 2 - always.
                They are rendered as single-pixel green dots over the image.)"
    };
    string              name = syn.next();
    RenderArgs          rend;
    while (syn.more()) {
        if (syn.peekNext()[0] == '-') {         // option
            String          opt = syn.next();
            if (opt == "-roll")
                rend.roll = degToRad(syn.nextAs<float>());
            else if (opt == "-tilt")
                rend.tilt = degToRad(syn.nextAs<float>());
            else if (opt == "-pan")
                rend.pan = degToRad(syn.nextAs<float>());
            else
                syn.error("Unrecognized option",opt);
        }
        //! Set up the default render options from the arguments:
        ModelFile           mf;
        mf.meshFilename = syn.next();
        while (syn.more() && hasImageFileExt(syn.peekNext()))
            mf.imgFilenames.push_back(syn.next());
        rend.models.push_back(mf);
    }
    // Load data from files to validate and set modelview:
    Meshes              meshes = loadMeshes(rend.models);
    Mat32F              bounds = cBounds(meshes);
    CameraParams        cps {fgF2D(bounds)};
    cps.logRelScale = std::log(0.9);
    cps.fovMaxDeg = 17.0;
    Camera              cam = cps.camera(rend.imagePixelSize);
    rend.modelview = cam.modelview;
    rend.itcsToIucs = cam.itcsToIucs;
    saveBsaXml(name,rend);
}

void                renderRun(String const & rendFile,String const & outName)
{
    RenderArgs          rend;
    // boost 1.58 introduced an XML deserialization bug on older compilers whereby std::vector
    // is appended rather than overwritten, so we must clear first:
    rend.options.lighting.lights.clear();
    loadBsaXml(rendFile,rend);
    Meshes              meshes = loadMeshes(rend.models);
    // Receive surf point projection data:
    rend.options.projSurfPoints = std::make_shared<ProjectedSurfPoints>();
    SimilarityD         mvm = rend.modelview * cRotateY(rend.pan) * cRotateX(rend.tilt) * cRotateZ(rend.roll);
    ImgRgba8            image = renderSoft(rend.imagePixelSize,meshes,mvm,rend.itcsToIucs,rend.options);
    saveImage(outName,image);
    String8             outBase = pathToBase(outName);
    Ofstream            ofs {outBase+"-landmarks.csv"};
    for (ProjectedSurfPoint const & psp : *rend.options.projSurfPoints)
        ofs << psp.label << "," << psp.posIucs << "," << (psp.visible ? "true" : "false") << "\n";
    Camera              cam {mvm,{},rend.itcsToIucs};
    saveBsaXml(outBase+"-matrix.xml",cam.projectIpcs(rend.imagePixelSize));
}

void                cmdRenderRun(CLArgs const & args)
{
    Syntax              syn {args,
        R"(<in>.xml <out>.
    <in>.xml    - the render configuration file created using 'fgbl render setup'
           - )" + getImageFileExtCLDescriptions() + R"(
OUTPUT:
    <out>.         -   the rendered image
    <out>-matrix.xml    -   the homogeneous combined projection*modelview matrix resulting from the camera model
    <out>-landmarks.csv -   label, image position (IUCS) and visibility of projected surface points,
                            ordered by mesh then surface then point. Surface points can be interactively placed
                            on a mesh (Windoows only) using 'fgbl view mesh' on a single mesh,
                            from the 'Edit' -> 'Points' tab, and saved in either TRI or FGMESH formats.)"
    };
    String              inFile = syn.next(),
                        outFile = syn.next();
    PushTimer           pt {"Rendering and writing files"};
    renderRun(inFile,outFile);
}

void                cmdRenderBatch(CLArgs const & args)
{
    Syntax              syn {args,
        R"(<files>.txt
           - )" + getImageFileExtCLDescriptions() + R"(
OUTPUT:
    for each render parameter file <name>.xml listed in <files>.txt, the following files are created:
    <name>.             the rendered image
    <name>-matrix.xml        the homogeneous combined projection*modelview matrix resulting from the camera model
    <name>-landmarks.csv     label, image position (IUCS) and visibility of projected surface points,
                             ordered by mesh then surface then point.
NOTES:
    renders are done in parallel using all physical cores on the current machine)"
    };
    Strings             rendFiles = splitWhitespace(loadRaw(syn.next()));
    String              imgExt = syn.next();
    if (!contains(getImageFileExts(),toLower(imgExt)))
        syn.error("Unrecognized image format",imgExt);
    auto                runFn = [](String const & rendFile,String const & imgFile)
    {
        try { renderRun(rendFile,imgFile); }
        catch (FgException & e) {fgout << "ERROR: " << rendFile << ": " << e.tr_message(); }
        catch (std::exception & e) { fgout << "ERROR: " << rendFile << ": " << e.what(); }
    };
    PushTimer           pt {"Dispatching renders "};
    ThreadDispatcher    td;
    for (String const & rendFile : rendFiles) {
        String              imgFile = pathToDirBase(rendFile).m_str+"."+imgExt;
        td.dispatch(bind(runFn,rendFile,imgFile));
        fgout << ".";
    }
}

bool                imgApproxEqual(String8 const & file0,String8 const & file1)
{
    ImgRgba8        img0 = loadImage(file0),
                    img1 = loadImage(file1);
    return fgImgApproxEqual(img0,img1,2);
}

}   // namespace

void                cmdRender(CLArgs const & args)
{
    Cmds            cmds {
        {cmdRenderBatch,"batch","batch render from a text file list of configuration file names"},
        {cmdRenderSetup,"setup","setup a render configuration file"},
        {cmdRenderRun,"run","run a render from a configuration file"},
    };
    doMenu(args,cmds);
}

void                testRenderCmd(CLArgs const & args)
{
    FGTESTDIR
    copyFileToCurrentDir("base/Jane.tri");
    copyFileToCurrentDir("base/Jane.jpg");
    copyFileToCurrentDir("base/test/cmd-render.xml");
    RenderArgs          rend = loadBsaXml<RenderArgs>("cmd-render.xml");
    cmdRenderRun(splitChar("run cmd-render.xml cmd-render.png"));
    regressFileRel("cmd-render.png","base/test/",imgApproxEqual);
}

}
<commit_msg>fix cmd render setup options parse<commit_after>//
// Coypright (c) 2022 Singular Inversions Inc. (facegen.com)
// Use, modification and distribution is subject to the MIT License,
// see accompanying file LICENSE.txt or facegen.com/base_library_license.txt
//
// Command to software-render meshes to image files.
//

#include "stdafx.h"

#include "FgCommand.hpp"
#include "FgFileSystem.hpp"
#include "Fg3dMeshIo.hpp"
#include "Fg3dCamera.hpp"
#include "FgSoftRender.hpp"
#include "FgTime.hpp"
#include "FgSyntax.hpp"
#include "FgMetaFormat.hpp"
#include "FgImgDisplay.hpp"
#include "FgParse.hpp"
#include "FgTestUtils.hpp"
#include "FgBuild.hpp"
#include "FgGridTriangles.hpp"

using namespace std;

namespace Fg {

namespace {

struct      ModelFile
{
    String              meshFilename;
    Strings             imgFilenames;
    bool                shiny = false;
    FG_SERIALIZE3(meshFilename,imgFilenames,shiny)
};
typedef Svec<ModelFile>     ModelFiles;

struct      RenderArgs
{
    ModelFiles              models;
    double                  roll = 0,       // Z axis rotation, radians, in order:
                            tilt = 0,       // X axis rotation
                            pan = 0;        // Y axis rotation
    SimilarityD             modelview;      // Transform world to openGL eye coordinate system (OECS)
    // transform from projected coordinates (image tangent CS) to image unit CS (x,y in [0,1]):
    AffineEw2D              itcsToIucs;
    Vec2UI                  imagePixelSize = Vec2UI(512,512);
    RenderOptions           options;

    FG_SERIALIZE8(models,roll,tilt,pan,modelview,itcsToIucs,imagePixelSize,options);
};

Meshes              loadMeshes(ModelFiles const & mfs)
{
    Meshes          meshes;
    for (ModelFile const & mf : mfs) {
        meshes.push_back(loadMesh(mf.meshFilename));
        for (size_t ss=0; ss<mf.imgFilenames.size(); ++ss) {
            if (ss < meshes.back().surfaces.size()) {
                meshes.back().surfaces[ss].setAlbedoMap(loadImage(mf.imgFilenames[ss]));
                meshes.back().surfaces[ss].material.shiny = mf.shiny;
            }
            else
                fgout << "WARNING: more images specified than surfaces for mesh " << mf.meshFilename;
        }
    }
    return meshes;
}

void                cmdRenderSetup(CLArgs const & args)
{
    Syntax              syn {args,
        R"(<name>.xml (-<option> <value>)* (<mesh>.<ext> [<albedo>.])*
    <option>        - (roll | tilt | pan) - specify object pose, with <value> given in degrees
    <ext>           - )" + getMeshLoadExtsCLDescription() + R"(
               - )" + getImageFileExtCLDescriptions() + R"(
OUTPUT:
    <name>.xml      - render configuration file
NOTES:
    * creates default rendering parameters for the given models
    * fields in <name>.xml can be modified as long as the XML structure remains valid
    <name>.xml description:
        <models>
            The list of mesh and related albedo map files to be rendered.
        <roll>,<tilt>,<pan>
            Euler angle rotations in radians applied to the models, in this order, before
            application of <modelview> below. Can be used to orient your meshes for proper viewing
            (FG head coordinate system is X - head's left, Y - head's up, Z - head's forward),
            or to orient the head as desired. Defaults are 0.
        <modelview>
            The similarity transform from mesh coordinates to openGL eye coordinates,
            consisting of scale, rotation (as a quaternion) and translation, applied in that order.
            Default places subject at a viewing distance from the camera to mostly fill the frame.
        <itcsToIucs>
            The 2D transform from projected coordinates ("image tangent CS") to the
            "image unit CS" in which x,y are in [0,1] with origin at top left of image.
        <imagePixelSize>
            Pixel width, height
        <options>
            <lighting> all color component values below are in the range [0,1]:
                <ambient> light coming from all directions.
                <lights>
                    <colour> RGB order
                    <direction> in order of X,Y,Z in OpenGL Eye Coordinates.
            <backgroundColor> RGBA order, values in [0,1].
            <antiAliasBitDepth> 3 is high quality (equivalent to 8x FSAA) without running too slowly
            <renderSurfPoints> 0 - don't, 1 - when visible, 2 - always.
                They are rendered as single-pixel green dots over the image.)"
    };
    string              name = syn.next();
    RenderArgs          rend;
    while (syn.more() && (syn.peekNext()[0] == '-')) {          // options
        String          opt = syn.next();
        if (opt == "-roll")
            rend.roll = degToRad(syn.nextAs<float>());
        else if (opt == "-tilt")
            rend.tilt = degToRad(syn.nextAs<float>());
        else if (opt == "-pan")
            rend.pan = degToRad(syn.nextAs<float>());
        else
            syn.error("Unrecognized option",opt);
    }
    while (syn.more()) {                                        // meshes & maps
        ModelFile           mf;
        mf.meshFilename = syn.next();
        while (syn.more() && hasImageFileExt(syn.peekNext()))
            mf.imgFilenames.push_back(syn.next());
        rend.models.push_back(mf);
    }
    // Load data from files to validate and set modelview:
    Meshes              meshes = loadMeshes(rend.models);
    Mat32F              bounds = cBounds(meshes);
    CameraParams        cps {fgF2D(bounds)};
    cps.logRelScale = std::log(0.9);
    cps.fovMaxDeg = 17.0;
    Camera              cam = cps.camera(rend.imagePixelSize);
    rend.modelview = cam.modelview;
    rend.itcsToIucs = cam.itcsToIucs;
    saveBsaXml(name,rend);
}

void                renderRun(String const & rendFile,String const & outName)
{
    RenderArgs          rend;
    // boost 1.58 introduced an XML deserialization bug on older compilers whereby std::vector
    // is appended rather than overwritten, so we must clear first:
    rend.options.lighting.lights.clear();
    loadBsaXml(rendFile,rend);
    Meshes              meshes = loadMeshes(rend.models);
    // Receive surf point projection data:
    rend.options.projSurfPoints = std::make_shared<ProjectedSurfPoints>();
    SimilarityD         mvm = rend.modelview * cRotateY(rend.pan) * cRotateX(rend.tilt) * cRotateZ(rend.roll);
    ImgRgba8            image = renderSoft(rend.imagePixelSize,meshes,mvm,rend.itcsToIucs,rend.options);
    saveImage(outName,image);
    String8             outBase = pathToBase(outName);
    Ofstream            ofs {outBase+"-landmarks.csv"};
    for (ProjectedSurfPoint const & psp : *rend.options.projSurfPoints)
        ofs << psp.label << "," << psp.posIucs << "," << (psp.visible ? "true" : "false") << "\n";
    Camera              cam {mvm,{},rend.itcsToIucs};
    saveBsaXml(outBase+"-matrix.xml",cam.projectIpcs(rend.imagePixelSize));
}

void                cmdRenderRun(CLArgs const & args)
{
    Syntax              syn {args,
        R"(<in>.xml <out>.
    <in>.xml    - the render configuration file created using 'fgbl render setup'
           - )" + getImageFileExtCLDescriptions() + R"(
OUTPUT:
    <out>.         -   the rendered image
    <out>-matrix.xml    -   the homogeneous combined projection*modelview matrix resulting from the camera model
    <out>-landmarks.csv -   label, image position (IUCS) and visibility of projected surface points,
                            ordered by mesh then surface then point. Surface points can be interactively placed
                            on a mesh (Windoows only) using 'fgbl view mesh' on a single mesh,
                            from the 'Edit' -> 'Points' tab, and saved in either TRI or FGMESH formats.)"
    };
    String              inFile = syn.next(),
                        outFile = syn.next();
    PushTimer           pt {"Rendering and writing files"};
    renderRun(inFile,outFile);
}

void                cmdRenderBatch(CLArgs const & args)
{
    Syntax              syn {args,
        R"(<files>.txt
           - )" + getImageFileExtCLDescriptions() + R"(
OUTPUT:
    for each render parameter file <name>.xml listed in <files>.txt, the following files are created:
    <name>.             the rendered image
    <name>-matrix.xml        the homogeneous combined projection*modelview matrix resulting from the camera model
    <name>-landmarks.csv     label, image position (IUCS) and visibility of projected surface points,
                             ordered by mesh then surface then point.
NOTES:
    renders are done in parallel using all physical cores on the current machine)"
    };
    Strings             rendFiles = splitWhitespace(loadRaw(syn.next()));
    String              imgExt = syn.next();
    if (!contains(getImageFileExts(),toLower(imgExt)))
        syn.error("Unrecognized image format",imgExt);
    auto                runFn = [](String const & rendFile,String const & imgFile)
    {
        try { renderRun(rendFile,imgFile); }
        catch (FgException & e) {fgout << "ERROR: " << rendFile << ": " << e.tr_message(); }
        catch (std::exception & e) { fgout << "ERROR: " << rendFile << ": " << e.what(); }
    };
    PushTimer           pt {"Dispatching renders "};
    ThreadDispatcher    td;
    for (String const & rendFile : rendFiles) {
        String              imgFile = pathToDirBase(rendFile).m_str+"."+imgExt;
        td.dispatch(bind(runFn,rendFile,imgFile));
        fgout << ".";
    }
}

bool                imgApproxEqual(String8 const & file0,String8 const & file1)
{
    ImgRgba8        img0 = loadImage(file0),
                    img1 = loadImage(file1);
    return fgImgApproxEqual(img0,img1,2);
}

}   // namespace

void                cmdRender(CLArgs const & args)
{
    Cmds            cmds {
        {cmdRenderBatch,"batch","batch render from a text file list of configuration file names"},
        {cmdRenderSetup,"setup","setup a render configuration file"},
        {cmdRenderRun,"run","run a render from a configuration file"},
    };
    doMenu(args,cmds);
}

void                testRenderCmd(CLArgs const & args)
{
    FGTESTDIR
    copyFileToCurrentDir("base/Jane.tri");
    copyFileToCurrentDir("base/Jane.jpg");
    copyFileToCurrentDir("base/test/cmd-render.xml");
    RenderArgs          rend = loadBsaXml<RenderArgs>("cmd-render.xml");
    cmdRenderRun(splitChar("run cmd-render.xml cmd-render.png"));
    regressFileRel("cmd-render.png","base/test/",imgApproxEqual);
}

}
<|endoftext|>


<commit_before>#ifndef BEDGE
#define BEDGE

#include "BVect.hpp"

class BEdge {
  private:
    BVect _a;
    BVect _b;
    bool _aClosed;
    bool _bClosed;
    bool _point;
  public:
    BEdge (BVect a, BVect b, bool aC = true, bool bC = true) : _a(a), _b(b), _aClosed(aC), _bClosed(bC), _point(a==b) {}
    BEdge (BVect a) : _a(a), _b(a), _aClosed(true), _bClosed(true), _point(true) {}
    BVect leftPoint() const {return _a;}
    BVect rightPoint() const {return _b;}
    bool isAPoint() const {return _point;}
    bool isInA1AreaOf(const BEdge& be) const {
      return (be.leftPoint().y1() > this->rightPoint().y1() && be.leftPoint().y2() < this->rightPoint().y2());
    }
    bool isInA2AreaOf(const BEdge& be) const {
      return be.isInA1AreaOf(*this);
    }
};

#endif
<commit_msg>BEdge: Reuse BVect method to determine A1 area<commit_after>#ifndef BEDGE
#define BEDGE

#include "BVect.hpp"

class BEdge {
  private:
    BVect _a;
    BVect _b;
    bool _aClosed;
    bool _bClosed;
    bool _point;
  public:
    BEdge (BVect a, BVect b, bool aC = true, bool bC = true) : _a(a), _b(b), _aClosed(aC), _bClosed(bC), _point(a==b) {}
    BEdge (BVect a) : _a(a), _b(a), _aClosed(true), _bClosed(true), _point(true) {}
    BVect leftPoint() const {return _a;}
    BVect rightPoint() const {return _b;}
    bool isAPoint() const {return _point;}
    bool isInA1AreaOf(const BEdge& be) const {
      return (this->rightPoint().isInA1AreaOf(be.leftPoint()));
    }
    bool isInA2AreaOf(const BEdge& be) const {
      return be.isInA1AreaOf(*this);
    }
};

#endif
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: datasetControl.C,v 1.13 2003/10/15 13:26:13 amoll Exp $

#include <BALL/VIEW/WIDGETS/datasetControl.h>
#include <BALL/VIEW/KERNEL/mainControl.h>
#include <BALL/VIEW/KERNEL/message.h>
#include <BALL/KERNEL/system.h>
#include <BALL/FORMAT/DCDFile.h>
#include <BALL/VIEW/DIALOGS/snapShotVisualisation.h>
#include <qpopupmenu.h>
#include <qmenubar.h>
#include <qfiledialog.h>
#include <qlistview.h>
#include <qtooltip.h>

using std::endl;

namespace BALL
{
	namespace VIEW
	{

DatasetControl::DatasetControl(QWidget* parent, const char* name)
	throw()
	:	GenericControl(parent, name),
		dialog_(0)
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "new DatasetControl " << this << std::endl;
#endif
	listview->addColumn("Name");
	listview->addColumn("from");
	listview->addColumn("Type");
	listview->setColumnWidth(0, 120);
	listview->setColumnWidth(1, 60);
	listview->setColumnWidth(2, 60);
	default_visible_ = false;
	connect(listview, SIGNAL(selectionChanged()), this, SLOT(updateSelection()));
}

DatasetControl::~DatasetControl()
	throw()
{
  #ifdef BALL_VIEW_DEBUG
	  Log.error() << "Destructing object " << this << " of class DatasetControl" << std::endl;
  #endif

	if (dialog_) delete dialog_;
}

void DatasetControl::initializeWidget(MainControl& main_control)
	throw()
{
	open_trajectory_id_ =
		main_control.insertMenuEntry(MainControl::FILE_OPEN, "Trajectory", this, SLOT(addTrajectory()), 0, -1,
		String("Open a trajectory file (1 System has to be selected)"));
	open_grid_id_ =
		main_control.insertMenuEntry(MainControl::FILE_OPEN, "3D Grid", this, SLOT(add3DGrid()), 0, -1,
		String("Open a 3D data grid"));
	GenericControl::initializeWidget(main_control);
}

void DatasetControl::finalizeWidget(MainControl& main_control)
	throw()
{
	main_control.removeMenuEntry(MainControl::FILE_OPEN, "Trajectory", this, SLOT(addTrajectory()));
	main_control.removeMenuEntry(MainControl::FILE_OPEN, "3D Grid", this, SLOT(add3DGrid()));
	GenericControl::finalizeWidget(main_control);
}

void DatasetControl::checkMenu(MainControl& main_control)
	throw()
{
	getMainControl()->menuBar()->setItemEnabled(open_trajectory_id_, main_control.getSelectedSystem());
}

void DatasetControl::addTrajectory()
	throw()
{
	if (!getMainControl()->getSelectedSystem()) return;
	QFileDialog *fd = new QFileDialog(this, "", true);
	fd->setMode(QFileDialog::ExistingFile);
	fd->setFilter("DCD files(*.dcd)");
	fd->setCaption("Select a DCD file");
	fd->setViewMode(QFileDialog::Detail);

	if (!fd->exec()== QDialog::Accepted) return;

	String filename(fd->selectedFile().ascii());
	delete fd;

	// construct a name for the system(the filename without the dir path)
	DCDFile* dcd = new DCDFile(filename, File::IN);
	insertTrajectory_(dcd, *getMainControl()->getSelectedSystem());
}

void DatasetControl::insertTrajectory_(TrajectoryFile* file, System& system)
	throw()
{
	if (file->getNumberOfAtoms() != system.countAtoms())
	{
		setStatusbarText("Number of atoms do not match. Aborting...");
		delete file;
		return;
	}

	SnapShotManager* manager = new SnapShotManager(&system, 0, file);

	String name = file->getName();

	Position pos = 0;
	for (Position p = 0; p < name.size(); p++)
	{
		if (name[p] == FileSystem::PATH_SEPARATOR) pos = p;
	}

	if (pos) pos++;
	name = name.getSubstring(pos);

	QListViewItem* item = new QListViewItem(listview, name.c_str(), system.getName().c_str(), "Trajectory");
	item_to_trajectory_[item] = manager;
	insertComposite_(&system, item);
}

void DatasetControl::insertComposite_(Composite* composite, QListViewItem* item)
	throw()
{
	listview->triggerUpdate();
	item_to_composite_[item] = composite;
	if (composite_to_items_.has(composite))
	{
		composite_to_items_[composite].insert(item);
	}
	else
	{
		HashSet<QListViewItem*> set;
		set.insert(item);
		composite_to_items_[composite] = set;
	}
}

void DatasetControl::onNotify(Message *message)
	throw()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "DatasetControl "<<this<<  " onNotify " << message << std::endl;
#endif
	if (RTTI::isKindOf<RegularData3DMessage>(*message))
	{
		RegularData3DMessage* ntm = RTTI::castTo<RegularData3DMessage>(*message);
		insertGrid_(ntm->getRegularData3D(), (System*)ntm->getComposite(), ntm->getCompositeName());
		return;
	}
	else if (RTTI::isKindOf<NewTrajectoryMessage>(*message))
	{
		NewTrajectoryMessage* ntm = RTTI::castTo<NewTrajectoryMessage>(*message);
		insertTrajectory_(ntm->getTrajectoryFile(), *(System*)ntm->getComposite());
		return;
	}
	else if (RTTI::isKindOf<CompositeMessage>(*message))
  {
    CompositeMessage *composite_message = RTTI::castTo<CompositeMessage>(*message);
		if (composite_message->getType() != CompositeMessage::REMOVED_COMPOSITE) return;
    Composite* composite = (Composite *)composite_message->getComposite();
		if (!composite_to_items_.has(composite)) return;

		// create a copy of the hashset, because it changes
		HashSet<QListViewItem*> to_delete = composite_to_items_[composite];

		HashSet<QListViewItem*>::Iterator lit = to_delete.begin();
		for (;lit != to_delete.end(); lit++)
		{
			context_item_ = *lit;
			deleteTrajectory_();
			deleteGrid_();
		}
	}
}

void DatasetControl::deleteTrajectory_()
{
	if (!item_to_trajectory_.has(context_item_)) return;
	SnapShotManager* ssm = item_to_trajectory_[context_item_];
	delete ssm;
	deleteItem_(context_item_);
	setStatusbarText("deleted trajectory");
}

void DatasetControl::deleteItem_(QListViewItem* item)
	throw()
{
	Composite* composite = item_to_composite_[item];
	composite_to_items_[composite].erase(item);
	item_to_trajectory_.erase(item);
	item_to_grid_.erase(item);
	item_to_composite_.erase(item);
	delete item;
	listview->triggerUpdate();
}

void DatasetControl::deleteGrid_()
{
	if (!item_to_grid_.has(context_item_)) return;

	RegularData3D* ssm = item_to_grid_[context_item_];

	RegularData3DMessage* msg = new RegularData3DMessage(RegularData3DMessage::REMOVE);
	msg->setRegularData3D(ssm);
	notify_(msg);

	delete ssm;
	deleteItem_(context_item_);
	setStatusbarText("deleted 3D grid");
}

void DatasetControl::onContextMenu_(QListViewItem* item,  const QPoint& point, int /* column */)
{
	if (item == 0) return;
	context_item_ = item;

	QPopupMenu context_menu;
	if (item_to_trajectory_.has(item))
	{
		context_menu.insertItem("Save", this, SLOT(saveTrajectory_()));
		context_menu.insertItem("Visualise/Export", this, SLOT(visualiseTrajectory_()));
		context_menu.insertItem("Delete", this, SLOT(deleteTrajectory_()));
		//	insertContextMenuEntry("Export to PNGs", this, SLOT(visualiseTrajectory_()));
	}
	else if (item_to_grid_.has(item))
	{
		context_menu.insertItem("Save", this, SLOT(save3DGrid_()));
		context_menu.insertItem("Delete", this, SLOT(deleteGrid_()));
	}

	// show the context menu if it is not empty
	if (context_menu.count()) context_menu.exec(point);
}

void DatasetControl::visualiseTrajectory_()
{
	if (dialog_)
	{
		dialog_->hide();
		delete dialog_;
	}

	SnapShotManager* ssm = item_to_trajectory_[context_item_];

	dialog_ = new SnapshotVisualisationDialog(this);
	dialog_->setSnapShotManager(ssm);
	dialog_->show();
}

void DatasetControl::saveTrajectory_()
{
	SnapShotManager* ssm = item_to_trajectory_[context_item_];

	QFileDialog *fd = new QFileDialog(this, "", true);
	fd->setMode(QFileDialog::AnyFile);
	fd->setFilter("DCD files(*.dcd)");
	fd->setCaption("Write to a DCD file");
	fd->setViewMode(QFileDialog::Detail);

	if (!fd->exec()== QDialog::Accepted) return;

	String filename(fd->selectedFile().ascii());
	ssm->getTrajectoryFile()->copyTo(filename);
	setStatusbarText("Writen DCDFile");
}

void DatasetControl::add3DGrid()
	throw()
{
	QString result = QFileDialog::getOpenFileName("", "*", 0, "Select a RegularData file");
	if (result.isEmpty()) return;

	RegularData3D* dat = new RegularData3D;
	File infile;

	try
	{
		infile.open(result.ascii(), std::ios::in);
	}
	catch(Exception::FileNotFound)
	{
		Log.error() << "File could not be found!" << std::endl;
		return;
	}

	infile >> *dat;
	infile.close();
	insertGrid_(dat, 0, String(result.ascii()));
	RegularData3DMessage* msg = new RegularData3DMessage(RegularData3DMessage::NEW);
	msg->setRegularData3D(dat);
	msg->setComposite(0);
	msg->setCompositeName(result.ascii());
	notify_(msg);
}

void DatasetControl::insertGrid_(RegularData3D* data, System* system, const String& name)
	throw()
{
	QListViewItem* item;
	if (system != 0)
	{
		item = new QListViewItem(listview, name.c_str(), system->getName().c_str(), "3D Grid");
	}
	else
	{
		item = new QListViewItem(listview, name.c_str(), "", "3D Grid");
	}
	item_to_grid_[item] = data;
	insertComposite_(system, item);
}

void DatasetControl::save3DGrid_()
	throw()
{
	String result = QFileDialog::getSaveFileName("", "*", 0, "Select a RegularData file").ascii();
	if (result.isEmpty()) return;

	File outfile;

	try
	{
		outfile.open(result, std::ios::out);
	}
	catch(Exception::GeneralException)
	{
		Log.error() << "File could not be written!" << std::endl;
		return;
	}

	outfile << * item_to_grid_[context_item_];
	outfile.close();
	setStatusbarText("3D Grid successfully written...");
}

void DatasetControl::updateSelection()
	throw()
{
	RegularData3DMessage* message = new RegularData3DMessage(RegularData3DMessage::SELECTED);
	message->setRegularData3D(0);
	QListViewItemIterator it(listview);
	for (; it.current(); ++it)
	{
		QListViewItem* item = it.current();
		if (item->isSelected() &&
				item_to_grid_.has(item))
		{
			message->setRegularData3D(item_to_grid_[item]);
			message->setCompositeName(item->text(0).ascii());
			break;
		}
	}
	notify_(message);
}

List<std::pair<RegularData3D*, String> > DatasetControl::getGrids()
	throw()
{
	List<std::pair<RegularData3D*,String> > grids;
	HashMap<QListViewItem*, RegularData3D*>::Iterator it = item_to_grid_.begin();
	for (; it != item_to_grid_.end(); it++)
	{
		std::pair<RegularData3D*, String> p((*it).second, (*it).first->text(0).ascii());
		grids.push_back(p);
	}
	return grids;
}

} } // namespaces
<commit_msg>improved: deleting of items improved: context menu fixed: core dump when file dialog for saveGrid was canceld<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: datasetControl.C,v 1.14 2003/12/01 19:36:35 amoll Exp $

#include <BALL/VIEW/WIDGETS/datasetControl.h>
#include <BALL/VIEW/KERNEL/mainControl.h>
#include <BALL/VIEW/KERNEL/message.h>
#include <BALL/KERNEL/system.h>
#include <BALL/FORMAT/DCDFile.h>
#include <BALL/VIEW/DIALOGS/snapShotVisualisation.h>
#include <qpopupmenu.h>
#include <qmenubar.h>
#include <qfiledialog.h>
#include <qlistview.h>
#include <qtooltip.h>

using std::endl;

namespace BALL
{
	namespace VIEW
	{

DatasetControl::DatasetControl(QWidget* parent, const char* name)
	throw()
	:	GenericControl(parent, name),
		dialog_(0)
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "new DatasetControl " << this << std::endl;
#endif
	listview->addColumn("Name");
	listview->addColumn("from");
	listview->addColumn("Type");
	listview->setColumnWidth(0, 120);
	listview->setColumnWidth(1, 60);
	listview->setColumnWidth(2, 60);
	default_visible_ = false;
	connect(listview, SIGNAL(selectionChanged()), this, SLOT(updateSelection()));
}

DatasetControl::~DatasetControl()
	throw()
{
  #ifdef BALL_VIEW_DEBUG
	  Log.error() << "Destructing object " << this << " of class DatasetControl" << std::endl;
  #endif

	if (dialog_) delete dialog_;
}

void DatasetControl::initializeWidget(MainControl& main_control)
	throw()
{
	open_trajectory_id_ =
		main_control.insertMenuEntry(MainControl::FILE_OPEN, "Trajectory", this, SLOT(addTrajectory()), 0, -1,
		String("Open a trajectory file (1 System has to be selected)"));
	open_grid_id_ =
		main_control.insertMenuEntry(MainControl::FILE_OPEN, "3D Grid", this, SLOT(add3DGrid()), 0, -1,
		String("Open a 3D data grid"));
	GenericControl::initializeWidget(main_control);
}

void DatasetControl::finalizeWidget(MainControl& main_control)
	throw()
{
	main_control.removeMenuEntry(MainControl::FILE_OPEN, "Trajectory", this, SLOT(addTrajectory()));
	main_control.removeMenuEntry(MainControl::FILE_OPEN, "3D Grid", this, SLOT(add3DGrid()));
	GenericControl::finalizeWidget(main_control);
}

void DatasetControl::checkMenu(MainControl& main_control)
	throw()
{
	getMainControl()->menuBar()->setItemEnabled(open_trajectory_id_, main_control.getSelectedSystem());
}

void DatasetControl::addTrajectory()
	throw()
{
	if (!getMainControl()->getSelectedSystem()) return;
	QFileDialog *fd = new QFileDialog(this, "", true);
	fd->setMode(QFileDialog::ExistingFile);
	fd->setFilter("DCD files(*.dcd)");
	fd->setCaption("Select a DCD file");
	fd->setViewMode(QFileDialog::Detail);

	if (!fd->exec()== QDialog::Accepted) return;

	String filename(fd->selectedFile().ascii());
	delete fd;

	// construct a name for the system(the filename without the dir path)
	DCDFile* dcd = new DCDFile(filename, File::IN);
	insertTrajectory_(dcd, *getMainControl()->getSelectedSystem());
}

void DatasetControl::insertTrajectory_(TrajectoryFile* file, System& system)
	throw()
{
	if (file->getNumberOfAtoms() != system.countAtoms())
	{
		setStatusbarText("Number of atoms do not match. Aborting...");
		delete file;
		return;
	}

	SnapShotManager* manager = new SnapShotManager(&system, 0, file);

	String name = file->getName();

	Position pos = 0;
	for (Position p = 0; p < name.size(); p++)
	{
		if (name[p] == FileSystem::PATH_SEPARATOR) pos = p;
	}

	if (pos) pos++;
	name = name.getSubstring(pos);

	QListViewItem* item = new QListViewItem(listview, name.c_str(), system.getName().c_str(), "Trajectory");
	item_to_trajectory_[item] = manager;
	insertComposite_(&system, item);
}

void DatasetControl::insertComposite_(Composite* composite, QListViewItem* item)
	throw()
{
	listview->triggerUpdate();
	item_to_composite_[item] = composite;
	if (composite_to_items_.has(composite))
	{
		composite_to_items_[composite].insert(item);
	}
	else
	{
		HashSet<QListViewItem*> set;
		set.insert(item);
		composite_to_items_[composite] = set;
	}
}

void DatasetControl::onNotify(Message *message)
	throw()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "DatasetControl "<<this<<  " onNotify " << message << std::endl;
#endif
	if (RTTI::isKindOf<RegularData3DMessage>(*message))
	{
		RegularData3DMessage* ntm = RTTI::castTo<RegularData3DMessage>(*message);
		insertGrid_(ntm->getRegularData3D(), (System*)ntm->getComposite(), ntm->getCompositeName());
		return;
	}
	else if (RTTI::isKindOf<NewTrajectoryMessage>(*message))
	{
		NewTrajectoryMessage* ntm = RTTI::castTo<NewTrajectoryMessage>(*message);
		insertTrajectory_(ntm->getTrajectoryFile(), *(System*)ntm->getComposite());
		return;
	}
	else if (RTTI::isKindOf<CompositeMessage>(*message))
  {
    CompositeMessage *composite_message = RTTI::castTo<CompositeMessage>(*message);
		if (composite_message->getType() != CompositeMessage::REMOVED_COMPOSITE) return;
    Composite* composite = (Composite *)composite_message->getComposite();
		if (!composite_to_items_.has(composite)) return;

		// create a copy of the hashset, because it changes
		HashSet<QListViewItem*> to_delete = composite_to_items_[composite];

		HashSet<QListViewItem*>::Iterator lit = to_delete.begin();
		for (;lit != to_delete.end(); lit++)
		{
			deleteItem_(**lit);
		}
	}
}

void DatasetControl::deleteItems_()
{
	ItemList item_list = getSelectedItems();
	ItemList::Iterator it = item_list.begin();
	for (; it != item_list.end(); it++)
	{
		deleteItem_(**it);
	}
}

void DatasetControl::deleteItem_(QListViewItem& item)
{
	if (!item_to_trajectory_.has(&item) &&
			!item_to_grid_.has(&item))
	{
		return;
	}

	if (item_to_trajectory_.has(&item))
	{
		SnapShotManager* ssm = item_to_trajectory_[&item];
		item_to_trajectory_.erase(&item);
		delete ssm;
		setStatusbarText("deleted trajectory");
	}
	else
	{
		RegularData3D* ssm = item_to_grid_[&item];

		RegularData3DMessage* msg = new RegularData3DMessage(RegularData3DMessage::REMOVE);
		msg->setRegularData3D(ssm);
		notify_(msg);

		item_to_grid_.erase(&item);
		delete ssm;
		setStatusbarText("deleted 3D grid");
	}

	Composite* composite = item_to_composite_[&item];
	composite_to_items_[composite].erase(&item);
	item_to_composite_.erase(&item);
	delete &item;
	listview->triggerUpdate();
}

void DatasetControl::onContextMenu_(QListViewItem* item,  const QPoint& point, int /* column */)
{
	if (item == 0) return;
	context_item_ = item;

	Position menu_entry_pos;
	Size nr_items = getSelectedItems().size();
	QPopupMenu context_menu;
	if (item_to_trajectory_.has(item))
	{
		menu_entry_pos = context_menu.insertItem("Save", this, SLOT(saveTrajectory_()));
		if (nr_items > 1) context_menu.setItemEnabled(menu_entry_pos, false);
		menu_entry_pos = context_menu.insertItem("Visualise/Export", this, SLOT(visualiseTrajectory_()));
		if (nr_items > 1) context_menu.setItemEnabled(menu_entry_pos, false);
	}
	else if (item_to_grid_.has(item))
	{
		menu_entry_pos = context_menu.insertItem("Save", this, SLOT(save3DGrid_()));
		if (nr_items > 1) context_menu.setItemEnabled(menu_entry_pos, false);
	}
	context_menu.insertItem("Delete", this, SLOT(deleteItems_()));

	// show the context menu if it is not empty
	if (context_menu.count()) context_menu.exec(point);
}

void DatasetControl::visualiseTrajectory_()
{
	if (dialog_)
	{
		dialog_->hide();
		delete dialog_;
	}

	SnapShotManager* ssm = item_to_trajectory_[context_item_];

	dialog_ = new SnapshotVisualisationDialog(this);
	dialog_->setSnapShotManager(ssm);
	dialog_->show();
}

void DatasetControl::saveTrajectory_()
{
	SnapShotManager* ssm = item_to_trajectory_[context_item_];

	QFileDialog *fd = new QFileDialog(this, "", true);
	fd->setMode(QFileDialog::AnyFile);
	fd->setFilter("DCD files(*.dcd)");
	fd->setCaption("Write to a DCD file");
	fd->setViewMode(QFileDialog::Detail);

	if (!fd->exec()== QDialog::Accepted) return;

	String filename(fd->selectedFile().ascii());
	ssm->getTrajectoryFile()->copyTo(filename);
	setStatusbarText("Writen DCDFile");
}

void DatasetControl::add3DGrid()
	throw()
{
	QString result = QFileDialog::getOpenFileName("", "*", 0, "Select a RegularData file");
	if (result.isEmpty()) return;

	RegularData3D* dat = new RegularData3D;
	File infile;

	try
	{
		infile.open(result.ascii(), std::ios::in);
	}
	catch(Exception::FileNotFound)
	{
		Log.error() << "File could not be found!" << std::endl;
		return;
	}

	infile >> *dat;
	infile.close();
	insertGrid_(dat, 0, String(result.ascii()));
	RegularData3DMessage* msg = new RegularData3DMessage(RegularData3DMessage::NEW);
	msg->setRegularData3D(dat);
	msg->setComposite(0);
	msg->setCompositeName(result.ascii());
	notify_(msg);
}

void DatasetControl::insertGrid_(RegularData3D* data, System* system, const String& name)
	throw()
{
	QListViewItem* item;
	if (system != 0)
	{
		item = new QListViewItem(listview, name.c_str(), system->getName().c_str(), "3D Grid");
	}
	else
	{
		item = new QListViewItem(listview, name.c_str(), "", "3D Grid");
	}
	item_to_grid_[item] = data;
	insertComposite_(system, item);
}

void DatasetControl::save3DGrid_()
	throw()
{
	QString qs = QFileDialog::getSaveFileName("", "*", 0, "Select a RegularData file");
	if (qs == QString::null) return;

	String result = qs.ascii();
	if (result.isEmpty()) return;

	File outfile;

	try
	{
		outfile.open(result, std::ios::out);
	}
	catch(Exception::GeneralException)
	{
		Log.error() << "File could not be written!" << std::endl;
		return;
	}

	outfile << * item_to_grid_[context_item_];
	outfile.close();
	setStatusbarText("3D Grid successfully written...");
}

void DatasetControl::updateSelection()
	throw()
{
	RegularData3DMessage* message = new RegularData3DMessage(RegularData3DMessage::SELECTED);
	message->setRegularData3D(0);
	QListViewItemIterator it(listview);
	for (; it.current(); ++it)
	{
		QListViewItem* item = it.current();
		if (item->isSelected() &&
				item_to_grid_.has(item))
		{
			message->setRegularData3D(item_to_grid_[item]);
			message->setCompositeName(item->text(0).ascii());
			break;
		}
	}
	notify_(message);
}

List<std::pair<RegularData3D*, String> > DatasetControl::getGrids()
	throw()
{
	List<std::pair<RegularData3D*,String> > grids;
	HashMap<QListViewItem*, RegularData3D*>::Iterator it = item_to_grid_.begin();
	for (; it != item_to_grid_.end(); it++)
	{
		std::pair<RegularData3D*, String> p((*it).second, (*it).first->text(0).ascii());
		grids.push_back(p);
	}
	return grids;
}

} } // namespaces
<|endoftext|>


<commit_before>#ifndef slic3r_BoundingBox_hpp_
#define slic3r_BoundingBox_hpp_

#include "libslic3r.h"
#include "Point.hpp"
#include "Polygon.hpp"

namespace Slic3r {

typedef Point   Size;
typedef Point3  Size3;
typedef Pointf  Sizef;
typedef Pointf3 Sizef3;

template <class PointClass>
class BoundingBoxBase
{
public:
    PointClass min;
    PointClass max;
    bool defined;

    BoundingBoxBase() : defined(false) {};
    BoundingBoxBase(const PointClass &pmin, const PointClass &pmax) :
        min(pmin), max(pmax), defined(pmin.x < pmax.x && pmin.y < pmax.y) {}
    BoundingBoxBase(const std::vector<PointClass>& points)
    {
        if (points.empty())
            CONFESS("Empty point set supplied to BoundingBoxBase constructor");

        typename std::vector<PointClass>::const_iterator it = points.begin();
        this->min.x = this->max.x = it->x;
        this->min.y = this->max.y = it->y;
        for (++it; it != points.end(); ++it)
        {
            this->min.x = std::min(it->x, this->min.x);
            this->min.y = std::min(it->y, this->min.y);
            this->max.x = std::max(it->x, this->max.x);
            this->max.y = std::max(it->y, this->max.y);
        }
        this->defined = (this->min.x < this->max.x) && (this->min.y < this->max.y);
    }
    void merge(const PointClass &point);
    void merge(const std::vector<PointClass> &points);
    void merge(const BoundingBoxBase<PointClass> &bb);
    void scale(double factor);
    PointClass size() const;
    double radius() const;
    void translate(coordf_t x, coordf_t y) { assert(this->defined); this->min.translate(x, y); this->max.translate(x, y); }
    void translate(const Pointf &pos) { this->translate(pos.x, pos.y); }
    void offset(coordf_t delta);
    PointClass center() const;
    bool contains(const PointClass &point) const {
        return point.x >= this->min.x && point.x <= this->max.x
            && point.y >= this->min.y && point.y <= this->max.y;
    }
    bool overlap(const BoundingBoxBase<PointClass> &other) const {
        return ! (this->max.x < other.min.x || this->min.x > other.max.x ||
                  this->max.y < other.min.y || this->min.y > other.max.y);
    }
    bool operator==(const BoundingBoxBase<PointClass> &rhs) { return this->min == rhs.min && this->max == rhs.max; }
    bool operator!=(const BoundingBoxBase<PointClass> &rhs) { return ! (*this == rhs); }
};

template <class PointClass>
class BoundingBox3Base : public BoundingBoxBase<PointClass>
{
public:
    BoundingBox3Base() : BoundingBoxBase<PointClass>() {};
    BoundingBox3Base(const PointClass &pmin, const PointClass &pmax) :
        BoundingBoxBase<PointClass>(pmin, pmax)
        { if (pmin.z >= pmax.z) BoundingBoxBase<PointClass>::defined = false; }
    BoundingBox3Base(const std::vector<PointClass>& points)
        : BoundingBoxBase<PointClass>(points)
    {
        if (points.empty())
            CONFESS("Empty point set supplied to BoundingBox3Base constructor");

        typename std::vector<PointClass>::const_iterator it = points.begin();
        this->min.z = this->max.z = it->z;
        for (++it; it != points.end(); ++it)
        {
            this->min.z = std::min(it->z, this->min.z);
            this->max.z = std::max(it->z, this->max.z);
        }
        this->defined &= (this->min.z < this->max.z);
    }
    void merge(const PointClass &point);
    void merge(const std::vector<PointClass> &points);
    void merge(const BoundingBox3Base<PointClass> &bb);
    PointClass size() const;
    double radius() const;
    void translate(coordf_t x, coordf_t y, coordf_t z) { this->min.translate(x, y, z); this->max.translate(x, y, z); }
    void translate(const Pointf3 &pos) { this->translate(pos.x, pos.y, pos.z); }
    void offset(coordf_t delta);
    PointClass center() const;
    coordf_t max_size() const;

    bool contains(const PointClass &point) const {
        return BoundingBoxBase<PointClass>::contains(point) && point.z >= this->min.z && point.z <= this->max.z;
    }

    bool contains(const BoundingBox3Base<PointClass>& other) const {
        return contains(other.min) && contains(other.max);
    }

    bool intersects(const BoundingBox3Base<PointClass>& other) const {
        return (min.x < other.max.x) && (max.x > other.min.x) && (min.y < other.max.y) && (max.y > other.min.y) && (min.z < other.max.z) && (max.z > other.min.z);
    }
};

class BoundingBox : public BoundingBoxBase<Point>
{
public:
    void polygon(Polygon* polygon) const;
    Polygon polygon() const;
    BoundingBox rotated(double angle) const;
    BoundingBox rotated(double angle, const Point &center) const;
    void rotate(double angle) { (*this) = this->rotated(angle); }
    void rotate(double angle, const Point &center) { (*this) = this->rotated(angle, center); }
    // Align the min corner to a grid of cell_size x cell_size cells,
    // to encompass the original bounding box.
    void align_to_grid(const coord_t cell_size);

    BoundingBox() : BoundingBoxBase<Point>() {};
    BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point>(pmin, pmax) {};
    BoundingBox(const Points &points) : BoundingBoxBase<Point>(points) {};
    BoundingBox(const Lines &lines);

    friend BoundingBox get_extents_rotated(const Points &points, double angle);
};

class BoundingBox3  : public BoundingBox3Base<Point3>
{
public:
    BoundingBox3() : BoundingBox3Base<Point3>() {};
    BoundingBox3(const Point3 &pmin, const Point3 &pmax) : BoundingBox3Base<Point3>(pmin, pmax) {};
    BoundingBox3(const Points3& points) : BoundingBox3Base<Point3>(points) {};
};

class BoundingBoxf : public BoundingBoxBase<Pointf>
{
public:
    BoundingBoxf() : BoundingBoxBase<Pointf>() {};
    BoundingBoxf(const Pointf &pmin, const Pointf &pmax) : BoundingBoxBase<Pointf>(pmin, pmax) {};
    BoundingBoxf(const std::vector<Pointf> &points) : BoundingBoxBase<Pointf>(points) {};
};

class BoundingBoxf3 : public BoundingBox3Base<Pointf3>
{
public:
    BoundingBoxf3() : BoundingBox3Base<Pointf3>() {};
    BoundingBoxf3(const Pointf3 &pmin, const Pointf3 &pmax) : BoundingBox3Base<Pointf3>(pmin, pmax) {};
    BoundingBoxf3(const std::vector<Pointf3> &points) : BoundingBox3Base<Pointf3>(points) {};

    BoundingBoxf3 transformed(const std::vector<float>& matrix) const;
};

template<typename VT>
inline bool empty(const BoundingBoxBase<VT> &bb)
{
    return ! bb.defined || bb.min.x >= bb.max.x || bb.min.y >= bb.max.y;
}

template<typename VT>
inline bool empty(const BoundingBox3Base<VT> &bb)
{
    return ! bb.defined || bb.min.x >= bb.max.x || bb.min.y >= bb.max.y || bb.min.z >= bb.max.z;
}

} // namespace Slic3r

#endif
<commit_msg>Fixed compile on Linux and Mac<commit_after>#ifndef slic3r_BoundingBox_hpp_
#define slic3r_BoundingBox_hpp_

#include "libslic3r.h"
#include "Point.hpp"
#include "Polygon.hpp"

namespace Slic3r {

typedef Point   Size;
typedef Point3  Size3;
typedef Pointf  Sizef;
typedef Pointf3 Sizef3;

template <class PointClass>
class BoundingBoxBase
{
public:
    PointClass min;
    PointClass max;
    bool defined;

    BoundingBoxBase() : defined(false) {};
    BoundingBoxBase(const PointClass &pmin, const PointClass &pmax) :
        min(pmin), max(pmax), defined(pmin.x < pmax.x && pmin.y < pmax.y) {}
    BoundingBoxBase(const std::vector<PointClass>& points)
    {
        if (points.empty())
            CONFESS("Empty point set supplied to BoundingBoxBase constructor");

        typename std::vector<PointClass>::const_iterator it = points.begin();
        this->min.x = this->max.x = it->x;
        this->min.y = this->max.y = it->y;
        for (++it; it != points.end(); ++it)
        {
            this->min.x = std::min(it->x, this->min.x);
            this->min.y = std::min(it->y, this->min.y);
            this->max.x = std::max(it->x, this->max.x);
            this->max.y = std::max(it->y, this->max.y);
        }
        this->defined = (this->min.x < this->max.x) && (this->min.y < this->max.y);
    }
    void merge(const PointClass &point);
    void merge(const std::vector<PointClass> &points);
    void merge(const BoundingBoxBase<PointClass> &bb);
    void scale(double factor);
    PointClass size() const;
    double radius() const;
    void translate(coordf_t x, coordf_t y) { assert(this->defined); this->min.translate(x, y); this->max.translate(x, y); }
    void translate(const Pointf &pos) { this->translate(pos.x, pos.y); }
    void offset(coordf_t delta);
    PointClass center() const;
    bool contains(const PointClass &point) const {
        return point.x >= this->min.x && point.x <= this->max.x
            && point.y >= this->min.y && point.y <= this->max.y;
    }
    bool overlap(const BoundingBoxBase<PointClass> &other) const {
        return ! (this->max.x < other.min.x || this->min.x > other.max.x ||
                  this->max.y < other.min.y || this->min.y > other.max.y);
    }
    bool operator==(const BoundingBoxBase<PointClass> &rhs) { return this->min == rhs.min && this->max == rhs.max; }
    bool operator!=(const BoundingBoxBase<PointClass> &rhs) { return ! (*this == rhs); }
};

template <class PointClass>
class BoundingBox3Base : public BoundingBoxBase<PointClass>
{
public:
    BoundingBox3Base() : BoundingBoxBase<PointClass>() {};
    BoundingBox3Base(const PointClass &pmin, const PointClass &pmax) :
        BoundingBoxBase<PointClass>(pmin, pmax)
        { if (pmin.z >= pmax.z) BoundingBoxBase<PointClass>::defined = false; }
    BoundingBox3Base(const std::vector<PointClass>& points)
        : BoundingBoxBase<PointClass>(points)
    {
        if (points.empty())
            CONFESS("Empty point set supplied to BoundingBox3Base constructor");

        typename std::vector<PointClass>::const_iterator it = points.begin();
        this->min.z = this->max.z = it->z;
        for (++it; it != points.end(); ++it)
        {
            this->min.z = std::min(it->z, this->min.z);
            this->max.z = std::max(it->z, this->max.z);
        }
        this->defined &= (this->min.z < this->max.z);
    }
    void merge(const PointClass &point);
    void merge(const std::vector<PointClass> &points);
    void merge(const BoundingBox3Base<PointClass> &bb);
    PointClass size() const;
    double radius() const;
    void translate(coordf_t x, coordf_t y, coordf_t z) { this->min.translate(x, y, z); this->max.translate(x, y, z); }
    void translate(const Pointf3 &pos) { this->translate(pos.x, pos.y, pos.z); }
    void offset(coordf_t delta);
    PointClass center() const;
    coordf_t max_size() const;

    bool contains(const PointClass &point) const {
        return BoundingBoxBase<PointClass>::contains(point) && point.z >= this->min.z && point.z <= this->max.z;
    }

    bool contains(const BoundingBox3Base<PointClass>& other) const {
        return contains(other.min) && contains(other.max);
    }

    bool intersects(const BoundingBox3Base<PointClass>& other) const {
        return (this->min.x < other.max.x) && (this->max.x > other.min.x) && (this->min.y < other.max.y) && (this->max.y > other.min.y) && (this->min.z < other.max.z) && (this->max.z > other.min.z);
    }
};

class BoundingBox : public BoundingBoxBase<Point>
{
public:
    void polygon(Polygon* polygon) const;
    Polygon polygon() const;
    BoundingBox rotated(double angle) const;
    BoundingBox rotated(double angle, const Point &center) const;
    void rotate(double angle) { (*this) = this->rotated(angle); }
    void rotate(double angle, const Point &center) { (*this) = this->rotated(angle, center); }
    // Align the min corner to a grid of cell_size x cell_size cells,
    // to encompass the original bounding box.
    void align_to_grid(const coord_t cell_size);

    BoundingBox() : BoundingBoxBase<Point>() {};
    BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point>(pmin, pmax) {};
    BoundingBox(const Points &points) : BoundingBoxBase<Point>(points) {};
    BoundingBox(const Lines &lines);

    friend BoundingBox get_extents_rotated(const Points &points, double angle);
};

class BoundingBox3  : public BoundingBox3Base<Point3>
{
public:
    BoundingBox3() : BoundingBox3Base<Point3>() {};
    BoundingBox3(const Point3 &pmin, const Point3 &pmax) : BoundingBox3Base<Point3>(pmin, pmax) {};
    BoundingBox3(const Points3& points) : BoundingBox3Base<Point3>(points) {};
};

class BoundingBoxf : public BoundingBoxBase<Pointf>
{
public:
    BoundingBoxf() : BoundingBoxBase<Pointf>() {};
    BoundingBoxf(const Pointf &pmin, const Pointf &pmax) : BoundingBoxBase<Pointf>(pmin, pmax) {};
    BoundingBoxf(const std::vector<Pointf> &points) : BoundingBoxBase<Pointf>(points) {};
};

class BoundingBoxf3 : public BoundingBox3Base<Pointf3>
{
public:
    BoundingBoxf3() : BoundingBox3Base<Pointf3>() {};
    BoundingBoxf3(const Pointf3 &pmin, const Pointf3 &pmax) : BoundingBox3Base<Pointf3>(pmin, pmax) {};
    BoundingBoxf3(const std::vector<Pointf3> &points) : BoundingBox3Base<Pointf3>(points) {};

    BoundingBoxf3 transformed(const std::vector<float>& matrix) const;
};

template<typename VT>
inline bool empty(const BoundingBoxBase<VT> &bb)
{
    return ! bb.defined || bb.min.x >= bb.max.x || bb.min.y >= bb.max.y;
}

template<typename VT>
inline bool empty(const BoundingBox3Base<VT> &bb)
{
    return ! bb.defined || bb.min.x >= bb.max.x || bb.min.y >= bb.max.y || bb.min.z >= bb.max.z;
}

} // namespace Slic3r

#endif
<|endoftext|>


<commit_before>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/indexQuadtree.h>
#include <geos/util.h>

namespace geos {

double
DoubleBits::powerOf2(int exp)
{
	if (exp>1023 || exp<-1022)
		throw new IllegalArgumentException("Exponent out of bounds");
#if 0
	long expBias=exp+EXPONENT_BIAS;
	int64 bits=(int64)expBias << 52;
	return (double) bits;
#else
	return pow(2.0, exp);
#endif
}

int
DoubleBits::exponent(double d)
{
	//DoubleBits db(d);
	//return db.getExponent();
	return (int)log(d)/log(2.0);
}

double
DoubleBits::truncateToPowerOfTwo(double d)
{
	auto_ptr<DoubleBits> db(new DoubleBits(d));
	db->zeroLowerBits(52);
	return db->getDouble();
}

string DoubleBits::toBinaryString(double d) {
	auto_ptr<DoubleBits> db(new DoubleBits(d));
	return db->toString();
}

double
DoubleBits::maximumCommonMantissa(double d1, double d2)
{
	if (d1==0.0 || d2==0.0) return 0.0;
	auto_ptr<DoubleBits> db1(new DoubleBits(d1));
	DoubleBits *db2=new DoubleBits(d2);
	if (db1->getExponent()!=db2->getExponent()) return 0.0;
	int maxCommon=db1->numCommonMantissaBits(db2);
	delete db2;
	db1->zeroLowerBits(64-(12+maxCommon));
	return db1->getDouble();
}

DoubleBits::DoubleBits(double nx)
{
	xBits=(int64)nx;
}

double DoubleBits::getDouble()
{
	return (double)xBits;
}

/**
 * Determines the exponent for the number
 *
 * @return
 */
int64
DoubleBits::biasedExponent()
{
	int64 signExp=(int64)(xBits>>52);
	int64 exp=signExp&0x07ff;
	return exp;
}

/*
 * Determines the exponent for the number
 *
 * @return
 */
int
DoubleBits::getExponent()
{
	return biasedExponent()-EXPONENT_BIAS;
}

void
DoubleBits::zeroLowerBits(int nBits)
{
	long invMask=(1L<<nBits)-1L;
	long mask=~invMask;
	xBits&=mask;
}

int
DoubleBits::getBit(int i)
{
	long mask=(1L<<i);
	return (xBits&mask)!=0?1:0;
}

/**
 * This computes the number of common most-significant bits in the mantissa.
 * It does not count the hidden bit, which is always 1.
 * It does not determine whether the numbers have the same exponent - if they do
 * not, the value computed by this function is meaningless.
 * @param db
 * @return the number of common most-significant mantissa bits
 */
int DoubleBits::numCommonMantissaBits(DoubleBits *db) {
	for (int i=0;i<52;i++) {
		int bitIndex=i+12;
		if (getBit(i)!=db->getBit(i))
			return i;
	}
	return 52;
}

/**
* A representation of the Double bits formatted for easy readability
* @return
*/
string DoubleBits::toString() {
//String numStr = Long.toBinaryString(xBits);
//// 64 zeroes!
//String zero64 = "0000000000000000000000000000000000000000000000000000000000000000";
//String padStr =  zero64 + numStr;
//String bitStr = padStr.substring(padStr.length() - 64);
//String str = bitStr.substring(0, 1) + "  "
//+ bitStr.substring(1, 12) + "(" + getExponent() + ") "
//+ bitStr.substring(12)
//+ " [ " + x + " ]";
//return str;
	return "";
}

} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.12  2004/11/01 16:43:04  strk
 * Added Profiler code.
 * Temporarly patched a bug in DoubleBits (must check drawbacks).
 * Various cleanups and speedups.
 *
 * Revision 1.11  2004/09/21 09:47:01  strk
 * Removed useless auto_ptr usage in ::exponent
 *
 * Revision 1.10  2004/07/02 13:28:27  strk
 * Fixed all #include lines to reflect headers layout change.
 * Added client application build tips in README.
 *
 * Revision 1.9  2003/11/07 01:23:42  pramsey
 * Add standard CVS headers licence notices and copyrights to all cpp and h
 * files.
 *
 *
 **********************************************************************/

<commit_msg>Fixed bug in IEEE-based exponent and PowerOf2 computation, but disabled at compile time.<commit_after>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/indexQuadtree.h>
#include <geos/util.h>

// Threating FP number as IEEE formatted will make the code
// loose portability w/out really speed things up
#define IEEE_DOUBLE 0

namespace geos {

double
DoubleBits::powerOf2(int exp)
{
	if (exp>1023 || exp<-1022)
		throw new IllegalArgumentException("Exponent out of bounds");
#ifdef IEEE_DOUBLE
	long expBias=exp+EXPONENT_BIAS;
	int64 bits=(int64)expBias << 52;
	return (double) bits;
#else
	return pow(2.0, exp);
#endif
}

int
DoubleBits::exponent(double d)
{
#ifdef IEEE_DOUBLE
	DoubleBits db(d);
	return db.getExponent();
#else
	return (int)(log(d)/log(2.0));
#endif
}

double
DoubleBits::truncateToPowerOfTwo(double d)
{
	auto_ptr<DoubleBits> db(new DoubleBits(d));
	db->zeroLowerBits(52);
	return db->getDouble();
}

string DoubleBits::toBinaryString(double d) {
	auto_ptr<DoubleBits> db(new DoubleBits(d));
	return db->toString();
}

double
DoubleBits::maximumCommonMantissa(double d1, double d2)
{
	if (d1==0.0 || d2==0.0) return 0.0;
	auto_ptr<DoubleBits> db1(new DoubleBits(d1));
	DoubleBits *db2=new DoubleBits(d2);
	if (db1->getExponent()!=db2->getExponent()) return 0.0;
	int maxCommon=db1->numCommonMantissaBits(db2);
	delete db2;
	db1->zeroLowerBits(64-(12+maxCommon));
	return db1->getDouble();
}

DoubleBits::DoubleBits(double nx)
{
	memcpy(&xBits,&nx,sizeof(double));
}

double DoubleBits::getDouble()
{
	return (double)xBits;
}

/**
 * Determines the exponent for the number
 *
 * @return
 */
int64
DoubleBits::biasedExponent()
{
	int64 signExp=xBits>>52;
	int64 exp=signExp&0x07ff;
	//cerr<<"xBits:"<<xBits<<" signExp:"<<signExp<<" exp:"<<exp<<endl;
	return exp;
}

/*
 * Determines the exponent for the number
 *
 * @return
 */
int
DoubleBits::getExponent()
{
	return biasedExponent()-EXPONENT_BIAS;
}

void
DoubleBits::zeroLowerBits(int nBits)
{
	long invMask=(1L<<nBits)-1L;
	long mask=~invMask;
	xBits&=mask;
}

int
DoubleBits::getBit(int i)
{
	long mask=(1L<<i);
	return (xBits&mask)!=0?1:0;
}

/**
 * This computes the number of common most-significant bits in the mantissa.
 * It does not count the hidden bit, which is always 1.
 * It does not determine whether the numbers have the same exponent - if they do
 * not, the value computed by this function is meaningless.
 * @param db
 * @return the number of common most-significant mantissa bits
 */
int DoubleBits::numCommonMantissaBits(DoubleBits *db) {
	for (int i=0;i<52;i++) {
		int bitIndex=i+12;
		if (getBit(i)!=db->getBit(i))
			return i;
	}
	return 52;
}

/**
* A representation of the Double bits formatted for easy readability
* @return
*/
string DoubleBits::toString() {
//String numStr = Long.toBinaryString(xBits);
//// 64 zeroes!
//String zero64 = "0000000000000000000000000000000000000000000000000000000000000000";
//String padStr =  zero64 + numStr;
//String bitStr = padStr.substring(padStr.length() - 64);
//String str = bitStr.substring(0, 1) + "  "
//+ bitStr.substring(1, 12) + "(" + getExponent() + ") "
//+ bitStr.substring(12)
//+ " [ " + x + " ]";
//return str;
	return "";
}

} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.13  2004/11/02 14:13:38  strk
 * Fixed bug in IEEE-based exponent and PowerOf2 computation, but disabled
 * at compile time.
 *
 * Revision 1.12  2004/11/01 16:43:04  strk
 * Added Profiler code.
 * Temporarly patched a bug in DoubleBits (must check drawbacks).
 * Various cleanups and speedups.
 *
 * Revision 1.11  2004/09/21 09:47:01  strk
 * Removed useless auto_ptr usage in ::exponent
 *
 * Revision 1.10  2004/07/02 13:28:27  strk
 * Fixed all #include lines to reflect headers layout change.
 * Added client application build tips in README.
 *
 * Revision 1.9  2003/11/07 01:23:42  pramsey
 * Add standard CVS headers licence notices and copyrights to all cpp and h
 * files.
 *
 *
 **********************************************************************/

<|endoftext|>


<commit_before>//******************************************************************************
// Board.cpp
// Revision History:
//
// Date           Author               Description
// 11/28/2017     Jason Chen           Added class
//******************************************************************************

#include <iostream>
#include <sstream>
#include <string>
#include "Deck.h"
#include "Hand.h"
#include "Card.h"
#include "Board.h"
#include "Player.h"
#include "ConsoleUI.h"
#include "helper.h"
using namespace std;

//constructor
//initialize the board for a new game
Board::Board(Player* hum, Player* AI, int smallBlindPlayer)
{
	human = hum;
	this->AI=AI;
	setCommunity();
	help=new helper();
	this->smallBlindPlayer=smallBlindPlayer;
}

void Board::setBlind(int bld)
{
	smallBlind = bld;
}

void Board::resetPot(){
	pot=0;
}

void Board::setCommunity()
{
	for(int i = 0; i < 5; i++)
	{
		community[i] = dek.draw();
	}
	//set player cards
	human->addOne(dek.draw());
	human->addTwo(dek.draw());
	AI->addOne(dek.draw());
	AI->addTwo(dek.draw());
}

void Board::printBoard()
{
	ConsoleUI* ui=new ConsoleUI();
	ui->output("");
	ui->output(AI->getName()+":\t$"+to_string(AI->getTotalChips()));
	ui->output("\t$"+to_string(AI->getTempPool()));
	ui->output("");
	ui->output("Pot:\t$"+to_string(pot));
	ui->output("");
	ui->output("\t$"+to_string(human->getTempPool()));
	ui->output(human->getName()+":\t$"+to_string(human->getTotalChips()));
	ui->output("");
	ui->output("*******************************");
}

bool Board::run()
{
	printBoard();
	string inputTemp;
	ConsoleUI* ui = new ConsoleUI();
	ui->output("Your turn: \n");
	if(human ->getTotalChips() < AI->getPrevBet())
	{
		inputTemp = ui->input("Fold (1) or All in (4)");
		while (!help->isInt(inputTemp)||(stoi(inputTemp)!=1 && stoi(inputTemp)!=4))
		{
			ui->output("Input must a choice number provided");
			inputTemp=ui->input("Fold (1) or All in (4)");
		}
	}
	else if(human->getTotalChips() < 2*AI->getPrevBet())
	{
		inputTemp=ui->input("Fold (1), Call (2), or All in (4)\n");
		while (!help->isInt(inputTemp)||(stoi(inputTemp)!=1 && stoi(inputTemp)!=3 &&stoi(inputTemp)!=4))
		{
			ui->output("Input must a choice number provided");
			inputTemp=ui->input("Fold (1), Call (2), or All in (4)");
		}
	}
	else if(human->getTempPool() < AI->getTempPool())
	{
		inputTemp=ui->input("Fold (1), Call (2), or Raise (3)\n");
		while (!help->isInt(inputTemp)||stoi(inputTemp)<1||stoi(inputTemp)>3)
		{
			ui->output("Input must a choice number provided");
			inputTemp=ui->input("Fold (1), Call (2), or Raise (3)");
		}
	}
	else
	{
		inputTemp=ui->input("Fold (1), Check (2), or Raise (3)\n");
		while (!help->isInt(inputTemp)||stoi(inputTemp)<1||stoi(inputTemp)>3)
		{
			ui->output("Input must be a choice number provided.");
			inputTemp=ui->input("Fold (1), Check (2), or Raise (3)");
		}
	}
	if(inputTemp == "1")
	{
		return true;
	}
	else if(inputTemp == "2")
	{
		human->call(AI);
		pot=human->getTempPool()+AI->getTempPool();
		printBoard();
		return false;
	}
	else if(inputTemp == "3")
	{
		int prev = AI->getPrevBet();
		string r = ui->input("How much do you want to raise by? ");
		while (!help->isInt(r)|| stoi(r) < prev*2 || stoi(r) > min(human->getTotalChips() + human->getTempPool(), AI->getTotalChips() + AI->getTempPool()) || stoi(r) % smallBlind != 0)
		{
			if(!help->isInt(r))
				ui->output("Input must be an integer.");
			else if(stoi(r) < prev*2)
				ui->output("Input must be at least double the previous bet.");
			else if(stoi(r) > min(human->getTotalChips() + human->getTempPool(), AI->getTotalChips() + AI->getTempPool()))
				ui->output("Input must be less than or equal to the effective chip amount.");
			else
				ui->output("Input must be a multiple of the small blind.");
			r=ui->input("How much do you want to raise by? ");
		}
		human->raise(stoi(r));
		pot=human->getTempPool()+AI->getTempPool();
		human->setPrevBet(stoi(r));
		printBoard();
		return false;
	}
	else
	{
		human->raise(human->getTotalChips());
		pot=human->getTempPool()+AI->getTempPool();
		if(human ->getTotalChips() < AI->getPrevBet())
		{
			result();
			pot = 0;
			return true;
		}
		printBoard();
		return false;
	}

}

bool Board::runAI(){
	ConsoleUI* ui = new ConsoleUI();
	ui->output("AI's turn: ");
	AI->call(human); //for now
	pot=AI->getTempPool()+human->getTempPool();
	printBoard();
	//return true if fold
	return false;
}
bool Board::preflop()
{
	human->setPrevBet(0);
	AI->setPrevBet(0);
	printBoard();
	ConsoleUI* ui=new ConsoleUI();
	string inputTemp;
	//print AI's hand
	ui->output("AI's hand: ");
	(AI->getHandOne()).printCard();
	(AI->getHandTwo()).printCard();
	ui->output("");
	//print user's hand
	ui->output("Your hand: ");
	(human->getHandOne()).printCard();
	(human->getHandTwo()).printCard();
	ui->output("");
	//force user to put in blind
	pot=smallBlind*3;
	if (smallBlindPlayer==1){
		AI->raise(smallBlind);
		human->raise(smallBlind*2);
		ui->output("AI paid the small blind: "+to_string(smallBlind));
		ui->output("You paid the big blind: "+to_string(smallBlind*2));
	}
	else{
		human->raise(smallBlind);
		AI->raise(smallBlind*2);
		ui->output("You paid the small blind: "+to_string(smallBlind));
		ui->output("AI paid the big blind: "+to_string(smallBlind*2));
	}
	ui->output("");
	//ui->output("Your total chips: "+to_string(human->getTotalChips()));
	//ui->output("AI's total chips: "+to_string(AI->getTotalChips()));

	//cout<<"small blind player : "<<smallBlindPlayer<<endl;
	while(human->getTempPool()!=AI->getTempPool()) //player facing a bet
	{
		if (smallBlindPlayer==1){
			//AI goes first
			bool flag=this->runAI();
			if (flag==true){
				human->setTotalChips(human->getTotalChips()+pot);
				return true;
			}
			flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
		}
		else if (smallBlindPlayer==0){
			//player goes first
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
			flag=this->runAI();
			if (flag==true){
				human->setTotalChips(human->getTotalChips()+pot);
				return true;
			}
		}
	}
	return false;
}

bool Board::flop()
{
	if(AI->getTotalChips() == 0 || human->getTotalChips() == 0)
	{
		result();
		return true;
	}
	ConsoleUI* ui=new ConsoleUI();
	cout << "The flop is " << endl;
	community[0].printCard();
	community[1].printCard();
	community[2].printCard();
<<<<<<< HEAD
	cout << endl;
	//print AI's hand
	ui->output("AI's hand: ");
	(AI->getHandOne()).printCard();
	(AI->getHandTwo()).printCard();
=======
>>>>>>> bd013e823e3aba595cdce6fa494a9af8efa96334
	ui->output("");
	//print user's hand
	ui->output("Your hand: ");
	(human->getHandOne()).printCard();
	(human->getHandTwo()).printCard();
	ui->output("");
	//cout<<"small blind player : "<<smallBlindPlayer<<endl;
	do
	{
		if (smallBlindPlayer==1){
			//AI goes first
			this->runAI();
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
		}
		else if (smallBlindPlayer==0){
			//player goes first
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
			this->runAI();
		}
	}
	while(human->getTempPool()!=AI->getTempPool()); //player facing a bet

	return false;
}

bool Board::turn()
{
	if(AI->getTotalChips() == 0 || human->getTotalChips() == 0)
	{
		result();
		return true;
	}
	cout << "The turn is " << endl;
	community[0].printCard();
	community[1].printCard();
	community[2].printCard();
	community[3].printCard();
	cout << endl;
	ConsoleUI* ui=new ConsoleUI();
	//print AI's hand
	ui->output("AI's hand: ");
	(AI->getHandOne()).printCard();
	(AI->getHandTwo()).printCard();
	ui->output("");
	//print user's hand
	ui->output("Your hand: ");
	(human->getHandOne()).printCard();
	(human->getHandTwo()).printCard();
	ui->output("");
	ui->output("");
	ui->output("Your total chips: "+to_string(human->getTotalChips()));
	ui->output("AI's total chips: "+to_string(AI->getTotalChips()));
	do
	{
		if (smallBlindPlayer==1){
			//AI goes first
			this->runAI();
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
		}
		else if (smallBlindPlayer==0){
			//player goes first
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
			this->runAI();
		}
	}
	while(human->getTempPool()!=AI->getTempPool()); //player facing a bet
	return false;
}

bool Board::river()
{
	if(AI->getTotalChips() == 0 || human->getTotalChips() == 0)
	{
		result();
		return true;
	}
	cout << "The river is " << endl;
	community[0].printCard();
	community[1].printCard();
	community[2].printCard();
	community[3].printCard();
	community[4].printCard();
	cout << endl;
	ConsoleUI* ui=new ConsoleUI();
	//print AI's hand
	ui->output("AI's hand: ");
	(AI->getHandOne()).printCard();
	(AI->getHandTwo()).printCard();
	ui->output("");
	//print user's hand
	ui->output("Your hand: ");
	(human->getHandOne()).printCard();
	(human->getHandTwo()).printCard();
	ui->output("");
	ui->output("");
	ui->output("Your total chips: "+to_string(human->getTotalChips()));
	ui->output("AI's total chips: "+to_string(AI->getTotalChips()));
	do
	{
		if (smallBlindPlayer==1){
			//AI goes first
			this->runAI();
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
		}
		else if (smallBlindPlayer==0){
			//player goes first
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
			this->runAI();
		}
	}
	while(human->getTempPool()!=AI->getTempPool()); //player facing a bet
	result();
	return false;
	//after everything is done
}
void Board::result()
{
	ConsoleUI* ui=new ConsoleUI();
	Hand* humanBest=help->bestHand((human->getHandOne()),(human->getHandTwo()),
					community[0],community[1],community[2],community[3],community[4]);
	Hand* AIBest=help->bestHand((AI->getHandOne()),(AI->getHandTwo()),
			community[0],community[1],community[2],community[3],community[4]);
	int result=help->compareHands(humanBest,AIBest);
	ui->output("Community Cards: ");
	for (int i=0;i<5;i++){
		community[i].printCard();
	}
	ui->output("");
	ui->output("AI's cards: ");
	AI->getHandOne().printCard();
	AI->getHandTwo().printCard();
	ui->output("");
	ui->output("Your cards: ");
	human->getHandOne().printCard();
	human->getHandTwo().printCard();
	ui->output("");
	ui->output("Your best hand: ");
	humanBest->printHand();
	ui->output("");
	ui->output("AI's best hand: ");
	AIBest->printHand();
	ui->output("");
	if (result==1){
		ui->output("You won.");
		human->setTotalChips(human->getTotalChips()+pot);
	}
	else if (result==0){
		ui->output("AI won");
		AI->setTotalChips(AI->getTotalChips()+pot);
	}
	else{
		ui->output("Tie");
		human->setTotalChips(human->getTotalChips()+pot/2);
		AI->setTotalChips(AI->getTotalChips()+pot/2);
	}
}

void Board::clearBoard()
{
	human->resetTempPool();
	AI->resetTempPool();
	pot=0;
	human->setPrevBet(0);
	AI->setPrevBet(0);
	dek.shuffle();
	setCommunity();
	if (smallBlindPlayer==0){
		smallBlindPlayer=1;
	}
	else{
		smallBlindPlayer=0;
	}
}
<commit_msg>Deleted syntax stuff<commit_after>//******************************************************************************
// Board.cpp
// Revision History:
//
// Date           Author               Description
// 11/28/2017     Jason Chen           Added class
//******************************************************************************

#include <iostream>
#include <sstream>
#include <string>
#include "Deck.h"
#include "Hand.h"
#include "Card.h"
#include "Board.h"
#include "Player.h"
#include "ConsoleUI.h"
#include "helper.h"
using namespace std;

//constructor
//initialize the board for a new game
Board::Board(Player* hum, Player* AI, int smallBlindPlayer)
{
	human = hum;
	this->AI=AI;
	setCommunity();
	help=new helper();
	this->smallBlindPlayer=smallBlindPlayer;
}

void Board::setBlind(int bld)
{
	smallBlind = bld;
}

void Board::resetPot(){
	pot=0;
}

void Board::setCommunity()
{
	for(int i = 0; i < 5; i++)
	{
		community[i] = dek.draw();
	}
	//set player cards
	human->addOne(dek.draw());
	human->addTwo(dek.draw());
	AI->addOne(dek.draw());
	AI->addTwo(dek.draw());
}

void Board::printBoard()
{
	ConsoleUI* ui=new ConsoleUI();
	ui->output("");
	ui->output(AI->getName()+":\t$"+to_string(AI->getTotalChips()));
	ui->output("\t$"+to_string(AI->getTempPool()));
	ui->output("");
	ui->output("Pot:\t$"+to_string(pot));
	ui->output("");
	ui->output("\t$"+to_string(human->getTempPool()));
	ui->output(human->getName()+":\t$"+to_string(human->getTotalChips()));
	ui->output("");
	ui->output("*******************************");
}

bool Board::run()
{
	printBoard();
	string inputTemp;
	ConsoleUI* ui = new ConsoleUI();
	ui->output("Your turn: \n");
	if(human ->getTotalChips() < AI->getPrevBet())
	{
		inputTemp = ui->input("Fold (1) or All in (4)");
		while (!help->isInt(inputTemp)||(stoi(inputTemp)!=1 && stoi(inputTemp)!=4))
		{
			ui->output("Input must a choice number provided");
			inputTemp=ui->input("Fold (1) or All in (4)");
		}
	}
	else if(human->getTotalChips() < 2*AI->getPrevBet())
	{
		inputTemp=ui->input("Fold (1), Call (2), or All in (4)\n");
		while (!help->isInt(inputTemp)||(stoi(inputTemp)!=1 && stoi(inputTemp)!=3 &&stoi(inputTemp)!=4))
		{
			ui->output("Input must a choice number provided");
			inputTemp=ui->input("Fold (1), Call (2), or All in (4)");
		}
	}
	else if(human->getTempPool() < AI->getTempPool())
	{
		inputTemp=ui->input("Fold (1), Call (2), or Raise (3)\n");
		while (!help->isInt(inputTemp)||stoi(inputTemp)<1||stoi(inputTemp)>3)
		{
			ui->output("Input must a choice number provided");
			inputTemp=ui->input("Fold (1), Call (2), or Raise (3)");
		}
	}
	else
	{
		inputTemp=ui->input("Fold (1), Check (2), or Raise (3)\n");
		while (!help->isInt(inputTemp)||stoi(inputTemp)<1||stoi(inputTemp)>3)
		{
			ui->output("Input must be a choice number provided.");
			inputTemp=ui->input("Fold (1), Check (2), or Raise (3)");
		}
	}
	if(inputTemp == "1")
	{
		return true;
	}
	else if(inputTemp == "2")
	{
		human->call(AI);
		pot=human->getTempPool()+AI->getTempPool();
		printBoard();
		return false;
	}
	else if(inputTemp == "3")
	{
		int prev = AI->getPrevBet();
		string r = ui->input("How much do you want to raise by? ");
		while (!help->isInt(r)|| stoi(r) < prev*2 || stoi(r) > min(human->getTotalChips() + human->getTempPool(), AI->getTotalChips() + AI->getTempPool()) || stoi(r) % smallBlind != 0)
		{
			if(!help->isInt(r))
				ui->output("Input must be an integer.");
			else if(stoi(r) < prev*2)
				ui->output("Input must be at least double the previous bet.");
			else if(stoi(r) > min(human->getTotalChips() + human->getTempPool(), AI->getTotalChips() + AI->getTempPool()))
				ui->output("Input must be less than or equal to the effective chip amount.");
			else
				ui->output("Input must be a multiple of the small blind.");
			r=ui->input("How much do you want to raise by? ");
		}
		human->raise(stoi(r));
		pot=human->getTempPool()+AI->getTempPool();
		human->setPrevBet(stoi(r));
		printBoard();
		return false;
	}
	else
	{
		human->raise(human->getTotalChips());
		pot=human->getTempPool()+AI->getTempPool();
		if(human ->getTotalChips() < AI->getPrevBet())
		{
			result();
			pot = 0;
			return true;
		}
		printBoard();
		return false;
	}

}

bool Board::runAI(){
	ConsoleUI* ui = new ConsoleUI();
	ui->output("AI's turn: ");
	AI->call(human); //for now
	pot=AI->getTempPool()+human->getTempPool();
	printBoard();
	//return true if fold
	return false;
}
bool Board::preflop()
{
	human->setPrevBet(0);
	AI->setPrevBet(0);
	printBoard();
	ConsoleUI* ui=new ConsoleUI();
	string inputTemp;
	//print AI's hand
	ui->output("AI's hand: ");
	(AI->getHandOne()).printCard();
	(AI->getHandTwo()).printCard();
	ui->output("");
	//print user's hand
	ui->output("Your hand: ");
	(human->getHandOne()).printCard();
	(human->getHandTwo()).printCard();
	ui->output("");
	//force user to put in blind
	pot=smallBlind*3;
	if (smallBlindPlayer==1){
		AI->raise(smallBlind);
		human->raise(smallBlind*2);
		ui->output("AI paid the small blind: "+to_string(smallBlind));
		ui->output("You paid the big blind: "+to_string(smallBlind*2));
	}
	else{
		human->raise(smallBlind);
		AI->raise(smallBlind*2);
		ui->output("You paid the small blind: "+to_string(smallBlind));
		ui->output("AI paid the big blind: "+to_string(smallBlind*2));
	}
	ui->output("");
	//ui->output("Your total chips: "+to_string(human->getTotalChips()));
	//ui->output("AI's total chips: "+to_string(AI->getTotalChips()));

	//cout<<"small blind player : "<<smallBlindPlayer<<endl;
	while(human->getTempPool()!=AI->getTempPool()) //player facing a bet
	{
		if (smallBlindPlayer==1){
			//AI goes first
			bool flag=this->runAI();
			if (flag==true){
				human->setTotalChips(human->getTotalChips()+pot);
				return true;
			}
			flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
		}
		else if (smallBlindPlayer==0){
			//player goes first
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
			flag=this->runAI();
			if (flag==true){
				human->setTotalChips(human->getTotalChips()+pot);
				return true;
			}
		}
	}
	return false;
}

bool Board::flop()
{
	if(AI->getTotalChips() == 0 || human->getTotalChips() == 0)
	{
		result();
		return true;
	}
	ConsoleUI* ui=new ConsoleUI();
	cout << "The flop is " << endl;
	community[0].printCard();
	community[1].printCard();
	community[2].printCard();
	cout << endl;
	//print AI's hand
	ui->output("AI's hand: ");
	(AI->getHandOne()).printCard();
	(AI->getHandTwo()).printCard();
	ui->output("");
	//print user's hand
	ui->output("Your hand: ");
	(human->getHandOne()).printCard();
	(human->getHandTwo()).printCard();
	ui->output("");
	//cout<<"small blind player : "<<smallBlindPlayer<<endl;
	do
	{
		if (smallBlindPlayer==1){
			//AI goes first
			this->runAI();
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
		}
		else if (smallBlindPlayer==0){
			//player goes first
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
			this->runAI();
		}
	}
	while(human->getTempPool()!=AI->getTempPool()); //player facing a bet

	return false;
}

bool Board::turn()
{
	if(AI->getTotalChips() == 0 || human->getTotalChips() == 0)
	{
		result();
		return true;
	}
	cout << "The turn is " << endl;
	community[0].printCard();
	community[1].printCard();
	community[2].printCard();
	community[3].printCard();
	cout << endl;
	ConsoleUI* ui=new ConsoleUI();
	//print AI's hand
	ui->output("AI's hand: ");
	(AI->getHandOne()).printCard();
	(AI->getHandTwo()).printCard();
	ui->output("");
	//print user's hand
	ui->output("Your hand: ");
	(human->getHandOne()).printCard();
	(human->getHandTwo()).printCard();
	ui->output("");
	ui->output("");
	ui->output("Your total chips: "+to_string(human->getTotalChips()));
	ui->output("AI's total chips: "+to_string(AI->getTotalChips()));
	do
	{
		if (smallBlindPlayer==1){
			//AI goes first
			this->runAI();
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
		}
		else if (smallBlindPlayer==0){
			//player goes first
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
			this->runAI();
		}
	}
	while(human->getTempPool()!=AI->getTempPool()); //player facing a bet
	return false;
}

bool Board::river()
{
	if(AI->getTotalChips() == 0 || human->getTotalChips() == 0)
	{
		result();
		return true;
	}
	cout << "The river is " << endl;
	community[0].printCard();
	community[1].printCard();
	community[2].printCard();
	community[3].printCard();
	community[4].printCard();
	cout << endl;
	ConsoleUI* ui=new ConsoleUI();
	//print AI's hand
	ui->output("AI's hand: ");
	(AI->getHandOne()).printCard();
	(AI->getHandTwo()).printCard();
	ui->output("");
	//print user's hand
	ui->output("Your hand: ");
	(human->getHandOne()).printCard();
	(human->getHandTwo()).printCard();
	ui->output("");
	ui->output("");
	ui->output("Your total chips: "+to_string(human->getTotalChips()));
	ui->output("AI's total chips: "+to_string(AI->getTotalChips()));
	do
	{
		if (smallBlindPlayer==1){
			//AI goes first
			this->runAI();
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
		}
		else if (smallBlindPlayer==0){
			//player goes first
			bool flag=this->run();
			if (flag==true){
				AI->setTotalChips(AI->getTotalChips()+pot);
				return true;
			}
			this->runAI();
		}
	}
	while(human->getTempPool()!=AI->getTempPool()); //player facing a bet
	result();
	return false;
	//after everything is done
}
void Board::result()
{
	ConsoleUI* ui=new ConsoleUI();
	Hand* humanBest=help->bestHand((human->getHandOne()),(human->getHandTwo()),
					community[0],community[1],community[2],community[3],community[4]);
	Hand* AIBest=help->bestHand((AI->getHandOne()),(AI->getHandTwo()),
			community[0],community[1],community[2],community[3],community[4]);
	int result=help->compareHands(humanBest,AIBest);
	ui->output("Community Cards: ");
	for (int i=0;i<5;i++){
		community[i].printCard();
	}
	ui->output("");
	ui->output("AI's cards: ");
	AI->getHandOne().printCard();
	AI->getHandTwo().printCard();
	ui->output("");
	ui->output("Your cards: ");
	human->getHandOne().printCard();
	human->getHandTwo().printCard();
	ui->output("");
	ui->output("Your best hand: ");
	humanBest->printHand();
	ui->output("");
	ui->output("AI's best hand: ");
	AIBest->printHand();
	ui->output("");
	if (result==1){
		ui->output("You won.");
		human->setTotalChips(human->getTotalChips()+pot);
	}
	else if (result==0){
		ui->output("AI won");
		AI->setTotalChips(AI->getTotalChips()+pot);
	}
	else{
		ui->output("Tie");
		human->setTotalChips(human->getTotalChips()+pot/2);
		AI->setTotalChips(AI->getTotalChips()+pot/2);
	}
}

void Board::clearBoard()
{
	human->resetTempPool();
	AI->resetTempPool();
	pot=0;
	human->setPrevBet(0);
	AI->setPrevBet(0);
	dek.shuffle();
	setCommunity();
	if (smallBlindPlayer==0){
		smallBlindPlayer=1;
	}
	else{
		smallBlindPlayer=0;
	}
}
<|endoftext|>