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

#ifndef _UTILS_HUB_HXX_
#define _UTILS_HUB_HXX_

#include <stdint.h>
#include <string>

#include "executor/Dispatcher.hxx"
#include "can_frame.h"

class PipeBuffer;
class PipeMember;

struct CanFrameContainer : public can_frame
{
    /* Constructor. Sets up (outgoing) frames to be empty extended frames by
     * default. */
    CanFrameContainer()
    {
        CLR_CAN_FRAME_ERR(*this);
        CLR_CAN_FRAME_RTR(*this);
        SET_CAN_FRAME_EFF(*this);
        can_dlc = 0;
    }

    /** @Returns a mutable pointer to the embedded CAN frame. */
    struct can_frame *mutable_frame()
    {
        return this;
    }
    /** @Returns the embedded CAN frame. */
    const struct can_frame &frame() const
    {
        return *this;
    }

    const void* data() const {
        return &frame();
    }

    size_t size() {
        return sizeof(struct can_frame);
    }
};

template <class T> class HubContainer : public T
{
public:
    // typedef FlowInterface<Buffer<HubContainer<T>>> HubMember;
    HubContainer() : skipMember_(0)
    {
    }
    typedef uintptr_t id_type;
    FlowInterface<Buffer<HubContainer<T>>> *skipMember_;
    id_type id()
    {
        return reinterpret_cast<uintptr_t>(skipMember_);
    }
};

/** This class can be sent via a Buffer to a hub.
 *
 * Access the data content via members char* data() and size_t size().
 *
 * Set skipMember_ to non-NULL to skip a particular entry flow of the output.
 */
typedef HubContainer<string> HubData;

/** This class can be sent via a Buffer to a CAN hub.
 *
 * Access the data content via members \ref mutable_frame and \ref frame.
 *
 * Set skipMember_ to non-NULL to skip a particular entry flow of the output.
 */
typedef HubContainer<CanFrameContainer> CanHubData;

/** All ports interfacing via a hub will have to derive from this flow. */
typedef FlowInterface<Buffer<HubData>> HubPortInterface;
typedef StateFlow<Buffer<HubData>, QList<1>> HubPort;
typedef FlowInterface<Buffer<CanHubData>> CanHubPortInterface;
typedef StateFlow<Buffer<CanHubData>, QList<1>> CanHubPort;

// This should work for both 32 and 64-bit architectures.
static const uintptr_t POINTER_MASK = UINTPTR_MAX;

/** A generic hub that proxies packets of untyped data. */
class HubFlow : public DispatchFlow<Buffer<HubData>, 1>
{
public:
    typedef HubData value_type;
    typedef Buffer<HubData> buffer_type;

    HubFlow(Service *s) : DispatchFlow<Buffer<HubData>, 1>(s)
    {
        negateMatch_ = true;
    }

    void register_port(HubPortInterface *port)
    {
        register_handler(port, reinterpret_cast<uintptr_t>(port), POINTER_MASK);
    }

    void unregister_port(HubPortInterface *port)
    {
        unregister_handler(port, reinterpret_cast<uintptr_t>(port),
                           POINTER_MASK);
    }
};

/** A hub that proxies packets of CAN frames. */
class CanHubFlow : public DispatchFlow<Buffer<CanHubData>, 1>
{
public:
    typedef CanHubData value_type;
    typedef Buffer<CanHubData> buffer_type;

    CanHubFlow(Service *s) : DispatchFlow<Buffer<CanHubData>, 1>(s)
    {
        negateMatch_ = true;
    }

    void register_port(CanHubPortInterface *port)
    {
        register_handler(port, reinterpret_cast<uintptr_t>(port), POINTER_MASK);
    }

    void unregister_port(CanHubPortInterface *port)
    {
        unregister_handler(port, reinterpret_cast<uintptr_t>(port),
                           POINTER_MASK);
    }
};

/** This port prints all traffic from a hub to stdout. */
class DisplayPort : public HubPort
{
public:
    DisplayPort(Service* service) : HubPort(service)
    {
    }

    virtual Action entry()
    {
        string s(message()->data()->data(), message()->data()->size());
        printf("%s", s.c_str());
        return release_and_exit();
    }
};

#endif // _UTILS_HUB_HXX_
<commit_msg>Additional utility functions.<commit_after>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file Hub.hxx
 * Implementation of the pipe dispatcher flow.
 *
 * @author Balazs Racz
 * @date 8 Dec 2013
 */

#ifndef _UTILS_HUB_HXX_
#define _UTILS_HUB_HXX_

#include <stdint.h>
#include <string>

#include "executor/Dispatcher.hxx"
#include "can_frame.h"

class PipeBuffer;
class PipeMember;

struct CanFrameContainer : public can_frame
{
    /* Constructor. Sets up (outgoing) frames to be empty extended frames by
     * default. */
    CanFrameContainer()
    {
        CLR_CAN_FRAME_ERR(*this);
        CLR_CAN_FRAME_RTR(*this);
        SET_CAN_FRAME_EFF(*this);
        can_dlc = 0;
    }

    /** @Returns a mutable pointer to the embedded CAN frame. */
    struct can_frame *mutable_frame()
    {
        return this;
    }
    /** @Returns the embedded CAN frame. */
    const struct can_frame &frame() const
    {
        return *this;
    }

    const void* data() const {
        return &frame();
    }

    void* data() {
        return mutable_frame();
    }

    size_t size() {
        return sizeof(struct can_frame);
    }
};

template <class T> class HubContainer : public T
{
public:
    // typedef FlowInterface<Buffer<HubContainer<T>>> HubMember;
    HubContainer() : skipMember_(0)
    {
    }
    typedef uintptr_t id_type;
    FlowInterface<Buffer<HubContainer<T>>> *skipMember_;
    id_type id()
    {
        return reinterpret_cast<uintptr_t>(skipMember_);
    }
};

/** This class can be sent via a Buffer to a hub.
 *
 * Access the data content via members char* data() and size_t size().
 *
 * Set skipMember_ to non-NULL to skip a particular entry flow of the output.
 */
typedef HubContainer<string> HubData;

/** This class can be sent via a Buffer to a CAN hub.
 *
 * Access the data content via members \ref mutable_frame and \ref frame.
 *
 * Set skipMember_ to non-NULL to skip a particular entry flow of the output.
 */
typedef HubContainer<CanFrameContainer> CanHubData;

/** All ports interfacing via a hub will have to derive from this flow. */
typedef FlowInterface<Buffer<HubData>> HubPortInterface;
typedef StateFlow<Buffer<HubData>, QList<1>> HubPort;
typedef FlowInterface<Buffer<CanHubData>> CanHubPortInterface;
typedef StateFlow<Buffer<CanHubData>, QList<1>> CanHubPort;

// This should work for both 32 and 64-bit architectures.
static const uintptr_t POINTER_MASK = UINTPTR_MAX;

/** A generic hub that proxies packets of untyped data. */
class HubFlow : public DispatchFlow<Buffer<HubData>, 1>
{
public:
    typedef HubData value_type;
    typedef Buffer<HubData> buffer_type;
    typedef HubPortInterface port_type;

    HubFlow(Service *s) : DispatchFlow<Buffer<HubData>, 1>(s)
    {
        negateMatch_ = true;
    }

    void register_port(HubPortInterface *port)
    {
        register_handler(port, reinterpret_cast<uintptr_t>(port), POINTER_MASK);
    }

    void unregister_port(HubPortInterface *port)
    {
        unregister_handler(port, reinterpret_cast<uintptr_t>(port),
                           POINTER_MASK);
    }
};

/** A hub that proxies packets of CAN frames. */
class CanHubFlow : public DispatchFlow<Buffer<CanHubData>, 1>
{
public:
    typedef CanHubData value_type;
    typedef Buffer<CanHubData> buffer_type;
    typedef CanHubPortInterface port_type;

    CanHubFlow(Service *s) : DispatchFlow<Buffer<CanHubData>, 1>(s)
    {
        negateMatch_ = true;
    }

    void register_port(CanHubPortInterface *port)
    {
        register_handler(port, reinterpret_cast<uintptr_t>(port), POINTER_MASK);
    }

    void unregister_port(CanHubPortInterface *port)
    {
        unregister_handler(port, reinterpret_cast<uintptr_t>(port),
                           POINTER_MASK);
    }
};

/** This port prints all traffic from a hub to stdout. */
class DisplayPort : public HubPort
{
public:
    DisplayPort(Service* service) : HubPort(service)
    {
    }

    virtual Action entry()
    {
        string s(message()->data()->data(), message()->data()->size());
        printf("%s", s.c_str());
        return release_and_exit();
    }
};

#endif // _UTILS_HUB_HXX_
<|endoftext|>


<commit_before>/** Copyright (C) 2017 Tim Kuipers - Released under terms of the AGPLv3 License */
#include "SVG.h"

namespace cura {

std::string SVG::toString(Color color)
{
    switch (color)
    {
        case SVG::Color::BLACK: return "black";
        case SVG::Color::WHITE: return "white";
        case SVG::Color::GRAY: return "gray";
        case SVG::Color::RED: return "red";
        case SVG::Color::BLUE: return "blue";
        case SVG::Color::GREEN: return "green";
        case SVG::Color::YELLOW: return "yellow";
        default: return "black";
    }
}

SVG::SVG(const char* filename, AABB aabb, Point canvas_size)
: aabb(aabb)
, aabb_size(aabb.max - aabb.min)
, border(200,100)
, canvas_size(canvas_size)
, scale(std::min(double(canvas_size.X - border.X * 2) / aabb_size.X, double(canvas_size.Y - border.Y * 2) / aabb_size.Y))
{
    output_is_html = strcmp(filename + strlen(filename) - 4, "html") == 0;
    out = fopen(filename, "w");
    if(!out)
    {
        logError("The file %s could not be opened for writing.",filename);
    }
    if (output_is_html)
    {
        fprintf(out, "<!DOCTYPE html>\n");
    }
    else
    {
        fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
    }
    fprintf(out, "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"width:%llipx;height:%llipx\">\n", canvas_size.X, canvas_size.Y);
}

SVG::~SVG()
{
    fprintf(out, "</svg>\n");
    if (output_is_html)
    {
        fprintf(out, "");
    }
    fclose(out);
}

double SVG::getScale() const
{
    return scale;
}

Point SVG::transform(const Point& p)
{
    return Point((p.X - aabb.min.X) * scale, canvas_size.X - border.X - (p.Y - aabb.min.Y) * scale) + border;
}

FPoint3 SVG::transformF(const Point& p)
{
    return FPoint3((p.X - aabb.min.X) * scale + border.X, canvas_size.X - border.X + border.Y - (p.Y-aabb.min.Y) * scale, 0.0);
}

void SVG::writeComment(std::string comment)
{
    fprintf(out, "\n", comment.c_str());
}

void SVG::writeAreas(const Polygons& polygons, Color color, Color outline_color, float stroke_width)
{
    for(PolygonsPart& parts : polygons.splitIntoParts())
    {
        for(unsigned int j=0;j<parts.size();j++)
        {
            fprintf(out, "<polygon points=\"");
            for (Point& p : parts[j])
            {
                FPoint3 fp = transformF(p);
                fprintf(out, "%f,%f ", fp.x, fp.y);
            }
            if (j == 0)
                fprintf(out, "\" style=\"fill:%s;stroke:%s;stroke-width:%f\" />\n", toString(color).c_str(), toString(outline_color).c_str(), stroke_width);
            else
                fprintf(out, "\" style=\"fill:white;stroke:%s;stroke-width:%f\" />\n", toString(outline_color).c_str(), stroke_width);
        }
    }
}

void SVG::writeAreas(ConstPolygonRef polygon, Color color, Color outline_color, float stroke_width)
{
    fprintf(out,"<polygon fill=\"%s\" stroke=\"%s\" stroke-width=\"%f\" points=\"",toString(color).c_str(),toString(outline_color).c_str(), stroke_width); //The beginning of the polygon tag.
    for (const Point& point : polygon) //Add every point to the list of points.
    {
        FPoint3 transformed = transformF(point);
        fprintf(out,"%f,%f ",transformed.x,transformed.y);
    }
    fprintf(out,"\" />\n"); //The end of the polygon tag.
}

void SVG::writePoint(const Point& p, bool write_coords, int size, Color color)
{
    FPoint3 pf = transformF(p);
    fprintf(out, "<circle cx=\"%f\" cy=\"%f\" r=\"%d\" stroke=\"%s\" stroke-width=\"1\" fill=\"%s\" />\n",pf.x, pf.y, size, toString(color).c_str(), toString(color).c_str());

    if (write_coords)
    {
        fprintf(out, "<text x=\"%f\" y=\"%f\" style=\"font-size: 10px;\" fill=\"black\">%lli,%lli</text>\n",pf.x, pf.y, p.X, p.Y);
    }
}

void SVG::writePoints(ConstPolygonRef poly, bool write_coords, int size, Color color)
{
    for (const Point& p : poly)
    {
        writePoint(p, write_coords, size, color);
    }
}

void SVG::writePoints(Polygons& polygons, bool write_coords, int size, Color color)
{
    for (PolygonRef poly : polygons)
    {
        writePoints(poly, write_coords, size, color);
    }
}

void SVG::writeLines(std::vector<Point> polyline, Color color)
{
    if(polyline.size() <= 1) //Need at least 2 points.
    {
        return;
    }

    FPoint3 transformed = transformF(polyline[0]); //Element 0 must exist due to the check above.
    fprintf(out,"<path fill=\"none\" stroke=\"%s\" stroke-width=\"1\" d=\"M%lli,%lli",toString(color).c_str(),transformed.x,transformed.y); //Write the start of the path tag and the first endpoint.
    for(size_t point = 1;point < polyline.size();point++)
    {
        transformed = transformF(polyline[point]);
        fprintf(out,"L%f,%f", transformed.x, transformed.y); //Write a line segment to the next point.
    }
    fprintf(out,"\" />\n"); //Write the end of the tag.
}

void SVG::writeLine(const Point& a, const Point& b, Color color, float stroke_width)
{
    FPoint3 fa = transformF(a);
    FPoint3 fb = transformF(b);
    fprintf(out, "<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:%s;stroke-width:%f\" />\n", fa.x, fa.y, fb.x, fb.y, toString(color).c_str(), stroke_width);
}

void SVG::writeLineRGB(const Point& from, const Point& to, int r, int g, int b, float stroke_width)
{
    FPoint3 fa = transformF(from);
    FPoint3 fb = transformF(to);
    fprintf(out, "<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:rgb(%i,%i,%i);stroke-width:%f\" />\n", fa.x, fa.y, fb.x, fb.y, r, g, b, stroke_width);
}

void SVG::writeDashedLine(const Point& a, const Point& b, Color color)
{
    FPoint3 fa = transformF(a);
    FPoint3 fb = transformF(b);
    fprintf(out,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"%s\" stroke-width=\"1\" stroke-dasharray=\"5,5\" />\n",fa.x,fa.y,fb.x,fb.y,toString(color).c_str());
}

void SVG::writeText(Point p, std::string txt, Color color, coord_t font_size)
{
    FPoint3 pf = transformF(p);
    fprintf(out, "<text x=\"%f\" y=\"%f\" style=\"font-size: %llipx;\" fill=\"%s\">%s</text>\n",pf.x, pf.y, font_size, toString(color).c_str(), txt.c_str());
}
void SVG::writePolygons(const Polygons& polys, Color color, float stroke_width)
{
    for (ConstPolygonRef poly : polys)
    {
        writePolygon(poly, color, stroke_width);
    }
}

void SVG::writePolygon(ConstPolygonRef poly, Color color, float stroke_width)
{
    if (poly.size() == 0)
    {
        return;
    }
    int size = poly.size();
    Point p0 = poly.back();
    int i = 0;
    for (Point p1 : poly)
    {
        if (color == Color::RAINBOW)
        {
            int g = (i * 255 * 11 / size) % (255 * 2);
            if (g > 255) g = 255 * 2 - g;
            int b = (i * 255 * 5 / size) % (255 * 2);
            if (b > 255) b = 255 * 2 - b;
            writeLineRGB(p0, p1, i * 255 / size, g, b, stroke_width);
        }
        else
        {
            writeLine(p0, p1, color, stroke_width);
        }
        p0 = p1;
        i++;
    }
}

} // namespace cura
<commit_msg>fix formatting error in SVG<commit_after>/** Copyright (C) 2017 Tim Kuipers - Released under terms of the AGPLv3 License */
#include "SVG.h"

namespace cura {

std::string SVG::toString(Color color)
{
    switch (color)
    {
        case SVG::Color::BLACK: return "black";
        case SVG::Color::WHITE: return "white";
        case SVG::Color::GRAY: return "gray";
        case SVG::Color::RED: return "red";
        case SVG::Color::BLUE: return "blue";
        case SVG::Color::GREEN: return "green";
        case SVG::Color::YELLOW: return "yellow";
        default: return "black";
    }
}

SVG::SVG(const char* filename, AABB aabb, Point canvas_size)
: aabb(aabb)
, aabb_size(aabb.max - aabb.min)
, border(200,100)
, canvas_size(canvas_size)
, scale(std::min(double(canvas_size.X - border.X * 2) / aabb_size.X, double(canvas_size.Y - border.Y * 2) / aabb_size.Y))
{
    output_is_html = strcmp(filename + strlen(filename) - 4, "html") == 0;
    out = fopen(filename, "w");
    if(!out)
    {
        logError("The file %s could not be opened for writing.",filename);
    }
    if (output_is_html)
    {
        fprintf(out, "<!DOCTYPE html>\n");
    }
    else
    {
        fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
    }
    fprintf(out, "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"width:%llipx;height:%llipx\">\n", canvas_size.X, canvas_size.Y);
}

SVG::~SVG()
{
    fprintf(out, "</svg>\n");
    if (output_is_html)
    {
        fprintf(out, "");
    }
    fclose(out);
}

double SVG::getScale() const
{
    return scale;
}

Point SVG::transform(const Point& p)
{
    return Point((p.X - aabb.min.X) * scale, canvas_size.X - border.X - (p.Y - aabb.min.Y) * scale) + border;
}

FPoint3 SVG::transformF(const Point& p)
{
    return FPoint3((p.X - aabb.min.X) * scale + border.X, canvas_size.X - border.X + border.Y - (p.Y-aabb.min.Y) * scale, 0.0);
}

void SVG::writeComment(std::string comment)
{
    fprintf(out, "\n", comment.c_str());
}

void SVG::writeAreas(const Polygons& polygons, Color color, Color outline_color, float stroke_width)
{
    for(PolygonsPart& parts : polygons.splitIntoParts())
    {
        for(unsigned int j=0;j<parts.size();j++)
        {
            fprintf(out, "<polygon points=\"");
            for (Point& p : parts[j])
            {
                FPoint3 fp = transformF(p);
                fprintf(out, "%f,%f ", fp.x, fp.y);
            }
            if (j == 0)
                fprintf(out, "\" style=\"fill:%s;stroke:%s;stroke-width:%f\" />\n", toString(color).c_str(), toString(outline_color).c_str(), stroke_width);
            else
                fprintf(out, "\" style=\"fill:white;stroke:%s;stroke-width:%f\" />\n", toString(outline_color).c_str(), stroke_width);
        }
    }
}

void SVG::writeAreas(ConstPolygonRef polygon, Color color, Color outline_color, float stroke_width)
{
    fprintf(out,"<polygon fill=\"%s\" stroke=\"%s\" stroke-width=\"%f\" points=\"",toString(color).c_str(),toString(outline_color).c_str(), stroke_width); //The beginning of the polygon tag.
    for (const Point& point : polygon) //Add every point to the list of points.
    {
        FPoint3 transformed = transformF(point);
        fprintf(out,"%f,%f ",transformed.x,transformed.y);
    }
    fprintf(out,"\" />\n"); //The end of the polygon tag.
}

void SVG::writePoint(const Point& p, bool write_coords, int size, Color color)
{
    FPoint3 pf = transformF(p);
    fprintf(out, "<circle cx=\"%f\" cy=\"%f\" r=\"%d\" stroke=\"%s\" stroke-width=\"1\" fill=\"%s\" />\n",pf.x, pf.y, size, toString(color).c_str(), toString(color).c_str());

    if (write_coords)
    {
        fprintf(out, "<text x=\"%f\" y=\"%f\" style=\"font-size: 10px;\" fill=\"black\">%lli,%lli</text>\n",pf.x, pf.y, p.X, p.Y);
    }
}

void SVG::writePoints(ConstPolygonRef poly, bool write_coords, int size, Color color)
{
    for (const Point& p : poly)
    {
        writePoint(p, write_coords, size, color);
    }
}

void SVG::writePoints(Polygons& polygons, bool write_coords, int size, Color color)
{
    for (PolygonRef poly : polygons)
    {
        writePoints(poly, write_coords, size, color);
    }
}

void SVG::writeLines(std::vector<Point> polyline, Color color)
{
    if(polyline.size() <= 1) //Need at least 2 points.
    {
        return;
    }

    FPoint3 transformed = transformF(polyline[0]); //Element 0 must exist due to the check above.
    fprintf(out,"<path fill=\"none\" stroke=\"%s\" stroke-width=\"1\" d=\"M%f,%f",toString(color).c_str(), transformed.x, transformed.y); //Write the start of the path tag and the first endpoint.
    for(size_t point = 1;point < polyline.size();point++)
    {
        transformed = transformF(polyline[point]);
        fprintf(out,"L%f,%f", transformed.x, transformed.y); //Write a line segment to the next point.
    }
    fprintf(out,"\" />\n"); //Write the end of the tag.
}

void SVG::writeLine(const Point& a, const Point& b, Color color, float stroke_width)
{
    FPoint3 fa = transformF(a);
    FPoint3 fb = transformF(b);
    fprintf(out, "<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:%s;stroke-width:%f\" />\n", fa.x, fa.y, fb.x, fb.y, toString(color).c_str(), stroke_width);
}

void SVG::writeLineRGB(const Point& from, const Point& to, int r, int g, int b, float stroke_width)
{
    FPoint3 fa = transformF(from);
    FPoint3 fb = transformF(to);
    fprintf(out, "<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:rgb(%i,%i,%i);stroke-width:%f\" />\n", fa.x, fa.y, fb.x, fb.y, r, g, b, stroke_width);
}

void SVG::writeDashedLine(const Point& a, const Point& b, Color color)
{
    FPoint3 fa = transformF(a);
    FPoint3 fb = transformF(b);
    fprintf(out,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"%s\" stroke-width=\"1\" stroke-dasharray=\"5,5\" />\n",fa.x,fa.y,fb.x,fb.y,toString(color).c_str());
}

void SVG::writeText(Point p, std::string txt, Color color, coord_t font_size)
{
    FPoint3 pf = transformF(p);
    fprintf(out, "<text x=\"%f\" y=\"%f\" style=\"font-size: %llipx;\" fill=\"%s\">%s</text>\n",pf.x, pf.y, font_size, toString(color).c_str(), txt.c_str());
}
void SVG::writePolygons(const Polygons& polys, Color color, float stroke_width)
{
    for (ConstPolygonRef poly : polys)
    {
        writePolygon(poly, color, stroke_width);
    }
}

void SVG::writePolygon(ConstPolygonRef poly, Color color, float stroke_width)
{
    if (poly.size() == 0)
    {
        return;
    }
    int size = poly.size();
    Point p0 = poly.back();
    int i = 0;
    for (Point p1 : poly)
    {
        if (color == Color::RAINBOW)
        {
            int g = (i * 255 * 11 / size) % (255 * 2);
            if (g > 255) g = 255 * 2 - g;
            int b = (i * 255 * 5 / size) % (255 * 2);
            if (b > 255) b = 255 * 2 - b;
            writeLineRGB(p0, p1, i * 255 / size, g, b, stroke_width);
        }
        else
        {
            writeLine(p0, p1, color, stroke_width);
        }
        p0 = p1;
        i++;
    }
}

} // namespace cura
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2012-2013 Danny Y., Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef GEARS_MATH_ALGORITHM_HPP
#define GEARS_MATH_ALGORITHM_HPP

namespace gears {
namespace math {
template<typename T = unsigned long long>
inline T fibonacci(T number) {
    if(number < 2)
        return number;
    T a(1);
    T b(0);
    T c(0);

    while(--number) {
        c = b;
        b = a;
        a = b + c;
    }

    return a;
}

template<typename T = unsigned long long>
constexpr T factorial(const T& number) {
    return number == 0 ? 1 : number * factorial(number - 1);
}

template<typename T = unsigned long long>
constexpr T gcd(const T& x, const T& y) {
    return y == 0 ? x : gcd(y, x % y);
}

template<typename T = unsigned long long>
inline T mod_pow(T base, T exponent, const T& modulus) {
    T result(1);

    while(exponent) {
        if((exponent % 2) == 1) {
            result = (base * result) % modulus;
        }
        exponent /= 2;
        base = (base * base) % modulus;
    }

    return result;
}
} // math
} // gears

#endif // GEARS_MATH_ALGORITHM_HPP<commit_msg>Add sum_of_divisors function<commit_after>// The MIT License (MIT)

// Copyright (c) 2012-2013 Danny Y., Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef GEARS_MATH_ALGORITHM_HPP
#define GEARS_MATH_ALGORITHM_HPP

namespace gears {
namespace math {
template<typename T = unsigned long long>
inline T fibonacci(T number) {
    if(number < 2)
        return number;
    T a(1);
    T b(0);
    T c(0);

    while(--number) {
        c = b;
        b = a;
        a = b + c;
    }

    return a;
}

template<typename T = unsigned long long>
constexpr T factorial(const T& number) {
    return number == 0 ? 1 : number * factorial(number - 1);
}

template<typename T = unsigned long long>
constexpr T gcd(const T& x, const T& y) {
    return y == 0 ? x : gcd(y, x % y);
}

template<typename T = unsigned long long>
inline T mod_pow(T base, T exponent, const T& modulus) {
    T result(1);

    while(exponent) {
        if((exponent % 2) == 1) {
            result = (base * result) % modulus;
        }
        exponent /= 2;
        base = (base * base) % modulus;
    }

    return result;
}

template<typename T = unsigned long long>
inline T sum_of_divisors(const T& number) noexcept {
    T result(1);
    for(T i = 2; i * i <= number; result += number % i ? 0 : (i * i == number ? i : i + number/i), ++i);
    return result;
}
} // math
} // gears

#endif // GEARS_MATH_ALGORITHM_HPP<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2004,2006 Matthias Kretz <kretz@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2
    as published by the Free Software Foundation.

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.

*/

#include "backendselection.h"

#include <kio/krun.h>
#include <kservicetypeprofile.h>
#include <kservicetypetrader.h>
#include <kconfig.h>
#include <QtCore/QStringList>
#include <QtGui/QListWidget>
#include <kapplication.h>
#include <kicon.h>
#include <QtCore/QList>
#include <QtDBus/QtDBus>
#include <kcmoduleproxy.h>

BackendSelection::BackendSelection(QWidget *parent)
    : QWidget(parent)
{
    setupUi(this);
    m_down->setIcon(KIcon("arrow-down"));
    m_up->setIcon(KIcon("arrow-up"));
    m_comment->setWordWrap(true);

    m_emptyPage = stackedWidget->addWidget(new QWidget());

    connect(m_select, SIGNAL(itemSelectionChanged()),
            SLOT(selectionChanged()));
    //connect(m_website, SIGNAL(leftClickedUrl(const QString  &)),
            //kapp, SLOT(invokeBrowser(const QString  &)));
    connect(m_up, SIGNAL(clicked()), SLOT(up()));
    connect(m_down, SIGNAL(clicked()), SLOT(down()));
}

void BackendSelection::load()
{
    const KService::List offers = KServiceTypeTrader::self()->query("PhononBackend",
            "Type == 'Service' and [X-KDE-PhononBackendInfo-InterfaceVersion] == 1");
    // the offers are already sorted for preference
    loadServices(offers);
    foreach (KCModuleProxy *proxy, m_kcms) {
        if (proxy) {
            proxy->load();
        }
    }
}

void BackendSelection::showBackendKcm(const KService::Ptr &backendService)
{
    QString parentComponent = backendService->library();
    if (!m_kcms.contains(parentComponent)) {
        const KService::List offers = KServiceTypeTrader::self()->query("KCModule",
                QString("'%1' in [X-KDE-ParentComponents]").arg(parentComponent));
        if (offers.isEmpty()) {
            m_kcms.insert(parentComponent, 0);
        } else {
            KCModuleProxy *proxy = new KCModuleProxy(offers.first());
            connect(proxy, SIGNAL(changed(bool)), SIGNAL(changed()));
            m_kcms.insert(parentComponent, proxy);
            stackedWidget->addWidget(proxy);
        }
    }
    QWidget *w = m_kcms.value(parentComponent);
    if (w) {
        stackedWidget->setCurrentWidget(w);
    } else {
        stackedWidget->setCurrentIndex(m_emptyPage);
    }
}

void BackendSelection::loadServices(const KService::List &offers)
{
    m_services.clear();
    m_select->clear();

    KService::List::const_iterator it = offers.begin();
    const KService::List::const_iterator end = offers.end();
    for (; it != end; ++it)
    {
        KService::Ptr service = *it;
        m_select->addItem(service->name());
        m_services[service->name()] = service;
    }
    m_select->setItemSelected(m_select->item(0), true);
}

void BackendSelection::save()
{
    // save embedded KCMs
    foreach (KCModuleProxy *proxy, m_kcms) {
        if (proxy) {
            proxy->save();
        }
    }

    // save to servicetype profile
    KService::List services;
    unsigned int count = m_select->count();
    for (unsigned int i = 0; i < count; ++i)
    {
        QListWidgetItem *item = m_select->item(i);
        KService::Ptr service = m_services[item->text()];
        services.append(service);
    }
    KServiceTypeProfile::writeServiceTypeProfile("PhononBackend", services);

    QDBusMessage signal = QDBusMessage::createSignal("/", "org.kde.Phonon.Factory", "phononBackendChanged");
    QDBusConnection::sessionBus().send(signal);
}

void BackendSelection::defaults()
{
    foreach (KCModuleProxy *proxy, m_kcms) {
        if (proxy) {
            proxy->defaults();
        }
    }

    loadServices(KServiceTypeTrader::self()->defaultOffers("PhononBackend"));
}

void BackendSelection::selectionChanged()
{
    KService::Ptr service;
    foreach (QListWidgetItem *item, m_select->selectedItems()) {
        service = m_services[item->text()];
        m_up->setEnabled(m_select->row(item) > 0);
        m_down->setEnabled(m_select->row(item) < m_select->count() - 1);
        break;
    }
    if(service) {
        m_icon->setPixmap(KIcon(service->icon()).pixmap(128));
        m_name->setText(QString());//service->name());
        m_comment->setText(service->comment());
        const QString website = service->property("X-KDE-PhononBackendInfo-Website").toString();
        m_website->setText(QString("%1").arg(website));
        connect(m_website, SIGNAL(linkActivated(const QString &)), SLOT(openWebsite(const QString &)));
        m_version->setText(service->property("X-KDE-PhononBackendInfo-Version").toString());
        showBackendKcm(service);
    } else {
        m_up->setEnabled(false);
        m_down->setEnabled(false);
    }
}

void BackendSelection::openWebsite(const QString &url)
{
    new KRun(KUrl(url), window());
}

void BackendSelection::up()
{
    QList<QListWidgetItem *> selectedList = m_select->selectedItems();
    foreach (QListWidgetItem *selected, selectedList)
    {
        int row = m_select->row(selected);
        if (row > 0)
        {
            QListWidgetItem *taken = m_select->takeItem(row - 1);
            m_select->insertItem(row, taken);
            emit changed();
        }
    }
}

void BackendSelection::down()
{
    QList<QListWidgetItem *> selectedList = m_select->selectedItems();
    foreach (QListWidgetItem *selected, selectedList)
    {
        int row = m_select->row(selected);
        if (row + 1 < m_select->count())
        {
            QListWidgetItem *taken = m_select->takeItem(row + 1);
            m_select->insertItem(row, taken);
            emit changed();
        }
    }
}

#include "backendselection.moc"

// vim: sw=4 ts=4
<commit_msg>update defer and prefer button enabled-ness when moving items<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2004,2006 Matthias Kretz <kretz@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2
    as published by the Free Software Foundation.

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.

*/

#include "backendselection.h"

#include <kio/krun.h>
#include <kservicetypeprofile.h>
#include <kservicetypetrader.h>
#include <kconfig.h>
#include <QtCore/QStringList>
#include <QtGui/QListWidget>
#include <kapplication.h>
#include <kicon.h>
#include <QtCore/QList>
#include <QtDBus/QtDBus>
#include <kcmoduleproxy.h>

BackendSelection::BackendSelection(QWidget *parent)
    : QWidget(parent)
{
    setupUi(this);
    m_down->setIcon(KIcon("arrow-down"));
    m_up->setIcon(KIcon("arrow-up"));
    m_comment->setWordWrap(true);

    m_emptyPage = stackedWidget->addWidget(new QWidget());

    connect(m_select, SIGNAL(itemSelectionChanged()),
            SLOT(selectionChanged()));
    //connect(m_website, SIGNAL(leftClickedUrl(const QString  &)),
            //kapp, SLOT(invokeBrowser(const QString  &)));
    connect(m_up, SIGNAL(clicked()), SLOT(up()));
    connect(m_down, SIGNAL(clicked()), SLOT(down()));
}

void BackendSelection::load()
{
    const KService::List offers = KServiceTypeTrader::self()->query("PhononBackend",
            "Type == 'Service' and [X-KDE-PhononBackendInfo-InterfaceVersion] == 1");
    // the offers are already sorted for preference
    loadServices(offers);
    foreach (KCModuleProxy *proxy, m_kcms) {
        if (proxy) {
            proxy->load();
        }
    }
}

void BackendSelection::showBackendKcm(const KService::Ptr &backendService)
{
    QString parentComponent = backendService->library();
    if (!m_kcms.contains(parentComponent)) {
        const KService::List offers = KServiceTypeTrader::self()->query("KCModule",
                QString("'%1' in [X-KDE-ParentComponents]").arg(parentComponent));
        if (offers.isEmpty()) {
            m_kcms.insert(parentComponent, 0);
        } else {
            KCModuleProxy *proxy = new KCModuleProxy(offers.first());
            connect(proxy, SIGNAL(changed(bool)), SIGNAL(changed()));
            m_kcms.insert(parentComponent, proxy);
            stackedWidget->addWidget(proxy);
        }
    }
    QWidget *w = m_kcms.value(parentComponent);
    if (w) {
        stackedWidget->setCurrentWidget(w);
    } else {
        stackedWidget->setCurrentIndex(m_emptyPage);
    }
}

void BackendSelection::loadServices(const KService::List &offers)
{
    m_services.clear();
    m_select->clear();

    KService::List::const_iterator it = offers.begin();
    const KService::List::const_iterator end = offers.end();
    for (; it != end; ++it)
    {
        KService::Ptr service = *it;
        m_select->addItem(service->name());
        m_services[service->name()] = service;
    }
    m_select->setItemSelected(m_select->item(0), true);
}

void BackendSelection::save()
{
    // save embedded KCMs
    foreach (KCModuleProxy *proxy, m_kcms) {
        if (proxy) {
            proxy->save();
        }
    }

    // save to servicetype profile
    KService::List services;
    unsigned int count = m_select->count();
    for (unsigned int i = 0; i < count; ++i)
    {
        QListWidgetItem *item = m_select->item(i);
        KService::Ptr service = m_services[item->text()];
        services.append(service);
    }
    KServiceTypeProfile::writeServiceTypeProfile("PhononBackend", services);

    QDBusMessage signal = QDBusMessage::createSignal("/", "org.kde.Phonon.Factory", "phononBackendChanged");
    QDBusConnection::sessionBus().send(signal);
}

void BackendSelection::defaults()
{
    foreach (KCModuleProxy *proxy, m_kcms) {
        if (proxy) {
            proxy->defaults();
        }
    }

    loadServices(KServiceTypeTrader::self()->defaultOffers("PhononBackend"));
}

void BackendSelection::selectionChanged()
{
    KService::Ptr service;
    foreach (QListWidgetItem *item, m_select->selectedItems()) {
        service = m_services[item->text()];
        m_up->setEnabled(m_select->row(item) > 0);
        m_down->setEnabled(m_select->row(item) < m_select->count() - 1);
        break;
    }
    if(service) {
        m_icon->setPixmap(KIcon(service->icon()).pixmap(128));
        m_name->setText(QString());//service->name());
        m_comment->setText(service->comment());
        const QString website = service->property("X-KDE-PhononBackendInfo-Website").toString();
        m_website->setText(QString("%1").arg(website));
        connect(m_website, SIGNAL(linkActivated(const QString &)), SLOT(openWebsite(const QString &)));
        m_version->setText(service->property("X-KDE-PhononBackendInfo-Version").toString());
        showBackendKcm(service);
    } else {
        m_up->setEnabled(false);
        m_down->setEnabled(false);
    }
}

void BackendSelection::openWebsite(const QString &url)
{
    new KRun(KUrl(url), window());
}

void BackendSelection::up()
{
    QList<QListWidgetItem *> selectedList = m_select->selectedItems();
    foreach (QListWidgetItem *selected, selectedList)
    {
        int row = m_select->row(selected);
        if (row > 0)
        {
            QListWidgetItem *taken = m_select->takeItem(row - 1);
            m_select->insertItem(row, taken);
            emit changed();
            selectionChanged();
        }
    }
}

void BackendSelection::down()
{
    QList<QListWidgetItem *> selectedList = m_select->selectedItems();
    foreach (QListWidgetItem *selected, selectedList)
    {
        int row = m_select->row(selected);
        if (row + 1 < m_select->count())
        {
            QListWidgetItem *taken = m_select->takeItem(row + 1);
            m_select->insertItem(row, taken);
            emit changed();
            selectionChanged();
        }
    }
}

#include "backendselection.moc"

// vim: sw=4 ts=4
<|endoftext|>


<commit_before>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * 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 "PipelineManager.h"

#include "internal.h"

#include <ctime>
#include <cstring>
#include <algorithm>
#include <utils.h>

using namespace tcam;

PipelineManager::PipelineManager ()
    : status(TCAM_PIPELINE_UNDEFINED), current_ppl_buffer(0)
{}

PipelineManager::~PipelineManager ()
{
    if (status == TCAM_PIPELINE_PLAYING)
    {
        stop_playing();
    }

    available_filter.clear();
    filter_pipeline.clear();
    filter_properties.clear();
}

std::vector<std::shared_ptr<Property>> PipelineManager::getFilterProperties ()
{
    return filter_properties;
}

std::vector<VideoFormatDescription> PipelineManager::getAvailableVideoFormats () const
{
    return available_output_formats;
}

bool PipelineManager::setVideoFormat(const VideoFormat& f)
{
    this->output_format = f;
    return true;
}

VideoFormat PipelineManager::getVideoFormat () const
{
    return this->output_format;
}

bool PipelineManager::set_status (TCAM_PIPELINE_STATUS s)
{
    if (status == s)
        return true;

    this->status = s;

    if (status == TCAM_PIPELINE_PLAYING)
    {
        if (create_pipeline())
        {
            start_playing();
            tcam_log(TCAM_LOG_INFO, "All pipeline elements set to PLAYING.");
        }
        else
        {
            status = TCAM_PIPELINE_ERROR;
            return false;
        }
    }
    else if (status == TCAM_PIPELINE_STOPPED)
    {
      stop_playing();
    }

    return true;
}

TCAM_PIPELINE_STATUS PipelineManager::get_status () const
{
    return status;
}

bool PipelineManager::destroyPipeline ()
{
    set_status(TCAM_PIPELINE_STOPPED);

    source = nullptr;
    sink = nullptr;

    return true;
}

bool PipelineManager::setSource (std::shared_ptr<DeviceInterface> device)
{
    if (status == TCAM_PIPELINE_PLAYING || status == TCAM_PIPELINE_PAUSED)
    {
        return false;
    }

    device_properties = device->getProperties();
    available_input_formats = device->get_available_video_formats();

    tcam_log(TCAM_LOG_DEBUG, "Received %zu formats.", available_input_formats.size());

    distributeProperties();

    this->source = std::make_shared<ImageSource>();
    source->setSink(shared_from_this());

    source->setDevice(device);

    for (const auto& f : available_filter)
    {
        auto p = f->getFilterProperties();

        if (!p.empty())
        {
            filter_properties.insert(filter_properties.end(), p.begin(), p.end());
        }
    }

    available_output_formats = available_input_formats;

    if (available_output_formats.empty())
    {
        tcam_log(TCAM_LOG_ERROR, "No output formats available.");
        return false;
    }

    return true;
}

std::shared_ptr<ImageSource> PipelineManager::getSource ()
{
    return source;
}

bool PipelineManager::setSink (std::shared_ptr<SinkInterface> s)
{
    if (status == TCAM_PIPELINE_PLAYING || status == TCAM_PIPELINE_PAUSED)
    {
        return false;
    }

    this->sink = s;

    this->sink->set_source(shared_from_this());

    return true;
}

std::shared_ptr<SinkInterface> PipelineManager::getSink ()
{
    return sink;
}

void PipelineManager::distributeProperties ()
{
    for (auto& f : available_filter)
    {
        f->setDeviceProperties(device_properties);
    }
}

static bool isFilterApplicable (uint32_t fourcc,
                                const std::vector<uint32_t>& vec)
{
    if (std::find(vec.begin(), vec.end(), fourcc) == vec.end())
    {
        return false;
    }
    return true;
}

void PipelineManager::create_input_format (uint32_t fourcc)
{
    input_format = output_format;
    input_format.set_fourcc(fourcc);
}

std::vector<uint32_t> PipelineManager::getDeviceFourcc ()
{
    // for easy usage we create a vector<fourcc> for avail. inputs
    std::vector<uint32_t> device_fourcc;

    for (const auto& v : available_input_formats)
    {
        tcam_log(TCAM_LOG_DEBUG,
                "Found device fourcc '%s' - %d",
                fourcc2description(v.get_fourcc()),
                v.get_fourcc());

        device_fourcc.push_back(v.get_fourcc());
    }
    return device_fourcc;
}

bool PipelineManager::set_source_status (TCAM_PIPELINE_STATUS _status)
{
    if (source == nullptr)
    {
        tcam_log(TCAM_LOG_ERROR, "Source is not defined");
        return false;
    }

    if (!source->set_status(_status))
    {
        tcam_log(TCAM_LOG_ERROR, "Source did not accept status change");
        return false;
    }

    return true;
}

bool PipelineManager::set_sink_status (TCAM_PIPELINE_STATUS _status)
{
    if (sink == nullptr)
    {
        if (_status != TCAM_PIPELINE_STOPPED) // additional check to prevent warning when pipeline comes up
        {
            tcam_warning("Sink is not defined.");
        }
        return false;
    }

    if (!sink->set_status(_status))
    {
        tcam_log(TCAM_LOG_ERROR, "Sink spewed error");
        return false;
    }

    return true;
}

bool PipelineManager::validate_pipeline ()
{
    // check if pipeline is valid
    if (source.get() == nullptr || sink.get() == nullptr)
    {
        return false;
    }

    // check source format
    auto in_format = source->getVideoFormat();

    if (in_format != this->input_format)
    {
        tcam_log(TCAM_LOG_DEBUG,
                "Video format in source does not match pipeline: '%s' != '%s'",
                in_format.to_string().c_str(),
                input_format.to_string().c_str());
        return false;
    }
    else
    {
        tcam_log(TCAM_LOG_DEBUG,
                 "Starting pipeline with format: '%s'",
                 in_format.to_string().c_str());
    }

    VideoFormat in;
    VideoFormat out;
    for (auto f : filter_pipeline)
    {

        f->getVideoFormat(in, out);

        if (in != in_format)
        {
            tcam_log(TCAM_LOG_ERROR,
                    "Ingoing video format for filter %s is not compatible with previous element. '%s' != '%s'",
                    f->getDescription().name.c_str(),
                    in_format.to_string().c_str(),
                    in.to_string().c_str());
            return false;
        }
        else
        {
            tcam_log(TCAM_LOG_DEBUG, "Filter %s connected to pipeline -- %s",
                    f->getDescription().name.c_str(),
                    out.to_string().c_str());
            // save output for next comparison
            in_format = out;
        }
    }

    if (in_format != this->output_format)
    {
        tcam_log(TCAM_LOG_ERROR, "Video format in sink does not match pipeline '%s' != '%s'",
                in_format.to_string().c_str(),
                output_format.to_string().c_str());
        return false;
    }

    return true;
}

bool PipelineManager::create_conversion_pipeline ()
{
    if (source.get() == nullptr || sink.get() == nullptr)
    {
        return false;
    }

    auto device_fourcc = getDeviceFourcc();
    create_input_format(output_format.get_fourcc());

    for (auto f : available_filter)
    {
        std::string s = f->getDescription().name;

        if (f->getDescription().type == FILTER_TYPE_CONVERSION)
        {

            if (isFilterApplicable(output_format.get_fourcc(), f->getDescription().output_fourcc))
            {
                bool filter_valid = false;
                uint32_t fourcc_to_use = 0;
                for (const auto& cc : device_fourcc)
                {
                    if (isFilterApplicable(cc, f->getDescription().input_fourcc))
                    {
                        filter_valid = true;
                        fourcc_to_use = cc;
                        break;
                    }
                }

                // set device format to use correct fourcc
                create_input_format(fourcc_to_use);

                if (filter_valid)
                {
                    if (f->setVideoFormat(input_format, output_format))
                    {
                        tcam_log(TCAM_LOG_DEBUG,
                                "Added filter \"%s\" to pipeline",
                                s.c_str());
                        filter_pipeline.push_back(f);
                    }
                    else
                    {
                        tcam_log(TCAM_LOG_DEBUG,
                                "Filter %s did not accept format settings",
                                s.c_str());
                    }
                }
                else
                {
                    tcam_log(TCAM_LOG_DEBUG, "Filter %s does not use the device output formats.", s.c_str());
                }
            }
            else
            {
                tcam_log(TCAM_LOG_DEBUG, "Filter %s is not applicable", s.c_str());

            }
        }
    }
    return true;
}

bool PipelineManager::add_interpretation_filter ()
{

    // if a valid pipeline can be created insert additional filter (e.g. autoexposure)
    // interpretations should be done as early as possible in the pipeline

    for (auto& f : available_filter)
    {
        if (f->getDescription().type == FILTER_TYPE_INTERPRET)
        {
            std::string s  = f->getDescription().name;
            // applicable to sink
            bool all_formats = false;
            if (f->getDescription().input_fourcc.size() == 1)
            {
                if (f->getDescription().input_fourcc.at(0) == 0)
                {
                    all_formats = true;
                }
            }

            if (all_formats ||isFilterApplicable(input_format.get_fourcc(), f->getDescription().input_fourcc))
            {
                tcam_log(TCAM_LOG_DEBUG, "Adding filter '%s' after source", s.c_str());
                f->setVideoFormat(input_format, input_format);
                filter_pipeline.insert(filter_pipeline.begin(), f);
                continue;
            }
            else
            {
                tcam_log(TCAM_LOG_DEBUG, "Filter '%s' not usable after source", s.c_str());
            }

            if (f->setVideoFormat(input_format, input_format))
            {
                continue;
            }
        }
    }
    return true;
}

bool PipelineManager::create_pipeline ()
{
    if (source.get() == nullptr || sink.get() == nullptr)
    {
        return false;
    }

    // assure everything is in a defined state
    filter_pipeline.clear();

    if (!create_conversion_pipeline())
    {
        tcam_log(TCAM_LOG_ERROR, "Unable to determine conversion pipeline.");
        return false;
    }

    if (!source->setVideoFormat(input_format))
    {
        tcam_log(TCAM_LOG_ERROR, "Unable to set video format in source.");
        return false;
    }

    if (!sink->setVideoFormat(output_format))
    {
        tcam_log(TCAM_LOG_ERROR, "Unable to set video format in sink.");
        return false;
    }

    if (!source->set_buffer_collection(sink->get_buffer_collection()))
    {
        tcam_log(TCAM_LOG_ERROR, "Unable to set buffer collection.");
        return false;
    }

    tcam_log(TCAM_LOG_INFO, "Pipeline creation successful.");

    std::string ppl = "source -> ";

    for (const auto& f : filter_pipeline)
    {
        ppl += f->getDescription().name;
        ppl += " -> ";
    }
    ppl += " sink";
    tcam_log(TCAM_LOG_INFO, "%s" , ppl.c_str());

    return true;
}

bool PipelineManager::start_playing ()
{

    if (!set_sink_status(TCAM_PIPELINE_PLAYING))
    {
        tcam_log(TCAM_LOG_ERROR, "Sink refused to change to state PLAYING");
        goto error;
    }

    if (!set_source_status(TCAM_PIPELINE_PLAYING))
    {
        tcam_log(TCAM_LOG_ERROR, "Source refused to change to state PLAYING");
        goto error;
    }

    status = TCAM_PIPELINE_PLAYING;

    return true;

error:
    stop_playing();
    return false;
}

bool PipelineManager::stop_playing ()
{
    status = TCAM_PIPELINE_STOPPED;

    if (!set_source_status(TCAM_PIPELINE_STOPPED))
    {
        tcam_log(TCAM_LOG_ERROR, "Source refused to change to state STOP");
        return false;
    }

    for (auto& f : filter_pipeline)
    {
        if (!f->setStatus(TCAM_PIPELINE_STOPPED))
        {
            tcam_log(TCAM_LOG_ERROR,
                    "Filter %s refused to change to state STOP",
                    f->getDescription().name.c_str());
            return false;
        }
    }

    set_sink_status(TCAM_PIPELINE_STOPPED);

    //destroyPipeline();

    return true;
}

void PipelineManager::push_image (std::shared_ptr<ImageBuffer> buffer)
{
    if (status == TCAM_PIPELINE_STOPPED)
    {
        return;
    }

    auto& current_buffer = buffer;

    // for (auto& f : filter_pipeline)
    // {
    //     if (f->getDescription().type == FILTER_TYPE_INTERPRET)
    //     {
    //         f->apply(current_buffer);
    //     }
    //     else if (f->getDescription().type == FILTER_TYPE_CONVERSION)
    //     {
    //         auto next_buffer = pipeline_buffer.at(current_ppl_buffer);

    //         next_buffer->set_statistics(current_buffer->get_statistics());

    //         f->transform(*current_buffer, *next_buffer);

    //         current_buffer = next_buffer;

    //         current_ppl_buffer++;
    //         if (current_ppl_buffer == pipeline_buffer.size())
    //             current_ppl_buffer = 0;
    //     }
    // }

    if (sink != nullptr)
    {
        sink->push_image(current_buffer);
    }
    else
    {
      tcam_log(TCAM_LOG_ERROR, "Sink is NULL");
    }
}

void PipelineManager::requeue_buffer (std::shared_ptr<ImageBuffer> buffer)
{
    if (source)
    {
        source->requeue_buffer(buffer);
    }
}

std::vector<std::shared_ptr<ImageBuffer>> PipelineManager::get_buffer_collection ()
{
    return std::vector<std::shared_ptr<ImageBuffer>>();
}

void PipelineManager::drop_incomplete_frames (bool drop_them)
{
    if (source)
    {
        source->drop_incomplete_frames(drop_them);
    }
}

bool PipelineManager::should_incomplete_frames_be_dropped () const
{
    if (source)
    {
        return source->should_incomplete_frames_be_dropped();
    }

    tcam_error("No shource to ask if incomplete frames should be dropped.");
    return true;
}
<commit_msg>logging: Print fourcc as hex<commit_after>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * 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 "PipelineManager.h"

#include "internal.h"

#include <ctime>
#include <cstring>
#include <algorithm>
#include <utils.h>

using namespace tcam;

PipelineManager::PipelineManager ()
    : status(TCAM_PIPELINE_UNDEFINED), current_ppl_buffer(0)
{}

PipelineManager::~PipelineManager ()
{
    if (status == TCAM_PIPELINE_PLAYING)
    {
        stop_playing();
    }

    available_filter.clear();
    filter_pipeline.clear();
    filter_properties.clear();
}

std::vector<std::shared_ptr<Property>> PipelineManager::getFilterProperties ()
{
    return filter_properties;
}

std::vector<VideoFormatDescription> PipelineManager::getAvailableVideoFormats () const
{
    return available_output_formats;
}

bool PipelineManager::setVideoFormat(const VideoFormat& f)
{
    this->output_format = f;
    return true;
}

VideoFormat PipelineManager::getVideoFormat () const
{
    return this->output_format;
}

bool PipelineManager::set_status (TCAM_PIPELINE_STATUS s)
{
    if (status == s)
        return true;

    this->status = s;

    if (status == TCAM_PIPELINE_PLAYING)
    {
        if (create_pipeline())
        {
            start_playing();
            tcam_log(TCAM_LOG_INFO, "All pipeline elements set to PLAYING.");
        }
        else
        {
            status = TCAM_PIPELINE_ERROR;
            return false;
        }
    }
    else if (status == TCAM_PIPELINE_STOPPED)
    {
      stop_playing();
    }

    return true;
}

TCAM_PIPELINE_STATUS PipelineManager::get_status () const
{
    return status;
}

bool PipelineManager::destroyPipeline ()
{
    set_status(TCAM_PIPELINE_STOPPED);

    source = nullptr;
    sink = nullptr;

    return true;
}

bool PipelineManager::setSource (std::shared_ptr<DeviceInterface> device)
{
    if (status == TCAM_PIPELINE_PLAYING || status == TCAM_PIPELINE_PAUSED)
    {
        return false;
    }

    device_properties = device->getProperties();
    available_input_formats = device->get_available_video_formats();

    tcam_log(TCAM_LOG_DEBUG, "Received %zu formats.", available_input_formats.size());

    distributeProperties();

    this->source = std::make_shared<ImageSource>();
    source->setSink(shared_from_this());

    source->setDevice(device);

    for (const auto& f : available_filter)
    {
        auto p = f->getFilterProperties();

        if (!p.empty())
        {
            filter_properties.insert(filter_properties.end(), p.begin(), p.end());
        }
    }

    available_output_formats = available_input_formats;

    if (available_output_formats.empty())
    {
        tcam_log(TCAM_LOG_ERROR, "No output formats available.");
        return false;
    }

    return true;
}

std::shared_ptr<ImageSource> PipelineManager::getSource ()
{
    return source;
}

bool PipelineManager::setSink (std::shared_ptr<SinkInterface> s)
{
    if (status == TCAM_PIPELINE_PLAYING || status == TCAM_PIPELINE_PAUSED)
    {
        return false;
    }

    this->sink = s;

    this->sink->set_source(shared_from_this());

    return true;
}

std::shared_ptr<SinkInterface> PipelineManager::getSink ()
{
    return sink;
}

void PipelineManager::distributeProperties ()
{
    for (auto& f : available_filter)
    {
        f->setDeviceProperties(device_properties);
    }
}

static bool isFilterApplicable (uint32_t fourcc,
                                const std::vector<uint32_t>& vec)
{
    if (std::find(vec.begin(), vec.end(), fourcc) == vec.end())
    {
        return false;
    }
    return true;
}

void PipelineManager::create_input_format (uint32_t fourcc)
{
    input_format = output_format;
    input_format.set_fourcc(fourcc);
}

std::vector<uint32_t> PipelineManager::getDeviceFourcc ()
{
    // for easy usage we create a vector<fourcc> for avail. inputs
    std::vector<uint32_t> device_fourcc;

    for (const auto& v : available_input_formats)
    {
        tcam_log(TCAM_LOG_DEBUG,
                "Found device fourcc '%s' - %x",
                fourcc2description(v.get_fourcc()),
                v.get_fourcc());

        device_fourcc.push_back(v.get_fourcc());
    }
    return device_fourcc;
}

bool PipelineManager::set_source_status (TCAM_PIPELINE_STATUS _status)
{
    if (source == nullptr)
    {
        tcam_log(TCAM_LOG_ERROR, "Source is not defined");
        return false;
    }

    if (!source->set_status(_status))
    {
        tcam_log(TCAM_LOG_ERROR, "Source did not accept status change");
        return false;
    }

    return true;
}

bool PipelineManager::set_sink_status (TCAM_PIPELINE_STATUS _status)
{
    if (sink == nullptr)
    {
        if (_status != TCAM_PIPELINE_STOPPED) // additional check to prevent warning when pipeline comes up
        {
            tcam_warning("Sink is not defined.");
        }
        return false;
    }

    if (!sink->set_status(_status))
    {
        tcam_log(TCAM_LOG_ERROR, "Sink spewed error");
        return false;
    }

    return true;
}

bool PipelineManager::validate_pipeline ()
{
    // check if pipeline is valid
    if (source.get() == nullptr || sink.get() == nullptr)
    {
        return false;
    }

    // check source format
    auto in_format = source->getVideoFormat();

    if (in_format != this->input_format)
    {
        tcam_log(TCAM_LOG_DEBUG,
                "Video format in source does not match pipeline: '%s' != '%s'",
                in_format.to_string().c_str(),
                input_format.to_string().c_str());
        return false;
    }
    else
    {
        tcam_log(TCAM_LOG_DEBUG,
                 "Starting pipeline with format: '%s'",
                 in_format.to_string().c_str());
    }

    VideoFormat in;
    VideoFormat out;
    for (auto f : filter_pipeline)
    {

        f->getVideoFormat(in, out);

        if (in != in_format)
        {
            tcam_log(TCAM_LOG_ERROR,
                    "Ingoing video format for filter %s is not compatible with previous element. '%s' != '%s'",
                    f->getDescription().name.c_str(),
                    in_format.to_string().c_str(),
                    in.to_string().c_str());
            return false;
        }
        else
        {
            tcam_log(TCAM_LOG_DEBUG, "Filter %s connected to pipeline -- %s",
                    f->getDescription().name.c_str(),
                    out.to_string().c_str());
            // save output for next comparison
            in_format = out;
        }
    }

    if (in_format != this->output_format)
    {
        tcam_log(TCAM_LOG_ERROR, "Video format in sink does not match pipeline '%s' != '%s'",
                in_format.to_string().c_str(),
                output_format.to_string().c_str());
        return false;
    }

    return true;
}

bool PipelineManager::create_conversion_pipeline ()
{
    if (source.get() == nullptr || sink.get() == nullptr)
    {
        return false;
    }

    auto device_fourcc = getDeviceFourcc();
    create_input_format(output_format.get_fourcc());

    for (auto f : available_filter)
    {
        std::string s = f->getDescription().name;

        if (f->getDescription().type == FILTER_TYPE_CONVERSION)
        {

            if (isFilterApplicable(output_format.get_fourcc(), f->getDescription().output_fourcc))
            {
                bool filter_valid = false;
                uint32_t fourcc_to_use = 0;
                for (const auto& cc : device_fourcc)
                {
                    if (isFilterApplicable(cc, f->getDescription().input_fourcc))
                    {
                        filter_valid = true;
                        fourcc_to_use = cc;
                        break;
                    }
                }

                // set device format to use correct fourcc
                create_input_format(fourcc_to_use);

                if (filter_valid)
                {
                    if (f->setVideoFormat(input_format, output_format))
                    {
                        tcam_log(TCAM_LOG_DEBUG,
                                "Added filter \"%s\" to pipeline",
                                s.c_str());
                        filter_pipeline.push_back(f);
                    }
                    else
                    {
                        tcam_log(TCAM_LOG_DEBUG,
                                "Filter %s did not accept format settings",
                                s.c_str());
                    }
                }
                else
                {
                    tcam_log(TCAM_LOG_DEBUG, "Filter %s does not use the device output formats.", s.c_str());
                }
            }
            else
            {
                tcam_log(TCAM_LOG_DEBUG, "Filter %s is not applicable", s.c_str());

            }
        }
    }
    return true;
}

bool PipelineManager::add_interpretation_filter ()
{

    // if a valid pipeline can be created insert additional filter (e.g. autoexposure)
    // interpretations should be done as early as possible in the pipeline

    for (auto& f : available_filter)
    {
        if (f->getDescription().type == FILTER_TYPE_INTERPRET)
        {
            std::string s  = f->getDescription().name;
            // applicable to sink
            bool all_formats = false;
            if (f->getDescription().input_fourcc.size() == 1)
            {
                if (f->getDescription().input_fourcc.at(0) == 0)
                {
                    all_formats = true;
                }
            }

            if (all_formats ||isFilterApplicable(input_format.get_fourcc(), f->getDescription().input_fourcc))
            {
                tcam_log(TCAM_LOG_DEBUG, "Adding filter '%s' after source", s.c_str());
                f->setVideoFormat(input_format, input_format);
                filter_pipeline.insert(filter_pipeline.begin(), f);
                continue;
            }
            else
            {
                tcam_log(TCAM_LOG_DEBUG, "Filter '%s' not usable after source", s.c_str());
            }

            if (f->setVideoFormat(input_format, input_format))
            {
                continue;
            }
        }
    }
    return true;
}

bool PipelineManager::create_pipeline ()
{
    if (source.get() == nullptr || sink.get() == nullptr)
    {
        return false;
    }

    // assure everything is in a defined state
    filter_pipeline.clear();

    if (!create_conversion_pipeline())
    {
        tcam_log(TCAM_LOG_ERROR, "Unable to determine conversion pipeline.");
        return false;
    }

    if (!source->setVideoFormat(input_format))
    {
        tcam_log(TCAM_LOG_ERROR, "Unable to set video format in source.");
        return false;
    }

    if (!sink->setVideoFormat(output_format))
    {
        tcam_log(TCAM_LOG_ERROR, "Unable to set video format in sink.");
        return false;
    }

    if (!source->set_buffer_collection(sink->get_buffer_collection()))
    {
        tcam_log(TCAM_LOG_ERROR, "Unable to set buffer collection.");
        return false;
    }

    tcam_log(TCAM_LOG_INFO, "Pipeline creation successful.");

    std::string ppl = "source -> ";

    for (const auto& f : filter_pipeline)
    {
        ppl += f->getDescription().name;
        ppl += " -> ";
    }
    ppl += " sink";
    tcam_log(TCAM_LOG_INFO, "%s" , ppl.c_str());

    return true;
}

bool PipelineManager::start_playing ()
{

    if (!set_sink_status(TCAM_PIPELINE_PLAYING))
    {
        tcam_log(TCAM_LOG_ERROR, "Sink refused to change to state PLAYING");
        goto error;
    }

    if (!set_source_status(TCAM_PIPELINE_PLAYING))
    {
        tcam_log(TCAM_LOG_ERROR, "Source refused to change to state PLAYING");
        goto error;
    }

    status = TCAM_PIPELINE_PLAYING;

    return true;

error:
    stop_playing();
    return false;
}

bool PipelineManager::stop_playing ()
{
    status = TCAM_PIPELINE_STOPPED;

    if (!set_source_status(TCAM_PIPELINE_STOPPED))
    {
        tcam_log(TCAM_LOG_ERROR, "Source refused to change to state STOP");
        return false;
    }

    for (auto& f : filter_pipeline)
    {
        if (!f->setStatus(TCAM_PIPELINE_STOPPED))
        {
            tcam_log(TCAM_LOG_ERROR,
                    "Filter %s refused to change to state STOP",
                    f->getDescription().name.c_str());
            return false;
        }
    }

    set_sink_status(TCAM_PIPELINE_STOPPED);

    //destroyPipeline();

    return true;
}

void PipelineManager::push_image (std::shared_ptr<ImageBuffer> buffer)
{
    if (status == TCAM_PIPELINE_STOPPED)
    {
        return;
    }

    auto& current_buffer = buffer;

    // for (auto& f : filter_pipeline)
    // {
    //     if (f->getDescription().type == FILTER_TYPE_INTERPRET)
    //     {
    //         f->apply(current_buffer);
    //     }
    //     else if (f->getDescription().type == FILTER_TYPE_CONVERSION)
    //     {
    //         auto next_buffer = pipeline_buffer.at(current_ppl_buffer);

    //         next_buffer->set_statistics(current_buffer->get_statistics());

    //         f->transform(*current_buffer, *next_buffer);

    //         current_buffer = next_buffer;

    //         current_ppl_buffer++;
    //         if (current_ppl_buffer == pipeline_buffer.size())
    //             current_ppl_buffer = 0;
    //     }
    // }

    if (sink != nullptr)
    {
        sink->push_image(current_buffer);
    }
    else
    {
      tcam_log(TCAM_LOG_ERROR, "Sink is NULL");
    }
}

void PipelineManager::requeue_buffer (std::shared_ptr<ImageBuffer> buffer)
{
    if (source)
    {
        source->requeue_buffer(buffer);
    }
}

std::vector<std::shared_ptr<ImageBuffer>> PipelineManager::get_buffer_collection ()
{
    return std::vector<std::shared_ptr<ImageBuffer>>();
}

void PipelineManager::drop_incomplete_frames (bool drop_them)
{
    if (source)
    {
        source->drop_incomplete_frames(drop_them);
    }
}

bool PipelineManager::should_incomplete_frames_be_dropped () const
{
    if (source)
    {
        return source->should_incomplete_frames_be_dropped();
    }

    tcam_error("No shource to ask if incomplete frames should be dropped.");
    return true;
}
<|endoftext|>


<commit_before>#include "emitter.h"

#include <stddef.h>

#include "particle.h"
#include "renderer.h"

Emitter::Emitter(const Vector4D &pos, const Vector4D &vel, int itv, int dur, int max) :
    _position(pos),
    _velocity(vel),
    _interval(itv),
    _duration(dur),
    _maxParticles(max),
    _renderer(NULL),
    _particles(NULL),
    _elapsed(0) {
    _particles = new Particle*[_maxParticles];
    for(int i = 0; i < _maxParticles; i++) {
        _particles[i] = NULL;
    }
}

Emitter::~Emitter() {
    for(int i = 0; i < _maxParticles; i++) {
        if(_particles[i]) {
            delete _particles[i];
            _particles[i] = NULL;
        }
    }
    delete[] _particles;
}

void Emitter::update(int elapsed) {
    for(int i = 0; i < _maxParticles; i++) {
        if(_particles[i]) {
            Particle* p = _particles[i];

            // This should be done with an operator (?)
            p->position += p->velocity * _elapsed;

            // This should be done with an operator
            p->lifetime -= elapsed;

            //@TODO: Apply operators on p

            if(p->lifetime < 0) {
                delete p;
                _particles[i] = NULL;

            }
        }
    }

    _elapsed += elapsed;
    while(_elapsed > _interval) {
        createParticle();
        _elapsed -= _interval;
    }
}

void Emitter::draw() {
    if(_renderer) {
        for(int i = 0; i < _maxParticles; i++) {
            if(_particles[i]) {
                _renderer->render(_particles[i]);
            }
        }
    }
}

void Emitter::renderer(Renderer *rend) {
    if(_renderer) {
        delete[] _renderer;
    }

    _renderer = rend;
}

bool Emitter::createParticle() {
    int index;
    for(int index  = 0; index  < _maxParticles; index ++) {
        if(!_particles[index]) break;
    }

    if(index >= _maxParticles) return false;

    Particle* particle = new Particle(_position, _velocity);
    //@TODO: Apply Initializers here

    _particles[index] = particle;

    return true;
}

void Emitter::removeParticle(int index) {
    delete _particles[index];
    _particles[index] = NULL;

    //@TODO: Keep track of free indexes (?)
}
<commit_msg>Fixed whitespace<commit_after>#include "emitter.h"

#include <stddef.h>

#include "particle.h"
#include "renderer.h"

Emitter::Emitter(const Vector4D &pos, const Vector4D &vel, int itv, int dur, int max) :
    _position(pos),
    _velocity(vel),
    _interval(itv),
    _duration(dur),
    _maxParticles(max),
    _renderer(NULL),
    _particles(NULL),
    _elapsed(0) {
    _particles = new Particle*[_maxParticles];
    for(int i = 0; i < _maxParticles; i++) {
        _particles[i] = NULL;
    }
}

Emitter::~Emitter() {
    for(int i = 0; i < _maxParticles; i++) {
        if(_particles[i]) {
            delete _particles[i];
            _particles[i] = NULL;
        }
    }
    delete[] _particles;
}

void Emitter::update(int elapsed) {
    for(int i = 0; i < _maxParticles; i++) {
        if(_particles[i]) {
            Particle* p = _particles[i];

            // This should be done with an operator (?)
            p->position += p->velocity * _elapsed;

            // This should be done with an operator
            p->lifetime -= elapsed;

            //@TODO: Apply operators on p

            if(p->lifetime < 0) {
                delete p;
                _particles[i] = NULL;

            }
        }
    }

    _elapsed += elapsed;
    while(_elapsed > _interval) {
        createParticle();
        _elapsed -= _interval;
    }
}

void Emitter::draw() {
    if(_renderer) {
        for(int i = 0; i < _maxParticles; i++) {
            if(_particles[i]) {
                _renderer->render(_particles[i]);
            }
        }
    }
}

void Emitter::renderer(Renderer *rend) {
    if(_renderer) {
        delete[] _renderer;
    }

    _renderer = rend;
}

bool Emitter::createParticle() {
    int index;
    for(int index = 0; index < _maxParticles; index++) {
        if(!_particles[index]) break;
    }

    if(index >= _maxParticles) return false;

    Particle* particle = new Particle(_position, _velocity);
    //@TODO: Apply Initializers here

    _particles[index] = particle;

    return true;
}

void Emitter::removeParticle(int index) {
    delete _particles[index];
    _particles[index] = NULL;

    //@TODO: Keep track of free indexes (?)
}
<|endoftext|>


<commit_before>#include "RobotStateSpace.h"
#include <openrave/openrave.h>

using namespace or_ompl;
namespace ob = ompl::base;

RobotState::RobotState(RobotStateSpace* stateSpace) :
        _stateSpace(stateSpace) {

}

RobotState::~RobotState() {
}

void RobotState::set(const std::vector<double> &dof_values) {

    for(unsigned int idx=0; idx < _stateSpace->getDimension(); idx++){
        value(idx) = dof_values[idx];
    }
}

double& RobotState::value(const size_t& idx) {
    return *(_stateSpace->getValueAddressAtIndex(this, idx));
}

const double& RobotState::value(const size_t& idx) const {
    return *(_stateSpace->getValueAddressAtLocation(this, _stateSpace->getValueLocations()[idx]));
}

std::vector<double> RobotState::getValues() const {
    std::vector<double> retval(_stateSpace->getDimension());

    for(unsigned int idx=0; idx < retval.size(); idx++){
        retval[idx] = value(idx);
    }

    return retval;
}

void RobotStateSpace::registerProjections() {
    registerProjection("default", _projectionEvaluator);
    registerDefaultProjection(_projectionEvaluator);
    StateSpace::registerProjections();
}

RobotStateSpace::RobotStateSpace(const std::vector<int> &dof_indices, const std::vector<bool>& is_continuous) :
        ompl::base::CompoundStateSpace(), _indices(dof_indices), _isContinuous(is_continuous) {
    BOOST_ASSERT(dof_indices.size() == is_continuous.size());
    // TODO: THIS AINT RIGHT
    size_t realDOFCount = 0;
    for (size_t i = 0; i < dof_indices.size(); i++) {
        if (is_continuous[i]) {
            if (realDOFCount > 0)
            {
                addSubspace(ompl::base::StateSpacePtr(new ompl::base::RealVectorStateSpace(realDOFCount)), 1.0);
                realDOFCount = 0;
            }
            addSubspace(ompl::base::StateSpacePtr(new ompl::base::SO2StateSpace()), 1.0);
        }
        else {
            realDOFCount++;
        }
    }
    if (realDOFCount > 0)
    {
        addSubspace(ompl::base::StateSpacePtr(new ompl::base::RealVectorStateSpace(realDOFCount)), 1.0);
    }
    _projectionEvaluator.reset(new RobotProjectionEvaluator(this));
}

ompl::base::State* RobotStateSpace::allocState() const {

    RobotState* state = new RobotState((RobotStateSpace*)this);
    allocStateComponents(state);
    return state;

}

void RobotStateSpace::setBounds(const ompl::base::RealVectorBounds& bounds) {
    BOOST_ASSERT(bounds.high.size() == bounds.low.size());

    for (size_t i = 0; i < bounds.high.size(); i++) {
        if (_isContinuous[i]) {
            continue;
        }
        else {
            // TODO: THIS AINT RIGHT
            ompl::base::RealVectorStateSpace* space = components_[i]->as<ompl::base::RealVectorStateSpace>();
            ompl::base::RealVectorBounds subBounds(space->getDimension());

            for (size_t k = 0; k < space->getDimension(); k++) {
                subBounds.high[k] = bounds.high[i + k];
                subBounds.low[k] = bounds.low[i + k];
            }

            space->setBounds(subBounds);
            i += space->getDimension();
        }
    }
}

RobotProjectionEvaluator::RobotProjectionEvaluator(ompl::base::StateSpace* stateSpace) :
    ompl::base::ProjectionEvaluator(stateSpace) {
    RobotStateSpace* robotStateSpace = dynamic_cast<RobotStateSpace*>(stateSpace);

    if (!robotStateSpace) {
        RAVELOG_ERROR("Can only use RobotStateSpace with RobotProjectionEvaluator!");
        return;
    }

    _robotStateSpace = robotStateSpace;
}

RobotProjectionEvaluator::RobotProjectionEvaluator(ompl::base::StateSpacePtr stateSpace) :
    ProjectionEvaluator(stateSpace) {
    RobotStateSpace* robotStateSpace = dynamic_cast<RobotStateSpace*>(stateSpace.get());

    if (!robotStateSpace) {
        RAVELOG_ERROR("Can only use RobotStateSpace with RobotProjectionEvaluator!");
        return;
    }

    _robotStateSpace = robotStateSpace;
}

RobotProjectionEvaluator::~RobotProjectionEvaluator() {

}

void RobotProjectionEvaluator::setup() {
    _projectionMatrix.mat = _projectionMatrix.ComputeRandom(_robotStateSpace->getDimension(), getDimension());
    defaultCellSizes();
    ProjectionEvaluator::setup();
}

void RobotProjectionEvaluator::defaultCellSizes() {
    cellSizes_.resize(getDimension());

    for (size_t i = 0; i < getDimension(); i++) {
        cellSizes_[i] = 0.5f;
    }
}

/** \brief Return the dimension of the projection defined by this evaluator */
unsigned int RobotProjectionEvaluator::getDimension() const {
    int dim = _robotStateSpace->getDimension();
    if (dim <= 2) {
        return dim;
    }
    else {
        return (int)(log(_robotStateSpace->getDimension())) + 1;
    }
}

/** \brief Compute the projection as an array of double values */
void RobotProjectionEvaluator::project(const ompl::base::State *state, ompl::base::EuclideanProjection &projection) const {
    const RobotState* robotState = dynamic_cast<const RobotState*>(state);

    if (!robotState) {
        RAVELOG_ERROR("Can only project robot states!");
        return;
    }

    std::vector<double> values = robotState->getValues();
    projection.resize(getDimension());
    _projectionMatrix.project(values.data(), projection);
}
<commit_msg>Update RobotStateSpace.cpp<commit_after>#include "RobotStateSpace.h"
#include <openrave/openrave.h>

using namespace or_ompl;
namespace ob = ompl::base;

RobotState::RobotState(RobotStateSpace* stateSpace) :
        _stateSpace(stateSpace) {

}

RobotState::~RobotState() {
}

void RobotState::set(const std::vector<double> &dof_values) {

    for(unsigned int idx=0; idx < _stateSpace->getDimension(); idx++){
        value(idx) = dof_values[idx];
    }
}

double& RobotState::value(const size_t& idx) {
    return *(_stateSpace->getValueAddressAtIndex(this, idx));
}

const double& RobotState::value(const size_t& idx) const {
    return *(_stateSpace->getValueAddressAtLocation(this, _stateSpace->getValueLocations()[idx]));
}

std::vector<double> RobotState::getValues() const {
    std::vector<double> retval(_stateSpace->getDimension());

    for(unsigned int idx=0; idx < retval.size(); idx++){
        retval[idx] = value(idx);
    }

    return retval;
}

void RobotStateSpace::registerProjections() {
    registerProjection("default", _projectionEvaluator);
    registerDefaultProjection(_projectionEvaluator);
    StateSpace::registerProjections();
}

RobotStateSpace::RobotStateSpace(const std::vector<int> &dof_indices, const std::vector<bool>& is_continuous) :
        ompl::base::CompoundStateSpace(), _indices(dof_indices), _isContinuous(is_continuous) {
    BOOST_ASSERT(dof_indices.size() == is_continuous.size());
    // TODO: THIS AINT RIGHT
    size_t realDOFCount = 0;
    for (size_t i = 0; i < dof_indices.size(); i++) {
        if (is_continuous[i]) {
            if (realDOFCount > 0)
            {
                addSubspace(ompl::base::StateSpacePtr(new ompl::base::RealVectorStateSpace(realDOFCount)), 1.0);
                realDOFCount = 0;
            }
            addSubspace(ompl::base::StateSpacePtr(new ompl::base::SO2StateSpace()), 1.0);
        }
        else {
            realDOFCount++;
        }
    }
    if (realDOFCount > 0)
    {
        addSubspace(ompl::base::StateSpacePtr(new ompl::base::RealVectorStateSpace(realDOFCount)), 1.0);
    }
    _projectionEvaluator.reset(new RobotProjectionEvaluator(this));
}

ompl::base::State* RobotStateSpace::allocState() const {

    RobotState* state = new RobotState((RobotStateSpace*)this);
    allocStateComponents(state);
    return state;

}

void RobotStateSpace::setBounds(const ompl::base::RealVectorBounds& bounds) {
    BOOST_ASSERT(bounds.high.size() == bounds.low.size());

    for (size_t i = 0; i < bounds.high.size(); i++) {
        if (_isContinuous[i]) {
            continue;
        }
        else {
            ompl::base::RealVectorStateSpace* space = components_[i]->as<ompl::base::RealVectorStateSpace>();
            ompl::base::RealVectorBounds subBounds(space->getDimension());

            for (size_t k = 0; k < space->getDimension(); k++) {
                subBounds.high[k] = bounds.high[i + k];
                subBounds.low[k] = bounds.low[i + k];
            }

            space->setBounds(subBounds);
            i += space->getDimension();
        }
    }
}

RobotProjectionEvaluator::RobotProjectionEvaluator(ompl::base::StateSpace* stateSpace) :
    ompl::base::ProjectionEvaluator(stateSpace) {
    RobotStateSpace* robotStateSpace = dynamic_cast<RobotStateSpace*>(stateSpace);

    if (!robotStateSpace) {
        RAVELOG_ERROR("Can only use RobotStateSpace with RobotProjectionEvaluator!");
        return;
    }

    _robotStateSpace = robotStateSpace;
}

RobotProjectionEvaluator::RobotProjectionEvaluator(ompl::base::StateSpacePtr stateSpace) :
    ProjectionEvaluator(stateSpace) {
    RobotStateSpace* robotStateSpace = dynamic_cast<RobotStateSpace*>(stateSpace.get());

    if (!robotStateSpace) {
        RAVELOG_ERROR("Can only use RobotStateSpace with RobotProjectionEvaluator!");
        return;
    }

    _robotStateSpace = robotStateSpace;
}

RobotProjectionEvaluator::~RobotProjectionEvaluator() {

}

void RobotProjectionEvaluator::setup() {
    _projectionMatrix.mat = _projectionMatrix.ComputeRandom(_robotStateSpace->getDimension(), getDimension());
    defaultCellSizes();
    ProjectionEvaluator::setup();
}

void RobotProjectionEvaluator::defaultCellSizes() {
    cellSizes_.resize(getDimension());

    for (size_t i = 0; i < getDimension(); i++) {
        cellSizes_[i] = 0.5f;
    }
}

/** \brief Return the dimension of the projection defined by this evaluator */
unsigned int RobotProjectionEvaluator::getDimension() const {
    int dim = _robotStateSpace->getDimension();
    if (dim <= 2) {
        return dim;
    }
    else {
        return (int)(log(_robotStateSpace->getDimension())) + 1;
    }
}

/** \brief Compute the projection as an array of double values */
void RobotProjectionEvaluator::project(const ompl::base::State *state, ompl::base::EuclideanProjection &projection) const {
    const RobotState* robotState = dynamic_cast<const RobotState*>(state);

    if (!robotState) {
        RAVELOG_ERROR("Can only project robot states!");
        return;
    }

    std::vector<double> values = robotState->getValues();
    projection.resize(getDimension());
    _projectionMatrix.project(values.data(), projection);
}
<|endoftext|>