<commit_before>// Ouzel by Elviss Strazdins

#ifndef OUZEL_SCENE_CAMERA_HPP
#define OUZEL_SCENE_CAMERA_HPP

#include <memory>
#include "Component.hpp"
#include "../math/Constants.hpp"
#include "../math/Matrix.hpp"
#include "../math/Rect.hpp"
#include "../graphics/DepthStencilState.hpp"
#include "../graphics/RenderTarget.hpp"

namespace ouzel::scene
{
    class Layer;

    class Camera: public Component
    {
        friend Layer;
    public:
        enum class ProjectionMode
        {
            custom,
            orthographic,
            perspective
        };

        enum class ScaleMode
        {
            noScale,
            exactFit,
            noBorder,
            showAll
        };

        explicit Camera(const math::Matrix<float, 4>& initProjection);
        explicit Camera(const math::Size<float, 2>& initTargetContentSize = math::Size<float, 2>{}, ScaleMode initScaleMode = ScaleMode::noScale);
        explicit Camera(float initFov, float initNearPlane = 1.0F, float initFarPlane = 100.0F);
        ~Camera() override;

        [[nodiscard]] auto getProjectionMode() const noexcept { return projectionMode; }
        void setProjectionMode(ProjectionMode newProjectionMode) { projectionMode = newProjectionMode; }

        [[nodiscard]] auto getFOV() const noexcept { return fov; }
        void setFOV(float newFOV) { fov = newFOV; }

        [[nodiscard]] auto getNearPlane() const noexcept { return nearPlane; }
        void setNearPlane(float newNearPlane) { nearPlane = newNearPlane; }

        [[nodiscard]] auto getFarPlane() const noexcept { return farPlane; }
        void setFarPlane(float newFarPlane) { farPlane = newFarPlane; }

        [[nodiscard]] auto& getProjection() const noexcept { return projection; }
        void recalculateProjection();

        const math::Matrix<float, 4>& getViewProjection() const;
        const math::Matrix<float, 4>& getRenderViewProjection() const;
        const math::Matrix<float, 4>& getInverseViewProjection() const;

        math::Vector<float, 3> convertNormalizedToWorld(const math::Vector<float, 2>& normalizedPosition) const;
        math::Vector<float, 2> convertWorldToNormalized(const math::Vector<float, 3>& worldPosition) const;

        bool checkVisibility(const math::Matrix<float, 4>& boxTransform, const math::Box<float, 3>& box) const;

        [[nodiscard]] auto& getViewport() const noexcept { return viewport; }
        [[nodiscard]] auto& getRenderViewport() const noexcept { return renderViewport; }
        void setViewport(const math::Rect<float>& newViewport);

        [[nodiscard]] auto getScaleMode() const noexcept { return scaleMode; }
        void setScaleMode(ScaleMode newScaleMode);

        [[nodiscard]] auto& getTargetContentSize() const noexcept { return targetContentSize; }
        void setTargetContentSize(const math::Size<float, 2>& newTargetContentSize);

        [[nodiscard]] auto& getContentSize() const noexcept { return contentSize; }
        [[nodiscard]] auto& getContentScale() const noexcept { return contentScale; }
        [[nodiscard]] auto& getContentPosition() const noexcept { return contentPosition; }

        [[nodiscard]] auto getRenderTarget() const noexcept { return renderTarget; }
        void setRenderTarget(graphics::RenderTarget* newRenderTarget);

        [[nodiscard]] auto getDepthTest() const noexcept { return depthTest; }
        void setDepthTest(bool newDepthTest);
        [[nodiscard]] auto& getDepthStencilState() const noexcept { return depthStencilState; }

        [[nodiscard]] auto getStencilReferenceValue() const noexcept { return stencilReferenceValue; }
        void setStencilReferenceValue(std::uint32_t newStencilReferenceValue) { stencilReferenceValue = newStencilReferenceValue; }

        [[nodiscard]] auto getWireframe() const noexcept { return wireframe; }
        void setWireframe(bool newWireframe) { wireframe = newWireframe; }

        [[nodiscard]] auto getClearColorBuffer() const noexcept { return clearColorBuffer; }
        void setClearColorBuffer(bool clear) { clearColorBuffer = clear; }

        [[nodiscard]] auto getClearDepthBuffer() const noexcept { return clearDepthBuffer; }
        void setClearDepthBuffer(bool clear) { clearDepthBuffer = clear; }

        [[nodiscard]] auto getClearStencilBuffer() const noexcept { return clearStencilBuffer; }
        void setClearStencilBuffer(bool clear) { clearStencilBuffer = clear; }

        [[nodiscard]] auto getClearColor() const noexcept { return clearColor; }
        void setClearColor(math::Color color) { clearColor = color; }

        [[nodiscard]] auto getClearDepth() const noexcept { return clearDepth; }
        void setClearDepth(float depth) { clearDepth = depth; }

        [[nodiscard]] auto getClearStencil() const noexcept { return clearStencil; }
        void setClearDepth(std::uint32_t stencil) { clearStencil = stencil; }

    private:
        void setActor(Actor* newActor) override;
        void setLayer(Layer* newLayer) override;

        void updateTransform() override;
        void calculateViewProjection() const;

        ProjectionMode projectionMode;
        float fov = math::tau<float> / 6.0F;
        float nearPlane = 1.0F;
        float farPlane = 100.0F;

        math::Matrix<float, 4> projection;

        math::Rect<float> viewport = math::Rect<float>{0.0F, 0.0F, 1.0F, 1.0F};
        math::Rect<float> renderViewport;
        math::Size<float, 2> targetContentSize;

        ScaleMode scaleMode = ScaleMode::noScale;
        math::Size<float, 2> contentSize{};
        math::Vector<float, 2> contentScale{};
        math::Vector<float, 2> contentPosition{};

        bool depthTest = false;
        bool wireframe = false;

        mutable bool viewProjectionDirty = true;
        mutable math::Matrix<float, 4> viewProjection;
        mutable math::Matrix<float, 4> renderViewProjection;

        mutable bool inverseViewProjectionDirty = true;
        mutable math::Matrix<float, 4> inverseViewProjection;

        graphics::RenderTarget* renderTarget = nullptr;
        std::unique_ptr<graphics::DepthStencilState> depthStencilState;
        std::uint32_t stencilReferenceValue = 0;

        bool clearColorBuffer = false;
        bool clearDepthBuffer = false;
        bool clearStencilBuffer = false;
        math::Color clearColor;
        float clearDepth = 1.0F;
        std::uint32_t clearStencil = 0;
    };
}

#endif // OUZEL_SCENE_CAMERA_HPP
<commit_msg>Change the casing of FOV<commit_after>// Ouzel by Elviss Strazdins

#ifndef OUZEL_SCENE_CAMERA_HPP
#define OUZEL_SCENE_CAMERA_HPP

#include <memory>
#include "Component.hpp"
#include "../math/Constants.hpp"
#include "../math/Matrix.hpp"
#include "../math/Rect.hpp"
#include "../graphics/DepthStencilState.hpp"
#include "../graphics/RenderTarget.hpp"

namespace ouzel::scene
{
    class Layer;

    class Camera: public Component
    {
        friend Layer;
    public:
        enum class ProjectionMode
        {
            custom,
            orthographic,
            perspective
        };

        enum class ScaleMode
        {
            noScale,
            exactFit,
            noBorder,
            showAll
        };

        explicit Camera(const math::Matrix<float, 4>& initProjection);
        explicit Camera(const math::Size<float, 2>& initTargetContentSize = math::Size<float, 2>{}, ScaleMode initScaleMode = ScaleMode::noScale);
        explicit Camera(float initFov, float initNearPlane = 1.0F, float initFarPlane = 100.0F);
        ~Camera() override;

        [[nodiscard]] auto getProjectionMode() const noexcept { return projectionMode; }
        void setProjectionMode(ProjectionMode newProjectionMode) { projectionMode = newProjectionMode; }

        [[nodiscard]] auto getFov() const noexcept { return fov; }
        void setFov(float newFov) { fov = newFov; }

        [[nodiscard]] auto getNearPlane() const noexcept { return nearPlane; }
        void setNearPlane(float newNearPlane) { nearPlane = newNearPlane; }

        [[nodiscard]] auto getFarPlane() const noexcept { return farPlane; }
        void setFarPlane(float newFarPlane) { farPlane = newFarPlane; }

        [[nodiscard]] auto& getProjection() const noexcept { return projection; }
        void recalculateProjection();

        const math::Matrix<float, 4>& getViewProjection() const;
        const math::Matrix<float, 4>& getRenderViewProjection() const;
        const math::Matrix<float, 4>& getInverseViewProjection() const;

        math::Vector<float, 3> convertNormalizedToWorld(const math::Vector<float, 2>& normalizedPosition) const;
        math::Vector<float, 2> convertWorldToNormalized(const math::Vector<float, 3>& worldPosition) const;

        bool checkVisibility(const math::Matrix<float, 4>& boxTransform, const math::Box<float, 3>& box) const;

        [[nodiscard]] auto& getViewport() const noexcept { return viewport; }
        [[nodiscard]] auto& getRenderViewport() const noexcept { return renderViewport; }
        void setViewport(const math::Rect<float>& newViewport);

        [[nodiscard]] auto getScaleMode() const noexcept { return scaleMode; }
        void setScaleMode(ScaleMode newScaleMode);

        [[nodiscard]] auto& getTargetContentSize() const noexcept { return targetContentSize; }
        void setTargetContentSize(const math::Size<float, 2>& newTargetContentSize);

        [[nodiscard]] auto& getContentSize() const noexcept { return contentSize; }
        [[nodiscard]] auto& getContentScale() const noexcept { return contentScale; }
        [[nodiscard]] auto& getContentPosition() const noexcept { return contentPosition; }

        [[nodiscard]] auto getRenderTarget() const noexcept { return renderTarget; }
        void setRenderTarget(graphics::RenderTarget* newRenderTarget);

        [[nodiscard]] auto getDepthTest() const noexcept { return depthTest; }
        void setDepthTest(bool newDepthTest);
        [[nodiscard]] auto& getDepthStencilState() const noexcept { return depthStencilState; }

        [[nodiscard]] auto getStencilReferenceValue() const noexcept { return stencilReferenceValue; }
        void setStencilReferenceValue(std::uint32_t newStencilReferenceValue) { stencilReferenceValue = newStencilReferenceValue; }

        [[nodiscard]] auto getWireframe() const noexcept { return wireframe; }
        void setWireframe(bool newWireframe) { wireframe = newWireframe; }

        [[nodiscard]] auto getClearColorBuffer() const noexcept { return clearColorBuffer; }
        void setClearColorBuffer(bool clear) { clearColorBuffer = clear; }

        [[nodiscard]] auto getClearDepthBuffer() const noexcept { return clearDepthBuffer; }
        void setClearDepthBuffer(bool clear) { clearDepthBuffer = clear; }

        [[nodiscard]] auto getClearStencilBuffer() const noexcept { return clearStencilBuffer; }
        void setClearStencilBuffer(bool clear) { clearStencilBuffer = clear; }

        [[nodiscard]] auto getClearColor() const noexcept { return clearColor; }
        void setClearColor(math::Color color) { clearColor = color; }

        [[nodiscard]] auto getClearDepth() const noexcept { return clearDepth; }
        void setClearDepth(float depth) { clearDepth = depth; }

        [[nodiscard]] auto getClearStencil() const noexcept { return clearStencil; }
        void setClearDepth(std::uint32_t stencil) { clearStencil = stencil; }

    private:
        void setActor(Actor* newActor) override;
        void setLayer(Layer* newLayer) override;

        void updateTransform() override;
        void calculateViewProjection() const;

        ProjectionMode projectionMode;
        float fov = math::tau<float> / 6.0F;
        float nearPlane = 1.0F;
        float farPlane = 100.0F;

        math::Matrix<float, 4> projection;

        math::Rect<float> viewport = math::Rect<float>{0.0F, 0.0F, 1.0F, 1.0F};
        math::Rect<float> renderViewport;
        math::Size<float, 2> targetContentSize;

        ScaleMode scaleMode = ScaleMode::noScale;
        math::Size<float, 2> contentSize{};
        math::Vector<float, 2> contentScale{};
        math::Vector<float, 2> contentPosition{};

        bool depthTest = false;
        bool wireframe = false;

        mutable bool viewProjectionDirty = true;
        mutable math::Matrix<float, 4> viewProjection;
        mutable math::Matrix<float, 4> renderViewProjection;

        mutable bool inverseViewProjectionDirty = true;
        mutable math::Matrix<float, 4> inverseViewProjection;

        graphics::RenderTarget* renderTarget = nullptr;
        std::unique_ptr<graphics::DepthStencilState> depthStencilState;
        std::uint32_t stencilReferenceValue = 0;

        bool clearColorBuffer = false;
        bool clearDepthBuffer = false;
        bool clearStencilBuffer = false;
        math::Color clearColor;
        float clearDepth = 1.0F;
        std::uint32_t clearStencil = 0;
    };
}

#endif // OUZEL_SCENE_CAMERA_HPP
<|endoftext|>


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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {ROI_QB_MUL_1.png}
//    OUTPUTS: {MSLabeledOutput.tif}, {MSClusteredOutput.tif} {MSLabeledOutput-pretty.png}, {MSClusteredOutput-pretty.png}
//  16 16 100 100 0.1
//  Software Guide : EndCommandLineArgs

//  Software Guide : BeginLatex
//
//  This example demonstrates the use of the
//  \doxygen{otb}{MeanShiftSegmentationFilter} class which implements
//  filtering and clustering using the mean shift algorithm
//  \cite{Comaniciu2002}. For a given pixel, the mean shift will
//  build a set of neighboring pixels within a given spatial radius
//  and a color range. The spatial and color center of this set is
//  then computed and the algorithm iterates with this new spatial and
//  color center. The Mean Shift can be used for edge-preserving
//  smoothing, or for clustering.
//
//  Software Guide : EndLatex

#include "itkMacro.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbImageFileWriter.h"
#include "otbPrintableImageFilter.h"

#include "itkRGBPixel.h"
#include "itkScalarToRGBPixelFunctor.h"
#include "itkUnaryFunctorImageFilter.h"

//  Software Guide : BeginLatex
//
//  We start by including the needed header file.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "otbMeanShiftSegmentationFilter.h"
// Software Guide : EndCodeSnippet
int main(int argc, char * argv[])
{
  if (argc != 11)
    {
    std::cerr << "Usage: " << argv[0] << " infname labeledfname clusteredfname labeledpretty clusteredpretty "
        << "spatialRadius rangeRadius minRegionSize maxiter thres" << std::endl;
    return EXIT_FAILURE;
    }

  const char * infname             = argv[1];
  const char * labeledfname        = argv[2];
  const char * clusteredfname      = argv[3];
  const char * labeledpretty       = argv[4];
  const char * clusteredpretty     = argv[5];
  const unsigned int spatialRadius = atoi(argv[6]);
  const double rangeRadius         = atof(argv[7]);
  const unsigned int minRegionSize = atoi(argv[8]);
  const unsigned int maxiter       = atoi(argv[9]);
  const double thres               = atof(argv[10]);

  //  Software Guide : BeginLatex
  //
  //  We start by the classical \code{typedef}s needed for reading and
  //  writing the images.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  const unsigned int Dimension = 2;

  typedef float                        PixelType;
  typedef unsigned int                 LabelPixelType;
  typedef itk::RGBPixel<unsigned char> ColorPixelType;

  typedef otb::VectorImage<PixelType, Dimension> ImageType;
  typedef otb::Image<LabelPixelType, Dimension>  LabelImageType;
  typedef otb::Image<ColorPixelType, Dimension>  RGBImageType;

  typedef otb::ImageFileReader<ImageType>               ReaderType;
  typedef otb::StreamingImageFileWriter<ImageType>      WriterType;
  typedef otb::StreamingImageFileWriter<LabelImageType> LabelWriterType;

  typedef otb::MeanShiftSegmentationFilter<ImageType, LabelImageType, ImageType> FilterType;
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  We instantiate the filter, the reader, and 2 writers (for the
  //  labeled and clustered images).
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  FilterType::Pointer filter = FilterType::New();
  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer1 = WriterType::New();
  LabelWriterType::Pointer writer2 = LabelWriterType::New();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  We set the file names for the reader and the writers:
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  reader->SetFileName(infname);
  writer1->SetFileName(clusteredfname);
  writer2->SetFileName(labeledfname);
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  We can now set the parameters for the filter. There are 3 main
  //  parameters: the spatial radius used for defining the neighborhood,
  //  the range radius used for defining the interval in the color space
  //  and the minimum size for the regions to be kept after clustering.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetSpatialBandwidth(spatialRadius);
  filter->SetRangeBandwidth(rangeRadius);
  filter->SetMinRegionSize(minRegionSize);
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  // Two another parameters can be set  : the maximum iteration number, which defines maximum number of iteration until convergence.
  //  Algorithm iterative scheme will stop if convergence hasn't been reached after the maximum number of iterations.
  //  Threshold parameter defines mean-shift vector convergence value. Algorithm iterative scheme will stop if mean-shift vector is below this threshold or if iteration number reached maximum number of iterations.
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetMaxIterationNumber(maxiter);
  filter->SetThreshold(thres);
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  //  We can now plug the pipeline and run it.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetInput(reader->GetOutput());
  writer1->SetInput(filter->GetClusteredOutput());
  writer2->SetInput(filter->GetLabelOutput());

  writer1->Update();
  writer2->Update();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  // Figure~\ref{fig:MeanShiftSegmentationFilter} shows the result of applying the mean shift
  // to a Quickbird image.
  // \begin{figure}
  // \center
  // \includegraphics[width=0.40\textwidth]{ROI_QB_MUL_1.eps}
  // \includegraphics[width=0.40\textwidth]{MSClusteredOutput-pretty.eps}
  // \includegraphics[width=0.40\textwidth]{MSLabeledOutput-pretty.eps}
  // \itkcaption[Mean Shift]{From top to bottom and left to right:
  // Original image, image filtered by
  // mean shift after clustering , and labeled image.}
  // \label{fig:MeanShiftSegmentationFilter}
  // \end{figure}
  // Software Guide : EndLatex

  typedef otb::PrintableImageFilter<ImageType> PrintableFilterType;
  PrintableFilterType::Pointer printableImageFilter = PrintableFilterType::New();

  printableImageFilter->SetChannel(1);
  printableImageFilter->SetChannel(2);
  printableImageFilter->SetChannel(3);

  typedef PrintableFilterType::OutputImageType OutputImageType;
  typedef otb::ImageFileWriter<OutputImageType> PrettyWriterType;

  PrettyWriterType::Pointer prettyWriter = PrettyWriterType::New();

  printableImageFilter->SetInput(filter->GetClusteredOutput());
  prettyWriter->SetFileName(clusteredpretty);
  prettyWriter->SetInput(printableImageFilter->GetOutput());
  prettyWriter->Update();

  typedef otb::ImageFileWriter<RGBImageType> LabelRGBWriterType;

  LabelRGBWriterType::Pointer labelRGBWriter = LabelRGBWriterType::New();

  // Label to RGB image
  typedef itk::Functor::ScalarToRGBPixelFunctor<LabelPixelType> FunctorType;
  typedef itk::UnaryFunctorImageFilter<LabelImageType, RGBImageType, FunctorType> ColorLabelFilterType;
  ColorLabelFilterType::Pointer labelToRGB = ColorLabelFilterType::New();

  labelToRGB->SetInput(filter->GetLabelOutput());

  labelRGBWriter->SetFileName(labeledpretty);
  labelRGBWriter->SetInput(labelToRGB->GetOutput());
  labelRGBWriter->Update();

  return EXIT_SUCCESS;
}
<commit_msg>COMP: command line change for Art generation in needed by SG.<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {ROI_QB_MUL_1.png}
//    OUTPUTS: {MSLabeledOutput.tif}, {MSClusteredOutput.tif}, {MSLabeledOutput-pretty.png}, {MSClusteredOutput-pretty.png}
//    16 16 100 100 0.1
//  Software Guide : EndCommandLineArgs

//  Software Guide : BeginLatex
//
//  This example demonstrates the use of the
//  \doxygen{otb}{MeanShiftSegmentationFilter} class which implements
//  filtering and clustering using the mean shift algorithm
//  \cite{Comaniciu2002}. For a given pixel, the mean shift will
//  build a set of neighboring pixels within a given spatial radius
//  and a color range. The spatial and color center of this set is
//  then computed and the algorithm iterates with this new spatial and
//  color center. The Mean Shift can be used for edge-preserving
//  smoothing, or for clustering.
//
//  Software Guide : EndLatex

#include "itkMacro.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbImageFileWriter.h"
#include "otbPrintableImageFilter.h"

#include "itkRGBPixel.h"
#include "itkScalarToRGBPixelFunctor.h"
#include "itkUnaryFunctorImageFilter.h"

//  Software Guide : BeginLatex
//
//  We start by including the needed header file.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "otbMeanShiftSegmentationFilter.h"
// Software Guide : EndCodeSnippet
int main(int argc, char * argv[])
{
  if (argc != 11)
    {
    std::cerr << "Usage: " << argv[0] << " infname labeledfname clusteredfname labeledpretty clusteredpretty "
        << "spatialRadius rangeRadius minRegionSize maxiter thres" << std::endl;
    return EXIT_FAILURE;
    }

  const char * infname             = argv[1];
  const char * labeledfname        = argv[2];
  const char * clusteredfname      = argv[3];
  const char * labeledpretty       = argv[4];
  const char * clusteredpretty     = argv[5];
  const unsigned int spatialRadius = atoi(argv[6]);
  const double rangeRadius         = atof(argv[7]);
  const unsigned int minRegionSize = atoi(argv[8]);
  const unsigned int maxiter       = atoi(argv[9]);
  const double thres               = atof(argv[10]);

  //  Software Guide : BeginLatex
  //
  //  We start by the classical \code{typedef}s needed for reading and
  //  writing the images.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  const unsigned int Dimension = 2;

  typedef float                        PixelType;
  typedef unsigned int                 LabelPixelType;
  typedef itk::RGBPixel<unsigned char> ColorPixelType;

  typedef otb::VectorImage<PixelType, Dimension> ImageType;
  typedef otb::Image<LabelPixelType, Dimension>  LabelImageType;
  typedef otb::Image<ColorPixelType, Dimension>  RGBImageType;

  typedef otb::ImageFileReader<ImageType>               ReaderType;
  typedef otb::StreamingImageFileWriter<ImageType>      WriterType;
  typedef otb::StreamingImageFileWriter<LabelImageType> LabelWriterType;

  typedef otb::MeanShiftSegmentationFilter<ImageType, LabelImageType, ImageType> FilterType;
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  We instantiate the filter, the reader, and 2 writers (for the
  //  labeled and clustered images).
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  FilterType::Pointer filter = FilterType::New();
  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer1 = WriterType::New();
  LabelWriterType::Pointer writer2 = LabelWriterType::New();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  We set the file names for the reader and the writers:
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  reader->SetFileName(infname);
  writer1->SetFileName(clusteredfname);
  writer2->SetFileName(labeledfname);
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  We can now set the parameters for the filter. There are 3 main
  //  parameters: the spatial radius used for defining the neighborhood,
  //  the range radius used for defining the interval in the color space
  //  and the minimum size for the regions to be kept after clustering.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetSpatialBandwidth(spatialRadius);
  filter->SetRangeBandwidth(rangeRadius);
  filter->SetMinRegionSize(minRegionSize);
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  // Two another parameters can be set  : the maximum iteration number, which defines maximum number of iteration until convergence.
  //  Algorithm iterative scheme will stop if convergence hasn't been reached after the maximum number of iterations.
  //  Threshold parameter defines mean-shift vector convergence value. Algorithm iterative scheme will stop if mean-shift vector is below this threshold or if iteration number reached maximum number of iterations.
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetMaxIterationNumber(maxiter);
  filter->SetThreshold(thres);
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  //  We can now plug the pipeline and run it.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetInput(reader->GetOutput());
  writer1->SetInput(filter->GetClusteredOutput());
  writer2->SetInput(filter->GetLabelOutput());

  writer1->Update();
  writer2->Update();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  // Figure~\ref{fig:MeanShiftSegmentationFilter} shows the result of applying the mean shift
  // to a Quickbird image.
  // \begin{figure}
  // \center
  // \includegraphics[width=0.40\textwidth]{ROI_QB_MUL_1.eps}
  // \includegraphics[width=0.40\textwidth]{MSClusteredOutput-pretty.eps}
  // \includegraphics[width=0.40\textwidth]{MSLabeledOutput-pretty.eps}
  // \itkcaption[Mean Shift]{From top to bottom and left to right:
  // Original image, image filtered by
  // mean shift after clustering , and labeled image.}
  // \label{fig:MeanShiftSegmentationFilter}
  // \end{figure}
  // Software Guide : EndLatex

  typedef otb::PrintableImageFilter<ImageType> PrintableFilterType;
  PrintableFilterType::Pointer printableImageFilter = PrintableFilterType::New();

  printableImageFilter->SetChannel(1);
  printableImageFilter->SetChannel(2);
  printableImageFilter->SetChannel(3);

  typedef PrintableFilterType::OutputImageType OutputImageType;
  typedef otb::ImageFileWriter<OutputImageType> PrettyWriterType;

  PrettyWriterType::Pointer prettyWriter = PrettyWriterType::New();

  printableImageFilter->SetInput(filter->GetClusteredOutput());
  prettyWriter->SetFileName(clusteredpretty);
  prettyWriter->SetInput(printableImageFilter->GetOutput());
  prettyWriter->Update();

  typedef otb::ImageFileWriter<RGBImageType> LabelRGBWriterType;

  LabelRGBWriterType::Pointer labelRGBWriter = LabelRGBWriterType::New();

  // Label to RGB image
  typedef itk::Functor::ScalarToRGBPixelFunctor<LabelPixelType> FunctorType;
  typedef itk::UnaryFunctorImageFilter<LabelImageType, RGBImageType, FunctorType> ColorLabelFilterType;
  ColorLabelFilterType::Pointer labelToRGB = ColorLabelFilterType::New();

  labelToRGB->SetInput(filter->GetLabelOutput());

  labelRGBWriter->SetFileName(labeledpretty);
  labelRGBWriter->SetInput(labelToRGB->GetOutput());
  labelRGBWriter->Update();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <OGL/OGLGpuBuffer.h>

std::vector<GLBufferId> OGLHgGPUBuffer::m_useableBufferIds;

GLBufferId::~GLBufferId()
{
	if (buffId > 0) {
		glDeleteBuffers(1, &buffId);
		glDeleteTextures(1, &texId);
	}
	texId = 0;
	buffId = 0;
}

void GLBufferId::AllocateOnGPU()
{
	if (texId == 0) {
		glGenBuffers(1, &buffId);
		glGenTextures(1, &texId);
	}
}

GLBufferId::GLBufferId(GLBufferId&& rhs)
{
	*this = std::move(rhs);
}

const GLBufferId& GLBufferId::operator=(GLBufferId&& rhs)
{
	std::swap(buffId, rhs.buffId);
	std::swap(texId, rhs.texId);
	return *this;
}

GLBufferId OGLHgGPUBuffer::getGLBufferId()
{
	if (m_useableBufferIds.size() > 0)
	{
		auto r = std::move(m_useableBufferIds.back());
		m_useableBufferIds.pop_back();
		return r;
	}

	GLBufferId ids;
	ids.AllocateOnGPU();
	return ids;
}

void  OGLHgGPUBuffer::freeGLBufferId(GLBufferId& rhs)
{
	m_useableBufferIds.emplace_back(std::move(rhs));
}

OGLHgGPUBuffer::~OGLHgGPUBuffer()
{
	freeGLBufferId(m_bufferIds);
}

void OGLHgGPUBuffer::SendToGPU(const IHgGPUBuffer* bufferObject) {
	m_bufferIds = getGLBufferId();

	glBindBuffer(GL_TEXTURE_BUFFER, m_bufferIds.buffId);

	const size_t size = bufferObject->sizeBytes();

	if (m_lastSize < size) {
		//grow buffer and load all data
		glBufferData(GL_TEXTURE_BUFFER, size, bufferObject->getBufferPtr(), GL_DYNAMIC_DRAW);
	}
	else {
		//load all data
		glBufferSubData(GL_TEXTURE_BUFFER, 0, size, bufferObject->getBufferPtr());
	}
	m_lastSize = size;
}

void OGLHgGPUBuffer::Bind() {
	glBindTexture(GL_TEXTURE_BUFFER, m_bufferIds.texId);
	glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_bufferIds.buffId);
}<commit_msg>Fix bug causing deletion of buffers<commit_after>#include <OGL/OGLGpuBuffer.h>

std::vector<GLBufferId> OGLHgGPUBuffer::m_useableBufferIds;

GLBufferId::~GLBufferId()
{
	if (buffId > 0) {
		glDeleteBuffers(1, &buffId);
		glDeleteTextures(1, &texId);
	}
	texId = 0;
	buffId = 0;
}

void GLBufferId::AllocateOnGPU()
{
	if (texId == 0) {
		glGenBuffers(1, &buffId);
		glGenTextures(1, &texId);
	}
}

GLBufferId::GLBufferId(GLBufferId&& rhs)
{
	*this = std::move(rhs);
}

const GLBufferId& GLBufferId::operator=(GLBufferId&& rhs)
{
	buffId = rhs.buffId;
	texId = rhs.texId;

	rhs.buffId = 0;
	rhs.texId = 0;

	return *this;
}

GLBufferId OGLHgGPUBuffer::getGLBufferId()
{
	if (m_useableBufferIds.size() > 0)
	{
		auto r = std::move(m_useableBufferIds.back());
		m_useableBufferIds.pop_back();
		return r;
	}

	GLBufferId ids;
	ids.AllocateOnGPU();
	return ids;
}

void  OGLHgGPUBuffer::freeGLBufferId(GLBufferId& rhs)
{
	m_useableBufferIds.emplace_back(std::move(rhs));
}

OGLHgGPUBuffer::~OGLHgGPUBuffer()
{
	freeGLBufferId(m_bufferIds);
}

void OGLHgGPUBuffer::SendToGPU(const IHgGPUBuffer* bufferObject) {
	m_bufferIds = getGLBufferId();

	glBindBuffer(GL_TEXTURE_BUFFER, m_bufferIds.buffId);

	const size_t size = bufferObject->sizeBytes();

	if (m_lastSize < size) {
		//grow buffer and load all data
		glBufferData(GL_TEXTURE_BUFFER, size, bufferObject->getBufferPtr(), GL_DYNAMIC_DRAW);
	}
	else {
		//load all data
		glBufferSubData(GL_TEXTURE_BUFFER, 0, size, bufferObject->getBufferPtr());
	}
	m_lastSize = size;
}

void OGLHgGPUBuffer::Bind() {
	glBindTexture(GL_TEXTURE_BUFFER, m_bufferIds.texId);
	glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_bufferIds.buffId);
}<|endoftext|>


<commit_before>#ifndef WISSBI_SUB_ENTRY_HPP_
#define WISSBI_SUB_ENTRY_HPP_

#include "util.hpp"
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <algorithm>
#include <string>
#include <stdexcept>

namespace wissbi {

class SubEntry {
    public:
    SubEntry(const std::string& meta_dir, const std::string& queue_name, const std::string& addr_str) :
        meta_dir_(meta_dir), queue_name_(queue_name), addr_str_(addr_str)
    {
        node_name_ = meta_dir_ + "/sub/" + queue_name_ + "/" + addr_str_ + "," +
                     wissbi::util::EscapeSubFolderPath(queue_name_);
        renew_();
    }

    ~SubEntry() {
        system(("rm " + node_name_).c_str());
    }

    void renew() const {
        renew_();
    }

    private:
    void renew_() const {
        mkdir((meta_dir_ + "/sub/" + queue_name_).c_str(), S_IRWXU);
        int fd = open(node_name_.c_str(), O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
        if(fd == -1) {
            throw std::runtime_error(std::string("Cannot create subscriber entry at ") + node_name_);
        }
        int res = futimes(fd, NULL);
        close(fd);
        if(res == -1) {
            throw std::runtime_error(std::string("Cannot update subscriber entry at ") + node_name_);
        }
    }

    std::string meta_dir_;
    std::string queue_name_;
    std::string node_name_;
    std::string addr_str_;
};

}

#endif  // WISSBI_SUB_ENTRY_HPP_
<commit_msg>use unlink to remove subscriber entry node<commit_after>#ifndef WISSBI_SUB_ENTRY_HPP_
#define WISSBI_SUB_ENTRY_HPP_

#include "util.hpp"
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <algorithm>
#include <string>
#include <stdexcept>

namespace wissbi {

class SubEntry {
    public:
    SubEntry(const std::string& meta_dir, const std::string& queue_name, const std::string& addr_str) :
        meta_dir_(meta_dir), queue_name_(queue_name), addr_str_(addr_str)
    {
        node_name_ = meta_dir_ + "/sub/" + queue_name_ + "/" + addr_str_ + "," +
                     wissbi::util::EscapeSubFolderPath(queue_name_);
        renew_();
    }

    ~SubEntry() {
        unlink(node_name_.c_str());
    }

    void renew() const {
        renew_();
    }

    private:
    void renew_() const {
        mkdir((meta_dir_ + "/sub/" + queue_name_).c_str(), S_IRWXU);
        int fd = open(node_name_.c_str(), O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
        if(fd == -1) {
            throw std::runtime_error(std::string("Cannot create subscriber entry at ") + node_name_);
        }
        int res = futimes(fd, NULL);
        close(fd);
        if(res == -1) {
            throw std::runtime_error(std::string("Cannot update subscriber entry at ") + node_name_);
        }
    }

    std::string meta_dir_;
    std::string queue_name_;
    std::string node_name_;
    std::string addr_str_;
};

}

#endif  // WISSBI_SUB_ENTRY_HPP_
<|endoftext|>


<commit_before>#include    <cstdlib>
#include    <cmath>
#include    <fstream>
#include    <sstream>
#include    <iostream>
#include    <iomanip>
#include    <string>
#include    <vector>
#include    <algorithm>
#include    <exception>
#include    <sys/time.h>
#include    "modules/htmTree.h"
#include    "modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
    //// Initializations ---------------------------------------------
    srand48(1234); // Make sure we have reproducability
    check_args(argc);
    Time t, time; // t for global, time for local
    init_time(t);
    Feat F;
    MTL M;

    // Read parameters file //
    F.readInputFile(argv[1]);
    printFile(argv[1]);
    // Read Secretfile
    // Secret contains the identity of each target: QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF
    Gals Secret;
    init_time_at(time,"# reading Secret file",t);

        Secret=read_Secretfile(F.Secretfile,F);
    printf("# Read %d galaxies from %s \n",Secret.size(),F.Secretfile.c_str());
    print_time(time,"# ... took :");
    std::vector<int> count(10);
    count=count_galaxies(Secret);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){if(count[i]>0)printf (" type %d number  %d  \n",i, count[i]);}
    //read the three input fits files
    init_time_at(time,"# read target, SS, SF files",t);
    MTL Targ=read_MTLfile(F.Targfile,F,0,0);
    MTL SStars=read_MTLfile(F.SStarsfile,F,1,0);
    MTL SkyF=read_MTLfile(F.SkyFfile,F,0,1);

    if(Targ.size() == 0) {
        std::cerr << "ERROR: No targets found in " << F.Targfile << std::endl;
        myexit(1);
    }

    print_time(time,"# ... took :");
    //combine the three input files
    M=Targ;
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SStars.begin(),SStars.end());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SkyF.begin(),SkyF.end());
    printf(" M size %d \n",M.size());
    F.Ngal=M.size();
    F.Ntarg=Secret.size();

    //establish priority classes
    init_time_at(time,"# establish priority clasess",t);
    assign_priority_class(M);
    std::vector <int> count_class(M.priority_list.size(),0);
    for(int i;i<M.size();++i){
        if(!M[i].SS&&!M[i].SF){
        count_class[M[i].priority_class]+=1;
        }
    }
    for(int i;i<M.priority_list.size();++i){
        printf("  class %d  priority %d  number %d\n",i,M.priority_list[i],count_class[i]);
    }
    print_time(time,"# ... took :");

    // fiber positioners
    PP pp;
    pp.read_fiber_positions(F);
    F.Nfiber = pp.fp.size()/2;
    F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
    pp.get_neighbors(F);
    pp.compute_fibsofsp(F);
    printf("computed neighbors\n");
    std::cout.flush();
    //P tiles in order specified by surveyFile
    Plates P = read_plate_centers(F);
    F.Nplate=P.size();
    printf("# Read %d plates from %s and %d fibers from %s\n",F.Nplate,F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

    // Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
    F.cb = create_cb(); // cb=central body
    F.fh = create_fh(); // fh=fiber holder

    //// Collect available galaxies <-> tilefibers --------------------
    // HTM Tree of galaxies
    const double MinTreeSize = 0.01;
    init_time_at(time,"# Start building HTM tree",t);

    htmTree<struct target> T(M,MinTreeSize);
    print_time(time,"# ... took :");//T.stats();
    init_time_at(time,"# collect galaxies at ",t);

    // For plates/fibers, collect available galaxies; done in parallel
    collect_galaxies_for_all(M,T,P,pp,F);
    print_time(time,"# ... took :");//T.stats();
    init_time_at(time,"# collect available tile-fibers at",t);
    // For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
    collect_available_tilefibers(M,P,F);

    //count number of galaxies in first pass and number not in first pass

    int inside=0;
    int outside=0;
    for(int g=0;g<F.Ntarg;++g){
        Plist v=M[g].av_tfs;
        for(int i=0;i<v.size();++i){
            if(v[i].f==0){
                ++outside;
                break;
            }
            ++inside;
        }
    }
    printf ("inside = %d  outisde = %d\n",inside,outside);
    //results_on_inputs("doc/figs/",G,P,F,true);

    //// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.Nplate, F.Ngal, F.Nfiber);
    Assignment A(M,F);

    print_time(t,"# Start assignment at : ");

    // Make a plan ----------------------------------------------------
    // Plans whole survey without sky fibers, standard stars
    // assumes maximum number of observations needed for QSOs, LRGs

    simple_assign(M,P,pp,F,A);

    //check to see if there are tiles with no galaxies
    //need to keep mapping of old tile list to new tile list
    //and inverse map
    A.inv_order=initList(F.Nplate,-1);
    int inv_count=0;
    for (int j=0;j<F.Nplate ;++j){

        bool not_done=true;
        for(int k=0;k<F.Nfiber && not_done;++k){
            if(A.TF[j][k]!=-1){//fiber and therefore plate is used
                A.suborder.push_back(j);//suborder[jused] is jused-th used plate
                not_done=false;
                A.inv_order[j]=inv_count;//inv_order[j] is -1 unless used
                                //and otherwise the position of plate j in list of used plates
                inv_count++;
            }
        }
    }
    F.NUsedplate=A.suborder.size();
    printf(" Plates actually used %d \n",F.NUsedplate);

    if(F.diagnose)diagnostic(M,Secret,F,A);

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs

    // Smooth out distribution of free fibers, and increase the number of assignments

    for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A,0);// more iterations will improve performance slightly
    for (int i=0; i<1; i++) {
        improve(M,P,pp,F,A,0);
        redistribute_tf(M,P,pp,F,A,0);
    }
    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int jused=0;jused<F.NUsedplate;++jused){
        int j=A.suborder[jused];
        assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF for each tile
        assign_unused(j,M,P,pp,F,A);
    }
    if(F.diagnose)diagnostic(M,Secret,F,A);
    init_time_at(time,"# Begin real time assignment",t);

    //Execute plan, updating targets at intervals
    for(int i=0;i<F.pass_intervals.size();i++){
        printf(" i=%d interval %d \n",i,F.pass_intervals[i]);
    }
    std::vector <int> update_intervals=F.pass_intervals;
    update_intervals.push_back(F.NUsedplate);//to end intervals at last plate
    for(int i=0;i<update_intervals.size();++i){
        printf("i %d  update_interval %d\n",i, update_intervals[i]);
    }
    for(int i=0;i<update_intervals.size()-1;++i){//go plate by used plate
        int starter=update_intervals[i];
        printf("-- interval %d\n",i);
        for (int jused=starter; jused<update_intervals[i+1] && jused<A.suborder.size()-1; jused++) {

            if (0<=jused-F.Analysis) {
                update_plan_from_one_obs(jused,Secret,M,P,pp,F,A);
            }
            else printf("\n no update\n");
            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else

        }
        printf("-- redistribute %d\n",i);
        redistribute_tf(M,P,pp,F,A,starter);
        printf("-- improve %d\n",i);
        improve(M,P,pp,F,A,starter);
        printf("-- improve again %d\n",i);
        redistribute_tf(M,P,pp,F,A,starter);
        printf("-- diagnose %d\n",i);
        if(F.diagnose)diagnostic(M,Secret,F,A);

    }
    // check on SS and SF

    printf("-- Checking SS/SF\n");
    List SS_hist=initList(11,0);
    List SF_hist=initList(41,0);
    for(int jused=0;jused<F.NUsedplate;++jused){
        int j=A.suborder[jused];
        for (int p=0;p<F.Npetal;++p){
            int count_SS=0;
            int count_SF=0;
            for (int k=0;k<F.Nfbp;++k){
                int kk=pp.fibers_of_sp[p][k];
                int g=A.TF[j][kk];
                if(g!=-1 && M[g].SS)count_SS++;
                if(g!=-1 && M[g].SF)count_SF++;
            }
            SS_hist[count_SS]++;
            SF_hist[count_SF]++;
        }
    }
    printf(" SS distribution \n");
    for(int i=0;i<10;i++)printf("%8d",SS_hist[i]);
    printf("\n %8d \n",SS_hist[10]);

    printf(" SF distribution \n");
    for(int i=0;i<10;i++)printf("%8d",SF_hist[i]);
    printf("\n");
    for(int i=10;i<20;i++)printf("%8d",SF_hist[i]);
    printf("\n");
    for(int i=20;i<30;i++)printf("%8d",SF_hist[i]);
    printf("\n");
    for(int i=30;i<40;i++)printf("%8d",SF_hist[i]);
    printf("\n %8d \n",SF_hist[40]);

    // Results -------------------------------------------------------
    if (F.PrintAscii){
        for (int jused=0; jused<F.NUsedplate; jused++){
            int j=A.suborder[jused];
            write_FAtile_ascii(A.suborder[jused],F.outDir,M,P,pp,F,A);
        }
    }

    if (F.PrintFits) {
        for (int jused=0; jused<F.NUsedplate; jused++){
            int j=A.suborder[jused];
            fa_write(A.suborder[jused],F.outDir,M,P,pp,F,A); // Write outpu
        }
    }

	display_results("doc/figs/",Secret,M,P,pp,F,A,F.Nplate,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

    print_time(t,"# Finished !... in");

    return(0);

}
<commit_msg>count galaxies in first pass<commit_after>#include    <cstdlib>
#include    <cmath>
#include    <fstream>
#include    <sstream>
#include    <iostream>
#include    <iomanip>
#include    <string>
#include    <vector>
#include    <algorithm>
#include    <exception>
#include    <sys/time.h>
#include    "modules/htmTree.h"
#include    "modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
    //// Initializations ---------------------------------------------
    srand48(1234); // Make sure we have reproducability
    check_args(argc);
    Time t, time; // t for global, time for local
    init_time(t);
    Feat F;
    MTL M;

    // Read parameters file //
    F.readInputFile(argv[1]);
    printFile(argv[1]);
    // Read Secretfile
    // Secret contains the identity of each target: QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF
    Gals Secret;
    init_time_at(time,"# reading Secret file",t);

        Secret=read_Secretfile(F.Secretfile,F);
    printf("# Read %d galaxies from %s \n",Secret.size(),F.Secretfile.c_str());
    print_time(time,"# ... took :");
    std::vector<int> count(10);
    count=count_galaxies(Secret);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){if(count[i]>0)printf (" type %d number  %d  \n",i, count[i]);}
    //read the three input fits files
    init_time_at(time,"# read target, SS, SF files",t);
    MTL Targ=read_MTLfile(F.Targfile,F,0,0);
    MTL SStars=read_MTLfile(F.SStarsfile,F,1,0);
    MTL SkyF=read_MTLfile(F.SkyFfile,F,0,1);

    if(Targ.size() == 0) {
        std::cerr << "ERROR: No targets found in " << F.Targfile << std::endl;
        myexit(1);
    }

    print_time(time,"# ... took :");
    //combine the three input files
    M=Targ;
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SStars.begin(),SStars.end());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SkyF.begin(),SkyF.end());
    printf(" M size %d \n",M.size());
    F.Ngal=M.size();
    F.Ntarg=Secret.size();

    //establish priority classes
    init_time_at(time,"# establish priority clasess",t);
    assign_priority_class(M);
    std::vector <int> count_class(M.priority_list.size(),0);
    for(int i;i<M.size();++i){
        if(!M[i].SS&&!M[i].SF){
        count_class[M[i].priority_class]+=1;
        }
    }
    for(int i;i<M.priority_list.size();++i){
        printf("  class %d  priority %d  number %d\n",i,M.priority_list[i],count_class[i]);
    }
    print_time(time,"# ... took :");

    // fiber positioners
    PP pp;
    pp.read_fiber_positions(F);
    F.Nfiber = pp.fp.size()/2;
    F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
    pp.get_neighbors(F);
    pp.compute_fibsofsp(F);
    printf("computed neighbors\n");
    std::cout.flush();
    //P tiles in order specified by surveyFile
    Plates P = read_plate_centers(F);
    F.Nplate=P.size();
    printf("# Read %d plates from %s and %d fibers from %s\n",F.Nplate,F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

    // Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
    F.cb = create_cb(); // cb=central body
    F.fh = create_fh(); // fh=fiber holder

    //// Collect available galaxies <-> tilefibers --------------------
    // HTM Tree of galaxies
    const double MinTreeSize = 0.01;
    init_time_at(time,"# Start building HTM tree",t);

    htmTree<struct target> T(M,MinTreeSize);
    print_time(time,"# ... took :");//T.stats();
    init_time_at(time,"# collect galaxies at ",t);

    // For plates/fibers, collect available galaxies; done in parallel
    collect_galaxies_for_all(M,T,P,pp,F);
    print_time(time,"# ... took :");//T.stats();
    init_time_at(time,"# collect available tile-fibers at",t);
    // For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
    collect_available_tilefibers(M,P,F);

    //count number of galaxies in first pass and number not in first pass

    int totalg=0;
    int outside=0;
    for(int g=0;g<F.Ntarg;++g){
        Plist v=M[g].av_tfs;
        int done=0;
        for(int i=0;i<v.size()&&done==0;++i){
            if(v[i].f==0){
                ++outside;
                done=1;
            }
        }
        ++totalg;
    }
    printf ("total = %d  outisde = %d\n",totalg,outside);
    //results_on_inputs("doc/figs/",G,P,F,true);

    //// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.Nplate, F.Ngal, F.Nfiber);
    Assignment A(M,F);

    print_time(t,"# Start assignment at : ");

    // Make a plan ----------------------------------------------------
    // Plans whole survey without sky fibers, standard stars
    // assumes maximum number of observations needed for QSOs, LRGs

    simple_assign(M,P,pp,F,A);

    //check to see if there are tiles with no galaxies
    //need to keep mapping of old tile list to new tile list
    //and inverse map
    A.inv_order=initList(F.Nplate,-1);
    int inv_count=0;
    for (int j=0;j<F.Nplate ;++j){

        bool not_done=true;
        for(int k=0;k<F.Nfiber && not_done;++k){
            if(A.TF[j][k]!=-1){//fiber and therefore plate is used
                A.suborder.push_back(j);//suborder[jused] is jused-th used plate
                not_done=false;
                A.inv_order[j]=inv_count;//inv_order[j] is -1 unless used
                                //and otherwise the position of plate j in list of used plates
                inv_count++;
            }
        }
    }
    F.NUsedplate=A.suborder.size();
    printf(" Plates actually used %d \n",F.NUsedplate);

    if(F.diagnose)diagnostic(M,Secret,F,A);

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs

    // Smooth out distribution of free fibers, and increase the number of assignments

    for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A,0);// more iterations will improve performance slightly
    for (int i=0; i<1; i++) {
        improve(M,P,pp,F,A,0);
        redistribute_tf(M,P,pp,F,A,0);
    }
    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int jused=0;jused<F.NUsedplate;++jused){
        int j=A.suborder[jused];
        assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF for each tile
        assign_unused(j,M,P,pp,F,A);
    }
    if(F.diagnose)diagnostic(M,Secret,F,A);
    init_time_at(time,"# Begin real time assignment",t);

    //Execute plan, updating targets at intervals
    for(int i=0;i<F.pass_intervals.size();i++){
        printf(" i=%d interval %d \n",i,F.pass_intervals[i]);
    }
    std::vector <int> update_intervals=F.pass_intervals;
    update_intervals.push_back(F.NUsedplate);//to end intervals at last plate
    for(int i=0;i<update_intervals.size();++i){
        printf("i %d  update_interval %d\n",i, update_intervals[i]);
    }
    for(int i=0;i<update_intervals.size()-1;++i){//go plate by used plate
        int starter=update_intervals[i];
        printf("-- interval %d\n",i);
        for (int jused=starter; jused<update_intervals[i+1] && jused<A.suborder.size()-1; jused++) {

            if (0<=jused-F.Analysis) {
                update_plan_from_one_obs(jused,Secret,M,P,pp,F,A);
            }
            else printf("\n no update\n");
            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else

        }
        printf("-- redistribute %d\n",i);
        redistribute_tf(M,P,pp,F,A,starter);
        printf("-- improve %d\n",i);
        improve(M,P,pp,F,A,starter);
        printf("-- improve again %d\n",i);
        redistribute_tf(M,P,pp,F,A,starter);
        printf("-- diagnose %d\n",i);
        if(F.diagnose)diagnostic(M,Secret,F,A);

    }
    // check on SS and SF

    printf("-- Checking SS/SF\n");
    List SS_hist=initList(11,0);
    List SF_hist=initList(41,0);
    for(int jused=0;jused<F.NUsedplate;++jused){
        int j=A.suborder[jused];
        for (int p=0;p<F.Npetal;++p){
            int count_SS=0;
            int count_SF=0;
            for (int k=0;k<F.Nfbp;++k){
                int kk=pp.fibers_of_sp[p][k];
                int g=A.TF[j][kk];
                if(g!=-1 && M[g].SS)count_SS++;
                if(g!=-1 && M[g].SF)count_SF++;
            }
            SS_hist[count_SS]++;
            SF_hist[count_SF]++;
        }
    }
    printf(" SS distribution \n");
    for(int i=0;i<10;i++)printf("%8d",SS_hist[i]);
    printf("\n %8d \n",SS_hist[10]);

    printf(" SF distribution \n");
    for(int i=0;i<10;i++)printf("%8d",SF_hist[i]);
    printf("\n");
    for(int i=10;i<20;i++)printf("%8d",SF_hist[i]);
    printf("\n");
    for(int i=20;i<30;i++)printf("%8d",SF_hist[i]);
    printf("\n");
    for(int i=30;i<40;i++)printf("%8d",SF_hist[i]);
    printf("\n %8d \n",SF_hist[40]);

    // Results -------------------------------------------------------
    if (F.PrintAscii){
        for (int jused=0; jused<F.NUsedplate; jused++){
            int j=A.suborder[jused];
            write_FAtile_ascii(A.suborder[jused],F.outDir,M,P,pp,F,A);
        }
    }

    if (F.PrintFits) {
        for (int jused=0; jused<F.NUsedplate; jused++){
            int j=A.suborder[jused];
            fa_write(A.suborder[jused],F.outDir,M,P,pp,F,A); // Write outpu
        }
    }

	display_results("doc/figs/",Secret,M,P,pp,F,A,F.Nplate,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

    print_time(t,"# Finished !... in");

    return(0);

}
<|endoftext|>


<commit_before>#include <X11/Xlib.h>
#include <include/wrapper/cef_helpers.h>
#include <include/cef_app.h>
#include <unistd.h>
#include <gdk/gdkx.h>

#include "brick_app.h"
#include "third-party/json/json.h"
#include "status_icon/status_icon.h"
#include "cef_handler.h"
#include "cef_app.h"
#include "window_util.h"
#include "helper.h"

#undef Status   // Definition conflicts with cef_urlrequest.h
#undef Success  // Definition conflicts with cef_message_router.h

namespace {
    std::string APPICONS[] = {"brick16.png", "brick32.png", "brick48.png", "brick128.png", "brick256.png"};
    std::string szWorkingDir;  // The current working directory

    bool GetWorkingDir(std::string& dir) {
      char buff[1024];

      // Retrieve the executable path.
      ssize_t len = readlink("/proc/self/exe", buff, sizeof(buff)-1);
      if (len == -1)
        return false;

      buff[len] = 0;
      dir = std::string(buff);
      // Remove the executable name from the path.
      dir = dir.substr(0, dir.find_last_of("/"));

      return true;
    }
}

// static
const char*
BrickApp::GetConfigHome() {
  return g_get_user_config_dir();
}

// static
const char*
BrickApp::GetCacheHome() {
  return g_get_user_cache_dir();
}

void
TerminationSignalHandler(int signatl) {
  CefQuitMessageLoop();
}

int main(int argc, char* argv[]) {
  CefMainArgs main_args(argc, argv);
  CefRefPtr<ClientApp> app(new ClientApp);

  // Execute the secondary process, if any.
  int exit_code = CefExecuteProcess(main_args, app.get(), NULL);
  if (exit_code >= 0)
    return exit_code;

  GetWorkingDir(szWorkingDir);
  std::string plain_config = BrickApp::GetConfig();
  AppSettings app_settings = AppSettings::InitByJson(plain_config);
  app_settings.resource_dir = helper::BaseDir(szWorkingDir) + "/resources/";

  CefRefPtr<AccountManager> account_manager(new AccountManager);
  // ToDo: Fix this bullshit!
  account_manager->Init(
     std::string(BrickApp::GetConfigHome()) + "/" + APP_COMMON_NAME + "/accounts.json"
  );

  // Initialize CEF.
  CefInitialize(main_args, BrickApp::GetCefSettings(szWorkingDir, app_settings), app.get(), NULL);

  // Create the handler.
  CefRefPtr<ClientHandler> client_handler(new ClientHandler);

  // Set default windows icon. Important to do this before any GTK window created!
  GList *list = NULL;
  std::string icon_path = app_settings.resource_dir + "/app_icons/";
  int icons_count = sizeof(APPICONS) / sizeof(APPICONS[0]);
  for (int i = 0; i < icons_count; ++i) {
    GdkPixbuf *icon = gdk_pixbuf_new_from_file((icon_path + APPICONS[i]).c_str(), NULL);
    if (!icon)
      continue;
    list = g_list_append(list, icon);
  }
  gtk_window_set_default_icon_list(list);
  g_list_foreach(list, (GFunc) g_object_unref, NULL);
  g_list_free(list);

  // Initialize main window
  CefRefPtr<MainWindow> main_window(new MainWindow);
  main_window->Init();
  main_window->SetTitle(APP_NAME);
  main_window->Show();
  client_handler->SetAppSettings(app_settings);
  client_handler->SetMainWindowHandle(main_window);
  client_handler->SetAccountManager(account_manager);

  // Initialize status icon
  CefRefPtr<StatusIcon> status_icon(new StatusIcon(app_settings.resource_dir + "/indicators/"));
  client_handler->SetStatusIconHandle(status_icon);

  CefWindowInfo window_info;
  // The GTK window must be visible before we can retrieve the XID.
  ::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(main_window->GetHandler()));
  window_info.SetAsChild(xwindow, CefRect(0, 0, 0, 0));
  window_util::SetLeaderWindow(xwindow);
  window_util::InitWindow(xwindow);
  window_util::InitHooks();

  std::string startup_url = account_manager->GetCurrentAccount()->GetBaseUrl();
  if (account_manager->GetCurrentAccount()->IsExisted()) {
    // Login to our account
    startup_url += "internals/pages/portal-loader#login=yes";
  } else {
    // Otherwise let's show error page
    startup_url += "internals/pages/home";
  }

  // Create browser
  CefBrowserHost::CreateBrowserSync(
     window_info, client_handler.get(),
     startup_url, BrickApp::GetBrowserSettings(szWorkingDir, app_settings), NULL);

  // Install a signal handler so we clean up after ourselves.
  signal(SIGINT, TerminationSignalHandler);
  signal(SIGTERM, TerminationSignalHandler);

  CefRunMessageLoop();

  CefShutdown();

  return 0;
}
<commit_msg>В простеньком виде реализовал "Another instance is already running" :-)<commit_after>#include <X11/Xlib.h>
#include <include/wrapper/cef_helpers.h>
#include <include/cef_app.h>
#include <unistd.h>
#include <gdk/gdkx.h>
#include <sys/file.h>

#include "brick_app.h"
#include "third-party/json/json.h"
#include "status_icon/status_icon.h"
#include "cef_handler.h"
#include "cef_app.h"
#include "window_util.h"
#include "helper.h"

#undef Status   // Definition conflicts with cef_urlrequest.h
#undef Success  // Definition conflicts with cef_message_router.h

namespace {
    std::string APPICONS[] = {"brick16.png", "brick32.png", "brick48.png", "brick128.png", "brick256.png"};
    std::string szWorkingDir;  // The current working directory

    bool GetWorkingDir(std::string& dir) {
      char buff[1024];

      // Retrieve the executable path.
      ssize_t len = readlink("/proc/self/exe", buff, sizeof(buff)-1);
      if (len == -1)
        return false;

      buff[len] = 0;
      dir = std::string(buff);
      // Remove the executable name from the path.
      dir = dir.substr(0, dir.find_last_of("/"));

      return true;
    }

    bool EnsureSingleInstance() {
      // ToDo: Replaced by IPC request, when IPC will be implemented
      std::string lock_file = std::string(BrickApp::GetCacheHome()) + "/" + APP_COMMON_NAME + "/run.lock";
      int fd = open(lock_file.c_str(), O_CREAT, 0600);
      if (fd == -1)
        return true;

      return flock(fd, LOCK_EX|LOCK_NB) == 0;
    }
}

// static
const char*
BrickApp::GetConfigHome() {
  return g_get_user_config_dir();
}

// static
const char*
BrickApp::GetCacheHome() {
  return g_get_user_cache_dir();
}

void
TerminationSignalHandler(int signatl) {
  CefQuitMessageLoop();
}

int main(int argc, char* argv[]) {
  CefMainArgs main_args(argc, argv);
  CefRefPtr<ClientApp> app(new ClientApp);

  // Execute the secondary process, if any.
  int exit_code = CefExecuteProcess(main_args, app.get(), NULL);
  if (exit_code >= 0)
    return exit_code;

  if (!EnsureSingleInstance()) {
    // ToDo: change main window stack order, when IPC will be implemented
    printf("Another instance is already running.\nExiting.");
    return 0;
  }

  GetWorkingDir(szWorkingDir);
  std::string plain_config = BrickApp::GetConfig();
  AppSettings app_settings = AppSettings::InitByJson(plain_config);
  app_settings.resource_dir = helper::BaseDir(szWorkingDir) + "/resources/";

  CefRefPtr<AccountManager> account_manager(new AccountManager);
  // ToDo: Fix this bullshit!
  account_manager->Init(
     std::string(BrickApp::GetConfigHome()) + "/" + APP_COMMON_NAME + "/accounts.json"
  );

  // Initialize CEF.
  CefInitialize(main_args, BrickApp::GetCefSettings(szWorkingDir, app_settings), app.get(), NULL);

  // Create the handler.
  CefRefPtr<ClientHandler> client_handler(new ClientHandler);

  // Set default windows icon. Important to do this before any GTK window created!
  GList *list = NULL;
  std::string icon_path = app_settings.resource_dir + "/app_icons/";
  int icons_count = sizeof(APPICONS) / sizeof(APPICONS[0]);
  for (int i = 0; i < icons_count; ++i) {
    GdkPixbuf *icon = gdk_pixbuf_new_from_file((icon_path + APPICONS[i]).c_str(), NULL);
    if (!icon)
      continue;
    list = g_list_append(list, icon);
  }
  gtk_window_set_default_icon_list(list);
  g_list_foreach(list, (GFunc) g_object_unref, NULL);
  g_list_free(list);

  // Initialize main window
  CefRefPtr<MainWindow> main_window(new MainWindow);
  main_window->Init();
  main_window->SetTitle(APP_NAME);
  main_window->Show();
  client_handler->SetAppSettings(app_settings);
  client_handler->SetMainWindowHandle(main_window);
  client_handler->SetAccountManager(account_manager);

  // Initialize status icon
  CefRefPtr<StatusIcon> status_icon(new StatusIcon(app_settings.resource_dir + "/indicators/"));
  client_handler->SetStatusIconHandle(status_icon);

  CefWindowInfo window_info;
  // The GTK window must be visible before we can retrieve the XID.
  ::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(main_window->GetHandler()));
  window_info.SetAsChild(xwindow, CefRect(0, 0, 0, 0));
  window_util::SetLeaderWindow(xwindow);
  window_util::InitWindow(xwindow);
  window_util::InitHooks();

  std::string startup_url = account_manager->GetCurrentAccount()->GetBaseUrl();
  if (account_manager->GetCurrentAccount()->IsExisted()) {
    // Login to our account
    startup_url += "internals/pages/portal-loader#login=yes";
  } else {
    // Otherwise let's show error page
    startup_url += "internals/pages/home";
  }

  // Create browser
  CefBrowserHost::CreateBrowserSync(
     window_info, client_handler.get(),
     startup_url, BrickApp::GetBrowserSettings(szWorkingDir, app_settings), NULL);

  // Install a signal handler so we clean up after ourselves.
  signal(SIGINT, TerminationSignalHandler);
  signal(SIGTERM, TerminationSignalHandler);

  CefRunMessageLoop();

  CefShutdown();

  return 0;
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

// This include needs to be the very first to prevent problems with warnings
// regarding redefinition of _POSIX_C_SOURCE
#include "boost/python.hpp"

#include "OpenEXR/ImathRandom.h"
#include "OpenEXR/ImathVec.h"

#include "IECore/bindings/ImathRandomBinding.h"

using namespace boost::python;
using namespace Imath;

namespace IECore
{

template<typename T, typename F>
void bindRand( const char *className )
{

	class_<T>( className )
		.def( init<unsigned long int>() )
		.def( "init", &T::init )
		.def( "nextb", &T::nextb )
		.def( "nexti", &T::nexti )
		.def( "nextf", (F (T::*)())&T::nextf )
		.def( "nextf", (F (T::*)( F, F ))&T::nextf )
		.def( "gauss", &gaussRand<T> )
		.def( "solidCirclef", &solidSphereRand<V2f,T> )
		.def( "solidCircled", &solidSphereRand<V2d,T> )
		.def( "solidSpheref", &solidSphereRand<V3f,T> )
		.def( "solidSphered", &solidSphereRand<V3d,T> )
		.def( "hollowCirclef", &hollowSphereRand<V2f,T> )
		.def( "hollowCircled", &hollowSphereRand<V2d,T> )
		.def( "hollowSpheref", &hollowSphereRand<V3f,T> )
		.def( "hollowSphered", &hollowSphereRand<V3d,T> )
		.def( "gaussCirclef", &gaussSphereRand<V2f,T> )
		.def( "gaussCircled", &gaussSphereRand<V2d,T> )
		.def( "gaussSpheref", &gaussSphereRand<V3f,T> )
		.def( "gaussSphered", &gaussSphereRand<V3d,T> )
	;

}

void bindImathRandom()
{
	bindRand<Rand32, float>( "Rand32" );
	bindRand<Rand48, double>( "Rand48" );

}

} // namespace IECore
<commit_msg>Added versions of random functions for returning many results at once, for when looping in python is just too slow.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

// This include needs to be the very first to prevent problems with warnings
// regarding redefinition of _POSIX_C_SOURCE
#include "boost/python.hpp"

#include "IECore/bindings/ImathRandomBinding.h"
#include "IECore/VectorTypedData.h"

#include "OpenEXR/ImathRandom.h"
#include "OpenEXR/ImathVec.h"
#include "OpenEXR/ImathColor.h"

#include "boost/type_traits.hpp"

using namespace boost::python;
using namespace boost;
using namespace Imath;

namespace IECore
{

template<typename R>
float nextFloat( R &r )
{
	return r.nextf();
}

template<typename T, typename R>
T nextVec( R &r )
{
	T result;
	for( unsigned int i=0; i<T::dimensions(); i++ )
	{
		result[i] = r.nextf();
	}
	return result;
}

template<typename R, typename T, T (*F)( R & )>
struct Vectoriser
{
	typedef TypedData<std::vector<T> > ResultType;
	typedef typename ResultType::Ptr ResultTypePtr;
	typedef typename ResultType::ValueType ValueType;
	typedef typename ValueType::iterator Iterator;

	static ResultTypePtr vectorise( R &r, size_t size )
	{
		ResultTypePtr result = new ResultType;
		ValueType &v = result->writable();
		v.resize( size );
		for( Iterator it=v.begin(); it!=v.end(); it++ )
		{
			*it = F( r );
		}
		return result;
	};

	template<typename S>
	static ResultTypePtr vectoriseSeededT( R &r, typename S::ConstPtr seeds )
	{
		const typename S::ValueType &seedsV = seeds->readable();
		ResultTypePtr result = new ResultType;
		ValueType &v = result->writable();
		v.resize( seedsV.size() );
		typename S::ValueType::const_iterator sIt = seedsV.begin();
		for( Iterator it=v.begin(); it!=v.end(); it++ )
		{
			r.init( (long unsigned int)(*sIt++) );
			*it = F( r );
		}
		return result;
	}

	static ResultTypePtr vectoriseSeeded( R &r, ConstDataPtr seeds )
	{
		switch( seeds->typeId() )
		{
			case FloatVectorDataTypeId :
				return vectoriseSeededT<FloatVectorData>( r, static_pointer_cast<const FloatVectorData>( seeds ) );
			case DoubleVectorDataTypeId :
				return vectoriseSeededT<DoubleVectorData>( r, static_pointer_cast<const DoubleVectorData>( seeds ) );
			case IntVectorDataTypeId :
				return vectoriseSeededT<IntVectorData>( r, static_pointer_cast<const IntVectorData>( seeds ) );
			case UIntVectorDataTypeId :
				return vectoriseSeededT<UIntVectorData>( r, static_pointer_cast<const UIntVectorData>( seeds ) );
			default :
				throw Exception( "Unsupported type for seeds parameter." );
		}
		return 0;
	}

};

template<typename T, typename F>
void bindRand( const char *className )
{

	class_<T>( className )
		.def( init<unsigned long int>() )
		.def( "init", &T::init )
		.def( "nextb", &T::nextb )
		.def( "nexti", &T::nexti )
		.def( "nextf", (F (T::*)())&T::nextf )
		.def( "nextf", (F (T::*)( F, F ))&T::nextf )
		.def( "fVector",  &Vectoriser<T, float, &nextFloat<T> >::vectorise )
		.def( "fVector",  &Vectoriser<T, float, &nextFloat<T> >::vectoriseSeeded )
		.def( "nextV2f", &nextVec<V2f, T> )
		.def( "nextV3f", &nextVec<V3f, T> )
		.def( "nextV2d", &nextVec<V2d, T> )
		.def( "nextV3d", &nextVec<V3d, T> )
		.def( "v2fVector", &Vectoriser<T, V2f, &nextVec<V2f, T> >::vectorise )
		.def( "v2fVector", &Vectoriser<T, V2f, &nextVec<V2f, T> >::vectoriseSeeded )
		.def( "v2dVector", &Vectoriser<T, V2d, &nextVec<V2d, T> >::vectorise )
		.def( "v2dVector", &Vectoriser<T, V2d, &nextVec<V2d, T> >::vectoriseSeeded )
		.def( "v3fVector", &Vectoriser<T, V3f, &nextVec<V3f, T> >::vectorise )
		.def( "v3fVector", &Vectoriser<T, V3f, &nextVec<V3f, T> >::vectoriseSeeded )
		.def( "v3dVector", &Vectoriser<T, V3d, &nextVec<V3d, T> >::vectorise )
		.def( "v3dVector", &Vectoriser<T, V3d, &nextVec<V3d, T> >::vectoriseSeeded )
		.def( "nextColor3f", &nextVec<Color3f, T> )
		.def( "gauss", &gaussRand<T> )
		.def( "solidCirclef", &solidSphereRand<V2f,T> )
		.def( "solidCircled", &solidSphereRand<V2d,T> )
		.def( "solidCirclefVector", &Vectoriser<T, V2f, &solidSphereRand<V2f, T> >::vectorise )
		.def( "solidCirclefVector", &Vectoriser<T, V2f, &solidSphereRand<V2f, T> >::vectoriseSeeded )
		.def( "solidCircledVector", &Vectoriser<T, V2d, &solidSphereRand<V2d, T> >::vectorise )
		.def( "solidCircledVector", &Vectoriser<T, V2d, &solidSphereRand<V2d, T> >::vectoriseSeeded )
		.def( "solidSpheref", &solidSphereRand<V3f,T> )
		.def( "solidSphered", &solidSphereRand<V3d,T> )
		.def( "solidSpherefVector", &Vectoriser<T, V3f, &solidSphereRand<V3f, T> >::vectorise )
		.def( "solidSpherefVector", &Vectoriser<T, V3f, &solidSphereRand<V3f, T> >::vectoriseSeeded )
		.def( "solidSpheredVector", &Vectoriser<T, V3d, &solidSphereRand<V3d, T> >::vectorise )
		.def( "solidSpheredVector", &Vectoriser<T, V3d, &solidSphereRand<V3d, T> >::vectoriseSeeded )
		.def( "hollowCirclef", &hollowSphereRand<V2f,T> )
		.def( "hollowCircled", &hollowSphereRand<V2d,T> )
		.def( "hollowCirclefVector", &Vectoriser<T, V2f, &hollowSphereRand<V2f, T> >::vectorise )
		.def( "hollowCirclefVector", &Vectoriser<T, V2f, &hollowSphereRand<V2f, T> >::vectoriseSeeded )
		.def( "hollowCircledVector", &Vectoriser<T, V2d, &hollowSphereRand<V2d, T> >::vectorise )
		.def( "hollowCircledVector", &Vectoriser<T, V2d, &hollowSphereRand<V2d, T> >::vectoriseSeeded )
		.def( "hollowSpheref", &hollowSphereRand<V3f,T> )
		.def( "hollowSphered", &hollowSphereRand<V3d,T> )
		.def( "hollowSpherefVector", &Vectoriser<T, V3f, &hollowSphereRand<V3f, T> >::vectorise )
		.def( "hollowSpherefVector", &Vectoriser<T, V3f, &hollowSphereRand<V3f, T> >::vectoriseSeeded )
		.def( "hollowSpheredVector", &Vectoriser<T, V3d, &hollowSphereRand<V3d, T> >::vectorise )
		.def( "hollowSpheredVector", &Vectoriser<T, V3d, &hollowSphereRand<V3d, T> >::vectoriseSeeded )
		.def( "gaussCirclef", &gaussSphereRand<V2f,T> )
		.def( "gaussCircled", &gaussSphereRand<V2d,T> )
		.def( "gaussCirclefVector", &Vectoriser<T, V2f, &gaussSphereRand<V2f, T> >::vectorise )
		.def( "gaussCirclefVector", &Vectoriser<T, V2f, &gaussSphereRand<V2f, T> >::vectoriseSeeded )
		.def( "gaussCircledVector", &Vectoriser<T, V2d, &gaussSphereRand<V2d, T> >::vectorise )
		.def( "gaussCircledVector", &Vectoriser<T, V2d, &gaussSphereRand<V2d, T> >::vectoriseSeeded )
		.def( "gaussSpheref", &gaussSphereRand<V3f,T> )
		.def( "gaussSphered", &gaussSphereRand<V3d,T> )
		.def( "gaussSpherefVector", &Vectoriser<T, V2f, &gaussSphereRand<V2f, T> >::vectorise )
		.def( "gaussSpherefVector", &Vectoriser<T, V2f, &gaussSphereRand<V2f, T> >::vectoriseSeeded )
		.def( "gaussSpheredVector", &Vectoriser<T, V2d, &gaussSphereRand<V2d, T> >::vectorise )
		.def( "gaussSpheredVector", &Vectoriser<T, V2d, &gaussSphereRand<V2d, T> >::vectoriseSeeded )
	;

}

void bindImathRandom()
{
	bindRand<Rand32, float>( "Rand32" );
	bindRand<Rand48, double>( "Rand48" );
}

} // namespace IECore
<|endoftext|>


<commit_before>// -*- coding: us-ascii-unix -*-
// Copyright 2012 Lukas Kemmer
//
// Licensed under the Apache License, Version 2.0 (the "License"); you
// may not use this file except in compliance with the License. You
// may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.

#include "wx/bitmap.h"
#include "wx/defs.h"
#include "wx/event.h"
#include "wx/clipbrd.h"
#ifdef __WXMSW__
#include "wx/dcmemory.h"
#endif
#include "wx/filename.h"
#include "wx/rawbmp.h"
#include "wx/tokenzr.h"
#include "bitmap/bitmap.hh"
#include "bitmap/color.hh"
#include "geo/int-point.hh"
#include "geo/int-rect.hh"
#include "gui/art.hh"
#include "text/utf8-string.hh"
#include "util-wx/file-path.hh"
#include "util/pos-info.hh"

namespace faint{

wxFileName absoluted(const wxFileName& filename){
  wxFileName other(filename);
  other.MakeAbsolute();
  return other;
}

wxColour to_wx(const ColRGB& c){
  return wxColour(c.r, c.g, c.b);
}

wxColour to_wx(const Color& c){
  return wxColour(c.r, c.g, c.b, c.a);
}

wxRect to_wx(const IntRect& r){
  return wxRect(r.x, r.y, r.w, r.h);
}

wxPoint to_wx(const IntPoint& p){
  return wxPoint(p.x, p.y);
}

wxSize to_wx(const IntSize& sz){
  return wxSize(sz.w, sz.h);
}

IntPoint to_faint(const wxPoint& p){
  return IntPoint(p.x, p.y);
}

Color to_faint(const wxColour& c){
  return Color(c.Red(), c.Green(), c.Blue(), c.Alpha());
}

IntRect to_faint(const wxRect& r){
  return IntRect(IntPoint(r.x, r.y), IntSize(r.width, r.height));
}

IntSize to_faint(const wxSize& sz){
  return IntSize(sz.GetWidth(), sz.GetHeight());
}

static ToolModifiers get_key_tool_modifiers(){
  ToolModifiers modifiers;
  if (wxGetKeyState(WXK_CONTROL)){
    modifiers.SetPrimary();
  }
  if (wxGetKeyState(WXK_SHIFT)){
    modifiers.SetSecondary();
  }
  return modifiers;
}

ToolModifiers get_tool_modifiers(){
  ToolModifiers modifiers = get_key_tool_modifiers();
  wxMouseState mouseState = wxGetMouseState();
  if (mouseState.LeftIsDown()){
    modifiers.SetLeftMouse();
  }
  else if (mouseState.RightIsDown()){
    modifiers.SetRightMouse();
  }
  return modifiers;
}

ToolModifiers mouse_modifiers(const wxMouseEvent& event){
  ToolModifiers modifiers = get_key_tool_modifiers();
  if (event.LeftUp() || event.LeftDown() || event.LeftDClick()){
    modifiers.SetLeftMouse();
  }
  else if (event.RightUp() || event.RightDown()){
    modifiers.SetRightMouse();
  }
  return modifiers;
}

Mod key_modifiers(const wxKeyEvent& event){
  return Ctrl.If(event.ControlDown()) +
    Shift.If(event.ShiftDown()) +
    Alt.If(event.AltDown());
}

wxImage to_wx_image(const Bitmap& bmp){
  const int stride = bmp.m_row_stride;
  const uchar* bgraData = bmp.m_data;

  // Using malloc to match wxWidgets free
  uchar* rgbData = (uchar*)malloc(to_size_t(bmp.m_w * bmp.m_h * 3));
  uchar* aData = (uchar*)malloc(to_size_t(bmp.m_w * bmp.m_h));

  for (int y = 0; y != bmp.m_h; y++){
    for (int x = 0; x != bmp.m_w; x++){
      size_t srcPos = to_size_t(y * stride + x * ByPP);
      size_t dstPos_rgb = to_size_t(y * bmp.m_w * 3 + x * 3);
      size_t dstPos_alpha = to_size_t(y * bmp.m_w + x);
      rgbData[dstPos_rgb] = bgraData[srcPos + iR];
      rgbData[dstPos_rgb + 1] = bgraData[srcPos + iG];
      rgbData[dstPos_rgb + 2] = bgraData[srcPos + iB];
      aData[dstPos_alpha] = bgraData[srcPos + iA];
    }
  }

  // wxWidgets takes ownership of rgbData and aData, and uses free()
  // to release the memory.
  wxImage result(bmp.m_w, bmp.m_h, rgbData, aData);
  return result;
}

using AlphaPixelData = wxPixelData<wxBitmap, wxAlphaPixelFormat>;
using PixelData = AlphaPixelData;
wxBitmap to_wx_bmp(const Bitmap& bmp){
  wxBitmap wxBmp(bmp.m_w, bmp.m_h, 32);
  PixelData pData(wxBmp);
  assert(pData);
  PixelData::Iterator p = pData;

  uchar* data = bmp.m_data;
  const int stride = bmp.m_row_stride;

  for (int y = 0; y != bmp.m_h; y++){
    PixelData::Iterator rowStart = p;
    for (int x = 0; x != bmp.m_w; x++){
      int pos = y *  stride + x * ByPP;
      #ifdef __WXMSW__
      const uchar alpha = *(data + pos + iA);
      p.Alpha() = alpha;
      // Todo: What. Simplify.
      p.Red() = (*(data + pos + iR) * alpha) / 255;
      p.Green() = (*(data + pos + iG) * alpha) / 255;
      p.Blue() = (*(data + pos + iB) * alpha) / 255;
      #else
      p.Alpha() = *(data + pos + iA);
      p.Red()   = *(data + pos + iR);
      p.Green() = *(data + pos + iG);
      p.Blue()  = *(data + pos + iB);
      #endif
      ++p;
    }
    p = rowStart;
    p.OffsetY(pData, 1);
  }
  return wxBmp;
}

Bitmap to_faint(wxBitmap wxBmp){
  Bitmap bmp(to_faint(wxBmp.GetSize()));
  if (wxBmp.GetDepth() == 24){
    wxNativePixelData pixelData(wxBmp);
    if (!pixelData){
      goto alpha_label;
    }
    wxNativePixelData::Iterator p = pixelData;
    const int stride = bmp.m_row_stride;
    uchar* data = bmp.GetRaw();
    for (int y = 0; y != bmp.m_h; y++){
      wxPixelData<wxBitmap, wxNativePixelFormat>::Iterator rowStart = p;
      for (int x = 0; x != bmp.m_w; x++){
        size_t pos = to_size_t(y * stride + x * ByPP);
        data[pos + iA] = 255;
        data[pos + iR] = p.Red();
        data[pos + iG] = p.Green();
        data[pos + iB] = p.Blue();
        ++p;
      }
      p = rowStart;
      p.OffsetY(pixelData, 1);
    }
  }
  else {
  alpha_label:
    AlphaPixelData pixelData(wxBmp);
    assert(pixelData);
    AlphaPixelData::Iterator p = pixelData;
    const int stride = bmp.m_row_stride;
    uchar* data = bmp.GetRaw();
    for (int y = 0; y != bmp.m_h; y++){
      AlphaPixelData::Iterator rowStart = p;
      for (int x = 0; x != bmp.m_w; x++){
        size_t pos = to_size_t(y * stride + x * ByPP);
        #ifdef __WXMSW__
        // Convert back from premultiplied alpha
        data[pos + iA] = p.Alpha();
        if (p.Alpha() != 0){
          data[pos + iR] = (p.Red() * 255) / (255 - (255 - p.Alpha()));
          data[pos + iG] = (p.Green() * 255) / (255 - (255 - p.Alpha()));
          data[pos + iB] = (p.Blue() * 255) / (255 - (255 - p.Alpha()));
        }
        #else
        data[pos + iA] = p.Alpha();
        data[pos + iR] = p.Red();
        data[pos + iG] = p.Green();
        data[pos + iB] = p.Blue();
        #endif
        ++p;
      }
      p = rowStart;
      p.OffsetY(pixelData, 1);
    }
  }
  return bmp;
}

#ifdef __WXMSW__
// Without this, pasting from clipboard in MSW causes this error:
// msw\bitmap.cpp(1287): assert "Assert failure" failed in
// wxBitmap::GetRawData(): failed to get DIBSECTION from a DIB?
//
// Probably this bug: http://trac.wxwidgets.org/ticket/11640
wxBitmap clean_bitmap(const wxBitmap& dirtyBmp){
  // Note: This uses 24-bits-per-pixel, thereby losing alpha
  // information, as wxMemoryDC does not support alpha.
  //
  // Using 32-bits-per-pixel here (or retrieving the necessary value
  // from the wxBitmap) works for pastes between applications and
  // within Faint, but fails for pastes from print screen (gives very
  // weird effects, probably random alpha values).
  //
  // ... I've also tried GCDC Blit and DrawBitmap, neither retained
  // alpha.
  wxBitmap cleanBmp(dirtyBmp.GetWidth(), dirtyBmp.GetHeight(), 24);
  wxMemoryDC cleanDC(cleanBmp);
  cleanDC.DrawBitmap(dirtyBmp, 0, 0);
  cleanDC.SelectObject(wxNullBitmap);
  return cleanBmp;
}
#endif

#ifndef __WXMSW__

wxBitmap clean_bitmap(const wxBitmap& dirtyBmp){
  return dirtyBmp;
}

#endif

utf8_char to_faint(const wxChar& ch){
  wxString s;
  s += ch;
  wxCharBuffer buf = s.utf8_str();
  return utf8_char(std::string(buf, buf.length()));
}

utf8_string to_faint(const wxString& str){
  wxCharBuffer buf(str.utf8_str());
  return utf8_string(std::string(buf, buf.length()));
}

wxString to_wx(const utf8_string& faintStr){
  return wxString::FromUTF8(faintStr.c_str());
}

FileList to_FileList(const wxArrayString& strings){
  FileList files;
  for (const wxString& str : strings){
    files.push_back(FilePath::FromAbsoluteWx(str));
  }
  return files;
}

wxString get_clipboard_text(){
  wxTextDataObject textObject;
  if (!wxTheClipboard->GetData(textObject)){
    return "";
  }
  return textObject.GetText();
}

std::vector<wxString> wx_split_lines(const wxString& text){
  wxStringTokenizer tokenizer(text, "\r\n");
  std::vector<wxString> v;
  while (tokenizer.HasMoreTokens()){
    v.push_back(tokenizer.GetNextToken());
  }
  return v;
}

#ifdef FAINT_MSW
std::wstring iostream_friendly(const wxString& path){
  // As best I can tell this wxWidgets method will provide an
  // UTF16-encoded std::wstring, which the Visual C++-implementation
  // of iostream accepts.
  return path.ToStdWstring();
}
#else
std::string iostream_friendly(const wxString& path){
  return to_faint(path).str();
}
#endif

} // namespace
<commit_msg>Removed unnecessary include.<commit_after>// -*- coding: us-ascii-unix -*-
// Copyright 2012 Lukas Kemmer
//
// Licensed under the Apache License, Version 2.0 (the "License"); you
// may not use this file except in compliance with the License. You
// may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.

#include "wx/bitmap.h"
#include "wx/defs.h"
#include "wx/event.h"
#include "wx/clipbrd.h"
#ifdef __WXMSW__
#include "wx/dcmemory.h"
#endif
#include "wx/filename.h"
#include "wx/rawbmp.h"
#include "wx/tokenzr.h"
#include "bitmap/bitmap.hh"
#include "bitmap/color.hh"
#include "geo/int-point.hh"
#include "geo/int-rect.hh"
#include "text/utf8-string.hh"
#include "util-wx/file-path.hh"
#include "util/pos-info.hh"

namespace faint{

wxFileName absoluted(const wxFileName& filename){
  wxFileName other(filename);
  other.MakeAbsolute();
  return other;
}

wxColour to_wx(const ColRGB& c){
  return wxColour(c.r, c.g, c.b);
}

wxColour to_wx(const Color& c){
  return wxColour(c.r, c.g, c.b, c.a);
}

wxRect to_wx(const IntRect& r){
  return wxRect(r.x, r.y, r.w, r.h);
}

wxPoint to_wx(const IntPoint& p){
  return wxPoint(p.x, p.y);
}

wxSize to_wx(const IntSize& sz){
  return wxSize(sz.w, sz.h);
}

IntPoint to_faint(const wxPoint& p){
  return IntPoint(p.x, p.y);
}

Color to_faint(const wxColour& c){
  return Color(c.Red(), c.Green(), c.Blue(), c.Alpha());
}

IntRect to_faint(const wxRect& r){
  return IntRect(IntPoint(r.x, r.y), IntSize(r.width, r.height));
}

IntSize to_faint(const wxSize& sz){
  return IntSize(sz.GetWidth(), sz.GetHeight());
}

static ToolModifiers get_key_tool_modifiers(){
  ToolModifiers modifiers;
  if (wxGetKeyState(WXK_CONTROL)){
    modifiers.SetPrimary();
  }
  if (wxGetKeyState(WXK_SHIFT)){
    modifiers.SetSecondary();
  }
  return modifiers;
}

ToolModifiers get_tool_modifiers(){
  ToolModifiers modifiers = get_key_tool_modifiers();
  wxMouseState mouseState = wxGetMouseState();
  if (mouseState.LeftIsDown()){
    modifiers.SetLeftMouse();
  }
  else if (mouseState.RightIsDown()){
    modifiers.SetRightMouse();
  }
  return modifiers;
}

ToolModifiers mouse_modifiers(const wxMouseEvent& event){
  ToolModifiers modifiers = get_key_tool_modifiers();
  if (event.LeftUp() || event.LeftDown() || event.LeftDClick()){
    modifiers.SetLeftMouse();
  }
  else if (event.RightUp() || event.RightDown()){
    modifiers.SetRightMouse();
  }
  return modifiers;
}

Mod key_modifiers(const wxKeyEvent& event){
  return Ctrl.If(event.ControlDown()) +
    Shift.If(event.ShiftDown()) +
    Alt.If(event.AltDown());
}

wxImage to_wx_image(const Bitmap& bmp){
  const int stride = bmp.m_row_stride;
  const uchar* bgraData = bmp.m_data;

  // Using malloc to match wxWidgets free
  uchar* rgbData = (uchar*)malloc(to_size_t(bmp.m_w * bmp.m_h * 3));
  uchar* aData = (uchar*)malloc(to_size_t(bmp.m_w * bmp.m_h));

  for (int y = 0; y != bmp.m_h; y++){
    for (int x = 0; x != bmp.m_w; x++){
      size_t srcPos = to_size_t(y * stride + x * ByPP);
      size_t dstPos_rgb = to_size_t(y * bmp.m_w * 3 + x * 3);
      size_t dstPos_alpha = to_size_t(y * bmp.m_w + x);
      rgbData[dstPos_rgb] = bgraData[srcPos + iR];
      rgbData[dstPos_rgb + 1] = bgraData[srcPos + iG];
      rgbData[dstPos_rgb + 2] = bgraData[srcPos + iB];
      aData[dstPos_alpha] = bgraData[srcPos + iA];
    }
  }

  // wxWidgets takes ownership of rgbData and aData, and uses free()
  // to release the memory.
  wxImage result(bmp.m_w, bmp.m_h, rgbData, aData);
  return result;
}

using AlphaPixelData = wxPixelData<wxBitmap, wxAlphaPixelFormat>;
using PixelData = AlphaPixelData;
wxBitmap to_wx_bmp(const Bitmap& bmp){
  wxBitmap wxBmp(bmp.m_w, bmp.m_h, 32);
  PixelData pData(wxBmp);
  assert(pData);
  PixelData::Iterator p = pData;

  uchar* data = bmp.m_data;
  const int stride = bmp.m_row_stride;

  for (int y = 0; y != bmp.m_h; y++){
    PixelData::Iterator rowStart = p;
    for (int x = 0; x != bmp.m_w; x++){
      int pos = y *  stride + x * ByPP;
      #ifdef __WXMSW__
      const uchar alpha = *(data + pos + iA);
      p.Alpha() = alpha;
      // Todo: What. Simplify.
      p.Red() = (*(data + pos + iR) * alpha) / 255;
      p.Green() = (*(data + pos + iG) * alpha) / 255;
      p.Blue() = (*(data + pos + iB) * alpha) / 255;
      #else
      p.Alpha() = *(data + pos + iA);
      p.Red()   = *(data + pos + iR);
      p.Green() = *(data + pos + iG);
      p.Blue()  = *(data + pos + iB);
      #endif
      ++p;
    }
    p = rowStart;
    p.OffsetY(pData, 1);
  }
  return wxBmp;
}

Bitmap to_faint(wxBitmap wxBmp){
  Bitmap bmp(to_faint(wxBmp.GetSize()));
  if (wxBmp.GetDepth() == 24){
    wxNativePixelData pixelData(wxBmp);
    if (!pixelData){
      goto alpha_label;
    }
    wxNativePixelData::Iterator p = pixelData;
    const int stride = bmp.m_row_stride;
    uchar* data = bmp.GetRaw();
    for (int y = 0; y != bmp.m_h; y++){
      wxPixelData<wxBitmap, wxNativePixelFormat>::Iterator rowStart = p;
      for (int x = 0; x != bmp.m_w; x++){
        size_t pos = to_size_t(y * stride + x * ByPP);
        data[pos + iA] = 255;
        data[pos + iR] = p.Red();
        data[pos + iG] = p.Green();
        data[pos + iB] = p.Blue();
        ++p;
      }
      p = rowStart;
      p.OffsetY(pixelData, 1);
    }
  }
  else {
  alpha_label:
    AlphaPixelData pixelData(wxBmp);
    assert(pixelData);
    AlphaPixelData::Iterator p = pixelData;
    const int stride = bmp.m_row_stride;
    uchar* data = bmp.GetRaw();
    for (int y = 0; y != bmp.m_h; y++){
      AlphaPixelData::Iterator rowStart = p;
      for (int x = 0; x != bmp.m_w; x++){
        size_t pos = to_size_t(y * stride + x * ByPP);
        #ifdef __WXMSW__
        // Convert back from premultiplied alpha
        data[pos + iA] = p.Alpha();
        if (p.Alpha() != 0){
          data[pos + iR] = (p.Red() * 255) / (255 - (255 - p.Alpha()));
          data[pos + iG] = (p.Green() * 255) / (255 - (255 - p.Alpha()));
          data[pos + iB] = (p.Blue() * 255) / (255 - (255 - p.Alpha()));
        }
        #else
        data[pos + iA] = p.Alpha();
        data[pos + iR] = p.Red();
        data[pos + iG] = p.Green();
        data[pos + iB] = p.Blue();
        #endif
        ++p;
      }
      p = rowStart;
      p.OffsetY(pixelData, 1);
    }
  }
  return bmp;
}

#ifdef __WXMSW__
// Without this, pasting from clipboard in MSW causes this error:
// msw\bitmap.cpp(1287): assert "Assert failure" failed in
// wxBitmap::GetRawData(): failed to get DIBSECTION from a DIB?
//
// Probably this bug: http://trac.wxwidgets.org/ticket/11640
wxBitmap clean_bitmap(const wxBitmap& dirtyBmp){
  // Note: This uses 24-bits-per-pixel, thereby losing alpha
  // information, as wxMemoryDC does not support alpha.
  //
  // Using 32-bits-per-pixel here (or retrieving the necessary value
  // from the wxBitmap) works for pastes between applications and
  // within Faint, but fails for pastes from print screen (gives very
  // weird effects, probably random alpha values).
  //
  // ... I've also tried GCDC Blit and DrawBitmap, neither retained
  // alpha.
  wxBitmap cleanBmp(dirtyBmp.GetWidth(), dirtyBmp.GetHeight(), 24);
  wxMemoryDC cleanDC(cleanBmp);
  cleanDC.DrawBitmap(dirtyBmp, 0, 0);
  cleanDC.SelectObject(wxNullBitmap);
  return cleanBmp;
}
#endif

#ifndef __WXMSW__

wxBitmap clean_bitmap(const wxBitmap& dirtyBmp){
  return dirtyBmp;
}

#endif

utf8_char to_faint(const wxChar& ch){
  wxString s;
  s += ch;
  wxCharBuffer buf = s.utf8_str();
  return utf8_char(std::string(buf, buf.length()));
}

utf8_string to_faint(const wxString& str){
  wxCharBuffer buf(str.utf8_str());
  return utf8_string(std::string(buf, buf.length()));
}

wxString to_wx(const utf8_string& faintStr){
  return wxString::FromUTF8(faintStr.c_str());
}

FileList to_FileList(const wxArrayString& strings){
  FileList files;
  for (const wxString& str : strings){
    files.push_back(FilePath::FromAbsoluteWx(str));
  }
  return files;
}

wxString get_clipboard_text(){
  wxTextDataObject textObject;
  if (!wxTheClipboard->GetData(textObject)){
    return "";
  }
  return textObject.GetText();
}

std::vector<wxString> wx_split_lines(const wxString& text){
  wxStringTokenizer tokenizer(text, "\r\n");
  std::vector<wxString> v;
  while (tokenizer.HasMoreTokens()){
    v.push_back(tokenizer.GetNextToken());
  }
  return v;
}

#ifdef FAINT_MSW
std::wstring iostream_friendly(const wxString& path){
  // As best I can tell this wxWidgets method will provide an
  // UTF16-encoded std::wstring, which the Visual C++-implementation
  // of iostream accepts.
  return path.ToStdWstring();
}
#else
std::string iostream_friendly(const wxString& path){
  return to_faint(path).str();
}
#endif

} // namespace
<|endoftext|>