<commit_before>//----------------------------------------------------------------------------
/// \file  basic_persist_array.hpp
//----------------------------------------------------------------------------
/// \brief Implementation of persistent array storage class.
//----------------------------------------------------------------------------
// Copyright (c) 2010 Omnibius, LLC
// Author:  Serge Aleynikov <saleyn@gmail.com>
// Created: 2010-10-25
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the util open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
vsn 2.1 of the License, or (at your option) any later vsn.

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

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/

#ifndef _UTIL_PERSISTENT_ARRAY_HPP_
#define _UTIL_PERSISTENT_ARRAY_HPP_

#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/static_assert.hpp>
#include <boost/scope_exit.hpp>
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
#include <util/compiler_hints.hpp>
#include <util/atomic.hpp>
#include <util/error.hpp>
#include <stdexcept>
#include <fstream>
#include <string>
#include <vector>
#include <cstring>
#include <cstddef>
#include <cstdlib>
#include <unistd.h>

namespace util {

    namespace {
        namespace bip = boost::interprocess;
        struct empty_data {};
    }

    template <
        typename T,
        size_t NLocks = 32,
        typename Lock = boost::mutex,
        typename ExtraHeaderData = empty_data>
    struct persist_array {
        struct header {
            static const uint32_t s_version = 0xa0b1c2d3;
            uint32_t        version;
            volatile long   rec_count;
            size_t          max_recs;
            size_t          rec_size;
            Lock            locks[NLocks];
            ExtraHeaderData extra_header_data;
            T               records[0];
        };

    protected:
        typedef persist_array<T, NLocks, Lock, ExtraHeaderData> self_type;

        BOOST_STATIC_ASSERT(!(NLocks & (NLocks - 1))); // must be power of 2

        static const size_t s_lock_mask = NLocks-1;
        // Shared memory file mapping
        bip::file_mapping  m_file;
        // Shared memory mapped region
        bip::mapped_region m_region;

        // Locks that guard access to internal record structures.
        header* m_header;
        T*      m_begin;
        T*      m_end;

        void check_range(size_t a_id) const throw (badarg_error) {
            size_t n = m_header->max_recs;
            if (likely(a_id < n))
                return;
            throw badarg_error("Invalid record id specified ", a_id, " (max=", n-1, ')');
        }

    public:
        typedef Lock                        lock_type;
        typedef typename Lock::scoped_lock  scoped_lock;
        typedef typename Lock::scoped_try_lock  scoped_try_lock;

        BOOST_STATIC_ASSERT((NLocks & (NLocks-1)) == 0); // Must be power of 2.

        persist_array()
            : m_header(NULL), m_begin(NULL), m_end(NULL)
        {}

        /// Default permission mask used for opening a file
        static int default_file_mode() { return S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; }

        /// Initialize the storage
        /// @return true if the storage file didn't exist and was created
        bool init(const char* a_filename, size_t a_max_recs, bool a_read_only = false,
            int a_mode = default_file_mode()) throw (io_error);

        size_t count()    const { return static_cast<size_t>(m_header->rec_count); }
        size_t capacity() const { return m_header->max_recs; }

        ExtraHeaderData& extra_header_data() { return m_header->extra_header_data; }

        /// Allocate next record and return its ID.
        /// @return
        size_t allocate_rec() throw(std::runtime_error) {
            size_t n = static_cast<size_t>(atomic::add(&m_header->rec_count,1));
            if (n >= capacity()) {
                atomic::dec(&m_header->rec_count);
                throw std::runtime_error("Out of storage capacity!");
            }
            return n;
        }

        std::pair<T*, size_t> get_next() {
            size_t n = allocate_rec();
            return std::make_pair(get(n), n);
        }

        Lock& get_lock(size_t a_rec_id) {
            return m_header->locks[a_rec_id & s_lock_mask];
        }

        /// Add a record with given ID to the store
        void add(size_t a_id, const T& a_rec) {
            BOOST_ASSERT(a_id < m_header->rec_count);
            scoped_lock guard(get_lock(a_id));
            *get(a_id) = a_rec;
        }

        /// Add a record to the storage and return it's id
        size_t add(const T& a_rec) {
            size_t n = allocate_rec();
            scoped_lock guard(get_lock(n));
            *(m_begin+n) = a_rec;
            return n;
        }

        /// @return id of the given object in the storage
        size_t id_of(const T* a_rec) const { return a_rec - m_begin; }

        const T& operator[] (size_t a_id) const throw(badarg_error) {
            check_range(a_id); return *get(a_id);
        }
        T& operator[] (size_t a_id) throw(badarg_error) {
            check_range(a_id); return *get(a_id);
        }

        const T* get(size_t a_rec_id) const {
            return likely(a_rec_id < m_header->max_recs) ? m_begin+a_rec_id : NULL;
        }

        T* get(size_t a_rec_id) {
            return likely(a_rec_id < m_header->max_recs) ? m_begin+a_rec_id : NULL;
        }

        /// Flush header to disk
        bool flush_header() { return m_region.flush(0, sizeof(header)); }

        /// Flush region of cached records to disk
        bool flush(size_t a_from_rec = 0, size_t a_num_recs = 0) {
            return m_region.flush(a_from_rec, a_num_recs*sizeof(T));
        }

        /// Remove memory mapped file from disk
        void remove() {
            m_file.remove(m_file.get_name());
        }

        const T*    begin() const { return m_begin; }
        const T*    end()   const { return m_end; }
        T*          begin()       { return m_begin; }
        T*          end()         { return m_end; }

        template <class Visitor>
        void for_each(const Visitor& a_visitor) {
            size_t n = 0;
            for (const T* p = begin(), *e = p + count(); p != e; ++p, ++n)
                a_visitor(n, p);
        }

        std::ostream& dump(std::ostream& out, const std::string& a_prefix="") {
            for (const T* p = begin(), *e = p + count(); p != e; ++p)
                out << a_prefix << *p << std::endl;
            return out;
        }
    };

    //-------------------------------------------------------------------------
    // Implementation
    //-------------------------------------------------------------------------

    template <typename T, size_t NLocks, typename Lock, typename Ext>
    bool persist_array<T,NLocks,Lock,Ext>::
    init(const char* a_filename, size_t a_max_recs, bool a_read_only, int a_mode)
        throw (io_error)
    {
        static const size_t s_pack_size = getpagesize();

        size_t sz = sizeof(header) + (a_max_recs * sizeof(T));
        sz += (s_pack_size - sz % s_pack_size);

        bool l_exists;
        try {
            boost::filesystem::path l_name(a_filename);
            try {
                boost::filesystem::create_directories(l_name.parent_path());
            } catch (boost::system::system_error& e) {
                throw io_error("Cannot create directory: ",
                    l_name.parent_path(), ": ", e.what());
            }

            {
                std::filebuf f;
                f.open(a_filename, std::ios_base::in | std::ios_base::out
                    | std::ios_base::binary);
                l_exists = f.is_open();

                if (l_exists && !a_read_only) {
                    bip::file_lock flock(a_filename);
                    bip::scoped_lock<bip::file_lock> g_lock(flock);

                    header h;
                    f.sgetn(reinterpret_cast<char*>(&h), sizeof(header));

                    if (h.version != header::s_version) {
                        throw io_error("Invalid file format ", a_filename);
                    }
                    if (h.rec_size != sizeof(T)) {
                        throw io_error("Invalid item size in file ", a_filename,
                            " (expected ", sizeof(T), " got ", h.rec_size, ')');
                    }
                    // Increase the file size if instructed to do so.
                    if (h.max_recs < a_max_recs) {
                        h.max_recs = a_max_recs;
                        f.pubseekoff(0, std::ios_base::beg);
                        f.sputn(reinterpret_cast<char*>(&h), sizeof(header));
                        f.pubseekoff(sz-1, std::ios_base::beg);
                        f.sputc(0);
                    }
                }
            }

            if (!l_exists && !a_read_only) {
                int l_fd = ::open(a_filename, O_RDWR | O_CREAT | O_TRUNC, a_mode);
                if (l_fd < 0)
                    throw io_error(errno, "Error creating file ", a_filename);

                BOOST_SCOPE_EXIT_TPL( (&l_fd) ) {
                    ::close(l_fd);
                } BOOST_SCOPE_EXIT_END;

                bip::file_lock flock(a_filename);
                bip::scoped_lock<bip::file_lock> g_lock(flock);

                header h;
                h.version   = header::s_version;
                h.rec_count = 0;
                h.max_recs  = a_max_recs;
                h.rec_size  = sizeof(T);

                if (::write(l_fd, &h, sizeof(h)) < 0)
                    throw io_error(errno, "Error writing to file ", a_filename);

                if (::ftruncate(l_fd, sz) < 0)
                    throw io_error(errno, "Error setting file ",
                        a_filename, " to size ", sz);

                ::fsync(l_fd);
            }

            bip::file_mapping shmf(a_filename, a_read_only ? bip::read_only : bip::read_write);
            bip::mapped_region region(shmf, a_read_only ? bip::read_only : bip::read_write);

            //Get the address of the mapped region
            void*  addr  = region.get_address();
            size_t size  = region.get_size();

            m_file.swap(shmf);
            m_region.swap(region);

            //if (!exists && !a_read_only)
            //    memset(static_cast<char*>(addr) + sizeof(header), 0, size - sizeof(header));
            m_header = static_cast<header*>(addr);
            m_begin  = m_header->records;
            m_end    = m_begin + a_max_recs;
            BOOST_ASSERT(reinterpret_cast<char*>(m_end) <= static_cast<char*>(addr)+size);

            //if (!l_exists && !a_read_only) {
            if (!a_read_only) {
                bip::file_lock flock(a_filename);
                bip::scoped_lock<bip::file_lock> g_lock(flock);

                // If the file is open for writing, initialize the locks
                // since previous program crash might have left locks in inconsistent state
                for (Lock* l = m_header->locks, *e = l + NLocks; l != e; ++l)
                    new (l) Lock();
            }

        } catch (io_error& e) {
            throw;
        } catch (std::exception& e) {
            throw io_error(e.what());
        }

        return !l_exists;
    }

} // namespace util

#endif // _UTIL_PERSISTENT_ARRAY_HPP_
<commit_msg>Moved type from anonymous namespace<commit_after>//----------------------------------------------------------------------------
/// \file  basic_persist_array.hpp
//----------------------------------------------------------------------------
/// \brief Implementation of persistent array storage class.
//----------------------------------------------------------------------------
// Copyright (c) 2010 Omnibius, LLC
// Author:  Serge Aleynikov <saleyn@gmail.com>
// Created: 2010-10-25
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the util open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
vsn 2.1 of the License, or (at your option) any later vsn.

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

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/

#ifndef _UTIL_PERSISTENT_ARRAY_HPP_
#define _UTIL_PERSISTENT_ARRAY_HPP_

#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/static_assert.hpp>
#include <boost/scope_exit.hpp>
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
#include <util/compiler_hints.hpp>
#include <util/atomic.hpp>
#include <util/error.hpp>
#include <stdexcept>
#include <fstream>
#include <string>
#include <vector>
#include <cstring>
#include <cstddef>
#include <cstdlib>
#include <unistd.h>

namespace util {

    namespace { namespace bip = boost::interprocess; }
    namespace detail { struct empty_data {}; }

    template <
        typename T,
        size_t NLocks = 32,
        typename Lock = boost::mutex,
        typename ExtraHeaderData = detail::empty_data>
    struct persist_array {
        struct header {
            static const uint32_t s_version = 0xa0b1c2d3;
            uint32_t        version;
            volatile long   rec_count;
            size_t          max_recs;
            size_t          rec_size;
            Lock            locks[NLocks];
            ExtraHeaderData extra_header_data;
            T               records[0];
        };

    protected:
        typedef persist_array<T, NLocks, Lock, ExtraHeaderData> self_type;

        BOOST_STATIC_ASSERT(!(NLocks & (NLocks - 1))); // must be power of 2

        static const size_t s_lock_mask = NLocks-1;
        // Shared memory file mapping
        bip::file_mapping  m_file;
        // Shared memory mapped region
        bip::mapped_region m_region;

        // Locks that guard access to internal record structures.
        header* m_header;
        T*      m_begin;
        T*      m_end;

        void check_range(size_t a_id) const throw (badarg_error) {
            size_t n = m_header->max_recs;
            if (likely(a_id < n))
                return;
            throw badarg_error("Invalid record id specified ", a_id, " (max=", n-1, ')');
        }

    public:
        typedef Lock                        lock_type;
        typedef typename Lock::scoped_lock  scoped_lock;
        typedef typename Lock::scoped_try_lock  scoped_try_lock;

        BOOST_STATIC_ASSERT((NLocks & (NLocks-1)) == 0); // Must be power of 2.

        persist_array()
            : m_header(NULL), m_begin(NULL), m_end(NULL)
        {}

        /// Default permission mask used for opening a file
        static int default_file_mode() { return S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; }

        /// Initialize the storage
        /// @return true if the storage file didn't exist and was created
        bool init(const char* a_filename, size_t a_max_recs, bool a_read_only = false,
            int a_mode = default_file_mode()) throw (io_error);

        size_t count()    const { return static_cast<size_t>(m_header->rec_count); }
        size_t capacity() const { return m_header->max_recs; }

        ExtraHeaderData& extra_header_data() { return m_header->extra_header_data; }

        /// Allocate next record and return its ID.
        /// @return
        size_t allocate_rec() throw(std::runtime_error) {
            size_t n = static_cast<size_t>(atomic::add(&m_header->rec_count,1));
            if (n >= capacity()) {
                atomic::dec(&m_header->rec_count);
                throw std::runtime_error("Out of storage capacity!");
            }
            return n;
        }

        std::pair<T*, size_t> get_next() {
            size_t n = allocate_rec();
            return std::make_pair(get(n), n);
        }

        Lock& get_lock(size_t a_rec_id) {
            return m_header->locks[a_rec_id & s_lock_mask];
        }

        /// Add a record with given ID to the store
        void add(size_t a_id, const T& a_rec) {
            BOOST_ASSERT(a_id < m_header->rec_count);
            scoped_lock guard(get_lock(a_id));
            *get(a_id) = a_rec;
        }

        /// Add a record to the storage and return it's id
        size_t add(const T& a_rec) {
            size_t n = allocate_rec();
            scoped_lock guard(get_lock(n));
            *(m_begin+n) = a_rec;
            return n;
        }

        /// @return id of the given object in the storage
        size_t id_of(const T* a_rec) const { return a_rec - m_begin; }

        const T& operator[] (size_t a_id) const throw(badarg_error) {
            check_range(a_id); return *get(a_id);
        }
        T& operator[] (size_t a_id) throw(badarg_error) {
            check_range(a_id); return *get(a_id);
        }

        const T* get(size_t a_rec_id) const {
            return likely(a_rec_id < m_header->max_recs) ? m_begin+a_rec_id : NULL;
        }

        T* get(size_t a_rec_id) {
            return likely(a_rec_id < m_header->max_recs) ? m_begin+a_rec_id : NULL;
        }

        /// Flush header to disk
        bool flush_header() { return m_region.flush(0, sizeof(header)); }

        /// Flush region of cached records to disk
        bool flush(size_t a_from_rec = 0, size_t a_num_recs = 0) {
            return m_region.flush(a_from_rec, a_num_recs*sizeof(T));
        }

        /// Remove memory mapped file from disk
        void remove() {
            m_file.remove(m_file.get_name());
        }

        const T*    begin() const { return m_begin; }
        const T*    end()   const { return m_end; }
        T*          begin()       { return m_begin; }
        T*          end()         { return m_end; }

        template <class Visitor>
        void for_each(const Visitor& a_visitor) {
            size_t n = 0;
            for (const T* p = begin(), *e = p + count(); p != e; ++p, ++n)
                a_visitor(n, p);
        }

        std::ostream& dump(std::ostream& out, const std::string& a_prefix="") {
            for (const T* p = begin(), *e = p + count(); p != e; ++p)
                out << a_prefix << *p << std::endl;
            return out;
        }
    };

    //-------------------------------------------------------------------------
    // Implementation
    //-------------------------------------------------------------------------

    template <typename T, size_t NLocks, typename Lock, typename Ext>
    bool persist_array<T,NLocks,Lock,Ext>::
    init(const char* a_filename, size_t a_max_recs, bool a_read_only, int a_mode)
        throw (io_error)
    {
        static const size_t s_pack_size = getpagesize();

        size_t sz = sizeof(header) + (a_max_recs * sizeof(T));
        sz += (s_pack_size - sz % s_pack_size);

        bool l_exists;
        try {
            boost::filesystem::path l_name(a_filename);
            try {
                boost::filesystem::create_directories(l_name.parent_path());
            } catch (boost::system::system_error& e) {
                throw io_error("Cannot create directory: ",
                    l_name.parent_path(), ": ", e.what());
            }

            {
                std::filebuf f;
                f.open(a_filename, std::ios_base::in | std::ios_base::out
                    | std::ios_base::binary);
                l_exists = f.is_open();

                if (l_exists && !a_read_only) {
                    bip::file_lock flock(a_filename);
                    bip::scoped_lock<bip::file_lock> g_lock(flock);

                    header h;
                    f.sgetn(reinterpret_cast<char*>(&h), sizeof(header));

                    if (h.version != header::s_version) {
                        throw io_error("Invalid file format ", a_filename);
                    }
                    if (h.rec_size != sizeof(T)) {
                        throw io_error("Invalid item size in file ", a_filename,
                            " (expected ", sizeof(T), " got ", h.rec_size, ')');
                    }
                    // Increase the file size if instructed to do so.
                    if (h.max_recs < a_max_recs) {
                        h.max_recs = a_max_recs;
                        f.pubseekoff(0, std::ios_base::beg);
                        f.sputn(reinterpret_cast<char*>(&h), sizeof(header));
                        f.pubseekoff(sz-1, std::ios_base::beg);
                        f.sputc(0);
                    }
                }
            }

            if (!l_exists && !a_read_only) {
                int l_fd = ::open(a_filename, O_RDWR | O_CREAT | O_TRUNC, a_mode);
                if (l_fd < 0)
                    throw io_error(errno, "Error creating file ", a_filename);

                BOOST_SCOPE_EXIT_TPL( (&l_fd) ) {
                    ::close(l_fd);
                } BOOST_SCOPE_EXIT_END;

                bip::file_lock flock(a_filename);
                bip::scoped_lock<bip::file_lock> g_lock(flock);

                header h;
                h.version   = header::s_version;
                h.rec_count = 0;
                h.max_recs  = a_max_recs;
                h.rec_size  = sizeof(T);

                if (::write(l_fd, &h, sizeof(h)) < 0)
                    throw io_error(errno, "Error writing to file ", a_filename);

                if (::ftruncate(l_fd, sz) < 0)
                    throw io_error(errno, "Error setting file ",
                        a_filename, " to size ", sz);

                ::fsync(l_fd);
            }

            bip::file_mapping shmf(a_filename, a_read_only ? bip::read_only : bip::read_write);
            bip::mapped_region region(shmf, a_read_only ? bip::read_only : bip::read_write);

            //Get the address of the mapped region
            void*  addr  = region.get_address();
            size_t size  = region.get_size();

            m_file.swap(shmf);
            m_region.swap(region);

            //if (!exists && !a_read_only)
            //    memset(static_cast<char*>(addr) + sizeof(header), 0, size - sizeof(header));
            m_header = static_cast<header*>(addr);
            m_begin  = m_header->records;
            m_end    = m_begin + a_max_recs;
            BOOST_ASSERT(reinterpret_cast<char*>(m_end) <= static_cast<char*>(addr)+size);

            //if (!l_exists && !a_read_only) {
            if (!a_read_only) {
                bip::file_lock flock(a_filename);
                bip::scoped_lock<bip::file_lock> g_lock(flock);

                // If the file is open for writing, initialize the locks
                // since previous program crash might have left locks in inconsistent state
                for (Lock* l = m_header->locks, *e = l + NLocks; l != e; ++l)
                    new (l) Lock();
            }

        } catch (io_error& e) {
            throw;
        } catch (std::exception& e) {
            throw io_error(e.what());
        }

        return !l_exists;
    }

} // namespace util

#endif // _UTIL_PERSISTENT_ARRAY_HPP_
<|endoftext|>


<commit_before>#include <BALL/VIEW/WIDGETS/SDWidget.h>

#include <BALL/VIEW/KERNEL/iconLoader.h>

#include <BALL/KERNEL/bond.h>
#include <BALL/KERNEL/PTE.h>
#include <BALL/STRUCTURE/geometricProperties.h>
#include <BALL/STRUCTURE/sdGenerator.h>

#include <QtGui/QPainter>
#include <QtGui/QStyle>
#include <QtGui/QStyleOptionFocusRect>
#include <QtGui/QAction>

#include <QtGui/QFileDialog>
#include <QtGui/QImageWriter>

#include <set>

namespace BALL
{
	namespace VIEW
	{
		const char* SDWidget::Option::SHOW_HYDROGENS = "sd_widget_show_hydrogens";
		const bool  SDWidget::Default::SHOW_HYDROGENS = false;

		SDWidget::SDWidget(QWidget *parent, bool show_hydrogens)
			: QWidget(parent)
		{
			setup_();

			options[SDWidget::Option::SHOW_HYDROGENS] = show_hydrogens;
		}

		SDWidget::SDWidget(const System& system, QWidget *parent)
			: QWidget(parent)
		{
			setup_();

			plot(system);
		}

		void SDWidget::setup_()
		{
			setDefaultOptions();
			setBackgroundRole(QPalette::Base);

			//Todo: Add a nice icon
			QAction* export_image = new QAction(tr("Export image"), this);

			export_image->setIcon(IconLoader::instance().getIcon("actions/document-save"));

			addAction(export_image);
			connect(export_image, SIGNAL(triggered()), this, SLOT(exportImage_()));
		}

		SDWidget::~SDWidget()
		{}

		void SDWidget::plot(const System& system, bool create_sd)
		{
			system_ = system;

			if (create_sd)
			{
				SDGenerator sdg;
				sdg.generateSD(system_);
			}

			update();
		}

		void SDWidget::paintEvent(QPaintEvent *)
		{
			drawFrame_();
			renderSD_(this);
		}

		void SDWidget::drawFrame_()
		{
			QPainter p(this);

			QStyleOptionFrame opt;
			opt.initFrom(this);
			opt.state |= QStyle::State_Sunken;
			QRect erase_area = rect();

			int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, this) + 1;
			erase_area.adjust(frameWidth, frameWidth, -frameWidth, -frameWidth);
			p.eraseRect(erase_area);
			style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, this);

			p.end();
		}

		void SDWidget::renderSD_(QPaintDevice* pd)
		{
			if(!pd)
			{
				return;
			}

			BoundingBoxProcessor bp;
			system_.apply(bp);
			Vector3 upper = bp.getUpper() + Vector3(5.,5.,5.);
			Vector3 lower = bp.getLower() - Vector3(5.,5.,5.);

			GeometricCenterProcessor gcp;
			system_.apply(gcp);
			Vector3 center = gcp.getCenter();

			float xscale = pd->width()  / (upper.x - lower.x);
			float yscale = pd->height() / (upper.y - lower.y);

			xscale = yscale = std::min(xscale, yscale);

			QPainter painter(pd);

			QPen pen(Qt::black, 3, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin);
			painter.setPen(pen);
			painter.setRenderHint(QPainter::Antialiasing, true);
			painter.translate(pd->width()/2, pd->height()/2);

		  QFont newFont = font();
 		  newFont.setPixelSize(12);
			painter.setFont(newFont);

			QFontMetrics fontMetrics(newFont);

			// check if hydrogen atoms should be shown!
			bool show_H = options.getBool(Option::SHOW_HYDROGENS);

			AtomIterator at_it = system_.beginAtom();
			std::set<Atom*> already_seen;
			for (; +at_it; ++at_it)
			{
				if ((at_it->getElement() == PTE[Element::H]) && !show_H) continue;
				already_seen.insert(&(*at_it));

				Atom::BondIterator b_it = at_it->beginBond();

				Vector3 from3d = at_it->getPosition() - center;
				QPointF from2d(from3d.x*xscale, from3d.y*yscale);

				for (; +b_it; ++b_it)
				{
					Atom* partner = b_it->getPartner(*at_it);

					if (
								 // treat each bond only once
								 (std::find(already_seen.begin(), already_seen.end(), partner) == already_seen.end())
								 // we don't draw hydrogens
							&& !((partner->getElement() == PTE[Element::H]) && !show_H)
						 )
					{
						Vector3 to3d = partner->getPosition() - center;
						QPointF to2d(to3d.x*xscale, to3d.y*yscale);
						QPointF shifted_from = from2d;

						// do we need to draw a character for the "to" atom?
						if (partner->getElement() != PTE[Element::C])
						{
							QRect br = fontMetrics.boundingRect(partner->getElement().getSymbol().c_str());
							QPointF label_pos(to2d.x() - br.width()/2, to2d.y() + br.height()/2 - 4);

							painter.drawText(label_pos, partner->getElement().getSymbol().c_str());

							QRectF bounding_box(to2d.x() - br.width()/2  - 3,
																	to2d.y() - br.height()/2 - 4,
																	br.width() + 6, br.height() + 6);
							to2d = getEndpoint_(bounding_box, to2d, from2d, false);

						}

						// and do we need to draw a character for the "from" atom?
						if (at_it->getElement() != PTE[Element::C])
						{
							QRect br = fontMetrics.boundingRect(at_it->getElement().getSymbol().c_str());

							QRectF bounding_box(from2d.x() - br.width()/2  - 3,
																	from2d.y() - br.height()/2 - 4,
																	br.width() + 6, br.height() + 6);
							shifted_from = getEndpoint_(bounding_box, to2d, from2d, true);
						}

						// do we need to draw a double bond?
						if (b_it->getOrder() == Bond::ORDER__DOUBLE)
						{
							// compute two lines, slightly shifted wrt the normal of this line
							QLineF bond_line  = QLineF(shifted_from, to2d);
							QLineF normal     = bond_line.normalVector();
							normal = normal.unitVector();

							QPointF shift;
							shift.setX(2*(normal.p2().x() - bond_line.p1().x()));
							shift.setY(2*(normal.p2().y() - bond_line.p1().y()));

							QLineF first_line = bond_line;
							first_line.translate(shift);

							shift.setX(-1.*shift.x());
							shift.setY(-1.*shift.y());

							QLineF second_line = bond_line;
							second_line.translate(shift);

							pen.setWidth(2);
							painter.setPen(pen);
							painter.drawLine(first_line);
							painter.drawLine(second_line);
							pen.setWidth(3);
							painter.setPen(pen);
						}
						else if (b_it->getOrder() == Bond::ORDER__TRIPLE)
						{
							// compute two lines, slightly shifted wrt the normal of this line
							QLineF bond_line  = QLineF(shifted_from, to2d);
							QLineF normal     = bond_line.normalVector();
							normal = normal.unitVector();

							QPointF shift;
							shift.setX(3*(normal.p2().x() - bond_line.p1().x()));
							shift.setY(3*(normal.p2().y() - bond_line.p1().y()));

							QLineF first_line = bond_line;
							first_line.translate(shift);

							shift.setX(-1.*shift.x());
							shift.setY(-1.*shift.y());

							QLineF second_line = bond_line;
							second_line.translate(shift);

							pen.setWidth(2);
							painter.setPen(pen);
							painter.drawLine(first_line);
							painter.drawLine(bond_line);
							painter.drawLine(second_line);
							pen.setWidth(3);
							painter.setPen(pen);
						}
						else // assume it's a single bond...
							painter.drawLine(shifted_from, to2d);
					}
				}
				// do we need to draw a character for the "from" atom?
				if (at_it->getElement() != PTE[Element::C])
				{
					QRect br = fontMetrics.boundingRect(at_it->getElement().getSymbol().c_str());
					QPointF label_pos(from2d.x() - br.width()/2, from2d.y() + br.height()/2 - 4);

					painter.drawText(label_pos, at_it->getElement().getSymbol().c_str());
				}
			}
		}

		QPointF SDWidget::getEndpoint_(QRectF& character_boundary, QPointF from, QPointF to, bool character_is_from)
		{
			// compute all relevant lines...

			// the line from "from" to "to" :-)
			QLineF line_from_to(from, to);

			// the upper part of the box
			QLineF upper(character_boundary.topLeft(), character_boundary.topRight());
			// the right part of the box
			QLineF right(character_boundary.topRight(), character_boundary.bottomRight());
			// the lower part of the box
			QLineF lower(character_boundary.bottomRight(), character_boundary.bottomLeft());
			// and finally the left part
			QLineF left(character_boundary.bottomLeft(), character_boundary.topLeft());

			// intersect them
			QPointF intersection_point;
			if (line_from_to.intersect(upper, &intersection_point) == QLineF::BoundedIntersection)
				return intersection_point;
			if (line_from_to.intersect(right, &intersection_point) == QLineF::BoundedIntersection)
				return intersection_point;
			if (line_from_to.intersect(lower, &intersection_point) == QLineF::BoundedIntersection)
				return intersection_point;
			if (line_from_to.intersect(left, &intersection_point) == QLineF::BoundedIntersection)
				return intersection_point;

			//If to and from are too close, the computed intersection is incorrect.
			//In this case just return the point not having the character
			return character_is_from ? from : to;
		}

		void SDWidget::clear()
		{
			system_.clear();
			update();
		}

		void SDWidget::setDefaultOptions()
		{
	 		options.setDefaultBool(SDWidget::Option::SHOW_HYDROGENS,
	 												 	 SDWidget::Default::SHOW_HYDROGENS);
		}

		void SDWidget::exportImage_()
		{
			QString file = QFileDialog::getSaveFileName(this, tr("Export image"), QString(), "Images (*.png *.xpm *.jpg *.bmp *.gif)");

			if(file != QString::null)
			{
				QImage image(width(), height(), QImage::Format_ARGB32);
				image.fill(0);
				renderSD_(&image);

				image.save(file);
			}
		}
	}
}
<commit_msg>Safeguard SDWidget against lines of width 0<commit_after>#include <BALL/VIEW/WIDGETS/SDWidget.h>

#include <BALL/VIEW/KERNEL/iconLoader.h>

#include <BALL/KERNEL/bond.h>
#include <BALL/KERNEL/PTE.h>
#include <BALL/STRUCTURE/geometricProperties.h>
#include <BALL/STRUCTURE/sdGenerator.h>

#include <QtGui/QPainter>
#include <QtGui/QStyle>
#include <QtGui/QStyleOptionFocusRect>
#include <QtGui/QAction>

#include <QtGui/QFileDialog>
#include <QtGui/QImageWriter>

#include <set>

namespace BALL
{
	namespace VIEW
	{
		const char* SDWidget::Option::SHOW_HYDROGENS = "sd_widget_show_hydrogens";
		const bool  SDWidget::Default::SHOW_HYDROGENS = false;

		SDWidget::SDWidget(QWidget *parent, bool show_hydrogens)
			: QWidget(parent)
		{
			setup_();

			options[SDWidget::Option::SHOW_HYDROGENS] = show_hydrogens;
		}

		SDWidget::SDWidget(const System& system, QWidget *parent)
			: QWidget(parent)
		{
			setup_();

			plot(system);
		}

		void SDWidget::setup_()
		{
			setDefaultOptions();
			setBackgroundRole(QPalette::Base);

			//Todo: Add a nice icon
			QAction* export_image = new QAction(tr("Export image"), this);

			export_image->setIcon(IconLoader::instance().getIcon("actions/document-save"));

			addAction(export_image);
			connect(export_image, SIGNAL(triggered()), this, SLOT(exportImage_()));
		}

		SDWidget::~SDWidget()
		{}

		void SDWidget::plot(const System& system, bool create_sd)
		{
			system_ = system;

			if (create_sd)
			{
				SDGenerator sdg;
				sdg.generateSD(system_);
			}

			update();
		}

		void SDWidget::paintEvent(QPaintEvent *)
		{
			drawFrame_();
			renderSD_(this);
		}

		void SDWidget::drawFrame_()
		{
			QPainter p(this);

			QStyleOptionFrame opt;
			opt.initFrom(this);
			opt.state |= QStyle::State_Sunken;
			QRect erase_area = rect();

			int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, this) + 1;
			erase_area.adjust(frameWidth, frameWidth, -frameWidth, -frameWidth);
			p.eraseRect(erase_area);
			style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, this);

			p.end();
		}

		void SDWidget::renderSD_(QPaintDevice* pd)
		{
			if(!pd)
			{
				return;
			}

			BoundingBoxProcessor bp;
			system_.apply(bp);
			Vector3 upper = bp.getUpper() + Vector3(5.,5.,5.);
			Vector3 lower = bp.getLower() - Vector3(5.,5.,5.);

			GeometricCenterProcessor gcp;
			system_.apply(gcp);
			Vector3 center = gcp.getCenter();

			float xscale = pd->width()  / (upper.x - lower.x);
			float yscale = pd->height() / (upper.y - lower.y);

			xscale = yscale = std::min(xscale, yscale);

			QPainter painter(pd);

			QPen pen(Qt::black, 3, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin);
			painter.setPen(pen);
			painter.setRenderHint(QPainter::Antialiasing, true);
			painter.translate(pd->width()/2, pd->height()/2);

		  QFont newFont = font();
 		  newFont.setPixelSize(12);
			painter.setFont(newFont);

			QFontMetrics fontMetrics(newFont);

			// check if hydrogen atoms should be shown!
			bool show_H = options.getBool(Option::SHOW_HYDROGENS);

			AtomIterator at_it = system_.beginAtom();
			std::set<Atom*> already_seen;
			for (; +at_it; ++at_it)
			{
				if ((at_it->getElement() == PTE[Element::H]) && !show_H) continue;
				already_seen.insert(&(*at_it));

				Atom::BondIterator b_it = at_it->beginBond();

				Vector3 from3d = at_it->getPosition() - center;
				QPointF from2d(from3d.x*xscale, from3d.y*yscale);

				for (; +b_it; ++b_it)
				{
					Atom* partner = b_it->getPartner(*at_it);

					if (
								 // treat each bond only once
								 (std::find(already_seen.begin(), already_seen.end(), partner) == already_seen.end())
								 // we don't draw hydrogens
							&& !((partner->getElement() == PTE[Element::H]) && !show_H)
						 )
					{
						Vector3 to3d = partner->getPosition() - center;
						QPointF to2d(to3d.x*xscale, to3d.y*yscale);
						QPointF shifted_from = from2d;

						// do we need to draw a character for the "to" atom?
						if (partner->getElement() != PTE[Element::C])
						{
							QRect br = fontMetrics.boundingRect(partner->getElement().getSymbol().c_str());
							QPointF label_pos(to2d.x() - br.width()/2, to2d.y() + br.height()/2 - 4);

							painter.drawText(label_pos, partner->getElement().getSymbol().c_str());

							QRectF bounding_box(to2d.x() - br.width()/2  - 3,
																	to2d.y() - br.height()/2 - 4,
																	br.width() + 6, br.height() + 6);
							to2d = getEndpoint_(bounding_box, to2d, from2d, false);

						}

						// and do we need to draw a character for the "from" atom?
						if (at_it->getElement() != PTE[Element::C])
						{
							QRect br = fontMetrics.boundingRect(at_it->getElement().getSymbol().c_str());

							QRectF bounding_box(from2d.x() - br.width()/2  - 3,
																	from2d.y() - br.height()/2 - 4,
																	br.width() + 6, br.height() + 6);
							shifted_from = getEndpoint_(bounding_box, to2d, from2d, true);
						}

						// don't draw if the points are too close to each other (Qt tends to crash if this happens...)
						if ((to2d - shifted_from).toPoint().manhattanLength() == 0)
							continue;

						// do we need to draw a double bond?
						if (b_it->getOrder() == Bond::ORDER__DOUBLE)
						{
							// compute two lines, slightly shifted wrt the normal of this line
							QLineF bond_line  = QLineF(shifted_from, to2d);
							QLineF normal     = bond_line.normalVector();
							normal = normal.unitVector();

							QPointF shift;
							shift.setX(2*(normal.p2().x() - bond_line.p1().x()));
							shift.setY(2*(normal.p2().y() - bond_line.p1().y()));

							QLineF first_line = bond_line;
							first_line.translate(shift);

							shift.setX(-1.*shift.x());
							shift.setY(-1.*shift.y());

							QLineF second_line = bond_line;
							second_line.translate(shift);

							pen.setWidth(2);
							painter.setPen(pen);
							painter.drawLine(first_line);
							painter.drawLine(second_line);
							pen.setWidth(3);
							painter.setPen(pen);
						}
						else if (b_it->getOrder() == Bond::ORDER__TRIPLE)
						{
							// compute two lines, slightly shifted wrt the normal of this line
							QLineF bond_line  = QLineF(shifted_from, to2d);
							QLineF normal     = bond_line.normalVector();
							normal = normal.unitVector();

							QPointF shift;
							shift.setX(3*(normal.p2().x() - bond_line.p1().x()));
							shift.setY(3*(normal.p2().y() - bond_line.p1().y()));

							QLineF first_line = bond_line;
							first_line.translate(shift);

							shift.setX(-1.*shift.x());
							shift.setY(-1.*shift.y());

							QLineF second_line = bond_line;
							second_line.translate(shift);

							pen.setWidth(2);
							painter.setPen(pen);
							painter.drawLine(first_line);
							painter.drawLine(bond_line);
							painter.drawLine(second_line);
							pen.setWidth(3);
							painter.setPen(pen);
						}
						else // assume it's a single bond...
							painter.drawLine(shifted_from, to2d);
					}
				}
				// do we need to draw a character for the "from" atom?
				if (at_it->getElement() != PTE[Element::C])
				{
					QRect br = fontMetrics.boundingRect(at_it->getElement().getSymbol().c_str());
					QPointF label_pos(from2d.x() - br.width()/2, from2d.y() + br.height()/2 - 4);

					painter.drawText(label_pos, at_it->getElement().getSymbol().c_str());
				}
			}
		}

		QPointF SDWidget::getEndpoint_(QRectF& character_boundary, QPointF from, QPointF to, bool character_is_from)
		{
			// compute all relevant lines...

			// the line from "from" to "to" :-)
			QLineF line_from_to(from, to);

			// the upper part of the box
			QLineF upper(character_boundary.topLeft(), character_boundary.topRight());
			// the right part of the box
			QLineF right(character_boundary.topRight(), character_boundary.bottomRight());
			// the lower part of the box
			QLineF lower(character_boundary.bottomRight(), character_boundary.bottomLeft());
			// and finally the left part
			QLineF left(character_boundary.bottomLeft(), character_boundary.topLeft());

			// intersect them
			QPointF intersection_point;
			if (line_from_to.intersect(upper, &intersection_point) == QLineF::BoundedIntersection)
				return intersection_point;
			if (line_from_to.intersect(right, &intersection_point) == QLineF::BoundedIntersection)
				return intersection_point;
			if (line_from_to.intersect(lower, &intersection_point) == QLineF::BoundedIntersection)
				return intersection_point;
			if (line_from_to.intersect(left, &intersection_point) == QLineF::BoundedIntersection)
				return intersection_point;

			//If to and from are too close, the computed intersection is incorrect.
			//In this case just return the point not having the character
			return character_is_from ? from : to;
		}

		void SDWidget::clear()
		{
			system_.clear();
			update();
		}

		void SDWidget::setDefaultOptions()
		{
	 		options.setDefaultBool(SDWidget::Option::SHOW_HYDROGENS,
	 												 	 SDWidget::Default::SHOW_HYDROGENS);
		}

		void SDWidget::exportImage_()
		{
			QString file = QFileDialog::getSaveFileName(this, tr("Export image"), QString(), "Images (*.png *.xpm *.jpg *.bmp *.gif)");

			if(file != QString::null)
			{
				QImage image(width(), height(), QImage::Format_ARGB32);
				image.fill(0);
				renderSD_(&image);

				image.save(file);
			}
		}
	}
}
<|endoftext|>


<commit_before>#ifndef V_SMC_CORE_PARTICLE_HPP
#define V_SMC_CORE_PARTICLE_HPP

#include <vector>
#include <cmath>
#include <cstddef>
#include <Eigen/Dense>
#include <Random123/aes.h>
#include <Random123/ars.h>
#include <Random123/philox.h>
#include <Random123/threefry.h>
#include <Random123/conventional/Engine.hpp>
#include <vSMC/internal/config.hpp>
#include <vSMC/internal/random.hpp>

/// The Parallel RNG (based on Rand123) seed, unsigned
#ifndef V_SMC_CRNG_SEED
#define V_SMC_CRNG_SEED 0xdeadbeefU
#endif // V_SMC_CRNG_SEED

/// The Parallel RNG (based on Rand123) type, philox or threefry
#ifndef V_SMC_CRNG_TYPE
#define V_SMC_CRNG_TYPE r123::Threefry4x64
#endif // V_SMC_CRNG_TYPE

namespace vSMC {

template <typename T> class Sampler;

/// Resample scheme
enum ResampleScheme {MULTINOMIAL, RESIDUAL, STRATIFIED, SYSTEMATIC,
    RESIDUAL_STRATIFIED, RESIDUAL_SYSTEMATIC};

/// \brief Particle class
///
/// Particle class store the particle set and arrays of weights and log
/// weights. It provides access to particle values as well as weights. It
/// computes and manages resources for ESS, resampling, etc, tasks unique to
/// each iteration.
template <typename T>
class Particle
{
    public :

    typedef r123::Engine< V_SMC_CRNG_TYPE > rng_type;
    typedef rng_type::result_type seed_type;

    /// \brief Construct a Particle object with given number of particles
    ///
    /// \param N The number of particles
    /// \param seed The seed to the parallel RNG system
    /// \param sampler The poiter to the Sampler which this particle set
    /// belongs to
    Particle (std::size_t N, rng_type::result_type seed = V_SMC_CRNG_SEED,
            const Sampler<T> *sampler = NULL) :
        size_(N), value_(N), sampler_(sampler),
        weight_(N), log_weight_(N), inc_weight_(N), replication_(N),
        ess_(0), resampled_(false), zconst_(0), prng_(N)
    {
        reset_prng(seed);
        weight_.setConstant(1.0 / size_);
        log_weight_.setConstant(0);
    }

    /// \brief Size of the particle set
    ///
    /// \return The number of particles
    std::size_t size () const
    {
        return size_;
    }

    /// \brief Read and write access to particle values
    ///
    /// \return A reference to the particle values, type (T &)
    ///
    /// \note The Particle class guarantee that during the life type of the
    /// object, the reference returned by this member will no be a dangle
    /// handler.
    T &value ()
    {
        return value_;
    }

    /// \brief Read only access to particle values
    ///
    /// \return A const reference to the particle values
    const T &value () const
    {
        return value_;
    }

    /// \brief Read only access to the weights
    ///
    /// \return A const pointer to the weights
    ///
    /// \note The Particle class guarantee that during the life type of the
    /// object, the pointer returned by this always valid and point to the
    /// same address
    const double *weight_ptr () const
    {
        return weight_.data();
    }

    /// \brief Read only access to the log weights
    ///
    /// \return A const pointer to the log weights
    const double *log_weight_ptr () const
    {
        return log_weight_.data();
    }

    const Eigen::VectorXd &weight () const
    {
        return weight_;
    }

    const Eigen::VectorXd &log_weight () const
    {
        return log_weight_;
    }

    /// \brief Set the log weights
    ///
    /// \param new_weight New log weights
    /// \param delta A multiplier appiled to new_weight
    void set_log_weight (const double *new_weight, double delta = 1)
    {
        Eigen::Map<const Eigen::VectorXd> w(new_weight, size_);
        log_weight_ = delta * w;
        set_weight();
    }

    /// \brief Add to the log weights
    ///
    /// \param inc_weight Incremental log weights
    /// \param delta A multiplier applied to inc_weight
    /// \param add_zconst Whether this incremental weights should contribute
    /// the esitmates of normalizing constants
    void add_log_weight (const double *inc_weight, double delta = 1,
            bool add_zconst = true)
    {
        Eigen::Map<const Eigen::VectorXd> w(inc_weight, size_);
        if (add_zconst) {
            inc_weight_ = (delta * w).array().exp();
            zconst_ += std::log(weight_.dot(inc_weight_));
        }
        log_weight_ += delta * w;
        set_weight();
    }

    /// \brief The ESS (Effective Sample Size)
    ///
    /// \return The value of ESS for current particle set
    double ess () const
    {
        return ess_;
    }

    /// \brief Get indicator of resampling
    ///
    /// \return A bool value, \b true if the current iteration was resampled
    bool resampled () const
    {
        return resampled_;
    }

    /// \brief Set indicator of resampling
    ///
    /// \param resampled \b true if the current iteration was resampled
    void resampled (bool resampled)
    {
        resampled_ = resampled;
    }

    /// \brief Read only access to the sampler containing this particle set
    ///
    /// \return A const reference to the sampler containing this particle set
    const Sampler<T> &sampler () const
    {
        return *sampler_;
    }

    /// \brief Get the value of SMC normalizing constant
    ///
    /// \return SMC normalizng constant estimate
    double zconst () const
    {
        return zconst_;
    }

    /// \brief Reset the value of SMC normalizing constant
    void reset_zconst ()
    {
        zconst_ = 0;
    }

    /// \brief Perform resampling
    ///
    /// \param scheme The resampling scheme, see ResamplingScheme
    void resample (ResampleScheme scheme)
    {
        switch (scheme) {
            case MULTINOMIAL :
                resample_multinomial();
                break;
            case RESIDUAL :
                resample_residual();
                break;
            case STRATIFIED :
                resample_stratified();
                break;
            case SYSTEMATIC :
                resample_systematic();
                break;
            case RESIDUAL_STRATIFIED :
                resample_residual_stratified ();
                break;
            default :
                resample_stratified();
                break;
        }
        resample_do();
    }

    rng_type &prng (std::size_t id)
    {
        return prng_[id];
    }

    void reset_prng (rng_type::result_type seed)
    {
        for (std::size_t i = 0; i != size_; ++i)
            prng_[i] = rng_type(seed + i);
    }

    private :

    std::size_t size_;
    T value_;
    const Sampler<T> *sampler_;

    Eigen::VectorXd weight_;
    Eigen::VectorXd log_weight_;
    Eigen::VectorXd inc_weight_;
    Eigen::VectorXi replication_;

    double ess_;
    bool resampled_;
    double zconst_;

    std::vector<rng_type> prng_;

    void set_weight ()
    {
        double max_weight = log_weight_.maxCoeff();
        log_weight_ = log_weight_.array() - max_weight;
        weight_ = log_weight_.array().exp();
        double sum = weight_.sum();
        weight_ *= 1 / sum;
        ess_ = 1 / weight_.squaredNorm();
    }

    void resample_multinomial ()
    {
        weight2replication(size_);
    }

    void resample_residual ()
    {
        // Reuse weight and log_weight. weight: act as the fractional part of
        // N * weight. log_weight: act as the integral part of N * weight.
        // They all will be reset to equal weights after resampling.  So it is
        // safe to modify them here.
        for (std::size_t i = 0; i != size_; ++i)
            weight_[i] = std::modf(size_ * weight_[i], log_weight_.data() + i);
        weight2replication(weight_.sum());
        for (std::size_t i = 0; i != size_; ++i)
            replication_[i] += log_weight_[i];
    }

    void resample_stratified ()
    {
        replication_.setConstant(0);
        std::size_t j = 0;
        std::size_t k = 0;
        internal::uniform_real_distribution<> unif(0,1);
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size_) {
            while (j < cw * size_ - u && j != size_) {
                ++replication_[k];
                u = unif(prng_[j++]);
            }
            cw += weight_[++k];
        }
    }

    void resample_systematic ()
    {
        replication_.setConstant(0);
        std::size_t j = 0;
        std::size_t k = 0;
        internal::uniform_real_distribution<> unif(0,1);
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size_) {
            while (j < cw * size_ - u && j != size_) {
                ++replication_[k];
		++j;
            }
            cw += weight_[++k];
        }
    }

    void resample_residual_stratified ()
    {
        replication_.setConstant(0);
        for (std::size_t i = 0; i != size_; ++i)
            weight_[i] = std::modf(size_ * weight_[i], log_weight_.data() + i);
        std::size_t size = weight_.sum();
        weight_ /= size;
        std::size_t j = 0;
        std::size_t k = 0;
        internal::uniform_real_distribution<> unif(0,1);
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size) {
            while (j < cw * size - u && j != size) {
                ++replication_[k];
                u = unif(prng_[j++]);
            }
            cw += weight_[++k];
        }
        for (std::size_t i = 0; i != size_; ++i)
            replication_[i] += log_weight_[i];
    }

    void resample_residual_systematic ()
    {
        replication_.setConstant(0);
        for (std::size_t i = 0; i != size_; ++i)
            weight_[i] = std::modf(size_ * weight_[i], log_weight_.data() + i);
        std::size_t size = weight_.sum();
        weight_ /= size;
        std::size_t j = 0;
        std::size_t k = 0;
        internal::uniform_real_distribution<> unif(0,1);
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size) {
            while (j < cw * size - u && j != size) {
                ++replication_[k];
		++j;
            }
            cw += weight_[++k];
        }
        for (std::size_t i = 0; i != size_; ++i)
            replication_[i] += log_weight_[i];
    }

    void weight2replication (std::size_t size)
    {
        double tp = weight_.sum();
        double sum_p = 0;
        std::size_t sum_n = 0;
        replication_.setConstant(0);
        for (std::size_t i = 0; i != size_; ++i) {
            if (sum_n < size && weight_[i] > 0) {
                internal::binomial_distribution<>
                    binom(size - sum_n, weight_[i] / (tp - sum_p));
                replication_[i] = binom(prng_[i]);
            }
            sum_p += weight_[i];
            sum_n += replication_[i];
        }
    }

    void resample_do ()
    {
	// Some times the nuemrical round error can cause the total childs
	// differ from number of particles
	std::size_t sum = replication_.sum();
	if (sum != size_) {
            Eigen::VectorXd::Index id_max;
            replication_.maxCoeff(&id_max);
            replication_[id_max] += size_ - sum;
	}

        std::size_t from = 0;
        std::size_t time = 0;
        for (std::size_t to = 0; to != size_; ++to) {
            if (!replication_[to]) {
                // replication_[to] has zero child, copy from elsewhere
                if (replication_[from] - time <= 1) {
                    // only 1 child left on replication_[from]
                    time = 0;
                    do // move from to some position with at least 2 children
                        ++from;
                    while (replication_[from] < 2);
                }
                value_.copy(from, to);
                ++time;
            }
        }

        ess_ = size_;
        weight_.setConstant(1.0 / size_);
        log_weight_.setConstant(0);
    }
}; // class Particle

} // namespace vSMC

#endif // V_SMC_CORE_PARTICLE_HPP
<commit_msg>workaround of possible 1offset situation in resampling due to numerical round<commit_after>#ifndef V_SMC_CORE_PARTICLE_HPP
#define V_SMC_CORE_PARTICLE_HPP

#include <vector>
#include <cmath>
#include <cstddef>
#include <Eigen/Dense>
#include <Random123/aes.h>
#include <Random123/ars.h>
#include <Random123/philox.h>
#include <Random123/threefry.h>
#include <Random123/conventional/Engine.hpp>
#include <vSMC/internal/config.hpp>
#include <vSMC/internal/random.hpp>

/// The Parallel RNG (based on Rand123) seed, unsigned
#ifndef V_SMC_CRNG_SEED
#define V_SMC_CRNG_SEED 0xdeadbeefU
#endif // V_SMC_CRNG_SEED

/// The Parallel RNG (based on Rand123) type, philox or threefry
#ifndef V_SMC_CRNG_TYPE
#define V_SMC_CRNG_TYPE r123::Threefry4x64
#endif // V_SMC_CRNG_TYPE

namespace vSMC {

template <typename T> class Sampler;

/// Resample scheme
enum ResampleScheme {MULTINOMIAL, RESIDUAL, STRATIFIED, SYSTEMATIC,
    RESIDUAL_STRATIFIED, RESIDUAL_SYSTEMATIC};

/// \brief Particle class
///
/// Particle class store the particle set and arrays of weights and log
/// weights. It provides access to particle values as well as weights. It
/// computes and manages resources for ESS, resampling, etc, tasks unique to
/// each iteration.
template <typename T>
class Particle
{
    public :

    typedef r123::Engine< V_SMC_CRNG_TYPE > rng_type;
    typedef rng_type::result_type seed_type;

    /// \brief Construct a Particle object with given number of particles
    ///
    /// \param N The number of particles
    /// \param seed The seed to the parallel RNG system
    /// \param sampler The poiter to the Sampler which this particle set
    /// belongs to
    Particle (std::size_t N, rng_type::result_type seed = V_SMC_CRNG_SEED,
            const Sampler<T> *sampler = NULL) :
        size_(N), value_(N), sampler_(sampler),
        weight_(N), log_weight_(N), inc_weight_(N), replication_(N),
        ess_(0), resampled_(false), zconst_(0), prng_(N)
    {
        reset_prng(seed);
        weight_.setConstant(1.0 / size_);
        log_weight_.setConstant(0);
    }

    /// \brief Size of the particle set
    ///
    /// \return The number of particles
    std::size_t size () const
    {
        return size_;
    }

    /// \brief Read and write access to particle values
    ///
    /// \return A reference to the particle values, type (T &)
    ///
    /// \note The Particle class guarantee that during the life type of the
    /// object, the reference returned by this member will no be a dangle
    /// handler.
    T &value ()
    {
        return value_;
    }

    /// \brief Read only access to particle values
    ///
    /// \return A const reference to the particle values
    const T &value () const
    {
        return value_;
    }

    /// \brief Read only access to the weights
    ///
    /// \return A const pointer to the weights
    ///
    /// \note The Particle class guarantee that during the life type of the
    /// object, the pointer returned by this always valid and point to the
    /// same address
    const double *weight_ptr () const
    {
        return weight_.data();
    }

    /// \brief Read only access to the log weights
    ///
    /// \return A const pointer to the log weights
    const double *log_weight_ptr () const
    {
        return log_weight_.data();
    }

    const Eigen::VectorXd &weight () const
    {
        return weight_;
    }

    const Eigen::VectorXd &log_weight () const
    {
        return log_weight_;
    }

    /// \brief Set the log weights
    ///
    /// \param new_weight New log weights
    /// \param delta A multiplier appiled to new_weight
    void set_log_weight (const double *new_weight, double delta = 1)
    {
        Eigen::Map<const Eigen::VectorXd> w(new_weight, size_);
        log_weight_ = delta * w;
        set_weight();
    }

    /// \brief Add to the log weights
    ///
    /// \param inc_weight Incremental log weights
    /// \param delta A multiplier applied to inc_weight
    /// \param add_zconst Whether this incremental weights should contribute
    /// the esitmates of normalizing constants
    void add_log_weight (const double *inc_weight, double delta = 1,
            bool add_zconst = true)
    {
        Eigen::Map<const Eigen::VectorXd> w(inc_weight, size_);
        if (add_zconst) {
            inc_weight_ = (delta * w).array().exp();
            zconst_ += std::log(weight_.dot(inc_weight_));
        }
        log_weight_ += delta * w;
        set_weight();
    }

    /// \brief The ESS (Effective Sample Size)
    ///
    /// \return The value of ESS for current particle set
    double ess () const
    {
        return ess_;
    }

    /// \brief Get indicator of resampling
    ///
    /// \return A bool value, \b true if the current iteration was resampled
    bool resampled () const
    {
        return resampled_;
    }

    /// \brief Set indicator of resampling
    ///
    /// \param resampled \b true if the current iteration was resampled
    void resampled (bool resampled)
    {
        resampled_ = resampled;
    }

    /// \brief Read only access to the sampler containing this particle set
    ///
    /// \return A const reference to the sampler containing this particle set
    const Sampler<T> &sampler () const
    {
        return *sampler_;
    }

    /// \brief Get the value of SMC normalizing constant
    ///
    /// \return SMC normalizng constant estimate
    double zconst () const
    {
        return zconst_;
    }

    /// \brief Reset the value of SMC normalizing constant
    void reset_zconst ()
    {
        zconst_ = 0;
    }

    /// \brief Perform resampling
    ///
    /// \param scheme The resampling scheme, see ResamplingScheme
    void resample (ResampleScheme scheme)
    {
        switch (scheme) {
            case MULTINOMIAL :
                resample_multinomial();
                break;
            case RESIDUAL :
                resample_residual();
                break;
            case STRATIFIED :
                resample_stratified();
                break;
            case SYSTEMATIC :
                resample_systematic();
                break;
            case RESIDUAL_STRATIFIED :
                resample_residual_stratified ();
                break;
            default :
                resample_stratified();
                break;
        }
        resample_do();
    }

    rng_type &prng (std::size_t id)
    {
        return prng_[id];
    }

    void reset_prng (rng_type::result_type seed)
    {
        for (std::size_t i = 0; i != size_; ++i)
            prng_[i] = rng_type(seed + i);
    }

    private :

    std::size_t size_;
    T value_;
    const Sampler<T> *sampler_;

    Eigen::VectorXd weight_;
    Eigen::VectorXd log_weight_;
    Eigen::VectorXd inc_weight_;
    Eigen::VectorXi replication_;

    double ess_;
    bool resampled_;
    double zconst_;

    std::vector<rng_type> prng_;

    void set_weight ()
    {
        double max_weight = log_weight_.maxCoeff();
        log_weight_ = log_weight_.array() - max_weight;
        weight_ = log_weight_.array().exp();
        double sum = weight_.sum();
        weight_ *= 1 / sum;
        ess_ = 1 / weight_.squaredNorm();
    }

    void resample_multinomial ()
    {
        weight2replication(size_);
    }

    void resample_residual ()
    {
        // Reuse weight and log_weight. weight: act as the fractional part of
        // N * weight. log_weight: act as the integral part of N * weight.
        // They all will be reset to equal weights after resampling.  So it is
        // safe to modify them here.
        for (std::size_t i = 0; i != size_; ++i)
            weight_[i] = std::modf(size_ * weight_[i], log_weight_.data() + i);
        weight2replication(weight_.sum());
        for (std::size_t i = 0; i != size_; ++i)
            replication_[i] += log_weight_[i];
    }

    void resample_stratified ()
    {
        replication_.setConstant(0);
        std::size_t j = 0;
        std::size_t k = 0;
        internal::uniform_real_distribution<> unif(0,1);
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size_) {
            while (j < cw * size_ - u && j != size_) {
                ++replication_[k];
                u = unif(prng_[j++]);
            }
            if (k == size_ - 1)
                break;
            cw += weight_[++k];
        }
    }

    void resample_systematic ()
    {
        replication_.setConstant(0);
        std::size_t j = 0;
        std::size_t k = 0;
        internal::uniform_real_distribution<> unif(0,1);
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size_) {
            while (j < cw * size_ - u && j != size_) {
                ++replication_[k];
		++j;
            }
            if (k == size_ - 1)
                break;
            cw += weight_[++k];
        }
    }

    void resample_residual_stratified ()
    {
        replication_.setConstant(0);
        for (std::size_t i = 0; i != size_; ++i)
            weight_[i] = std::modf(size_ * weight_[i], log_weight_.data() + i);
        std::size_t size = weight_.sum();
        weight_ /= size;
        std::size_t j = 0;
        std::size_t k = 0;
        internal::uniform_real_distribution<> unif(0,1);
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size) {
            while (j < cw * size - u && j != size) {
                ++replication_[k];
                u = unif(prng_[j++]);
            }
            if (k == size_ - 1)
                break;
            cw += weight_[++k];
        }
        for (std::size_t i = 0; i != size_; ++i)
            replication_[i] += log_weight_[i];
    }

    void resample_residual_systematic ()
    {
        replication_.setConstant(0);
        for (std::size_t i = 0; i != size_; ++i)
            weight_[i] = std::modf(size_ * weight_[i], log_weight_.data() + i);
        std::size_t size = weight_.sum();
        weight_ /= size;
        std::size_t j = 0;
        std::size_t k = 0;
        internal::uniform_real_distribution<> unif(0,1);
        double u = unif(prng_[0]);
        double cw = weight_[0];
        while (j != size) {
            while (j < cw * size - u && j != size) {
                ++replication_[k];
		++j;
            }
            if (k == size_ - 1)
                break;
            cw += weight_[++k];
        }
        for (std::size_t i = 0; i != size_; ++i)
            replication_[i] += log_weight_[i];
    }

    void weight2replication (std::size_t size)
    {
        double tp = weight_.sum();
        double sum_p = 0;
        std::size_t sum_n = 0;
        replication_.setConstant(0);
        for (std::size_t i = 0; i != size_; ++i) {
            if (sum_n < size && weight_[i] > 0) {
                internal::binomial_distribution<>
                    binom(size - sum_n, weight_[i] / (tp - sum_p));
                replication_[i] = binom(prng_[i]);
            }
            sum_p += weight_[i];
            sum_n += replication_[i];
        }
    }

    void resample_do ()
    {
	// Some times the nuemrical round error can cause the total childs
	// differ from number of particles
	std::size_t sum = replication_.sum();
	if (sum != size_) {
            Eigen::VectorXd::Index id_max;
            replication_.maxCoeff(&id_max);
            replication_[id_max] += size_ - sum;
	}

        std::size_t from = 0;
        std::size_t time = 0;
        for (std::size_t to = 0; to != size_; ++to) {
            if (!replication_[to]) {
                // replication_[to] has zero child, copy from elsewhere
                if (replication_[from] - time <= 1) {
                    // only 1 child left on replication_[from]
                    time = 0;
                    do // move from to some position with at least 2 children
                        ++from;
                    while (replication_[from] < 2);
                }
                value_.copy(from, to);
                ++time;
            }
        }

        ess_ = size_;
        weight_.setConstant(1.0 / size_);
        log_weight_.setConstant(0);
    }
}; // class Particle

} // namespace vSMC

#endif // V_SMC_CORE_PARTICLE_HPP
<|endoftext|>


<commit_before>#include "GUM_Sprite2.h"
#include "GUM_DTex.h"
#include "RenderTargetMgr.h"
#include "RenderTarget.h"

#include <sprite2/S2_RenderTargetMgr.h>
#include <sprite2/S2_RenderTarget.h>
#include <sprite2/S2_Sprite.h>
#include <sprite2/S2_Symbol.h>
#include <sprite2/RenderParams.h>
#include <sprite2/DrawNode.h>
#include <dtex2/DebugDraw.h>

#include <stdint.h>

namespace gum
{

SINGLETON_DEFINITION(Sprite2);

Sprite2::Sprite2()
{
}

void Sprite2::DebugDraw() const
{
	s2::RenderTargetMgr* RT = s2::RenderTargetMgr::Instance();
	for (int i = 0; i < 4; ++i) {
		int texid = RT->GetTexID(i);
		if (texid < 0) {
			continue;
		}
		dtex::DebugDraw::Draw(texid, i + 1);
	}
}

static void prepare_render_params(const s2::RenderParams& parent,
								  const s2::Sprite* spr,
								  s2::RenderParams& child)
{
	if (parent.IsDisableDTexC2() || spr->IsDTexDisable()) {
		child.SetDisableDTexC2(true);
	}
}

static void
dtex_sym_insert(UID uid, const sm::rect& bounding, int tex_id, int tex_w, int tex_h)
{
	DTex* dtex = DTex::Instance();
	dtex->LoadSymStart();

	sm::i16_rect r_dst;
	r_dst.xmin = bounding.xmin + tex_w * 0.5f;
	r_dst.ymin = bounding.ymin + tex_h * 0.5f;
	r_dst.xmax = bounding.xmax + tex_w * 0.5f;
	r_dst.ymax = bounding.ymax + tex_h * 0.5f;

	dtex->LoadSymbol(uid, tex_id, tex_w, tex_h, r_dst, 1, 0, 0);

	dtex->LoadSymFinish();
}

static const float*
dtex_sym_query(UID uid, int* tex_id)
{
	return DTex::Instance()->QuerySymbol(uid, tex_id);
}

static uint64_t
get_sym_uid(const s2::Symbol* sym)
{
	return ResourceUID::BinNode(sym->GetID());
}

static uint64_t
get_spr_uid(const s2::Sprite* spr)
{
	return ResourceUID::Sprite(spr->GetID());
}

static uint64_t
get_actor_uid(const s2::Actor* actor)
{
	return ResourceUID::Actor(actor);
}

static s2::RenderTarget*
fetch_screen()
{
	return RenderTargetMgr::Instance()->Fetch();
}

static void
return_screen(s2::RenderTarget* rt)
{
	RenderTargetMgr::Instance()->Return(dynamic_cast<gum::RenderTarget*>(rt));
}

void Sprite2::Init()
{
	s2::DrawNode::InitDTexCB(prepare_render_params, dtex_sym_insert, dtex_sym_query);
	s2::DrawNode::InitUIDCB(get_sym_uid, get_spr_uid, get_actor_uid);

	s2::RenderTargetMgr::Instance()->InitScreenCB(fetch_screen, return_screen);
}

}<commit_msg>fix compile<commit_after>#include "GUM_Sprite2.h"
#include "GUM_DTex.h"
#include "RenderTargetMgr.h"
#include "RenderTarget.h"

#include <sprite2/S2_RenderTargetMgr.h>
#include <sprite2/S2_RenderTarget.h>
#include <sprite2/S2_Sprite.h>
#include <sprite2/S2_Symbol.h>
#include <sprite2/RenderParams.h>
#include <sprite2/DrawNode.h>
#include <dtex2/DebugDraw.h>

#include <stdint.h>

namespace gum
{

SINGLETON_DEFINITION(Sprite2);

Sprite2::Sprite2()
{
}

void Sprite2::DebugDraw() const
{
	s2::RenderTargetMgr* RT = s2::RenderTargetMgr::Instance();
	for (int i = 0; i < 4; ++i) {
		int texid = RT->GetTexID(i);
		if (texid < 0) {
			continue;
		}
		dtex::DebugDraw::Draw(texid, i + 1);
	}
}

static void prepare_render_params(const s2::RenderParams& parent,
								  const s2::Sprite* spr,
								  s2::RenderParams& child)
{
	if (parent.IsDisableDTexC2() || spr->IsDTexDisable()) {
		child.SetDisableDTexC2(true);
	}
}

static void
dtex_sym_insert(UID uid, const sm::rect& bounding, int tex_id, int tex_w, int tex_h)
{
	DTex* dtex = DTex::Instance();
	dtex->LoadSymStart();

	sm::i16_rect r_dst;
	r_dst.xmin = bounding.xmin + tex_w * 0.5f;
	r_dst.ymin = bounding.ymin + tex_h * 0.5f;
	r_dst.xmax = bounding.xmax + tex_w * 0.5f;
	r_dst.ymax = bounding.ymax + tex_h * 0.5f;

	dtex->LoadSymbol(uid, tex_id, tex_w, tex_h, r_dst, 1, 0, 0);

	dtex->LoadSymFinish();
}

static const float*
dtex_sym_query(UID uid, int* tex_id)
{
	return DTex::Instance()->QuerySymbol(uid, tex_id);
}

static uint64_t
get_sym_uid(const s2::Symbol* sym)
{
	return ResourceUID::BinNode(sym->GetID());
}

static uint64_t
get_spr_uid(const s2::Sprite* spr)
{
	return ResourceUID::Sprite(spr->GetID());
}

static uint64_t
get_actor_uid(const s2::Actor* actor)
{
	return ResourceUID::Actor(actor);
}

static s2::RenderTarget*
fetch_screen()
{
	return RenderTargetMgr::Instance()->Fetch();
}

static void
return_screen(s2::RenderTarget* rt)
{
	RenderTargetMgr::Instance()->Return(static_cast<gum::RenderTarget*>(rt));
}

void Sprite2::Init()
{
	s2::DrawNode::InitDTexCB(prepare_render_params, dtex_sym_insert, dtex_sym_query);
	s2::DrawNode::InitUIDCB(get_sym_uid, get_spr_uid, get_actor_uid);

	s2::RenderTargetMgr::Instance()->InitScreenCB(fetch_screen, return_screen);
}

}<|endoftext|>


<commit_before>
#include <GUIDOEngine/GUIDOEngine.h>
#include <GUIDOEngine/GDeviceOSX.h>
#include <GUIDOEngine/GFontOSX.h>
#include <GUIDOEngine/GMemoryDeviceOSX.h>
#include <GUIDOEngine/GPrinterDeviceOSX.h>
#include <GUIDOEngine/GSystemOSX.h>
#include <GUIDOEngine/SVGSystem.h>

#include <guido-c.h>

// const char *byte_to_binary(int x);

const char* GuidoCGetVersion()
{
        return "0.5.0";
}

// System

GuidoCGraphicSystem * GuidoCCreateSystem()
{
        fprintf(stderr, "Creating system!\n");

        // FIXME need to pass CGContextRef as first param here
        /*
           In a WX paint handler:
            wxPaintDC MyDC(this);
            CGContextRef context = ((wxMacCGContext*)MyDC.GetGraphicContext())->GetNativeContext();
         */
    	GuidoCGraphicSystem * system = (GuidoCGraphicSystem*) new GSystemOSX(0,0);
        return system;
}

uint32_t* GuidoCNativePaint(GuidoCGraphicDevice * device)
{
        CGContextRef context = CGContextRef(((VGDevice*) device)->GetNativeContext());
        uint32_t* data = (uint32_t*)::CGBitmapContextGetData(context);
        return data;
}

void GuidoCPrintDeviceInfo(GuidoCGraphicDevice * device)
{
        CGContextRef context = CGContextRef(((VGDevice*) device)->GetNativeContext());
        uint32_t* data = (uint32_t*)::CGBitmapContextGetData(context);

        int m = CGBitmapContextGetBitsPerComponent(context);
        int n = CGBitmapContextGetBitsPerPixel(context);
        int w = CGBitmapContextGetWidth(context);
        int h = CGBitmapContextGetHeight(context);

        unsigned i = CGBitmapContextGetBitmapInfo(context);
        unsigned a = CGBitmapContextGetAlphaInfo(context);

        fprintf(stderr, "Data format: bitsPerComp=%d bitsPerPixel=%d width=%d height=%d\n", m, n, w, h);
        // fprintf(stderr, "Info: %s\n", byte_to_binary(i));
        // fprintf(stderr, "Alpha info: %s\n", byte_to_binary(a));

        if (i & kCGBitmapFloatComponents)   fprintf(stderr, "The components are floats\n");
        if ((i & kCGBitmapByteOrderMask) == kCGBitmapByteOrderDefault) fprintf(stderr, "The byte order is the default\n");
        if ((i & kCGBitmapByteOrderMask) == kCGBitmapByteOrder16Little) fprintf(stderr, "The byte order is 16LE\n");
        if ((i & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Little) fprintf(stderr, "The byte order is 32LE\n");
        if ((i & kCGBitmapByteOrderMask) == kCGBitmapByteOrder16Big)    fprintf(stderr, "The byte order is 16BE\n");
        if ((i & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Big)    fprintf(stderr, "The byte order is 32BE\n");

        if (a == kCGImageAlphaNone)                  fprintf(stderr, "Alpha: kCGImageAlphaNone\n");
        if (a == kCGImageAlphaPremultipliedLast)     fprintf(stderr, "Alpha: kCGImageAlphaPremultipliedLast\n");
        if (a == kCGImageAlphaPremultipliedFirst)    fprintf(stderr, "Alpha: kCGImageAlphaPremultipliedFirst\n");
        if (a == kCGImageAlphaLast)                  fprintf(stderr, "Alpha: kCGImageAlphaLast\n");
        if (a == kCGImageAlphaFirst)                 fprintf(stderr, "Alpha: kCGImageAlphaFirst\n");
        if (a == kCGImageAlphaNoneSkipLast)          fprintf(stderr, "Alpha: kCGImageAlphaNoneSkipLast\n");
        if (a == kCGImageAlphaNoneSkipFirst)         fprintf(stderr, "Alpha: kCGImageAlphaNoneSkipFirst\n");
}

GuidoCGraphicSystem * GuidoCCreateSVGSystem()
{
        GuidoCGraphicSystem * system = (GuidoCGraphicSystem*) new SVGSystem();
        return system;
}

void GuidoCFreeSystem(GuidoCGraphicSystem * system)
{
    	delete (GSystemOSX*) system;
}

void GuidoCFreeSVGSystem(GuidoCGraphicSystem * system)
{
    	delete (SVGSystem*) system;
}

GuidoCGraphicDevice * GuidoCCreateDisplayDevice(GuidoCGraphicSystem * system)
{
        return (GuidoCGraphicDevice*) ((VGSystem*) system)->CreateDisplayDevice();
}

GuidoCGraphicDevice * GuidoCCreateMemoryDevice(GuidoCGraphicSystem * system, int width, int height)
{
        return (GuidoCGraphicDevice*) ((VGSystem*) system)->CreateMemoryDevice(width, height);
}

GuidoCGraphicDevice * GuidoCCreateMemoryDevicePath(GuidoCGraphicSystem * system, const char* path)
{
        return (GuidoCGraphicDevice*) ((VGSystem*) system)->CreateMemoryDevice(path);
}

GuidoCGraphicDevice * GuidoCCreatePrinterDevice(GuidoCGraphicSystem * system)
{
        return (GuidoCGraphicDevice*) ((VGSystem*) system)->CreatePrinterDevice();
}

// const char *byte_to_binary(int x)
// {
//     static char b[9];
//     b[0] = '\0';
//     int z;
//     for (z = 128; z > 0; z >>= 1)
//         strcat(b, ((x & z) == z) ? "1" : "0");
//     return b;
// }
<commit_msg>Cleaning<commit_after>
#include <GUIDOEngine/GUIDOEngine.h>
#include <GUIDOEngine/GDeviceOSX.h>
#include <GUIDOEngine/GFontOSX.h>
#include <GUIDOEngine/GMemoryDeviceOSX.h>
#include <GUIDOEngine/GPrinterDeviceOSX.h>
#include <GUIDOEngine/GSystemOSX.h>
#include <GUIDOEngine/SVGSystem.h>

#include <guido-c.h>

const char* GuidoCGetVersion()
{
        return "0.5.0";
}

GuidoCGraphicSystem * GuidoCCreateSystem()
{
    	GuidoCGraphicSystem * system = (GuidoCGraphicSystem*) new GSystemOSX(0,0);
        return system;
}

uint32_t* GuidoCNativePaint(GuidoCGraphicDevice * device)
{
        CGContextRef context = CGContextRef(((VGDevice*) device)->GetNativeContext());
        uint32_t* data = (uint32_t*)::CGBitmapContextGetData(context);
        return data;
}

void GuidoCPrintDeviceInfo(GuidoCGraphicDevice * device)
{
        CGContextRef context = CGContextRef(((VGDevice*) device)->GetNativeContext());
        uint32_t* data = (uint32_t*)::CGBitmapContextGetData(context);

        int m = CGBitmapContextGetBitsPerComponent(context);
        int n = CGBitmapContextGetBitsPerPixel(context);
        int w = CGBitmapContextGetWidth(context);
        int h = CGBitmapContextGetHeight(context);

        unsigned i = CGBitmapContextGetBitmapInfo(context);
        unsigned a = CGBitmapContextGetAlphaInfo(context);

        fprintf(stderr, "Data format: bitsPerComp=%d bitsPerPixel=%d width=%d height=%d\n", m, n, w, h);
        // fprintf(stderr, "Info: %s\n", byte_to_binary(i));
        // fprintf(stderr, "Alpha info: %s\n", byte_to_binary(a));

        if (i & kCGBitmapFloatComponents)   fprintf(stderr, "The components are floats\n");
        if ((i & kCGBitmapByteOrderMask) == kCGBitmapByteOrderDefault) fprintf(stderr, "The byte order is the default\n");
        if ((i & kCGBitmapByteOrderMask) == kCGBitmapByteOrder16Little) fprintf(stderr, "The byte order is 16LE\n");
        if ((i & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Little) fprintf(stderr, "The byte order is 32LE\n");
        if ((i & kCGBitmapByteOrderMask) == kCGBitmapByteOrder16Big)    fprintf(stderr, "The byte order is 16BE\n");
        if ((i & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Big)    fprintf(stderr, "The byte order is 32BE\n");

        if (a == kCGImageAlphaNone)                  fprintf(stderr, "Alpha: kCGImageAlphaNone\n");
        if (a == kCGImageAlphaPremultipliedLast)     fprintf(stderr, "Alpha: kCGImageAlphaPremultipliedLast\n");
        if (a == kCGImageAlphaPremultipliedFirst)    fprintf(stderr, "Alpha: kCGImageAlphaPremultipliedFirst\n");
        if (a == kCGImageAlphaLast)                  fprintf(stderr, "Alpha: kCGImageAlphaLast\n");
        if (a == kCGImageAlphaFirst)                 fprintf(stderr, "Alpha: kCGImageAlphaFirst\n");
        if (a == kCGImageAlphaNoneSkipLast)          fprintf(stderr, "Alpha: kCGImageAlphaNoneSkipLast\n");
        if (a == kCGImageAlphaNoneSkipFirst)         fprintf(stderr, "Alpha: kCGImageAlphaNoneSkipFirst\n");
}

GuidoCGraphicSystem * GuidoCCreateSVGSystem()
{
        GuidoCGraphicSystem * system = (GuidoCGraphicSystem*) new SVGSystem();
        return system;
}

void GuidoCFreeSystem(GuidoCGraphicSystem * system)
{
    	delete (GSystemOSX*) system;
}

void GuidoCFreeSVGSystem(GuidoCGraphicSystem * system)
{
    	delete (SVGSystem*) system;
}

GuidoCGraphicDevice * GuidoCCreateDisplayDevice(GuidoCGraphicSystem * system)
{
        return (GuidoCGraphicDevice*) ((VGSystem*) system)->CreateDisplayDevice();
}

GuidoCGraphicDevice * GuidoCCreateMemoryDevice(GuidoCGraphicSystem * system, int width, int height)
{
        return (GuidoCGraphicDevice*) ((VGSystem*) system)->CreateMemoryDevice(width, height);
}

GuidoCGraphicDevice * GuidoCCreateMemoryDevicePath(GuidoCGraphicSystem * system, const char* path)
{
        return (GuidoCGraphicDevice*) ((VGSystem*) system)->CreateMemoryDevice(path);
}

GuidoCGraphicDevice * GuidoCCreatePrinterDevice(GuidoCGraphicSystem * system)
{
        return (GuidoCGraphicDevice*) ((VGSystem*) system)->CreatePrinterDevice();
}

// const char *byte_to_binary(int x)
// {
//     static char b[9];
//     b[0] = '\0';
//     int z;
//     for (z = 128; z > 0; z >>= 1)
//         strcat(b, ((x & z) == z) ? "1" : "0");
//     return b;
// }
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkUnstructuredGrid.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 vtkUnstructuredGrid - dataset represents arbitrary combinations of all possible cell types
// .SECTION Description
// vtkUnstructuredGrid is a data object that is a concrete implementation
// of vtkDataSet. vtkUnstructuredGrid represents any combinations of any cell
// types. This includes 0D (e.g., points), 1D (e.g., lines, polylines), 2D
// (e.g., triangles, polygons), and 3D (e.g., hexahedron, tetrahedron).

#ifndef __vtkUnstructuredGrid_h
#define __vtkUnstructuredGrid_h

#include "vtkPointSet.hh"
#include "vtkIdList.hh"
#include "vtkCellArray.hh"
#include "vtkCellList.hh"
#include "vtkLinkList.hh"

class vtkUnstructuredGrid : public vtkPointSet {
public:
  vtkUnstructuredGrid();
  vtkUnstructuredGrid(const vtkUnstructuredGrid& up);
  ~vtkUnstructuredGrid();
  char *GetClassName() {return "vtkUnstructuredGrid";};
  char *GetDataType() {return "vtkUnstructuredGrid";};
  void PrintSelf(ostream& os, vtkIndent indent);

  // cell creation/manipulation methods
  void Allocate(int numCells=1000, int extSize=1000);
  int InsertNextCell(int type, int npts, int *pts);
  int InsertNextCell(int type, vtkIdList& ptIds);
  void Reset();
  void SetCells(int *types, vtkCellArray *cells);
  vtkCellArray *GetCells() {return this->Connectivity;};

  // dataset interface
  vtkDataSet *MakeObject() {return new vtkUnstructuredGrid(*this);};
  void CopyStructure(vtkDataSet *ds);
  int GetNumberOfCells();
  vtkCell *GetCell(int cellId);
  void GetCellPoints(int cellId, vtkIdList& ptIds);
  void GetPointCells(int ptId, vtkIdList& cellIds);
  int GetCellType(int cellId);
  void Squeeze();
  void Initialize();
  int GetMaxCellSize();

protected:

  // points inherited
  // point data (i.e., scalars, vectors, normals, tcoords) inherited
  vtkCellList *Cells;
  vtkCellArray *Connectivity;
  vtkLinkList *Links;
  void BuildLinks();
};

#endif
<commit_msg>ENH: Added additional cell structure functionality.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkUnstructuredGrid.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 vtkUnstructuredGrid - dataset represents arbitrary combinations of all possible cell types
// .SECTION Description
// vtkUnstructuredGrid is a data object that is a concrete implementation
// of vtkDataSet. vtkUnstructuredGrid represents any combinations of any cell
// types. This includes 0D (e.g., points), 1D (e.g., lines, polylines), 2D
// (e.g., triangles, polygons), and 3D (e.g., hexahedron, tetrahedron).

#ifndef __vtkUnstructuredGrid_h
#define __vtkUnstructuredGrid_h

#include "vtkPointSet.hh"
#include "vtkIdList.hh"
#include "vtkCellArray.hh"
#include "vtkCellList.hh"
#include "vtkLinkList.hh"

class vtkUnstructuredGrid : public vtkPointSet {
public:
  vtkUnstructuredGrid();
  vtkUnstructuredGrid(const vtkUnstructuredGrid& up);
  ~vtkUnstructuredGrid();
  char *GetClassName() {return "vtkUnstructuredGrid";};
  char *GetDataType() {return "vtkUnstructuredGrid";};
  void PrintSelf(ostream& os, vtkIndent indent);

  // cell creation/manipulation methods
  void Allocate(int numCells=1000, int extSize=1000);
  int InsertNextCell(int type, int npts, int *pts);
  int InsertNextCell(int type, vtkIdList& ptIds);
  void Reset();
  void SetCells(int *types, vtkCellArray *cells);
  vtkCellArray *GetCells() {return this->Connectivity;};

  // dataset interface
  vtkDataSet *MakeObject() {return new vtkUnstructuredGrid(*this);};
  void CopyStructure(vtkDataSet *ds);
  int GetNumberOfCells();
  vtkCell *GetCell(int cellId);
  void GetCellPoints(int cellId, vtkIdList& ptIds);
  void GetPointCells(int ptId, vtkIdList& cellIds);
  int GetCellType(int cellId);
  void Squeeze();
  void Initialize();
  int GetMaxCellSize();

  // special cell structure methods
  void BuildLinks();
  void GetCellPoints(int cellId, int& npts, int* &pts);
  void ReplaceCell(int cellId, int npts, int *pts);
  int InsertNextLinkedCell(int type, int npts, int *pts);
  void RemoveReferenceToCell(int ptId, int cellId);
  void AddReferenceToCell(int ptId, int cellId);
  void ResizeCellList(int ptId, int size);

protected:

  // points inherited
  // point data (i.e., scalars, vectors, normals, tcoords) inherited
  vtkCellList *Cells;
  vtkCellArray *Connectivity;
  vtkLinkList *Links;
};

#endif
<|endoftext|>