<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#pragma once

#include <seastar/core/circular_buffer.hh>
#include <seastar/core/future.hh>
#include <queue>
#include <seastar/util/std-compat.hh>

namespace seastar {

/// Asynchronous single-producer single-consumer queue with limited capacity.
/// There can be at most one producer-side and at most one consumer-side operation active at any time.
/// Operations returning a future are considered to be active until the future resolves.
template <typename T>
class queue {
    std::queue<T, circular_buffer<T>> _q;
    size_t _max;
    std::optional<promise<>> _not_empty;
    std::optional<promise<>> _not_full;
    std::exception_ptr _ex = nullptr;
private:
    void notify_not_empty() noexcept;
    void notify_not_full() noexcept;
public:
    explicit queue(size_t size);

    /// \brief Push an item.
    ///
    /// Returns false if the queue was full and the item was not pushed.
    bool push(T&& a);

    /// \brief Pop an item.
    ///
    /// Popping from an empty queue will result in undefined behavior.
    T pop();

    /// \brief access the front element in the queue
    ///
    /// Accessing the front of an empty queue will result in undefined
    /// behaviour.
    T& front();

    /// Consumes items from the queue, passing them to \c func, until \c func
    /// returns false or the queue it empty
    ///
    /// Returns false if func returned false.
    template <typename Func>
    bool consume(Func&& func);

    /// Returns true when the queue is empty.
    bool empty() const;

    /// Returns true when the queue is full.
    bool full() const;

    /// Returns a future<> that becomes available when pop() or consume()
    /// can be called.
    /// A consumer-side operation. Cannot be called concurrently with other consumer-side operations.
    future<> not_empty();

    /// Returns a future<> that becomes available when push() can be called.
    /// A producer-side operation. Cannot be called concurrently with other producer-side operations.
    future<> not_full();

    /// Pops element now or when there is some. Returns a future that becomes
    /// available when some element is available.
    /// If the queue is, or already was, abort()ed, the future resolves with
    /// the exception provided to abort().
    /// A consumer-side operation. Cannot be called concurrently with other consumer-side operations.
    future<T> pop_eventually();

    /// Pushes the element now or when there is room. Returns a future<> which
    /// resolves when data was pushed.
    /// If the queue is, or already was, abort()ed, the future resolves with
    /// the exception provided to abort().
    /// A producer-side operation. Cannot be called concurrently with other producer-side operations.
    future<> push_eventually(T&& data);

    /// Returns the number of items currently in the queue.
    size_t size() const { return _q.size(); }

    /// Returns the size limit imposed on the queue during its construction
    /// or by a call to set_max_size(). If the queue contains max_size()
    /// items (or more), further items cannot be pushed until some are popped.
    size_t max_size() const noexcept { return _max; }

    /// Set the maximum size to a new value. If the queue's max size is reduced,
    /// items already in the queue will not be expunged and the queue will be temporarily
    /// bigger than its max_size.
    void set_max_size(size_t max) {
        _max = max;
        if (!full()) {
            notify_not_full();
        }
    }

    /// Destroy any items in the queue, and pass the provided exception to any
    /// waiting readers or writers - or to any later read or write attempts.
    void abort(std::exception_ptr ex) {
        while (!_q.empty()) {
            _q.pop();
        }
        _ex = ex;
        if (_not_full) {
            _not_full->set_exception(ex);
            _not_full= std::nullopt;
        }
        if (_not_empty) {
            _not_empty->set_exception(std::move(ex));
            _not_empty = std::nullopt;
        }
    }

    /// \brief Check if there is an active consumer
    ///
    /// Returns true if another fiber waits for an item to be pushed into the queue
    bool has_blocked_consumer() const noexcept {
        return bool(_not_empty);
    }
};

template <typename T>
inline
queue<T>::queue(size_t size)
    : _max(size) {
}

template <typename T>
inline
void queue<T>::notify_not_empty() noexcept {
    if (_not_empty) {
        _not_empty->set_value();
        _not_empty = std::optional<promise<>>();
    }
}

template <typename T>
inline
void queue<T>::notify_not_full() noexcept {
    if (_not_full) {
        _not_full->set_value();
        _not_full = std::optional<promise<>>();
    }
}

template <typename T>
inline
bool queue<T>::push(T&& data) {
    if (_q.size() < _max) {
        _q.push(std::move(data));
        notify_not_empty();
        return true;
    } else {
        return false;
    }
}

template <typename T>
inline
T& queue<T>::front() {
    return _q.front();
}

template <typename T>
inline
T queue<T>::pop() {
    if (_q.size() == _max) {
        notify_not_full();
    }
    T data = std::move(_q.front());
    _q.pop();
    return data;
}

template <typename T>
inline
future<T> queue<T>::pop_eventually() {
    if (_ex) {
        return make_exception_future<T>(_ex);
    }
    if (empty()) {
        return not_empty().then([this] {
            if (_ex) {
                return make_exception_future<T>(_ex);
            } else {
                return make_ready_future<T>(pop());
            }
        });
    } else {
        return make_ready_future<T>(pop());
    }
}

template <typename T>
inline
future<> queue<T>::push_eventually(T&& data) {
    if (_ex) {
        return make_exception_future<>(_ex);
    }
    if (full()) {
        return not_full().then([this, data = std::move(data)] () mutable {
            _q.push(std::move(data));
            notify_not_empty();
        });
    } else {
        _q.push(std::move(data));
        notify_not_empty();
        return make_ready_future<>();
    }
}

template <typename T>
template <typename Func>
inline
bool queue<T>::consume(Func&& func) {
    if (_ex) {
        std::rethrow_exception(_ex);
    }
    bool running = true;
    while (!_q.empty() && running) {
        running = func(std::move(_q.front()));
        _q.pop();
    }
    if (!full()) {
        notify_not_full();
    }
    return running;
}

template <typename T>
inline
bool queue<T>::empty() const {
    return _q.empty();
}

template <typename T>
inline
bool queue<T>::full() const {
    return _q.size() >= _max;
}

template <typename T>
inline
future<> queue<T>::not_empty() {
    if (_ex) {
        return make_exception_future<>(_ex);
    }
    if (!empty()) {
        return make_ready_future<>();
    } else {
        _not_empty = promise<>();
        return _not_empty->get_future();
    }
}

template <typename T>
inline
future<> queue<T>::not_full() {
    if (_ex) {
        return make_exception_future<>(_ex);
    }
    if (!full()) {
        return make_ready_future<>();
    } else {
        _not_full = promise<>();
        return _not_full->get_future();
    }
}

}

<commit_msg>queue: require element type to be nothrow move-constructible<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#pragma once

#include <seastar/core/circular_buffer.hh>
#include <seastar/core/future.hh>
#include <queue>
#include <seastar/util/std-compat.hh>

namespace seastar {

/// Asynchronous single-producer single-consumer queue with limited capacity.
/// There can be at most one producer-side and at most one consumer-side operation active at any time.
/// Operations returning a future are considered to be active until the future resolves.
///
/// Note: queue requires the data type T to be nothrow move constructible as it's
/// returned as future<T> by \ref pop_eventually and seastar futurized data type
/// are required to be nothrow move-constructible.
template <typename T>
SEASTAR_CONCEPT(requires std::is_nothrow_move_constructible_v<T>)
class queue {
    std::queue<T, circular_buffer<T>> _q;
    size_t _max;
    std::optional<promise<>> _not_empty;
    std::optional<promise<>> _not_full;
    std::exception_ptr _ex = nullptr;
private:
    void notify_not_empty() noexcept;
    void notify_not_full() noexcept;
public:
    explicit queue(size_t size);

    /// \brief Push an item.
    ///
    /// Returns false if the queue was full and the item was not pushed.
    bool push(T&& a);

    /// \brief Pop an item.
    ///
    /// Popping from an empty queue will result in undefined behavior.
    T pop();

    /// \brief access the front element in the queue
    ///
    /// Accessing the front of an empty queue will result in undefined
    /// behaviour.
    T& front();

    /// Consumes items from the queue, passing them to \c func, until \c func
    /// returns false or the queue it empty
    ///
    /// Returns false if func returned false.
    template <typename Func>
    bool consume(Func&& func);

    /// Returns true when the queue is empty.
    bool empty() const;

    /// Returns true when the queue is full.
    bool full() const;

    /// Returns a future<> that becomes available when pop() or consume()
    /// can be called.
    /// A consumer-side operation. Cannot be called concurrently with other consumer-side operations.
    future<> not_empty();

    /// Returns a future<> that becomes available when push() can be called.
    /// A producer-side operation. Cannot be called concurrently with other producer-side operations.
    future<> not_full();

    /// Pops element now or when there is some. Returns a future that becomes
    /// available when some element is available.
    /// If the queue is, or already was, abort()ed, the future resolves with
    /// the exception provided to abort().
    /// A consumer-side operation. Cannot be called concurrently with other consumer-side operations.
    future<T> pop_eventually();

    /// Pushes the element now or when there is room. Returns a future<> which
    /// resolves when data was pushed.
    /// If the queue is, or already was, abort()ed, the future resolves with
    /// the exception provided to abort().
    /// A producer-side operation. Cannot be called concurrently with other producer-side operations.
    future<> push_eventually(T&& data);

    /// Returns the number of items currently in the queue.
    size_t size() const { return _q.size(); }

    /// Returns the size limit imposed on the queue during its construction
    /// or by a call to set_max_size(). If the queue contains max_size()
    /// items (or more), further items cannot be pushed until some are popped.
    size_t max_size() const noexcept { return _max; }

    /// Set the maximum size to a new value. If the queue's max size is reduced,
    /// items already in the queue will not be expunged and the queue will be temporarily
    /// bigger than its max_size.
    void set_max_size(size_t max) {
        _max = max;
        if (!full()) {
            notify_not_full();
        }
    }

    /// Destroy any items in the queue, and pass the provided exception to any
    /// waiting readers or writers - or to any later read or write attempts.
    void abort(std::exception_ptr ex) {
        while (!_q.empty()) {
            _q.pop();
        }
        _ex = ex;
        if (_not_full) {
            _not_full->set_exception(ex);
            _not_full= std::nullopt;
        }
        if (_not_empty) {
            _not_empty->set_exception(std::move(ex));
            _not_empty = std::nullopt;
        }
    }

    /// \brief Check if there is an active consumer
    ///
    /// Returns true if another fiber waits for an item to be pushed into the queue
    bool has_blocked_consumer() const noexcept {
        return bool(_not_empty);
    }
};

template <typename T>
inline
queue<T>::queue(size_t size)
    : _max(size) {
}

template <typename T>
inline
void queue<T>::notify_not_empty() noexcept {
    if (_not_empty) {
        _not_empty->set_value();
        _not_empty = std::optional<promise<>>();
    }
}

template <typename T>
inline
void queue<T>::notify_not_full() noexcept {
    if (_not_full) {
        _not_full->set_value();
        _not_full = std::optional<promise<>>();
    }
}

template <typename T>
inline
bool queue<T>::push(T&& data) {
    if (_q.size() < _max) {
        _q.push(std::move(data));
        notify_not_empty();
        return true;
    } else {
        return false;
    }
}

template <typename T>
inline
T& queue<T>::front() {
    return _q.front();
}

template <typename T>
inline
T queue<T>::pop() {
    if (_q.size() == _max) {
        notify_not_full();
    }
    T data = std::move(_q.front());
    _q.pop();
    return data;
}

template <typename T>
inline
future<T> queue<T>::pop_eventually() {
    // seastar allows only nothrow_move_constructible types
    // to be returned as future<T>
    static_assert(std::is_nothrow_move_constructible_v<T>,
                  "Queue element type must be no-throw move constructible");

    if (_ex) {
        return make_exception_future<T>(_ex);
    }
    if (empty()) {
        return not_empty().then([this] {
            if (_ex) {
                return make_exception_future<T>(_ex);
            } else {
                return make_ready_future<T>(pop());
            }
        });
    } else {
        return make_ready_future<T>(pop());
    }
}

template <typename T>
inline
future<> queue<T>::push_eventually(T&& data) {
    if (_ex) {
        return make_exception_future<>(_ex);
    }
    if (full()) {
        return not_full().then([this, data = std::move(data)] () mutable {
            _q.push(std::move(data));
            notify_not_empty();
        });
    } else {
        _q.push(std::move(data));
        notify_not_empty();
        return make_ready_future<>();
    }
}

template <typename T>
template <typename Func>
inline
bool queue<T>::consume(Func&& func) {
    if (_ex) {
        std::rethrow_exception(_ex);
    }
    bool running = true;
    while (!_q.empty() && running) {
        running = func(std::move(_q.front()));
        _q.pop();
    }
    if (!full()) {
        notify_not_full();
    }
    return running;
}

template <typename T>
inline
bool queue<T>::empty() const {
    return _q.empty();
}

template <typename T>
inline
bool queue<T>::full() const {
    return _q.size() >= _max;
}

template <typename T>
inline
future<> queue<T>::not_empty() {
    if (_ex) {
        return make_exception_future<>(_ex);
    }
    if (!empty()) {
        return make_ready_future<>();
    } else {
        _not_empty = promise<>();
        return _not_empty->get_future();
    }
}

template <typename T>
inline
future<> queue<T>::not_full() {
    if (_ex) {
        return make_exception_future<>(_ex);
    }
    if (!full()) {
        return make_ready_future<>();
    } else {
        _not_full = promise<>();
        return _not_full->get_future();
    }
}

}

<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkTransformFilter.hh
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
// .NAME vtkTransformFilter - transform points and associated normals and vectors
// .SECTION Description
// vtkTransformFilter is a filter to transform point coordinates and
// associated point normals and vectors. Other point data is passed
// through the filter.
//   (An alternative method of transformation is to use vtkActors methods
// to scale, rotate, and translate objects. The difference between the
// two methods is that vtkActor's transformation simply effects where
// objects are rendered (via the graphics pipeline), whereas
// vtkTransformFilter actually modifies point coordinates in the
// visualization pipeline. This is necessary for some objects
// (e.g., vtkProbeFilter) that require point coordinates as input).
// .EXAMPLE XFormSph.cc

#ifndef __vtkTransformFilter_h
#define __vtkTransformFilter_h

#include "vtkPointSetToPointSetFilter.hh"
#include "vtkTransform.hh"

class vtkTransformFilter : public vtkPointSetToPointSetFilter
{
public:
  vtkTransformFilter() : Transform(NULL) {};
  ~vtkTransformFilter() {};
  char *GetClassName() {return "vtkTransformFilter";};
  void PrintSelf(ostream& os, vtkIndent indent);

  unsigned long int GetMTime();

  // Description:
  // Specify the transform object used to transform points.
  vtkSetObjectMacro(Transform,vtkTransform);
  vtkGetObjectMacro(Transform,vtkTransform);

protected:
  void Execute();
  vtkTransform *Transform;
};

#endif

<commit_msg>*** empty log message ***<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTransformFilter.hh
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
// .NAME vtkTransformFilter - transform points and associated normals and vectors
// .SECTION Description
// vtkTransformFilter is a filter to transform point coordinates and
// associated point normals and vectors. Other point data is passed
// through the filter.
//
// (An alternative method of transformation is to use vtkActors methods
// to scale, rotate, and translate objects. The difference between the
// two methods is that vtkActor's transformation simply effects where
// objects are rendered (via the graphics pipeline), whereas
// vtkTransformFilter actually modifies point coordinates in the
// visualization pipeline. This is necessary for some objects
// (e.g., vtkProbeFilter) that require point coordinates as input).
// .EXAMPLE XFormSph.cc

#ifndef __vtkTransformFilter_h
#define __vtkTransformFilter_h

#include "vtkPointSetToPointSetFilter.hh"
#include "vtkTransform.hh"

class vtkTransformFilter : public vtkPointSetToPointSetFilter
{
public:
  vtkTransformFilter() : Transform(NULL) {};
  ~vtkTransformFilter() {};
  char *GetClassName() {return "vtkTransformFilter";};
  void PrintSelf(ostream& os, vtkIndent indent);

  unsigned long int GetMTime();

  // Description:
  // Specify the transform object used to transform points.
  vtkSetObjectMacro(Transform,vtkTransform);
  vtkGetObjectMacro(Transform,vtkTransform);

protected:
  void Execute();
  vtkTransform *Transform;
};

#endif

<|endoftext|>


<commit_before>#pragma once

#include "zmsg_types.hpp"

namespace zmsg {

template<>
struct zmsg<mid_t::set_fs_spec> {
public:
	uint16_t window_x_row;			// unit: pixel
	uint16_t window_x_col;			// unit: pixel
	uint16_t window_y_row;			// unit: pixel
	uint16_t window_y_col;			// unit: pixel

	uint32_t nm_per_pixel;			// unit: nm/pixel
	uint32_t nm_per_step;			// unit: nm/step

	uint16_t img_cap_delay;			// unit: ms

	uint32_t clr_discharge_gap;		// unit: nm
	uint16_t check_fiber_exist_time;	// unit: ms

	uint16_t motor_min_speed[motorId_t::NUM];
	uint16_t motor_max_speed[motorId_t::NUM];

	uint16_t motor_lzrz_fs_speed;
	uint16_t motor_xy_precise_calibrate_speed;

	uint16_t motor_xy_steps_per_pixel;	// unit: step/pixel

	double   fiber_outline_blacklevel;		// 0.0 ~ 1.0
	double   calibrating_xy_dist_threshold;		// unit: pixel
	double   precise_calibrating_xy_dist_threshold;	// unit: pixel
	double   z_dist_threshold;			// unit: pixel

	discharge_data_t discharge_base;
	discharge_data_t discharge_revise;

	double   dust_check_threshold0;
	double   dust_check_threshold1;

	double   led_brightness[ledId_t::LED_NUM];
public:
        ZMSG_PU(
		window_x_row,
		window_x_col,
		window_y_row,
		window_y_col,

		nm_per_pixel,
		nm_per_step,

		img_cap_delay,

		clr_discharge_gap,
		check_fiber_exist_time,

		motor_min_speed,
		motor_max_speed,

		motor_lzrz_fs_speed,
		motor_xy_precise_calibrate_speed,

		motor_xy_steps_per_pixel,

		fiber_outline_blacklevel,
		calibrating_xy_dist_threshold,
		precise_calibrating_xy_dist_threshold,
		z_dist_threshold,

		discharge_base,
		discharge_revise,

		dust_check_threshold0,
		dust_check_threshold1,

		led_brightness)
};

}
<commit_msg>zmsg: xy precise calibrate: change data type to uint32_t<commit_after>#pragma once

#include "zmsg_types.hpp"

namespace zmsg {

template<>
struct zmsg<mid_t::set_fs_spec> {
public:
	uint16_t window_x_row;			// unit: pixel
	uint16_t window_x_col;			// unit: pixel
	uint16_t window_y_row;			// unit: pixel
	uint16_t window_y_col;			// unit: pixel

	uint32_t nm_per_pixel;			// unit: nm/pixel
	uint32_t nm_per_step;			// unit: nm/step

	uint16_t img_cap_delay;			// unit: ms

	uint32_t clr_discharge_gap;		// unit: nm
	uint16_t check_fiber_exist_time;	// unit: ms

	uint16_t motor_min_speed[motorId_t::NUM];
	uint16_t motor_max_speed[motorId_t::NUM];

	uint16_t motor_lzrz_fs_speed;
	uint32_t motor_xy_precise_calibrate_speed;

	uint16_t motor_xy_steps_per_pixel;	// unit: step/pixel

	double   fiber_outline_blacklevel;		// 0.0 ~ 1.0
	double   calibrating_xy_dist_threshold;		// unit: pixel
	double   precise_calibrating_xy_dist_threshold;	// unit: pixel
	double   z_dist_threshold;			// unit: pixel

	discharge_data_t discharge_base;
	discharge_data_t discharge_revise;

	double   dust_check_threshold0;
	double   dust_check_threshold1;

	double   led_brightness[ledId_t::LED_NUM];
public:
        ZMSG_PU(
		window_x_row,
		window_x_col,
		window_y_row,
		window_y_col,

		nm_per_pixel,
		nm_per_step,

		img_cap_delay,

		clr_discharge_gap,
		check_fiber_exist_time,

		motor_min_speed,
		motor_max_speed,

		motor_lzrz_fs_speed,
		motor_xy_precise_calibrate_speed,

		motor_xy_steps_per_pixel,

		fiber_outline_blacklevel,
		calibrating_xy_dist_threshold,
		precise_calibrating_xy_dist_threshold,
		z_dist_threshold,

		discharge_base,
		discharge_revise,

		dust_check_threshold0,
		dust_check_threshold1,

		led_brightness)
};

}
<|endoftext|>


<commit_before>#pragma once

#include <cassert>
#include <type_traits>
#include <initializer_list>

#include <gpc/gui/renderer.hpp> // TODO: other source & namespace

#include "./basic_types.hpp"
#include "./geometry.hpp"
#include "./aspects.hpp"
#include "./layouting.hpp"

//#include "./Stylesheet.hpp"
#include "./Resource.hpp"
#include "./Full_resource_mapper.hpp"

namespace cppgui {

    // Forward declarations

    template <class Config, bool With_layout> class Root_widget;
    template <class Config, bool With_layout> class Abstract_container;
    /*template <class Config, bool With_layout>*/ class Drag_controller;

    enum Key_state { pressed, released }; // TODO: move to basic_types.hpp ?

    template <class Renderer> class Canvas;

    /** Abstract_widget: functionality common to both Root_widget and Widget, i.e. not including the ability
        to function as an element in a container.
     */
    template <class Config, bool With_layout>
    class Abstract_widget
    {
    public:
        using Abstract_widget_t = Abstract_widget;
        using Root_widget_t     = Root_widget<Config, With_layout>;
        using Canvas_t          = typename Canvas<typename Config::Renderer>;
        using Native_color      = typename Canvas_t::Native_color;
        using Font_handle       = typename Canvas_t::Font_handle;
        using Keyboard          = typename Config::Keyboard;
        using Keycode           = typename Keyboard::Keycode;
        // TODO: move the following resource type definitions into a special struct and inherit from that ?
        using Color_resource    = Resource<const Color &, Native_color, Canvas_t, true>;
        using Font_resource     = Resource<const Rasterized_font *, Font_handle, Canvas_t, false>;

        using Click_handler     = std::function<void(const Point &, int button, int clicks)>; // TODO: support return value ?
        using Pushed_handler    = std::function<void()>; // for buttons TODO: renamed event to "Push" (as in "a push happened") ?

        auto& rectangle() { return _rect; }
        auto& rectangle() const { return _rect; }
        auto& position() { return _rect.pos; }
        auto& position() const { return _rect.pos; }
        auto& extents() { return _rect.ext; }
        auto& extents() const { return _rect.ext; }
        void set_position(const Point &);
        void set_extents(const Extents &);

        // TODO: color and other style definitions belong into stylesheets
        //static auto button_face_color        () { return Color{ 0.8f, 0.8f, 0.8f, 1 }; }
        //static auto button_face_hovered_color() { return Color{ 0.9f, 0.9f, 0.9f, 1 }; }

        /** The init() entry point is where a widget "connects" to its backends (the most important of
            which being the canvas).
         */
        virtual void init() {}

        /** The update_view_from_data() entry point must be called after init(), and also after
            layout() if run-time layouting is enabled.
         */
        virtual void compute_view_from_data() {}

        virtual auto root_widget() -> Root_widget_t * = 0;

        // Input event injection

        /** By convention, mouse positions are passed to a widget as relative to
            their own origin (meaning that it falls to the caller, i.e. usually
            the container, to subtract the child widget's position() from the
            coordinates it gets from yet higher up).
         */
        virtual void mouse_motion(const Point &) {}
        virtual void mouse_button(const Point &, int /*button*/, Key_state) {}
        virtual void mouse_click(const Point &, int button, int count);
        virtual void mouse_wheel(const Vector &) {}
        virtual void text_input(const char32_t *, size_t) {}
        virtual void key_down(const Keycode &) {}

        virtual void mouse_enter() {}       // TODO: provide "entry point" parameter ?
        virtual void mouse_exit() {}        // TODO: provide "exit point" parameter ?

        bool disabled() const { return false; } // TODO!!!

        /** Convention: the provided position is an offset to be added to the widget's
            own coordinates.
         */
        virtual void render(Canvas_t *, const Point &offs) = 0;

        virtual bool handle_key_down(const Keycode &) { return false; }

    protected:

        // Rendering conveniences

        // auto rgba_to_native(Canvas_t *, const Color &) -> Native_color;
        auto rgba_to_native(const Color &) -> Native_color;
        void fill_rect(Canvas_t *, const Rectangle &rect, const Native_color &);
        void fill_rect(Canvas_t *, const Rectangle &rect, const Point &offs, const Native_color &);
        void fill_rect(Canvas_t *, const Point &pos, const Extents &ext, const Native_color &);
        void fill(Canvas_t *, const Point &offs, const Native_color &);
        auto convert_position_to_inner(const Point &) -> Point;
        auto advance_to_glyph_at(const Rasterized_font *, const std::u32string &text, size_t from, size_t to, Point &pos)
            -> const Glyph_control_box *;
        void draw_borders(Canvas_t *, const Point & offs, Width width, const Color &color);
        void draw_borders(Canvas_t *, const Rectangle &rect, const Point &offs, Width width, const Color &color);
        void draw_borders(Canvas_t *, const Rectangle &rect, const Point &offs,
            Width width, const Color & top, const Color & right, const Color & bottom, const Color & left);
        // PROVISIONAL
        void draw_stippled_inner_rect(Canvas_t *, const Rectangle &, const Point &offs);

        // Experimental & temporary: implement more sophisticated (and flexible!) styling
        // - May not / should not stay static; make const if possible

        static auto stroke_width() -> int { return 1; }
        static auto stroke_color() -> Color { return { 0, 0, 0, 1 }; }
        //static auto padding() -> int { return 5; }
        static auto paper_color() -> Color { return {1, 1, 1, 1}; }

    private:

        Rectangle   _rect = {};
    };

    template <class Config, bool With_layout> struct Widget__Layouter {

        template <class Aspect_parent> struct Aspect: Aspect_parent {
            void init_layout() {}
        };
    };

    // Widget

    template <class Config, bool With_layout>
    class Widget:
        public Config::template Widget_updater<
            Widget__Layouter<Config, With_layout>::template Aspect<
                Abstract_widget<Config, With_layout> > >
    {
    public:
        using Renderer = typename Config::Renderer;
        using Font_handle = typename Renderer::font_handle;
        using Keyboard = typename Config::Keyboard;
        using Keycode = typename Keyboard::Keycode;
        using Abstract_container_t = Abstract_container<Config, With_layout>;
        using Root_widget_t = Root_widget<Config, With_layout>;
        using Click_handler = typename Abstract_widget::Click_handler;

        void set_background_color(const Color &);
        auto background_color() const;

        void on_click(Click_handler);

        // void init();

        void set_visible(bool visible = true);
        bool visible() const { return _visible; }

        void set_focussable(bool state = true) { _focussable = state; }
        bool focussable() const { return _focussable; } // TODO: replace with can_take_focus() that takes other factors into consideration ?

        void added_to_container(Abstract_container_t *);
        void removed_from_container(Abstract_container_t *);

        // TODO: should the following be protected ?
        bool hovered() const { return _hovered; }

        virtual void take_focus();
        /** Important: do not call gained_focus() from a child; call child_obtained_focus() instead,
            to inform the container.
         */
        virtual void gained_focus();
        virtual void loosing_focus();

        // TODO: rename to has_keyboard_focus() ?
        bool has_focus() { return container()->container_has_focus() && container()->focused_child() == this; }

        bool is_first_child() { return container()->children().front() == this; }
        bool is_last_child () { return container()->children().back () == this; }

        void key_down(const Keycode &);
        //void key_up(const Keycode &);

        void mouse_enter() override;
        void mouse_exit() override;

        void mouse_click(const Point &, int button, int count) override;

        void change_visible(bool visible = true);

    protected:

        auto container() const { return _container; }
        auto root_widget() -> Root_widget_t * override { return _container->container_root_widget(); }

        void pass_up_and_notify_focus(); // default take_focus() action

        // Graphics system integration
        void shift_horizontally(Position_delta);
        void shift_vertically(Position_delta);
        void shift_up  (Length);
        void shift_down(Length);

        // Static styles
        // TODO: move to "stylesheet"
        static auto default_dialog_background_color() -> Color { return {0.6f, 0.6f, 0.6f, 1}; }

        // Styling
        // TODO: move to new class Abstract_button<> ?
        auto button_face_color() -> Color;
        auto button_border_color() -> Color;
        auto button_border_width() -> int;

        Abstract_container_t   *_container = nullptr;

        //Rectangle               _inner_rect;

    private:
        friend class Drag_controller;
        friend class Root_widget<Config, With_layout>;

        Color                   _bkgnd_clr = {0, 0, 0, 0};
        Click_handler           _click_hndlr;
        bool                    _visible = true;
        bool                    _focussable = true;
        bool                    _hovered = false;
    };

    // Default implementations for Updating_aspect

    /** The "Updater" aspect of a widget is responsible for making sure it gets
        redrawn when invalidate() has been called.

        The default implementation uses a pointer to parent to pass up redraw
        requests until they reach the root widget, which "handles" the request
        by passing it along to callback function.

        Because there is chance that a different implementation may not need
        to follow that route (e.g. by calling render() directly), the pointer
        to container may not be needed, so it is a member of this aspect
        implementation rather than of Widget<> itself.

        TODO: THIS IS PROVISIONAL. If it turns out, during further development,
        that a pointer to container is needed for reasons that are not dependent
        on the Updater (or any other) aspect family, that pointer, and the
        methods associated with it, should be moved to the Widget<> stem class.
     */
    template<class Config, bool With_layout> class Abstract_container;
    template<class Config, bool With_layout> class Default_container_updater;

    template<class Config, bool With_layout>
    struct Default__Widget__Updater {

        template<class Aspect_parent> struct Aspect: public Aspect_parent
        {
            class Widget_t: public Widget<Config, true> { friend struct Aspect; };
            using Abstract_container_t = Abstract_container<Config, With_layout>;

            void invalidate();

        private:
            auto p() { return static_cast<Widget_t*>(this); }
        };
    };

    // Layouting aspect

    template <class Config> struct Widget__Layouter<Config, true> {

        template <class Aspect_parent> struct Aspect: public Aspect_parent {

            /** It is up to the implementation to guarantee that any internal state/data
            needed for layouting (including computing/returning the get_minimal_size())
            is kept up to date.
            */

            // Layouter aspect contract

            virtual void init_layout() = 0;
            virtual auto get_minimal_size  () -> Extents = 0;
            virtual auto get_preferred_size() -> Extents { return get_minimal_size(); }
            virtual void layout() = 0;

            //void set_padding(Width);
            //void set_padding(const std::initializer_list<Width> &);

            void set_rectangle(const Point &nw, const Point &se);
            void set_rectangle_nw(const Point &, const Extents &);
            void set_rectangle_ne(const Point &, const Extents &);
            void set_rectangle_se(const Point &, const Extents &);
            void set_rectangle_sw(const Point &, const Extents &);

        protected:

            class Widget_t: public Widget<Config, true> { friend struct Aspect; };
            auto p() { return static_cast<Widget_t*>(this); }

            // "Stylesheet" TODO: make this into another aspect ?
            static constexpr auto button_padding() -> Padding { return { 5, 5, 5, 5 }; }

            // void compute_inner_rect();

            //Padding                 _padding = {};  // TODO: provide accessor ?
        };
    };

} // ns cppgui

#define CPPGUI_INSTANTIATE_WIDGET(Config, With_layout) \
    template cppgui::Widget           <Config, With_layout>; \
    template cppgui::Widget__Layouter <Config, With_layout>;

<commit_msg>Safety commit before some experimentation<commit_after>#pragma once

#include <cassert>
#include <type_traits>
#include <initializer_list>

#include <gpc/gui/renderer.hpp> // TODO: other source & namespace

#include "./basic_types.hpp"
#include "./geometry.hpp"
#include "./aspects.hpp"
#include "./layouting.hpp"

//#include "./Stylesheet.hpp"
#include "./Resource.hpp"
#include "./Full_resource_mapper.hpp"

namespace cppgui {

    // Forward declarations

    template <class Config, bool With_layout> class Root_widget;
    template <class Config, bool With_layout> class Abstract_container;
    /*template <class Config, bool With_layout>*/ class Drag_controller;

    enum Key_state { pressed, released }; // TODO: move to basic_types.hpp ?

    template <class Renderer> class Canvas;

    /** Abstract_widget: functionality common to both Root_widget and Widget, i.e. not including the ability
        to function as an element in a container.
     */
    template <class Config, bool With_layout>
    class Abstract_widget
    {
    public:
        using Abstract_widget_t = Abstract_widget;
        using Root_widget_t     = Root_widget<Config, With_layout>;
        using Canvas_t          = typename Canvas<typename Config::Renderer>;
        using Native_color      = typename Canvas_t::Native_color;
        using Font_handle       = typename Canvas_t::Font_handle;
        using Keyboard          = typename Config::Keyboard;
        using Keycode           = typename Keyboard::Keycode;
        // TODO: move the following resource type definitions into a special struct and inherit from that ?
        using Color_resource    = Resource<const Color &, Native_color, Canvas_t, true>;
        using Font_resource     = Resource<const Rasterized_font *, Font_handle, Canvas_t, false>;

        using Click_handler     = std::function<void(const Point &, int button, int clicks)>; // TODO: support return value ?
        using Pushed_handler    = std::function<void()>; // for buttons TODO: renamed event to "Push" (as in "a push happened") ?

        auto& rectangle() { return _rect; }
        auto& rectangle() const { return _rect; }
        auto& position() { return _rect.pos; }
        auto& position() const { return _rect.pos; }
        auto& extents() { return _rect.ext; }
        auto& extents() const { return _rect.ext; }
        void set_position(const Point &);
        void set_extents(const Extents &);

        // TODO: color and other style definitions belong into stylesheets
        //static auto button_face_color        () { return Color{ 0.8f, 0.8f, 0.8f, 1 }; }
        //static auto button_face_hovered_color() { return Color{ 0.9f, 0.9f, 0.9f, 1 }; }

        /** The init() entry point is where a widget "connects" to its backends (the most important of
            which being the canvas).
         */
        virtual void init() {}

        /** The update_view_from_data() entry point must be called after init(), and also after
            layout() if run-time layouting is enabled.
         */
        virtual void compute_view_from_data() {}

        virtual auto root_widget() -> Root_widget_t * = 0;

        // Input event injection

        /** By convention, mouse positions are passed to a widget as relative to
            their own origin (meaning that it falls to the caller, i.e. usually
            the container, to subtract the child widget's position() from the
            coordinates it gets from yet higher up).
         */
        virtual void mouse_motion(const Point &) {}
        virtual void mouse_button(const Point &, int /*button*/, Key_state) {}
        virtual void mouse_click(const Point &, int button, int count);
        virtual void mouse_wheel(const Vector &) {}
        virtual void text_input(const char32_t *, size_t) {}
        virtual void key_down(const Keycode &) {}

        virtual void mouse_enter() {}       // TODO: provide "entry point" parameter ?
        virtual void mouse_exit() {}        // TODO: provide "exit point" parameter ?

        bool disabled() const { return false; } // TODO!!!

        /** Convention: the provided position is an offset to be added to the widget's
            own coordinates.
         */
        virtual void render(Canvas_t *, const Point &offs) = 0;

        virtual bool handle_key_down(const Keycode &) { return false; }

    protected:

        // Rendering conveniences

        // auto rgba_to_native(Canvas_t *, const Color &) -> Native_color;
        auto rgba_to_native(const Color &) -> Native_color;
        void fill_rect(Canvas_t *, const Rectangle &rect, const Native_color &);
        void fill_rect(Canvas_t *, const Rectangle &rect, const Point &offs, const Native_color &);
        void fill_rect(Canvas_t *, const Point &pos, const Extents &ext, const Native_color &);
        void fill(Canvas_t *, const Point &offs, const Native_color &);
        auto convert_position_to_inner(const Point &) -> Point;
        auto advance_to_glyph_at(const Rasterized_font *, const std::u32string &text, size_t from, size_t to, Point &pos)
            -> const Glyph_control_box *;
        void draw_borders(Canvas_t *, const Point & offs, Width width, const Color &color);
        void draw_borders(Canvas_t *, const Rectangle &rect, const Point &offs, Width width, const Color &color);
        void draw_borders(Canvas_t *, const Rectangle &rect, const Point &offs,
            Width width, const Color & top, const Color & right, const Color & bottom, const Color & left);
        // PROVISIONAL
        void draw_stippled_inner_rect(Canvas_t *, const Rectangle &, const Point &offs);

        // Experimental & temporary: implement more sophisticated (and flexible!) styling
        // - May not / should not stay static; make const if possible

        static auto stroke_width() -> int { return 1; }
        static auto stroke_color() -> Color { return { 0, 0, 0, 1 }; }
        //static auto padding() -> int { return 5; }
        static auto paper_color() -> Color { return {1, 1, 1, 1}; }

    private:

        Rectangle   _rect = {};
    };

    template <class Config, bool With_layout> struct Widget__Layouter {

        template <class Aspect_parent> struct Aspect: Aspect_parent {
            void init_layout() {}
        };
    };

    // Widget

    template <class Config, bool With_layout>
    class Widget:
        public Config::template Widget_updater<
            Widget__Layouter<Config, With_layout>::template Aspect<
                Abstract_widget<Config, With_layout> > >
    {
    public:
        using Renderer = typename Config::Renderer;
        using Font_handle = typename Renderer::font_handle;
        using Keyboard = typename Config::Keyboard;
        using Keycode = typename Keyboard::Keycode;
        using Abstract_container_t = Abstract_container<Config, With_layout>;
        using Root_widget_t = Root_widget<Config, With_layout>;
        using Click_handler = typename Abstract_widget::Click_handler;

        void set_background_color(const Color &);
        auto background_color() const;

        void on_click(Click_handler);

        // void init();

        void set_visible(bool visible = true);
        bool visible() const { return _visible; }

        void set_focussable(bool state = true) { _focussable = state; }
        bool focussable() const { return _focussable; } // TODO: replace with can_take_focus() that takes other factors into consideration ?

        void added_to_container(Abstract_container_t *);
        void removed_from_container(Abstract_container_t *);

        // TODO: should the following be protected ?
        bool hovered() const { return _hovered; }

        virtual void take_focus();
        /** Important: do not call gained_focus() from a child; call child_obtained_focus() instead,
            to inform the container.
         */
        virtual void gained_focus();
        virtual void loosing_focus();

        // TODO: rename to has_keyboard_focus() ?
        bool has_focus() { return container()->container_has_focus() && container()->focused_child() == this; }

        bool is_first_child() { return container()->children().front() == this; }
        bool is_last_child () { return container()->children().back () == this; }

        void key_down(const Keycode &);
        //void key_up(const Keycode &);

        void mouse_enter() override;
        void mouse_exit() override;

        void mouse_click(const Point &, int button, int count) override;

        void change_visible(bool visible = true);

    protected:

        auto container() const { return _container; }
        auto root_widget() -> Root_widget_t * override { return _container->container_root_widget(); }

        void pass_up_and_notify_focus(); // default take_focus() action

        // Graphics system integration
        void shift_horizontally(Position_delta);
        void shift_vertically(Position_delta);
        void shift_up  (Length);
        void shift_down(Length);

        // Static styles
        // TODO: move to "stylesheet"
        static auto default_dialog_background_color() -> Color { return {0.6f, 0.6f, 0.6f, 1}; }

        // Styling
        // TODO: move to new class Abstract_button<> ?
        auto button_face_color() -> Color;
        auto button_border_color() -> Color;
        auto button_border_width() -> int;

        Abstract_container_t   *_container = nullptr;

        //Rectangle               _inner_rect;

    private:
        friend class Drag_controller;
        friend class Root_widget<Config, With_layout>;

        Color                   _bkgnd_clr = {0, 0, 0, 0};
        Click_handler           _click_hndlr;
        bool                    _visible = true;
        bool                    _focussable = true;
        bool                    _hovered = false;
    };

    // Default implementations for Updating_aspect

    /** The "Updater" aspect of a widget is responsible for making sure it gets
        redrawn when invalidate() has been called.

        The default implementation uses a pointer to parent to pass up redraw
        requests until they reach the root widget, which "handles" the request
        by passing it along to callback function.

        Because there is chance that a different implementation may not need
        to follow that route (e.g. by calling render() directly), the pointer
        to container may not be needed, so it is a member of this aspect
        implementation rather than of Widget<> itself.

        TODO: THIS IS PROVISIONAL. If it turns out, during further development,
        that a pointer to container is needed for reasons that are not dependent
        on the Updater (or any other) aspect family, that pointer, and the
        methods associated with it, should be moved to the Widget<> stem class.
     */
    template<class Config, bool With_layout> class Abstract_container;
    template<class Config, bool With_layout> class Default_container_updater;

    template<class Config, bool With_layout>
    struct Default__Widget__Updater {

        template<class Aspect_parent> struct Aspect: public Aspect_parent
        {
            class Widget_t: public Widget<Config, true> { friend struct Aspect; };
            using Abstract_container_t = Abstract_container<Config, With_layout>;

            void invalidate();

        private:
            auto p() { return static_cast<Widget_t*>(this); }
        };
    };

    // Layouting aspect

    /** TODO: rename to reflect the fact that this is abstract ?
     */
    template <class Config> struct Widget__Layouter<Config, true> {

        template <class Aspect_parent> struct Aspect: public Aspect_parent {

            /** It is up to the implementation to guarantee that any internal state/data
            needed for layouting (including computing/returning the get_minimal_size())
            is kept up to date.
            */

            // Layouter aspect contract

            virtual void init_layout() = 0;
            virtual auto get_minimal_size  () -> Extents = 0;
            virtual auto get_preferred_size() -> Extents { return get_minimal_size(); }
            virtual void layout() = 0;

            //void set_padding(Width);
            //void set_padding(const std::initializer_list<Width> &);

            void set_rectangle(const Point &nw, const Point &se);
            void set_rectangle_nw(const Point &, const Extents &);
            void set_rectangle_ne(const Point &, const Extents &);
            void set_rectangle_se(const Point &, const Extents &);
            void set_rectangle_sw(const Point &, const Extents &);

        protected:

            class Widget_t: public Widget<Config, true> { friend struct Aspect; };
            auto p() { return static_cast<Widget_t*>(this); }

            // "Stylesheet" TODO: make this into another aspect ?
            static constexpr auto button_padding() -> Padding { return { 5, 5, 5, 5 }; }

            // void compute_inner_rect();

            //Padding                 _padding = {};  // TODO: provide accessor ?
        };
    };

} // ns cppgui

#define CPPGUI_INSTANTIATE_WIDGET(Config, With_layout) \
    template cppgui::Widget           <Config, With_layout>; \
    template cppgui::Widget__Layouter <Config, With_layout>;

<|endoftext|>


<commit_before>#include <QCoreApplication>
#include <QTemporaryFile>
#include <QDir>

#include <objedutils/objedconsole.h>
#include <objedutils/objedconf.h>
#include <objedutils/objedexp.h>
#include <objedutils/objedio.h>

#include <objed/src/additivecl.h>
#include <objed/src/linearcl.h>

#include "visualizer.h"

int Visualizer::falseNodeCount = 0;
int Visualizer::trueNodeCount = 0;

int main(int argc, char *argv[])
{
  QCoreApplication app(argc, argv);

  if (app.arguments().count() < 3)
  {
    QTextStream out(stdout);
    out << "Visualizer. Visualize objed classifier as a graph (using graphviz)" << endl;
    out << "Usage: visualizer <classifier-path> <output-image-path> [<graphviz-dir-path>]" << endl;
    return -1;
  }

  QString classifierPath = app.arguments()[1];
  QString outputImagePath = app.arguments()[2];

  Visualizer visualizer(app.arguments().count() > 3 ? app.arguments()[3] : "");
  return visualizer.main(classifierPath, outputImagePath);
}

Visualizer::Visualizer(const QString &graphvizDirPath)
{
#ifdef Q_OS_WIN
  if (graphvizDirPath.isEmpty() == false)
  {
    dotProcess.setWorkingDirectory(graphvizDirPath);
  }
  else
  {
    QStringList graphvizDirPathList;
    QDir programFilesDir(qgetenv("ProgramFiles"));
    foreach (QString dirName, programFilesDir.entryList(QStringList("Graphviz*"), QDir::Dirs))
      graphvizDirPathList.append(programFilesDir.absoluteFilePath(dirName));

    if (graphvizDirPathList.count() > 0)
      dotProcess.setWorkingDirectory(graphvizDirPathList.last() + "/bin");
  }
#else //Q_OS_WIN
  if (graphvizDirPath.isEmpty() == false)
  {
    dotProcess.setWorkingDirectory(graphvizDirPath);
  }
#endif //Q_OS_WIN
}

Visualizer::~Visualizer()
{
  return;
}

int Visualizer::main(const QString &classifierPath, const QString &outputImagePath)
{
  QDir appDir(QCoreApplication::applicationDirPath());

  try
  {
    QTemporaryFile digraphFile;
    if (digraphFile.open() == false)
      throw ObjedException("Cannot create temporary file");

    QTextStream out(&digraphFile);
    out << "digraph Cascade {" << endl;

    QSharedPointer<objed::Classifier> classifier = ObjedIO::loadClassifier(classifierPath);
    if (classifier.isNull() == true)
      throw ObjedException("Cannot load classifier");

    if (classifier->type() == objed::CascadeClassifier::typeStatic())
      visualizeCascade(QTextStream(&digraphFile), classifier.dynamicCast<objed::CascadeClassifier>().data());
    else if (classifier->type() == objed::TreeClassifier::typeStatic())
      visualizeTree(QTextStream(&digraphFile), classifier.dynamicCast<objed::TreeClassifier>().data());
    else
      throw ObjedException("Unsupported classifier type");

    out << "}" << endl;

    QStringList dotArguments;
    dotArguments.append(QString("-T%0").arg(QFileInfo(outputImagePath).suffix().toLower()));
    dotArguments.append(QString("-o%0").arg(appDir.absoluteFilePath(outputImagePath)));
    dotArguments.append(digraphFile.fileName());

    QString dotPath = dotProcess.workingDirectory().isEmpty() ?
      "dot" : QDir(dotProcess.workingDirectory()).absoluteFilePath("dot");

    dotProcess.start(dotPath, dotArguments);
    if (dotProcess.waitForFinished() == false)
      throw ObjedException("Cannot run dot process");

    QByteArray dotOutput = dotProcess.readAllStandardOutput();
    if (dotOutput.length() > 0) ObjedConsole::printWarning(dotOutput.trimmed());

    QByteArray dotError = dotProcess.readAllStandardError();
    if (dotError.length() > 0) ObjedConsole::printWarning(dotError.trimmed());
  }
  catch (ObjedException ex)
  {
    ObjedConsole::printError(ex.details());
  }

  return 0;
}

int Visualizer::computeWCCount(const objed::Classifier *classifier)
{
  if (classifier == 0)
    throw ObjedException("Invalid classifier (classifier == null)");

  if (classifier->type() == objed::LinearClassifier::typeStatic())
    return dynamic_cast<const objed::LinearClassifier *>(classifier)->clList.size();
  if (classifier->type() == objed::AdditiveClassifier::typeStatic())
    return dynamic_cast<const objed::AdditiveClassifier *>(classifier)->clList.size();

  throw ObjedException("Unsupported strong classifier");
}

void Visualizer::connect(QTextStream &out, const QString &node1, const QString &node2, bool type)
{
  out << QString("%0 -> %1 [label = \" %3\"];").arg(node1).arg(node2).arg(type ? "T" : "F");
}

void Visualizer::connect(QTextStream &out, const QString &node1, bool type)
{
  QString nodeId = type ? QString("true%0").arg(trueNodeCount++) : QString("false%0").arg(falseNodeCount++);
  QString nodeColor = type ? QString("darkgreen") : QString("red");
  QString nodeLabel = type ? QString("True") : QString("False");

  out << QString("%0 [label = \"%1\", shape = ellipse, color = %2, fontcolor = %2];").
    arg(nodeId).arg(nodeLabel).arg(nodeColor) << endl;

  connect(out, node1, nodeId, type);
}

int Visualizer::visualizeCascade(QTextStream &out, objed::CascadeClassifier *cascade)
{
  if (cascade == 0 || cascade->clList.size() == 0)
    throw ObjedException("The cascade has no levels");

  for (size_t i = 0; i < cascade->clList.size() - 1; i++)
  {
    int wcCount = computeWCCount(cascade->clList[i]);
    out << QString("sc%0 [label = \"Sc (%1 Wc)\"];").arg(i).arg(wcCount) << endl;
    connect(out, QString("sc%0").arg(i), false);
    connect(out, QString("sc%0").arg(i), QString("sc%0").arg(i + 1), true);
  }

  connect(out, QString("sc%0").arg(cascade->clList.size() - 1), false);
  connect(out, QString("sc%0").arg(cascade->clList.size() - 1), true);

  return 0;
}

int Visualizer::visualizeTree(QTextStream &out, objed::TreeClassifier *tree)
{
  static int scIndex = 0;

  if (tree == 0 || tree->centralCl == 0)
    throw ObjedException("The tree has no nodes");

  const int myIndex = scIndex++;
  const int wcCount = computeWCCount(tree->centralCl);
  out << QString("sc%0 [label = \"Sc (%1 Wc)\"];").arg(myIndex).arg(wcCount) << endl;

  if (tree->leftCl != 0)
  {
    int leftIndex = visualizeTree(out, dynamic_cast<objed::TreeClassifier *>(tree->leftCl));
    connect(out, QString("sc%0").arg(myIndex), QString("sc%0").arg(leftIndex), false);
  }
  else
  {
    connect(out, QString("sc%0").arg(myIndex), false);
  }

  if (tree->rightCl != 0)
  {
    int rightIndex = visualizeTree(out, dynamic_cast<objed::TreeClassifier *>(tree->rightCl));
    connect(out, QString("sc%0").arg(myIndex), QString("sc%0").arg(rightIndex), true);

  }
  else
  {
    connect(out, QString("sc%0").arg(myIndex), true);
  }

  return myIndex;
}
<commit_msg>Fix visualizing of cascades<commit_after>#include <QCoreApplication>
#include <QTemporaryFile>
#include <QDir>

#include <objedutils/objedconsole.h>
#include <objedutils/objedconf.h>
#include <objedutils/objedexp.h>
#include <objedutils/objedio.h>

#include <objed/src/additivecl.h>
#include <objed/src/linearcl.h>

#include "visualizer.h"

int Visualizer::falseNodeCount = 0;
int Visualizer::trueNodeCount = 0;

int main(int argc, char *argv[])
{
  QCoreApplication app(argc, argv);

  if (app.arguments().count() < 3)
  {
    QTextStream out(stdout);
    out << "Visualizer. Visualize objed classifier as a graph (using graphviz)" << endl;
    out << "Usage: visualizer <classifier-path> <output-image-path> [<graphviz-dir-path>]" << endl;
    return -1;
  }

  QString classifierPath = app.arguments()[1];
  QString outputImagePath = app.arguments()[2];

  Visualizer visualizer(app.arguments().count() > 3 ? app.arguments()[3] : "");
  return visualizer.main(classifierPath, outputImagePath);
}

Visualizer::Visualizer(const QString &graphvizDirPath)
{
#ifdef Q_OS_WIN
  if (graphvizDirPath.isEmpty() == false)
  {
    dotProcess.setWorkingDirectory(graphvizDirPath);
  }
  else
  {
    QStringList graphvizDirPathList;
    QDir programFilesDir(qgetenv("ProgramFiles"));
    foreach (QString dirName, programFilesDir.entryList(QStringList("Graphviz*"), QDir::Dirs))
      graphvizDirPathList.append(programFilesDir.absoluteFilePath(dirName));

    if (graphvizDirPathList.count() > 0)
      dotProcess.setWorkingDirectory(graphvizDirPathList.last() + "/bin");
  }
#else //Q_OS_WIN
  if (graphvizDirPath.isEmpty() == false)
  {
    dotProcess.setWorkingDirectory(graphvizDirPath);
  }
#endif //Q_OS_WIN
}

Visualizer::~Visualizer()
{
  return;
}

int Visualizer::main(const QString &classifierPath, const QString &outputImagePath)
{
  QDir appDir(QCoreApplication::applicationDirPath());

  try
  {
    QTemporaryFile digraphFile;
    if (digraphFile.open() == false)
      throw ObjedException("Cannot create temporary file");

    QTextStream out(&digraphFile);
    out << "digraph Cascade {" << endl;

    QSharedPointer<objed::Classifier> classifier = ObjedIO::loadClassifier(classifierPath);
    if (classifier.isNull() == true)
      throw ObjedException("Cannot load classifier");

    if (classifier->type() == objed::CascadeClassifier::typeStatic())
      visualizeCascade(QTextStream(&digraphFile), classifier.dynamicCast<objed::CascadeClassifier>().data());
    else if (classifier->type() == objed::TreeClassifier::typeStatic())
      visualizeTree(QTextStream(&digraphFile), classifier.dynamicCast<objed::TreeClassifier>().data());
    else
      throw ObjedException("Unsupported classifier type");

    out << "}" << endl;

    QStringList dotArguments;
    dotArguments.append(QString("-T%0").arg(QFileInfo(outputImagePath).suffix().toLower()));
    dotArguments.append(QString("-o%0").arg(appDir.absoluteFilePath(outputImagePath)));
    dotArguments.append(digraphFile.fileName());

    QString dotPath = dotProcess.workingDirectory().isEmpty() ?
      "dot" : QDir(dotProcess.workingDirectory()).absoluteFilePath("dot");

    dotProcess.start(dotPath, dotArguments);
    if (dotProcess.waitForFinished() == false)
      throw ObjedException("Cannot run dot process");

    QByteArray dotOutput = dotProcess.readAllStandardOutput();
    if (dotOutput.length() > 0) ObjedConsole::printWarning(dotOutput.trimmed());

    QByteArray dotError = dotProcess.readAllStandardError();
    if (dotError.length() > 0) ObjedConsole::printWarning(dotError.trimmed());
  }
  catch (ObjedException ex)
  {
    ObjedConsole::printError(ex.details());
  }

  return 0;
}

int Visualizer::computeWCCount(const objed::Classifier *classifier)
{
  if (classifier == 0)
    throw ObjedException("Invalid classifier (classifier == null)");

  if (classifier->type() == objed::LinearClassifier::typeStatic())
    return dynamic_cast<const objed::LinearClassifier *>(classifier)->clList.size();
  if (classifier->type() == objed::AdditiveClassifier::typeStatic())
    return dynamic_cast<const objed::AdditiveClassifier *>(classifier)->clList.size();

  throw ObjedException("Unsupported strong classifier");
}

void Visualizer::connect(QTextStream &out, const QString &node1, const QString &node2, bool type)
{
  out << QString("%0 -> %1 [label = \" %3\"];").arg(node1).arg(node2).arg(type ? "T" : "F");
}

void Visualizer::connect(QTextStream &out, const QString &node1, bool type)
{
  QString nodeId = type ? QString("true%0").arg(trueNodeCount++) : QString("false%0").arg(falseNodeCount++);
  QString nodeColor = type ? QString("darkgreen") : QString("red");
  QString nodeLabel = type ? QString("True") : QString("False");

  out << QString("%0 [label = \"%1\", shape = ellipse, color = %2, fontcolor = %2];").
    arg(nodeId).arg(nodeLabel).arg(nodeColor) << endl;

  connect(out, node1, nodeId, type);
}

int Visualizer::visualizeCascade(QTextStream &out, objed::CascadeClassifier *cascade)
{
  if (cascade == 0 || cascade->clList.size() == 0)
    throw ObjedException("The cascade has no levels");

  size_t i = 0;
  for (i = 0; i < cascade->clList.size() - 1; i++)
  {
    int wcCount = computeWCCount(cascade->clList[i]);
    out << QString("sc%0 [label = \"Sc (%1 Wc)\"];").arg(i).arg(wcCount) << endl;
    connect(out, QString("sc%0").arg(i), false);
    connect(out, QString("sc%0").arg(i), QString("sc%0").arg(i + 1), true);
  }
  int wcCount = computeWCCount(cascade->clList[i]);
  out << QString("sc%0 [label = \"Sc (%1 Wc)\"];").arg(i).arg(wcCount) << endl;
  connect(out, QString("sc%0").arg(i), false);
  connect(out, QString("sc%0").arg(i), true);

  return 0;
}

int Visualizer::visualizeTree(QTextStream &out, objed::TreeClassifier *tree)
{
  static int scIndex = 0;

  if (tree == 0 || tree->centralCl == 0)
    throw ObjedException("The tree has no nodes");

  const int myIndex = scIndex++;
  const int wcCount = computeWCCount(tree->centralCl);
  out << QString("sc%0 [label = \"Sc (%1 Wc)\"];").arg(myIndex).arg(wcCount) << endl;

  if (tree->leftCl != 0)
  {
    int leftIndex = visualizeTree(out, dynamic_cast<objed::TreeClassifier *>(tree->leftCl));
    connect(out, QString("sc%0").arg(myIndex), QString("sc%0").arg(leftIndex), false);
  }
  else
  {
    connect(out, QString("sc%0").arg(myIndex), false);
  }

  if (tree->rightCl != 0)
  {
    int rightIndex = visualizeTree(out, dynamic_cast<objed::TreeClassifier *>(tree->rightCl));
    connect(out, QString("sc%0").arg(myIndex), QString("sc%0").arg(rightIndex), true);

  }
  else
  {
    connect(out, QString("sc%0").arg(myIndex), true);
  }

  return myIndex;
}
<|endoftext|>


<commit_before>#include "Player.h"
#include "InputHandler.h"

/**
 * The joystick button and sticks states are checked. If the button 1 (B on
 * xbox controller) is pressed, the player's speed is increased (it makes him
 * run), if the left stick is tilted in any direction, the player's velocity is
 * set.
 */
void Player::handleInput() {
	float xAxisValue, yAxisValue, velocityBasis = 1.0;
	InputHandler* handlerInstance = InputHandler::Instance();

	if (handlerInstance->joysticksInitialised()) {
		if (handlerInstance->getButtonState(0, 1)) {
			velocityBasis = 2.5;
		}

		xAxisValue = (float) handlerInstance->stickXValue(0, LEFT_STICK);
		yAxisValue = (float) handlerInstance->stickYValue(0, LEFT_STICK);
		if (xAxisValue > 0 || xAxisValue < 0) {
			m_velocity.setX(velocityBasis * xAxisValue);
			setAnimated(true);
		}

		if (yAxisValue > 0 || yAxisValue < 0) {
			m_velocity.setY(velocityBasis * yAxisValue);
			setAnimated(true);
		}
	}
}

/**
 * Reset the player velocity and update the input even polling and the player
 */
void Player::update() {
	setAnimated(false);
	m_velocity.setX(0);
	m_velocity.setY(0);

	handleInput();
	SDLDrawable::update();
}
<commit_msg>when sprinting, the player is animated faster<commit_after>#include "Player.h"
#include "InputHandler.h"

/**
 * The joystick button and sticks states are checked. If the button 1 (B on
 * xbox controller) is pressed, the player's speed is increased (it makes him
 * run), if the left stick is tilted in any direction, the player's velocity is
 * set.
 */
void Player::handleInput() {
	float xAxisValue, yAxisValue, velocityBasis = 1.0;
	InputHandler* handlerInstance = InputHandler::Instance();

	if (handlerInstance->joysticksInitialised()) {
		if (handlerInstance->getButtonState(0, 1)) {
			velocityBasis = 2.5;
			setAnimationSpeed(15);
		}
		else {
			setAnimationSpeed(10);
		}

		xAxisValue = (float) handlerInstance->stickXValue(0, LEFT_STICK);
		yAxisValue = (float) handlerInstance->stickYValue(0, LEFT_STICK);
		if (xAxisValue > 0 || xAxisValue < 0) {
			m_velocity.setX(velocityBasis * xAxisValue);
			setAnimated(true);
		}

		if (yAxisValue > 0 || yAxisValue < 0) {
			m_velocity.setY(velocityBasis * yAxisValue);
			setAnimated(true);
		}
	}
}

/**
 * Reset the player velocity and update the input even polling and the player
 */
void Player::update() {
	setAnimated(false);
	m_velocity.setX(0);
	m_velocity.setY(0);

	handleInput();
	SDLDrawable::update();
}
<|endoftext|>


<commit_before>/*
 * template.cpp
 *
 * Just some boilerplate stuff to use for each file.
 */

#include <iostream>
#include <complex>
using namespace std;

struct Vector {
    int size;
    double *elem;
};

void vector_init(Vector & v, int s)
{
    v.elem = new double[s];
    v.size = s;
}

double read_and_sum(int s)
{
    Vector v;
    vector_init(v, s);
    for (auto i=0; i!=s; ++i)
        cin >> v.elem[i];

    double sum = 0;
    for (auto i=0; i!=s; ++i)
        sum += v.elem[i];

    return sum;
}

int main()
{
    const auto num_vals = 5;

    cout << "Please give me " << num_vals << " floating point numbers.\n";
    double sum = read_and_sum(num_vals);
    cout << "The sum is: " << sum << "\n";
}

// vim: set ai sw=4 et sm:
<commit_msg>Just for grins, break vector handling into 3 separate routines: init, read, sum.<commit_after>/*
 * template.cpp
 *
 * Just some boilerplate stuff to use for each file.
 */

#include <iostream>
#include <complex>
using namespace std;

struct Vector {
    int size;
    double *elem;
};

void vector_init(Vector & v, int s)
{
    v.elem = new double[s];
    v.size = s;
}

/* Fill values in a Vector.  Assume an already initialized vector is passed in */
void read_vector(Vector & v)
{
    cout << "Please give me " << v.size << " floating point numbers.\n";

    for (auto i=0; i!=v.size; ++i)
        cin >> v.elem[i];
}

/* Sum values in a Vector. */
double sum_vector(Vector & v)
{
    double sum = 0;
    for (auto i=0; i!=v.size; ++i)
        sum += v.elem[i];

    return sum;
}

int main()
{
    int num_vals;

    cout << "How many elements in the vector? ";
    cin >> num_vals;

    Vector v;
    vector_init(v, num_vals);
    read_vector(v);

    // double sum = read_and_sum(num_vals);
    cout << "The sum is: " << sum_vector(v) << "\n";
}

// vim: set ai sw=4 et sm:
<|endoftext|>


<commit_before>#include "RTimer.h"
#include "RTimerEvent.h"
#include "RCoreApplication.h"
#include "RScopedPointer.h"

RTimer::RTimer() : mIsSingleShot(false)
{
  // NOTE: Set timer run as idle task by default, but we can't set interval to
  // zero, otherwise the created timer will return to NULL, so we give value 1 .
  mHandle = xTimerCreate(
    "",
    1,
    pdFALSE,                           // one-shot timer
    reinterpret_cast<void *>(0),
    onTimeout
    );
  vTimerSetTimerID(mHandle, this);
}

RTimer::~RTimer()
{
  xTimerDelete(mHandle, 0);
}

int
RTimer::interval() const
{
  return xTimerGetPeriod(mHandle) * portTICK_PERIOD_MS;
}

bool
RTimer::isActive() const
{
  return xTimerIsTimerActive(mHandle);
}

bool
RTimer::isSingleShot() const
{
  return mIsSingleShot;
}

void
RTimer::setInterval(int msec)
{
  xTimerChangePeriod(mHandle, msec / portTICK_PERIOD_MS, 0);

  // xTimerChangePeriod will cause timer start, so we need to stop it
  // immediately
  stop();
}

void
RTimer::setSingleShot(bool singleShot)
{
  mIsSingleShot = singleShot;
}

int
RTimer::timerId() const
{
  // WARNING: We shorten handle to id value, but it may lead duplicate id values.
  return rShortenPtr(pvTimerGetTimerID(mHandle));
}

void
RTimer::start(int msec)
{
  setInterval(msec);
  start();
}

void
RTimer::start()
{
  stop();
  xTimerStart(mHandle, 0);
}

void
RTimer::stop()
{
  xTimerStop(mHandle, 0);
}

bool
RTimer::event(REvent *e)
{
  if(e->type() == RTimerEvent::staticType())
  {
    // FIXME: Here may be generate a potential crash
    auto timerEvent = static_cast<RTimerEvent *>(e);

    timeout.emit();

    if(!mIsSingleShot)
    {
      start(); // Restart timer for next round
    }

    timerEvent->accept();
    return true;
  }

  return RObject::event(e);
}

void
RTimer::onTimeout(TimerHandle_t handle)
{
  auto self = static_cast<RTimer *>(pvTimerGetTimerID(handle));

  // NOTE: Event will be deleted in REventLoop after they handled that event.
  RScopedPointer<RTimerEvent> event(new RTimerEvent(self->timerId()));

  RCoreApplication::postEvent(self, event.take());
}
<commit_msg>Fixed period may less or equal to 0<commit_after>#include "RTimer.h"
#include "RTimerEvent.h"
#include "RCoreApplication.h"
#include "RScopedPointer.h"

RTimer::RTimer() : mIsSingleShot(false)
{
  // NOTE: Set timer run as idle task by default, but we can't set interval to
  // zero, otherwise the created timer will return to NULL, so we give value 1 .
  mHandle = xTimerCreate(
    "",
    1,
    pdFALSE,                           // one-shot timer
    reinterpret_cast<void *>(0),
    onTimeout
    );
  vTimerSetTimerID(mHandle, this);
}

RTimer::~RTimer()
{
  xTimerDelete(mHandle, 0);
}

int
RTimer::interval() const
{
  return xTimerGetPeriod(mHandle) * portTICK_PERIOD_MS;
}

bool
RTimer::isActive() const
{
  return xTimerIsTimerActive(mHandle);
}

bool
RTimer::isSingleShot() const
{
  return mIsSingleShot;
}

void
RTimer::setInterval(int msec)
{
  msec /= portTICK_PERIOD_MS;

  if(msec <= 0)
  {
    msec = 1;
  }

  xTimerChangePeriod(mHandle, msec, 0);

  // xTimerChangePeriod will cause timer start, so we need to stop it
  // immediately
  stop();
}

void
RTimer::setSingleShot(bool singleShot)
{
  mIsSingleShot = singleShot;
}

int
RTimer::timerId() const
{
  // WARNING: We shorten handle to id value, but it may lead duplicate id values.
  return rShortenPtr(pvTimerGetTimerID(mHandle));
}

void
RTimer::start(int msec)
{
  setInterval(msec);
  start();
}

void
RTimer::start()
{
  stop();
  xTimerStart(mHandle, 0);
}

void
RTimer::stop()
{
  xTimerStop(mHandle, 0);
}

bool
RTimer::event(REvent *e)
{
  if(e->type() == RTimerEvent::staticType())
  {
    // FIXME: Here may be generate a potential crash
    auto timerEvent = static_cast<RTimerEvent *>(e);

    timeout.emit();

    if(!mIsSingleShot)
    {
      start(); // Restart timer for next round
    }

    timerEvent->accept();
    return true;
  }

  return RObject::event(e);
}

void
RTimer::onTimeout(TimerHandle_t handle)
{
  auto self = static_cast<RTimer *>(pvTimerGetTimerID(handle));

  // NOTE: Event will be deleted in REventLoop after they handled that event.
  RScopedPointer<RTimerEvent> event(new RTimerEvent(self->timerId()));

  RCoreApplication::postEvent(self, event.take());
}
<|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.

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

#include "otbVectorImage.h"
#include "itkMacro.h"
#include <iostream>
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "otbMultiChannelExtractROI.h"

int otbImageFileWriterWithExtendedOptionBox(int argc, char* argv[])
{
  // Verify the number of parameters in the command line
  const std::string inputFilename = argv[1];
  const std::string outputFilename = argv[2];

  const unsigned int startx = atoi(argv[3]);
  const unsigned int starty = atoi(argv[4]);
  const unsigned int sizex = atoi(argv[5]);
  const unsigned int sizey = atoi(argv[6]);
  const unsigned int ram = atoi(argv[7]);
  const std::string separator = ":";

  typedef float InputPixelType;
  typedef float OutputPixelType;

  typedef otb::VectorImage<InputPixelType, 2> InputImageType;

  typedef InputImageType::PixelType   PixelType;

  typedef otb::MultiChannelExtractROI<InputImageType::InternalPixelType,
                                      InputImageType::InternalPixelType> ExtractROIFilterType;

  typedef otb::ImageFileReader<InputImageType> ReaderType;
  typedef otb::ImageFileWriter<InputImageType> WriterType;

  typedef itk::ImageRegionIterator< InputImageType >       IteratorType;
  typedef itk::ImageRegionConstIterator< InputImageType >  ConstIteratorType;

  ReaderType::Pointer reader = ReaderType::New();
  ExtractROIFilterType::Pointer extractROIFilter = ExtractROIFilterType::New();
  WriterType::Pointer writer = WriterType::New();

  reader->SetFileName(inputFilename);

  //Build output filename with extended box
  std::ostringstream outputFilenameExtended;
  outputFilenameExtended
                         << outputFilename
                         << "?&box=" << startx << separator
                         << starty << separator
                         << sizex << separator
                         << sizey
 ;

  std::cout << "Output image with user defined path " << outputFilenameExtended.str() << std::endl;

  writer->SetFileName(outputFilenameExtended.str());
  writer->SetInput(reader->GetOutput());
  writer->SetAutomaticAdaptativeStreaming(ram);

  extractROIFilter->SetStartX(startx);
  extractROIFilter->SetStartY(starty);
  extractROIFilter->SetSizeX(sizex);
  extractROIFilter->SetSizeY(sizey);
  extractROIFilter->SetInput(reader->GetOutput());

  writer->Update();
  extractROIFilter->Update();

  ReaderType::Pointer reader2 = ReaderType::New();
  reader2->SetFileName(outputFilename);

  reader2->Update();

  InputImageType::ConstPointer readImage = reader2->GetOutput();
  InputImageType::ConstPointer extractImage = extractROIFilter->GetOutput();

  ConstIteratorType ritr( readImage, readImage->GetLargestPossibleRegion() );
  ConstIteratorType extractitr( extractImage, extractImage->GetLargestPossibleRegion() );

  ritr.GoToBegin();
  extractitr.GoToBegin();

  std::cout << "Comparing the pixel values.. :" << std::endl;

  while( !ritr.IsAtEnd() &&  !extractitr.IsAtEnd() )
    {
    if( ritr.Get() != extractitr.Get() )
      {
      std::cerr << "Pixel comparison failed at index = " << ritr.GetIndex() << std::endl;
      std::cerr << "Expected pixel value " << extractitr.Get() << std::endl;
      std::cerr << "Read Image pixel value " << ritr.Get() << std::endl;
      return EXIT_FAILURE;
      }
    ++extractitr;
    ++ritr;
    }

  std::cout << std::endl;
  std::cout << "Test PASSED !" << std::endl;

  return EXIT_SUCCESS;
}
<commit_msg>STYLE<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.

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

#include "otbVectorImage.h"
#include "itkMacro.h"
#include <iostream>
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "otbMultiChannelExtractROI.h"

int otbImageFileWriterWithExtendedOptionBox(int argc, char* argv[])
{
  // Verify the number of parameters in the command line
  const std::string inputFilename = argv[1];
  const std::string outputFilename = argv[2];

  const unsigned int startx = atoi(argv[3]);
  const unsigned int starty = atoi(argv[4]);
  const unsigned int sizex = atoi(argv[5]);
  const unsigned int sizey = atoi(argv[6]);
  const unsigned int ram = atoi(argv[7]);
  const std::string separator = ":";

  typedef float InputPixelType;
  typedef float OutputPixelType;

  typedef otb::VectorImage<InputPixelType, 2> InputImageType;

  typedef InputImageType::PixelType   PixelType;

  typedef otb::MultiChannelExtractROI<InputImageType::InternalPixelType,
                                      InputImageType::InternalPixelType> ExtractROIFilterType;

  typedef otb::ImageFileReader<InputImageType> ReaderType;
  typedef otb::ImageFileWriter<InputImageType> WriterType;

  typedef itk::ImageRegionIterator< InputImageType >       IteratorType;
  typedef itk::ImageRegionConstIterator< InputImageType >  ConstIteratorType;

  ReaderType::Pointer reader = ReaderType::New();
  ExtractROIFilterType::Pointer extractROIFilter = ExtractROIFilterType::New();
  WriterType::Pointer writer = WriterType::New();

  reader->SetFileName(inputFilename);

  //Build output filename with extended box
  std::ostringstream outputFilenameExtended;
  outputFilenameExtended
                         << outputFilename
                         << "?&box=" << startx << separator
                         << starty << separator
                         << sizex << separator
                         << sizey
;

  std::cout << "Output image with user defined path " << outputFilenameExtended.str() << std::endl;

  writer->SetFileName(outputFilenameExtended.str());
  writer->SetInput(reader->GetOutput());
  writer->SetAutomaticAdaptativeStreaming(ram);

  extractROIFilter->SetStartX(startx);
  extractROIFilter->SetStartY(starty);
  extractROIFilter->SetSizeX(sizex);
  extractROIFilter->SetSizeY(sizey);
  extractROIFilter->SetInput(reader->GetOutput());

  writer->Update();
  extractROIFilter->Update();

  ReaderType::Pointer reader2 = ReaderType::New();
  reader2->SetFileName(outputFilename);

  reader2->Update();

  InputImageType::ConstPointer readImage = reader2->GetOutput();
  InputImageType::ConstPointer extractImage = extractROIFilter->GetOutput();

  ConstIteratorType ritr( readImage, readImage->GetLargestPossibleRegion() );
  ConstIteratorType extractitr( extractImage, extractImage->GetLargestPossibleRegion() );

  ritr.GoToBegin();
  extractitr.GoToBegin();

  std::cout << "Comparing the pixel values.. :" << std::endl;

  while( !ritr.IsAtEnd() &&  !extractitr.IsAtEnd() )
    {
    if( ritr.Get() != extractitr.Get() )
      {
      std::cerr << "Pixel comparison failed at index = " << ritr.GetIndex() << std::endl;
      std::cerr << "Expected pixel value " << extractitr.Get() << std::endl;
      std::cerr << "Read Image pixel value " << ritr.Get() << std::endl;
      return EXIT_FAILURE;
      }
    ++extractitr;
    ++ritr;
    }

  std::cout << std::endl;
  std::cout << "Test PASSED !" << std::endl;

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "SAMdisk.h"
#include "Sector.h"

Sector::Sector (DataRate datarate_, Encoding encoding_, const Header &header_, int gap3_)
	: header(header_), datarate(datarate_), encoding(encoding_), gap3(gap3_)
{
}

bool Sector::operator== (const Sector &sector) const
{
	// Headers must match
	if (sector.header != header)
		return false;

	// If neither has data it's a match
	if (sector.m_data.size() == 0 && m_data.size() == 0)
		return true;

	// Both sectors must have some data
	if (sector.copies() == 0 || copies() == 0)
		return false;

	// Both first sectors must have at least the natural size to compare
	if (sector.data_size() < sector.size() || data_size() < size())
		return false;

	// The natural data contents must match
	return std::equal(data_copy().begin(), data_copy().begin() + size(), sector.data_copy().begin());
}

int Sector::size () const
{
	return header.sector_size();
}

int Sector::data_size () const
{
	return copies() ? static_cast<int>(m_data[0].size()) : 0;
}

const DataList &Sector::datas () const
{
	return m_data;
}

DataList &Sector::datas ()
{
	return m_data;
}

const Data &Sector::data_copy (int copy/*=0*/) const
{
	copy = std::max(std::min(copy, static_cast<int>(m_data.size()) - 1), 0);
	return m_data[copy];
}

Data &Sector::data_copy (int copy/*=0*/)
{
	assert(m_data.size() != 0);
	copy = std::max(std::min(copy, static_cast<int>(m_data.size()) - 1), 0);
	return m_data[copy];
}

int Sector::copies () const
{
	return static_cast<int>(m_data.size());
}

Sector::Merge Sector::add (Data &&data, bool bad_crc, uint8_t new_dam)
{
	Merge ret = Merge::NewData;
	assert(!copies() || dam == new_dam);

	// If the sector has a bad header CRC, it can't have any data
	if (has_badidcrc())
		return Merge::Unchanged;

	// If there's enough data, check the CRC state
	if (static_cast<int>(data.size()) >= (size() + 2))
	{
		CRC16 crc;
		if (encoding == Encoding::MFM) crc.init(CRC16::A1A1A1);
		crc.add(new_dam);
		auto bad_data_crc = crc.add(data.data(), size() + 2) != 0;
		assert(bad_crc == bad_data_crc);
		(void)bad_data_crc;
	}

	// If the exising sector has good data, ignore supplied data if it's bad
	if (bad_crc && copies() && !has_baddatacrc())
		return Merge::Unchanged;

	// If the existing sector is bad, new good data will replace it all
	if (!bad_crc && has_baddatacrc())
	{
		remove_data();
		ret = Merge::Improved;
	}

	// 8K sectors always have a CRC error, but may include a secondary checksum
	if (is_8k_sector())
	{
		// Attempt to identify the 8K checksum method used by the new data
		auto chk8k_method = Get8KChecksumMethod(data.data(), data.size());

		// If it's recognised, replace any existing data with it
		if (chk8k_method >= CHK8K_FOUND)
		{
			remove_data();
			ret = Merge::Improved;
		}
		// Do we already have a copy?
		else if (copies() == 1)
		{
			// Can we identify the method used by the existing copy?
			chk8k_method = Get8KChecksumMethod(m_data[0].data(), m_data[0].size());
			if (chk8k_method >= CHK8K_FOUND)
			{
				// Keep the existing, ignoring the new data
				return Merge::Unchanged;
			}
		}
	}

	// Look for existing data that is a superset of what we're adding
	auto it = std::find_if(m_data.begin(), m_data.end(), [&] (const Data &d) {
		return d.size() >= data.size() && std::equal(data.begin(), data.end(), d.begin());
	});

	// Return if we already have a better copy
	if (it != m_data.end())
		return Merge::Unchanged;

	// Look for existing data that is a subset of what we're adding
	it = std::find_if(m_data.begin(), m_data.end(), [&] (const Data &d) {
		return d.size() <= data.size() && std::equal(d.begin(), d.end(), data.begin());
	});

	// Remove the inferior copy
	if (it != m_data.end())
	{
		m_data.erase(it);
		ret = Merge::Improved;
	}

	// DD 8K sectors are considered complete at 6K, everything else at natural size
	auto complete_size = is_8k_sector() ? 0x1800 : data.size();

	// Is the supplied data enough for a complete sector?
	if (data.size() >= complete_size)
	{
		// Look for existing data that contains the same normal sector data
		it = std::find_if(m_data.begin(), m_data.end(), [&] (const Data &d) {
			return d.size() >= complete_size && std::equal(d.begin(), d.begin() + complete_size, data.begin());
		});

		// Found a match?
		if (it != m_data.end())
		{
			// Return if the new one isn't larger
			if (data.size() <= it->size())
				return Merge::Unchanged;

			// Remove the existing smaller copy
			m_data.erase(it);
		}

		// Will we now have multiple copies?
		if (m_data.size() > 0)
		{
			// Keep multiple copies the same size, whichever is shortest
			auto new_size = std::min(data.size(), m_data[0].size());
			data.resize(new_size);

			// Resize any existing copies to match
			for (auto &d : m_data)
				d.resize(new_size);
		}
	}

	// Insert the new data copy, unless it the copy count (default is 3)
	if (copies() < opt.maxcopies)
		m_data.emplace_back(std::move(data));

	// Update the data CRC state and DAM
	m_bad_data_crc = bad_crc;
	dam = new_dam;

	return ret;
}

Sector::Merge Sector::merge (Sector &&sector)
{
	Merge ret = Merge::Unchanged;

	// If the new header CRC is bad there's nothing we can use
	if (sector.has_badidcrc())
		return Merge::Unchanged;

	// Something is wrong if the new details don't match the existing one
	assert(sector.header == header);
	assert(sector.datarate == datarate);
	assert(sector.encoding == encoding);

	// If the existing header is bad, repair it
	if (has_badidcrc())
	{
		header = sector.header;
		set_badidcrc(false);
		ret = Merge::Improved;
	}

	// We can't repair good data with bad
	if (!has_baddatacrc() && sector.has_baddatacrc())
		return ret;

	// Add the new data snapshots
	for (Data &data : sector.m_data)
	{
		// Move the data into place, passing on the existing data CRC status and DAM
		if (add(std::move(data), sector.has_baddatacrc(), sector.dam) != Merge::Unchanged)
			ret = Merge::Improved;	// ToDo: detect NewData return?
	}
	sector.m_data.clear();

	return ret;
}

bool Sector::has_data () const
{
	return copies() != 0;
}

bool Sector::has_gapdata () const
{
	return data_size() > size();
}

bool Sector::has_shortdata () const
{
	return data_size() < size();
}

bool Sector::has_badidcrc () const
{
	return m_bad_id_crc;
}

bool Sector::has_baddatacrc () const
{
	return m_bad_data_crc;
}

bool Sector::is_deleted () const
{
	return dam == 0xf8 || dam == 0xf9;
}

bool Sector::is_altdam () const
{
	return dam == 0xfa;
}

bool Sector::is_rx02dam () const
{
	return dam == 0xfd;
}

bool Sector::is_8k_sector () const
{
	// +3 and CPC disks treat this as a virtual complete sector
	return datarate == DataRate::_250K && encoding == Encoding::MFM && header.size == 6;
}

void Sector::set_badidcrc (bool bad)
{
	m_bad_id_crc = bad;

	if (bad)
		remove_data();
}

void Sector::set_baddatacrc (bool bad)
{
	m_bad_data_crc = bad;

	if (!bad && copies() > 1)
		m_data.resize(1);
}

void Sector::remove_data ()
{
	m_data.clear();
	m_bad_data_crc = false;
	dam = 0xfb;
}

void Sector::remove_gapdata ()
{
	if (!has_gapdata())
		return;

	for (auto &data : m_data)
		data.resize(size());
}

// Map a size code to how it's treated by the uPD765 FDC on the PC
int Sector::SizeCodeToRealSizeCode (int size)
{
	// Sizes above 8 are treated as 8 (32K)
	return (size <= 7) ? size : 8;
}

// Return the sector length for a given sector size code
int Sector::SizeCodeToLength (int size)
{
	// 2 ^ (7 + size)
	return 128 << SizeCodeToRealSizeCode(size);
}
<commit_msg>Improved clearing sector data errors<commit_after>#include "SAMdisk.h"
#include "Sector.h"

Sector::Sector (DataRate datarate_, Encoding encoding_, const Header &header_, int gap3_)
	: header(header_), datarate(datarate_), encoding(encoding_), gap3(gap3_)
{
}

bool Sector::operator== (const Sector &sector) const
{
	// Headers must match
	if (sector.header != header)
		return false;

	// If neither has data it's a match
	if (sector.m_data.size() == 0 && m_data.size() == 0)
		return true;

	// Both sectors must have some data
	if (sector.copies() == 0 || copies() == 0)
		return false;

	// Both first sectors must have at least the natural size to compare
	if (sector.data_size() < sector.size() || data_size() < size())
		return false;

	// The natural data contents must match
	return std::equal(data_copy().begin(), data_copy().begin() + size(), sector.data_copy().begin());
}

int Sector::size () const
{
	return header.sector_size();
}

int Sector::data_size () const
{
	return copies() ? static_cast<int>(m_data[0].size()) : 0;
}

const DataList &Sector::datas () const
{
	return m_data;
}

DataList &Sector::datas ()
{
	return m_data;
}

const Data &Sector::data_copy (int copy/*=0*/) const
{
	copy = std::max(std::min(copy, static_cast<int>(m_data.size()) - 1), 0);
	return m_data[copy];
}

Data &Sector::data_copy (int copy/*=0*/)
{
	assert(m_data.size() != 0);
	copy = std::max(std::min(copy, static_cast<int>(m_data.size()) - 1), 0);
	return m_data[copy];
}

int Sector::copies () const
{
	return static_cast<int>(m_data.size());
}

Sector::Merge Sector::add (Data &&data, bool bad_crc, uint8_t new_dam)
{
	Merge ret = Merge::NewData;
	assert(!copies() || dam == new_dam);

	// If the sector has a bad header CRC, it can't have any data
	if (has_badidcrc())
		return Merge::Unchanged;

	// If there's enough data, check the CRC state
	if (static_cast<int>(data.size()) >= (size() + 2))
	{
		CRC16 crc;
		if (encoding == Encoding::MFM) crc.init(CRC16::A1A1A1);
		crc.add(new_dam);
		auto bad_data_crc = crc.add(data.data(), size() + 2) != 0;
		assert(bad_crc == bad_data_crc);
		(void)bad_data_crc;
	}

	// If the exising sector has good data, ignore supplied data if it's bad
	if (bad_crc && copies() && !has_baddatacrc())
		return Merge::Unchanged;

	// If the existing sector is bad, new good data will replace it all
	if (!bad_crc && has_baddatacrc())
	{
		remove_data();
		ret = Merge::Improved;
	}

	// 8K sectors always have a CRC error, but may include a secondary checksum
	if (is_8k_sector())
	{
		// Attempt to identify the 8K checksum method used by the new data
		auto chk8k_method = Get8KChecksumMethod(data.data(), data.size());

		// If it's recognised, replace any existing data with it
		if (chk8k_method >= CHK8K_FOUND)
		{
			remove_data();
			ret = Merge::Improved;
		}
		// Do we already have a copy?
		else if (copies() == 1)
		{
			// Can we identify the method used by the existing copy?
			chk8k_method = Get8KChecksumMethod(m_data[0].data(), m_data[0].size());
			if (chk8k_method >= CHK8K_FOUND)
			{
				// Keep the existing, ignoring the new data
				return Merge::Unchanged;
			}
		}
	}

	// Look for existing data that is a superset of what we're adding
	auto it = std::find_if(m_data.begin(), m_data.end(), [&] (const Data &d) {
		return d.size() >= data.size() && std::equal(data.begin(), data.end(), d.begin());
	});

	// Return if we already have a better copy
	if (it != m_data.end())
		return Merge::Unchanged;

	// Look for existing data that is a subset of what we're adding
	it = std::find_if(m_data.begin(), m_data.end(), [&] (const Data &d) {
		return d.size() <= data.size() && std::equal(d.begin(), d.end(), data.begin());
	});

	// Remove the inferior copy
	if (it != m_data.end())
	{
		m_data.erase(it);
		ret = Merge::Improved;
	}

	// DD 8K sectors are considered complete at 6K, everything else at natural size
	auto complete_size = is_8k_sector() ? 0x1800 : data.size();

	// Is the supplied data enough for a complete sector?
	if (data.size() >= complete_size)
	{
		// Look for existing data that contains the same normal sector data
		it = std::find_if(m_data.begin(), m_data.end(), [&] (const Data &d) {
			return d.size() >= complete_size && std::equal(d.begin(), d.begin() + complete_size, data.begin());
		});

		// Found a match?
		if (it != m_data.end())
		{
			// Return if the new one isn't larger
			if (data.size() <= it->size())
				return Merge::Unchanged;

			// Remove the existing smaller copy
			m_data.erase(it);
		}

		// Will we now have multiple copies?
		if (m_data.size() > 0)
		{
			// Keep multiple copies the same size, whichever is shortest
			auto new_size = std::min(data.size(), m_data[0].size());
			data.resize(new_size);

			// Resize any existing copies to match
			for (auto &d : m_data)
				d.resize(new_size);
		}
	}

	// Insert the new data copy, unless it the copy count (default is 3)
	if (copies() < opt.maxcopies)
		m_data.emplace_back(std::move(data));

	// Update the data CRC state and DAM
	m_bad_data_crc = bad_crc;
	dam = new_dam;

	return ret;
}

Sector::Merge Sector::merge (Sector &&sector)
{
	Merge ret = Merge::Unchanged;

	// If the new header CRC is bad there's nothing we can use
	if (sector.has_badidcrc())
		return Merge::Unchanged;

	// Something is wrong if the new details don't match the existing one
	assert(sector.header == header);
	assert(sector.datarate == datarate);
	assert(sector.encoding == encoding);

	// If the existing header is bad, repair it
	if (has_badidcrc())
	{
		header = sector.header;
		set_badidcrc(false);
		ret = Merge::Improved;
	}

	// We can't repair good data with bad
	if (!has_baddatacrc() && sector.has_baddatacrc())
		return ret;

	// Add the new data snapshots
	for (Data &data : sector.m_data)
	{
		// Move the data into place, passing on the existing data CRC status and DAM
		if (add(std::move(data), sector.has_baddatacrc(), sector.dam) != Merge::Unchanged)
			ret = Merge::Improved;	// ToDo: detect NewData return?
	}
	sector.m_data.clear();

	return ret;
}

bool Sector::has_data () const
{
	return copies() != 0;
}

bool Sector::has_gapdata () const
{
	return data_size() > size();
}

bool Sector::has_shortdata () const
{
	return data_size() < size();
}

bool Sector::has_badidcrc () const
{
	return m_bad_id_crc;
}

bool Sector::has_baddatacrc () const
{
	return m_bad_data_crc;
}

bool Sector::is_deleted () const
{
	return dam == 0xf8 || dam == 0xf9;
}

bool Sector::is_altdam () const
{
	return dam == 0xfa;
}

bool Sector::is_rx02dam () const
{
	return dam == 0xfd;
}

bool Sector::is_8k_sector () const
{
	// +3 and CPC disks treat this as a virtual complete sector
	return datarate == DataRate::_250K && encoding == Encoding::MFM && header.size == 6;
}

void Sector::set_badidcrc (bool bad)
{
	m_bad_id_crc = bad;

	if (bad)
		remove_data();
}

void Sector::set_baddatacrc (bool bad)
{
	m_bad_data_crc = bad;

	if (!bad)
	{
		auto fill_byte = static_cast<uint8_t>((opt.fill >= 0) ? opt.fill : 0);

		if (!has_data())
			m_data.push_back(Data(size(), fill_byte));
		else if (copies() > 1)
		{
			m_data.resize(1);

			if (data_size() < size())
			{
				auto pad{ Data(size() - data_size(), fill_byte) };
				m_data[0].insert(m_data[0].begin(), pad.begin(), pad.end());
			}
		}
	}
}

void Sector::remove_data ()
{
	m_data.clear();
	m_bad_data_crc = false;
	dam = 0xfb;
}

void Sector::remove_gapdata ()
{
	if (!has_gapdata())
		return;

	for (auto &data : m_data)
		data.resize(size());
}

// Map a size code to how it's treated by the uPD765 FDC on the PC
int Sector::SizeCodeToRealSizeCode (int size)
{
	// Sizes above 8 are treated as 8 (32K)
	return (size <= 7) ? size : 8;
}

// Return the sector length for a given sector size code
int Sector::SizeCodeToLength (int size)
{
	// 2 ^ (7 + size)
	return 128 << SizeCodeToRealSizeCode(size);
}
<|endoftext|>