<commit_before>/*************************************************************************
 *
 *  $RCSfile: fontlb.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: dr $ $Date: 2002-07-23 10:47:34 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SVX_FONTLB_HXX
#define SVX_FONTLB_HXX

#ifndef _SVTABBOX_HXX
#include <svtools/svtabbx.hxx>
#endif
#ifndef _SV_VIRDEV_HXX
#include <vcl/virdev.hxx>
#endif

// ============================================================================

/** A list box string item which stores its text and font. */
class SvLBoxFontString : public SvLBoxString
{
private:
    Font                        maFont;     /// The font used by this item.
    bool                        mbUseColor; /// true = use font color, false = default listbox color.

public:
                                SvLBoxFontString();
                                SvLBoxFontString(
                                    SvLBoxEntry* pEntry,
                                    sal_uInt16 nFlags,
                                    const XubString& rString,
                                    const Font& rFont,
                                    const Color* pColor = NULL );

    virtual                     ~SvLBoxFontString();

    /** Creates a new empty list box item. */
    virtual SvLBoxItem*         Create() const;

    void            InitViewData( SvLBox*,SvLBoxEntry*,SvViewDataItem* );

    /** Paints this entry to the specified position, using the own font settings. */
    void                        Paint(
                                    const Point& rPos,
                                    SvLBox& rDev,
                                    sal_uInt16 nFlags,
                                    SvLBoxEntry* pEntry );
};

// ============================================================================

/** A list box supporting formatted string entries. */
class SvxFontListBox : public SvTabListBox
{
private:
    Font                        maStdFont;      /// Used for entries without specific font.

    // The following members are used to store additional parameters for InitEntry().
    Font                        maEntryFont;    /// Current entry font used in InitEntry().
    const Color*                mpEntryColor;   /// Current entry color used in InitEntry().
    bool                        mbUseFont;      /// true = Use maEntryFont/mpEntryColor in InitEntry().

public:
                                SvxFontListBox( Window* pParent, const ResId& rResId );

    /** Inserts a list entry and sets the font used for this entry.
        @param pColor  The font color. NULL = use default listbox text color. */
    void                        InsertFontEntry(
                                    const String& rString, const Font& rFont, const Color* pColor = NULL );

    /** Selects/deselects an entry specified by its position in the list box. */
    void                        SelectEntryPos( sal_uInt16 nPos, bool bSelect = true );
    /** Removes a selection. */
    void                        SetNoSelection();

    /** Returns the position of the entry currently selected or LIST_ENTRY_NOTFOUND. */
    sal_uInt32                  GetSelectEntryPos() const;
    /** Returns the text of the selected entry or an empty string. */
    XubString                   GetSelectEntry() const;

protected:
    /** Initializes a new SvLBoxFontString entry.
        @descr  Uses current value of maEntryFont to set the entry font (if mbUseFont is true). */
    virtual void                InitEntry(
                                    SvLBoxEntry* pEntry,
                                    const XubString& rEntryText,
                                    const Image& rCollImg,
                                    const Image& rExpImg );
};

// ============================================================================

#endif

<commit_msg>INTEGRATION: CWS visibility01 (1.2.1010); FILE MERGED 2004/12/06 08:10:20 mnicel 1.2.1010.1: Part of symbol visibility markup - #i35758#<commit_after>/*************************************************************************
 *
 *  $RCSfile: fontlb.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-21 14:36:20 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SVX_FONTLB_HXX
#define SVX_FONTLB_HXX

#ifndef _SVTABBOX_HXX
#include <svtools/svtabbx.hxx>
#endif
#ifndef _SV_VIRDEV_HXX
#include <vcl/virdev.hxx>
#endif

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

// ============================================================================

/** A list box string item which stores its text and font. */
class SvLBoxFontString : public SvLBoxString
{
private:
    Font                        maFont;     /// The font used by this item.
    bool                        mbUseColor; /// true = use font color, false = default listbox color.

public:
                                SvLBoxFontString();
                                SvLBoxFontString(
                                    SvLBoxEntry* pEntry,
                                    sal_uInt16 nFlags,
                                    const XubString& rString,
                                    const Font& rFont,
                                    const Color* pColor = NULL );

    virtual                     ~SvLBoxFontString();

    /** Creates a new empty list box item. */
    virtual SvLBoxItem*         Create() const;

    void            InitViewData( SvLBox*,SvLBoxEntry*,SvViewDataItem* );

    /** Paints this entry to the specified position, using the own font settings. */
    void                        Paint(
                                    const Point& rPos,
                                    SvLBox& rDev,
                                    sal_uInt16 nFlags,
                                    SvLBoxEntry* pEntry );
};

// ============================================================================

/** A list box supporting formatted string entries. */
class SVX_DLLPUBLIC SvxFontListBox : public SvTabListBox
{
private:
    Font                        maStdFont;      /// Used for entries without specific font.

    // The following members are used to store additional parameters for InitEntry().
    Font                        maEntryFont;    /// Current entry font used in InitEntry().
    const Color*                mpEntryColor;   /// Current entry color used in InitEntry().
    bool                        mbUseFont;      /// true = Use maEntryFont/mpEntryColor in InitEntry().

public:
                                SvxFontListBox( Window* pParent, const ResId& rResId );

    /** Inserts a list entry and sets the font used for this entry.
        @param pColor  The font color. NULL = use default listbox text color. */
    void                        InsertFontEntry(
                                    const String& rString, const Font& rFont, const Color* pColor = NULL );

    /** Selects/deselects an entry specified by its position in the list box. */
    void                        SelectEntryPos( sal_uInt16 nPos, bool bSelect = true );
    /** Removes a selection. */
    void                        SetNoSelection();

    /** Returns the position of the entry currently selected or LIST_ENTRY_NOTFOUND. */
    sal_uInt32                  GetSelectEntryPos() const;
    /** Returns the text of the selected entry or an empty string. */
    XubString                   GetSelectEntry() const;

protected:
    /** Initializes a new SvLBoxFontString entry.
        @descr  Uses current value of maEntryFont to set the entry font (if mbUseFont is true). */
    virtual void                InitEntry(
                                    SvLBoxEntry* pEntry,
                                    const XubString& rEntryText,
                                    const Image& rCollImg,
                                    const Image& rExpImg );
};

// ============================================================================

#endif

<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include "TestBlock.hpp"

#include <nix/util/util.hpp>

#include <nix/valid/validate.hpp>
#include <nix/Exception.hpp>

#include <ctime>

using namespace std;
using namespace nix;
using namespace valid;

void TestBlock::setUp() {
    startup_time = time(NULL);
    file = File::open("test_block.h5", FileMode::Overwrite);

    section = file.createSection("foo_section", "metadata");

    block = file.createBlock("block_one", "dataset");
    block_other = file.createBlock("block_two", "dataset");
    block_null  = nullptr;
}

void TestBlock::tearDown() {
    file.close();
}

void TestBlock::testValidate() {
    valid::Result result = validate(block);
    CPPUNIT_ASSERT(result.getErrors().size() == 0);
    CPPUNIT_ASSERT(result.getWarnings().size() == 0);
}

void TestBlock::testId() {
    CPPUNIT_ASSERT(block.id().size() == 36);
}

void TestBlock::testName() {
    CPPUNIT_ASSERT(block.name() == "block_one");
}

void TestBlock::testType() {
    CPPUNIT_ASSERT(block.type() == "dataset");
    string typ = util::createId();
    block.type(typ);
    CPPUNIT_ASSERT(block.type() == typ);
}

void TestBlock::testDefinition() {
    string def = util::createId();
    block.definition(def);
    CPPUNIT_ASSERT(*block.definition() == def);
}

void TestBlock::testMetadataAccess() {
    CPPUNIT_ASSERT(!block.metadata());

    block.metadata(section);
    CPPUNIT_ASSERT(block.metadata());

    // test none-unsetter
    block.metadata(none);
    CPPUNIT_ASSERT(!block.metadata());
    // test deleter removing link too
    block.metadata(section);
    file.deleteSection(section.id());
    CPPUNIT_ASSERT(!block.metadata());
    // re-create section
    section = file.createSection("foo_section", "metadata");
}

void TestBlock::testSourceAccess() {
    vector<string> names = { "source_a", "source_b", "source_c", "source_d", "source_e" };
    Source s;
    CPPUNIT_ASSERT_THROW(block.hasSource(s), std::runtime_error);
    CPPUNIT_ASSERT(block.sourceCount() == 0);
    CPPUNIT_ASSERT(block.sources().size() == 0);
    CPPUNIT_ASSERT(block.getSource("invalid_id") == false);
    CPPUNIT_ASSERT(!block.hasSource("invalid_id"));

    vector<string> ids;
    for (const auto &name : names) {
        Source src = block.createSource(name, "channel");
        CPPUNIT_ASSERT(src.name() == name);
        CPPUNIT_ASSERT(block.hasSource(name));
        CPPUNIT_ASSERT(block.hasSource(src));

        ids.push_back(src.id());
    }
    CPPUNIT_ASSERT_THROW(block.createSource(names[0], "channel"),
                         DuplicateName);

    CPPUNIT_ASSERT(block.sourceCount() == names.size());
    CPPUNIT_ASSERT(block.sources().size() == names.size());

    for (const auto &id : ids) {
        Source src = block.getSource(id);
        CPPUNIT_ASSERT(block.hasSource(id) == true);
        CPPUNIT_ASSERT(src.id() == id);
        block.deleteSource(id);
    }

    s = block.createSource("test", "test");
    CPPUNIT_ASSERT(block.sourceCount() == 1);
    CPPUNIT_ASSERT_NO_THROW(block.deleteSource(s));

    CPPUNIT_ASSERT(block.sourceCount() == 0);
    CPPUNIT_ASSERT(block.sources().size() == 0);
    CPPUNIT_ASSERT(block.getSource("invalid_id") == false);
}

void TestBlock::testDataArrayAccess() {
    vector<string> names = { "data_array_a", "data_array_b", "data_array_c",
                             "data_array_d", "data_array_e" };
    DataArray data_array, a;

    CPPUNIT_ASSERT(block.dataArrayCount() == 0);
    CPPUNIT_ASSERT(block.dataArrays().size() == 0);
    CPPUNIT_ASSERT(block.getDataArray("invalid_id") == false);

    vector<string> ids;
    for (const auto &name : names) {
        data_array = block.createDataArray(name, "channel",
                                           DataType::Double, nix::NDSize({ 0 }));
        CPPUNIT_ASSERT(data_array.name() == name);
        CPPUNIT_ASSERT(data_array.type() == "channel");

        ids.push_back(data_array.id());
    }
    CPPUNIT_ASSERT_THROW(block.createDataArray(names[0], "channel", DataType::Double, nix::NDSize({ 0 })),
                         DuplicateName);
    CPPUNIT_ASSERT(block.hasDataArray(data_array));
    CPPUNIT_ASSERT_THROW(block.hasDataArray(a), std::runtime_error);
    CPPUNIT_ASSERT(block.dataArrayCount() == names.size());
    CPPUNIT_ASSERT(block.dataArrays().size() == names.size());

    for (const auto &name : names) {
        DataArray da_name = block.getDataArray(name);
        CPPUNIT_ASSERT(da_name);

        DataArray da_id = block.getDataArray(da_name.id());
        CPPUNIT_ASSERT(da_id);
        CPPUNIT_ASSERT_EQUAL(da_name.name(), da_id.name());
    }

    vector<DataArray> filteredArrays = block.dataArrays(util::TypeFilter<DataArray>("channel"));
    CPPUNIT_ASSERT_EQUAL(names.size(), filteredArrays.size());

    filteredArrays = block.dataArrays(util::NameFilter<DataArray>("data_array_c"));
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), filteredArrays.size());
    if (filteredArrays.size() > 0) {
        boost::optional<std::string> name = filteredArrays[0].name();
        CPPUNIT_ASSERT(name && *name == "data_array_c");
    }

    for (auto it = ids.begin(); it != ids.end(); it++) {
        DataArray data_array = block.getDataArray(*it);
        CPPUNIT_ASSERT(block.hasDataArray(*it) == true);
        CPPUNIT_ASSERT(data_array.id() == *it);

        block.deleteDataArray(*it);
    }
    CPPUNIT_ASSERT_THROW(block.deleteDataArray(a), std::runtime_error);
    CPPUNIT_ASSERT(block.dataArrayCount() == 0);
    CPPUNIT_ASSERT(block.dataArrays().size() == 0);
    CPPUNIT_ASSERT(block.getDataArray("invalid_id") == false);

}

void TestBlock::testTagAccess() {
    vector<string> names = { "tag_a", "tag_b", "tag_c", "tag_d", "tag_e" };
    vector<string> array_names = { "data_array_a", "data_array_b", "data_array_c",
                                   "data_array_d", "data_array_e" };
    vector<DataArray> refs;
    Tag tag, t;
    for (const auto &name : array_names) {
        refs.push_back(block.createDataArray(name,
                                             "reference",
                                             DataType::Double,
                                             nix::NDSize({ 0 })));
    }

    CPPUNIT_ASSERT(block.tagCount() == 0);
    CPPUNIT_ASSERT(block.tags().size() == 0);
    CPPUNIT_ASSERT(block.getTag("invalid_id") == false);
    CPPUNIT_ASSERT_THROW(block.hasTag(t), std::runtime_error);

    vector<string> ids;
    for (auto it = names.begin(); it != names.end(); ++it) {
        tag = block.createTag(*it, "segment", {0.0, 2.0, 3.4});
        tag.references(refs);
        CPPUNIT_ASSERT(tag.name() == *it);
        CPPUNIT_ASSERT(block.hasTag(tag));
        ids.push_back(tag.id());
    }
    CPPUNIT_ASSERT_THROW(block.createTag(names[0], "segment", {0.0, 2.0, 3.4}),
                         DuplicateName);

    CPPUNIT_ASSERT(block.tagCount() == names.size());
    CPPUNIT_ASSERT(block.tags().size() == names.size());

    for (auto it = ids.begin(); it != ids.end(); ++it) {
        tag = block.getTag(*it);
        CPPUNIT_ASSERT(block.hasTag(*it) == true);
        CPPUNIT_ASSERT(tag.id() == *it);

        block.deleteTag(*it);
    }

    tag = block.createTag("test", "test", {0.0});
    CPPUNIT_ASSERT(block.hasTag(tag));
    CPPUNIT_ASSERT_NO_THROW(block.deleteTag(tag));
    CPPUNIT_ASSERT_THROW(block.deleteTag(t), std::runtime_error);

    CPPUNIT_ASSERT(block.tagCount() == 0);
    CPPUNIT_ASSERT(block.tags().size() == 0);
    CPPUNIT_ASSERT(block.getTag("invalid_id") == false);
}

void TestBlock::testMultiTagAccess() {
    vector<string> names = { "tag_a", "tag_b", "tag_c", "tag_d", "tag_e" };
    // create a valid positions data array below
    typedef boost::multi_array<double, 3>::index index;
    DataArray positions = block.createDataArray("array_one",
                                                "testdata",
                                                DataType::Double,
                                                nix::NDSize({ 3, 4, 2 }));
    boost::multi_array<double, 3> A(boost::extents[3][4][2]);
    int values = 0;
    for(index i = 0; i != 3; ++i)
        for(index j = 0; j != 4; ++j)
            for(index k = 0; k != 2; ++k)
                A[i][j][k] = values++;

    positions.setData(A);

    CPPUNIT_ASSERT(block.multiTagCount() == 0);
    CPPUNIT_ASSERT(block.multiTags().size() == 0);
    CPPUNIT_ASSERT(block.getMultiTag("invalid_id") == false);

    vector<string> ids;
    for (auto it = names.begin(); it != names.end(); it++) {
        MultiTag tag = block.createMultiTag(*it, "segment", positions);
        CPPUNIT_ASSERT(tag.name() == *it);

        ids.push_back(tag.id());
    }
    CPPUNIT_ASSERT_THROW(block.createMultiTag(names[0], "segment", positions),
                         DuplicateName);

    CPPUNIT_ASSERT(block.multiTagCount() == names.size());
    CPPUNIT_ASSERT(block.multiTags().size() == names.size());

    for (auto it = ids.begin(); it != ids.end(); it++) {
        MultiTag tag = block.getMultiTag(*it);
        CPPUNIT_ASSERT(block.hasMultiTag(*it) == true);
        CPPUNIT_ASSERT(tag.id() == *it);

        block.deleteMultiTag(*it);
    }

    CPPUNIT_ASSERT(block.multiTagCount() == 0);
    CPPUNIT_ASSERT(block.multiTags().size() == 0);
    CPPUNIT_ASSERT(block.getMultiTag("invalid_id") == false);
}

void TestBlock::testOperators() {
    CPPUNIT_ASSERT(block_null == false);
    CPPUNIT_ASSERT(block_null == none);

    CPPUNIT_ASSERT(block != false);
    CPPUNIT_ASSERT(block != none);

    CPPUNIT_ASSERT(block == block);
    CPPUNIT_ASSERT(block != block_other);

    block_other = block;
    CPPUNIT_ASSERT(block == block_other);

    block_other = none;
    CPPUNIT_ASSERT(block_null == false);
    CPPUNIT_ASSERT(block_null == none);
}

void TestBlock::testCreatedAt() {
    CPPUNIT_ASSERT(block.createdAt() >= startup_time);
    time_t past_time = time(NULL) - 10000000;
    block.forceCreatedAt(past_time);
    CPPUNIT_ASSERT(block.createdAt() == past_time);
}

void TestBlock::testUpdatedAt() {
    CPPUNIT_ASSERT(block.updatedAt() >= startup_time);
}
<commit_msg>[TestBlock] complete MultiTag tests<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include "TestBlock.hpp"

#include <nix/util/util.hpp>

#include <nix/valid/validate.hpp>
#include <nix/Exception.hpp>

#include <ctime>

using namespace std;
using namespace nix;
using namespace valid;

void TestBlock::setUp() {
    startup_time = time(NULL);
    file = File::open("test_block.h5", FileMode::Overwrite);

    section = file.createSection("foo_section", "metadata");

    block = file.createBlock("block_one", "dataset");
    block_other = file.createBlock("block_two", "dataset");
    block_null  = nullptr;
}

void TestBlock::tearDown() {
    file.close();
}

void TestBlock::testValidate() {
    valid::Result result = validate(block);
    CPPUNIT_ASSERT(result.getErrors().size() == 0);
    CPPUNIT_ASSERT(result.getWarnings().size() == 0);
}

void TestBlock::testId() {
    CPPUNIT_ASSERT(block.id().size() == 36);
}

void TestBlock::testName() {
    CPPUNIT_ASSERT(block.name() == "block_one");
}

void TestBlock::testType() {
    CPPUNIT_ASSERT(block.type() == "dataset");
    string typ = util::createId();
    block.type(typ);
    CPPUNIT_ASSERT(block.type() == typ);
}

void TestBlock::testDefinition() {
    string def = util::createId();
    block.definition(def);
    CPPUNIT_ASSERT(*block.definition() == def);
}

void TestBlock::testMetadataAccess() {
    CPPUNIT_ASSERT(!block.metadata());

    block.metadata(section);
    CPPUNIT_ASSERT(block.metadata());

    // test none-unsetter
    block.metadata(none);
    CPPUNIT_ASSERT(!block.metadata());
    // test deleter removing link too
    block.metadata(section);
    file.deleteSection(section.id());
    CPPUNIT_ASSERT(!block.metadata());
    // re-create section
    section = file.createSection("foo_section", "metadata");
}

void TestBlock::testSourceAccess() {
    vector<string> names = { "source_a", "source_b", "source_c", "source_d", "source_e" };
    Source s;
    CPPUNIT_ASSERT_THROW(block.hasSource(s), std::runtime_error);
    CPPUNIT_ASSERT(block.sourceCount() == 0);
    CPPUNIT_ASSERT(block.sources().size() == 0);
    CPPUNIT_ASSERT(block.getSource("invalid_id") == false);
    CPPUNIT_ASSERT(!block.hasSource("invalid_id"));

    vector<string> ids;
    for (const auto &name : names) {
        Source src = block.createSource(name, "channel");
        CPPUNIT_ASSERT(src.name() == name);
        CPPUNIT_ASSERT(block.hasSource(name));
        CPPUNIT_ASSERT(block.hasSource(src));

        ids.push_back(src.id());
    }
    CPPUNIT_ASSERT_THROW(block.createSource(names[0], "channel"),
                         DuplicateName);

    CPPUNIT_ASSERT(block.sourceCount() == names.size());
    CPPUNIT_ASSERT(block.sources().size() == names.size());

    for (const auto &id : ids) {
        Source src = block.getSource(id);
        CPPUNIT_ASSERT(block.hasSource(id) == true);
        CPPUNIT_ASSERT(src.id() == id);
        block.deleteSource(id);
    }

    s = block.createSource("test", "test");
    CPPUNIT_ASSERT(block.sourceCount() == 1);
    CPPUNIT_ASSERT_NO_THROW(block.deleteSource(s));

    CPPUNIT_ASSERT(block.sourceCount() == 0);
    CPPUNIT_ASSERT(block.sources().size() == 0);
    CPPUNIT_ASSERT(block.getSource("invalid_id") == false);
}

void TestBlock::testDataArrayAccess() {
    vector<string> names = { "data_array_a", "data_array_b", "data_array_c",
                             "data_array_d", "data_array_e" };
    DataArray data_array, a;

    CPPUNIT_ASSERT(block.dataArrayCount() == 0);
    CPPUNIT_ASSERT(block.dataArrays().size() == 0);
    CPPUNIT_ASSERT(block.getDataArray("invalid_id") == false);

    vector<string> ids;
    for (const auto &name : names) {
        data_array = block.createDataArray(name, "channel",
                                           DataType::Double, nix::NDSize({ 0 }));
        CPPUNIT_ASSERT(data_array.name() == name);
        CPPUNIT_ASSERT(data_array.type() == "channel");

        ids.push_back(data_array.id());
    }
    CPPUNIT_ASSERT_THROW(block.createDataArray(names[0], "channel", DataType::Double, nix::NDSize({ 0 })),
                         DuplicateName);
    CPPUNIT_ASSERT(block.hasDataArray(data_array));
    CPPUNIT_ASSERT_THROW(block.hasDataArray(a), std::runtime_error);
    CPPUNIT_ASSERT(block.dataArrayCount() == names.size());
    CPPUNIT_ASSERT(block.dataArrays().size() == names.size());

    for (const auto &name : names) {
        DataArray da_name = block.getDataArray(name);
        CPPUNIT_ASSERT(da_name);

        DataArray da_id = block.getDataArray(da_name.id());
        CPPUNIT_ASSERT(da_id);
        CPPUNIT_ASSERT_EQUAL(da_name.name(), da_id.name());
    }

    vector<DataArray> filteredArrays = block.dataArrays(util::TypeFilter<DataArray>("channel"));
    CPPUNIT_ASSERT_EQUAL(names.size(), filteredArrays.size());

    filteredArrays = block.dataArrays(util::NameFilter<DataArray>("data_array_c"));
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), filteredArrays.size());
    if (filteredArrays.size() > 0) {
        boost::optional<std::string> name = filteredArrays[0].name();
        CPPUNIT_ASSERT(name && *name == "data_array_c");
    }

    for (auto it = ids.begin(); it != ids.end(); it++) {
        DataArray data_array = block.getDataArray(*it);
        CPPUNIT_ASSERT(block.hasDataArray(*it) == true);
        CPPUNIT_ASSERT(data_array.id() == *it);

        block.deleteDataArray(*it);
    }
    CPPUNIT_ASSERT_THROW(block.deleteDataArray(a), std::runtime_error);
    CPPUNIT_ASSERT(block.dataArrayCount() == 0);
    CPPUNIT_ASSERT(block.dataArrays().size() == 0);
    CPPUNIT_ASSERT(block.getDataArray("invalid_id") == false);

}

void TestBlock::testTagAccess() {
    vector<string> names = { "tag_a", "tag_b", "tag_c", "tag_d", "tag_e" };
    vector<string> array_names = { "data_array_a", "data_array_b", "data_array_c",
                                   "data_array_d", "data_array_e" };
    vector<DataArray> refs;
    Tag tag, t;
    for (const auto &name : array_names) {
        refs.push_back(block.createDataArray(name,
                                             "reference",
                                             DataType::Double,
                                             nix::NDSize({ 0 })));
    }

    CPPUNIT_ASSERT(block.tagCount() == 0);
    CPPUNIT_ASSERT(block.tags().size() == 0);
    CPPUNIT_ASSERT(block.getTag("invalid_id") == false);
    CPPUNIT_ASSERT_THROW(block.hasTag(t), std::runtime_error);

    vector<string> ids;
    for (auto it = names.begin(); it != names.end(); ++it) {
        tag = block.createTag(*it, "segment", {0.0, 2.0, 3.4});
        tag.references(refs);
        CPPUNIT_ASSERT(tag.name() == *it);
        CPPUNIT_ASSERT(block.hasTag(tag));
        ids.push_back(tag.id());
    }
    CPPUNIT_ASSERT_THROW(block.createTag(names[0], "segment", {0.0, 2.0, 3.4}),
                         DuplicateName);

    CPPUNIT_ASSERT(block.tagCount() == names.size());
    CPPUNIT_ASSERT(block.tags().size() == names.size());

    for (auto it = ids.begin(); it != ids.end(); ++it) {
        tag = block.getTag(*it);
        CPPUNIT_ASSERT(block.hasTag(*it) == true);
        CPPUNIT_ASSERT(tag.id() == *it);

        block.deleteTag(*it);
    }

    tag = block.createTag("test", "test", {0.0});
    CPPUNIT_ASSERT(block.hasTag(tag));
    CPPUNIT_ASSERT_NO_THROW(block.deleteTag(tag));
    CPPUNIT_ASSERT_THROW(block.deleteTag(t), std::runtime_error);

    CPPUNIT_ASSERT(block.tagCount() == 0);
    CPPUNIT_ASSERT(block.tags().size() == 0);
    CPPUNIT_ASSERT(block.getTag("invalid_id") == false);
}

void TestBlock::testMultiTagAccess() {
    vector<string> names = { "tag_a", "tag_b", "tag_c", "tag_d", "tag_e" };
    MultiTag mtag, m;
    // create a valid positions data array below
    typedef boost::multi_array<double, 3>::index index;
    DataArray positions = block.createDataArray("array_one",
                                                "testdata",
                                                DataType::Double,
                                                nix::NDSize({ 3, 4, 2 }));
    boost::multi_array<double, 3> A(boost::extents[3][4][2]);
    int values = 0;
    for(index i = 0; i != 3; ++i)
        for(index j = 0; j != 4; ++j)
            for(index k = 0; k != 2; ++k)
                A[i][j][k] = values++;

    positions.setData(A);

    CPPUNIT_ASSERT(block.multiTagCount() == 0);
    CPPUNIT_ASSERT(block.multiTags().size() == 0);
    CPPUNIT_ASSERT(block.getMultiTag("invalid_id") == false);
    CPPUNIT_ASSERT_THROW(block.hasMultiTag(m), std::runtime_error);
    vector<string> ids;
    for (auto it = names.begin(); it != names.end(); it++) {
        mtag = block.createMultiTag(*it, "segment", positions);
        CPPUNIT_ASSERT(mtag.name() == *it);
        CPPUNIT_ASSERT(block.hasMultiTag(mtag));
        ids.push_back(mtag.id());
    }
    CPPUNIT_ASSERT_THROW(block.createMultiTag(names[0], "segment", positions),
                         DuplicateName);

    CPPUNIT_ASSERT(block.multiTagCount() == names.size());
    CPPUNIT_ASSERT(block.multiTags().size() == names.size());

    for (auto it = ids.begin(); it != ids.end(); it++) {
        mtag = block.getMultiTag(*it);
        CPPUNIT_ASSERT(block.hasMultiTag(*it) == true);
        CPPUNIT_ASSERT(mtag.id() == *it);

        block.deleteMultiTag(*it);
    }
    mtag = block.createMultiTag("test", "test", positions);
    CPPUNIT_ASSERT(block.hasMultiTag(mtag));
    CPPUNIT_ASSERT_THROW(block.deleteMultiTag(m), std::runtime_error);
    CPPUNIT_ASSERT_NO_THROW(block.deleteMultiTag(mtag));
    CPPUNIT_ASSERT(block.multiTagCount() == 0);
    CPPUNIT_ASSERT(block.multiTags().size() == 0);
    CPPUNIT_ASSERT(block.getMultiTag("invalid_id") == false);
}

void TestBlock::testOperators() {
    CPPUNIT_ASSERT(block_null == false);
    CPPUNIT_ASSERT(block_null == none);

    CPPUNIT_ASSERT(block != false);
    CPPUNIT_ASSERT(block != none);

    CPPUNIT_ASSERT(block == block);
    CPPUNIT_ASSERT(block != block_other);

    block_other = block;
    CPPUNIT_ASSERT(block == block_other);

    block_other = none;
    CPPUNIT_ASSERT(block_null == false);
    CPPUNIT_ASSERT(block_null == none);
}

void TestBlock::testCreatedAt() {
    CPPUNIT_ASSERT(block.createdAt() >= startup_time);
    time_t past_time = time(NULL) - 10000000;
    block.forceCreatedAt(past_time);
    CPPUNIT_ASSERT(block.createdAt() == past_time);
}

void TestBlock::testUpdatedAt() {
    CPPUNIT_ASSERT(block.updatedAt() >= startup_time);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: drawdoc.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-08-14 15:20:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/
#ifndef _DRAWDOC_HXX
#define _DRAWDOC_HXX

#ifndef _FM_FMMODEL_HXX
#include <svx/fmmodel.hxx>
#endif

class SwDoc;
class SwDocShell;

//==================================================================

class SwDrawDocument : public FmFormModel
{
    SwDoc* pDoc;
public:
    SwDrawDocument( SwDoc* pDoc );
    SwDrawDocument( SfxItemPool *pPool, SwDocShell *pDocSh );
    ~SwDrawDocument();

    const SwDoc& GetDoc() const { return *pDoc; }
          SwDoc& GetDoc()       { return *pDoc; }

    virtual SdrPage* AllocPage(FASTBOOL bMasterPage);

    // fuers "load on demand" von Grafiken im DrawingLayer
    virtual SvStream* GetDocumentStream( SdrDocumentStreamInfo& rInfo ) const;

    // fuers Speicher von Rechtecken als Control-Ersatz fuker Versionen < 5.0
    virtual SdrLayerID GetControlExportLayerId( const SdrObject & ) const;

protected:
    // --> OD 2006-03-01 #b6382898#
    // overload of <SdrModel::createUnoModel()> is needed to provide corresponding uno model.
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > createUnoModel();
    // <--
};

#endif
<commit_msg>INTEGRATION: CWS os94 (1.4.266); FILE MERGED 2007/03/12 08:07:29 os 1.4.266.1: #i75235# unused methods removed<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: drawdoc.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2007-04-25 08:53:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/
#ifndef _DRAWDOC_HXX
#define _DRAWDOC_HXX

#ifndef _FM_FMMODEL_HXX
#include <svx/fmmodel.hxx>
#endif

class SwDoc;
class SwDocShell;

//==================================================================

class SwDrawDocument : public FmFormModel
{
    SwDoc* pDoc;
public:
    SwDrawDocument( SwDoc* pDoc );
    ~SwDrawDocument();

    const SwDoc& GetDoc() const { return *pDoc; }
          SwDoc& GetDoc()       { return *pDoc; }

    virtual SdrPage* AllocPage(FASTBOOL bMasterPage);

    // fuers "load on demand" von Grafiken im DrawingLayer
    virtual SvStream* GetDocumentStream( SdrDocumentStreamInfo& rInfo ) const;

    // fuers Speicher von Rechtecken als Control-Ersatz fuker Versionen < 5.0
    virtual SdrLayerID GetControlExportLayerId( const SdrObject & ) const;

protected:
    // --> OD 2006-03-01 #b6382898#
    // overload of <SdrModel::createUnoModel()> is needed to provide corresponding uno model.
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > createUnoModel();
    // <--
};

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fmtsrnd.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-15 11:40:00 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/
#ifndef _FMTSRND_HXX
#define _FMTSRND_HXX

#ifndef INCLUDED_SWDLLAPI_H
#include "swdllapi.h"
#endif
#ifndef _HINTIDS_HXX
#include <hintids.hxx>
#endif
#ifndef _FORMAT_HXX //autogen
#include <format.hxx>
#endif
#ifndef _SFXENUMITEM_HXX //autogen
#include <svtools/eitem.hxx>
#endif

// --> OD 2006-08-15 #i68520# - refactoring
// separate enumeration <SwSurround> in own header file
#ifndef _FMTSRNDENUM_HXX
#include <fmtsrndenum.hxx>
#endif
// <--
class IntlWrapper;

//SwFmtSurround, wie soll sich der ---------------
//  Dokumentinhalt unter dem Rahmen verhalten ---

class SW_DLLPUBLIC SwFmtSurround: public SfxEnumItem
{
    BOOL    bAnchorOnly :1;
    BOOL    bContour    :1;
    BOOL    bOutside    :1;
public:
    SwFmtSurround( SwSurround eNew = SURROUND_PARALLEL );
    SwFmtSurround( const SwFmtSurround & );
    inline SwFmtSurround &operator=( const SwFmtSurround &rCpy );

    // "pure virtual Methoden" vom SfxPoolItem
    virtual int             operator==( const SfxPoolItem& ) const;
    virtual SfxPoolItem*    Clone( SfxItemPool* pPool = 0 ) const;
    virtual USHORT          GetValueCount() const;
    virtual SfxItemPresentation GetPresentation( SfxItemPresentation ePres,
                                    SfxMapUnit eCoreMetric,
                                    SfxMapUnit ePresMetric,
                                    String &rText,
                                    const IntlWrapper*    pIntl = 0 ) const;
    virtual BOOL             QueryValue( com::sun::star::uno::Any& rVal, BYTE nMemberId = 0 ) const;
    virtual BOOL             PutValue( const com::sun::star::uno::Any& rVal, BYTE nMemberId = 0 );

    SwSurround GetSurround()const { return SwSurround( GetValue() ); }
    BOOL    IsAnchorOnly()  const { return bAnchorOnly; }
    BOOL    IsContour()     const { return bContour; }
    BOOL    IsOutside()     const { return bOutside; }
    void    SetSurround  ( SwSurround eNew ){ SfxEnumItem::SetValue( USHORT( eNew ) ); }
    void    SetAnchorOnly( BOOL bNew )      { bAnchorOnly = bNew; }
    void    SetContour( BOOL bNew )         { bContour = bNew; }
    void    SetOutside( BOOL bNew )         { bOutside = bNew; }
};

inline SwFmtSurround &SwFmtSurround::operator=( const SwFmtSurround &rCpy )
{
    bAnchorOnly = rCpy.IsAnchorOnly();
    bContour = rCpy.IsContour();
    bOutside = rCpy.IsOutside();
    SfxEnumItem::SetValue( rCpy.GetValue() );
    return *this;
}

inline const SwFmtSurround &SwAttrSet::GetSurround(BOOL bInP) const
    { return (const SwFmtSurround&)Get( RES_SURROUND,bInP); }

inline const SwFmtSurround &SwFmt::GetSurround(BOOL bInP) const
    { return aSet.GetSurround(bInP); }

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.9.718); FILE MERGED 2008/04/01 15:56:13 thb 1.9.718.3: #i85898# Stripping all external header guards 2008/04/01 12:53:30 thb 1.9.718.2: #i85898# Stripping all external header guards 2008/03/31 16:52:38 rt 1.9.718.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: fmtsrnd.hxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _FMTSRND_HXX
#define _FMTSRND_HXX

#include "swdllapi.h"
#include <hintids.hxx>
#include <format.hxx>
#include <svtools/eitem.hxx>

// --> OD 2006-08-15 #i68520# - refactoring
// separate enumeration <SwSurround> in own header file
#include <fmtsrndenum.hxx>
// <--
class IntlWrapper;

//SwFmtSurround, wie soll sich der ---------------
//  Dokumentinhalt unter dem Rahmen verhalten ---

class SW_DLLPUBLIC SwFmtSurround: public SfxEnumItem
{
    BOOL    bAnchorOnly :1;
    BOOL    bContour    :1;
    BOOL    bOutside    :1;
public:
    SwFmtSurround( SwSurround eNew = SURROUND_PARALLEL );
    SwFmtSurround( const SwFmtSurround & );
    inline SwFmtSurround &operator=( const SwFmtSurround &rCpy );

    // "pure virtual Methoden" vom SfxPoolItem
    virtual int             operator==( const SfxPoolItem& ) const;
    virtual SfxPoolItem*    Clone( SfxItemPool* pPool = 0 ) const;
    virtual USHORT          GetValueCount() const;
    virtual SfxItemPresentation GetPresentation( SfxItemPresentation ePres,
                                    SfxMapUnit eCoreMetric,
                                    SfxMapUnit ePresMetric,
                                    String &rText,
                                    const IntlWrapper*    pIntl = 0 ) const;
    virtual BOOL             QueryValue( com::sun::star::uno::Any& rVal, BYTE nMemberId = 0 ) const;
    virtual BOOL             PutValue( const com::sun::star::uno::Any& rVal, BYTE nMemberId = 0 );

    SwSurround GetSurround()const { return SwSurround( GetValue() ); }
    BOOL    IsAnchorOnly()  const { return bAnchorOnly; }
    BOOL    IsContour()     const { return bContour; }
    BOOL    IsOutside()     const { return bOutside; }
    void    SetSurround  ( SwSurround eNew ){ SfxEnumItem::SetValue( USHORT( eNew ) ); }
    void    SetAnchorOnly( BOOL bNew )      { bAnchorOnly = bNew; }
    void    SetContour( BOOL bNew )         { bContour = bNew; }
    void    SetOutside( BOOL bNew )         { bOutside = bNew; }
};

inline SwFmtSurround &SwFmtSurround::operator=( const SwFmtSurround &rCpy )
{
    bAnchorOnly = rCpy.IsAnchorOnly();
    bContour = rCpy.IsContour();
    bOutside = rCpy.IsOutside();
    SfxEnumItem::SetValue( rCpy.GetValue() );
    return *this;
}

inline const SwFmtSurround &SwAttrSet::GetSurround(BOOL bInP) const
    { return (const SwFmtSurround&)Get( RES_SURROUND,bInP); }

inline const SwFmtSurround &SwFmt::GetSurround(BOOL bInP) const
    { return aSet.GetSurround(bInP); }

#endif

<|endoftext|>


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

#include "array.h"
#include "test.h"

#include <cstring>

namespace nda {

TEST(array_ref_indices) {
  int data[100];
  for (int i = 0; i < 100; i++) {
    data[i] = i;
  }

  dense_array_ref<int, 1> ref_1d(data, {100});
  for_all_indices(ref_1d.shape(), [&](int x) {
    ASSERT_EQ(ref_1d(x), x);
  });

  dense_array_ref<int, 2> ref_2d(data, {20, 5});
  ASSERT_EQ(ref_2d.width(), 20);
  ASSERT_EQ(ref_2d.height(), 5);
  ASSERT_EQ(ref_2d.rows(), 20);
  ASSERT_EQ(ref_2d.columns(), 5);
  for_all_indices(ref_2d.shape(), [&](int x, int y) {
    ASSERT_EQ(ref_2d(x, y), y*20 + x);
  });
}

TEST(reinterpret) {
  float eight = 8.0f;
  int eight_int;
  ASSERT_EQ(sizeof(eight), sizeof(eight_int));
  std::memcpy(&eight_int, &eight, sizeof(eight));

  dense_array<int, 3> int_array({4, 5, 6}, eight_int);
  dense_array_ref<float, 3> float_array = reinterpret<float>(int_array);
  ASSERT_EQ(float_array.width(), 4);
  ASSERT_EQ(float_array.height(), 5);
  ASSERT_EQ(float_array.channels(), 6);
  ASSERT_EQ(float_array.rows(), 4);
  ASSERT_EQ(float_array.columns(), 5);
  for_all_indices(int_array.shape(), [&](int x, int y, int z) {
    ASSERT_EQ(int_array(x, y, z), eight_int);
    ASSERT_EQ(float_array(x, y, z), eight);
  });
}

TEST(array_ref_copy) {
  int data[100];
  for (int i = 0; i < 100; i++) {
    data[i] = i;
  }

  array_ref_of_rank<int, 1> evens(data, {dim<>(0, 50, 2)});
  dense_array<int, 1> evens_copy = make_dense_copy(evens);
  for (int i = 0; i < 50; i++) {
    ASSERT_EQ(evens(i), i * 2);
    ASSERT_EQ(evens_copy(i), i * 2);
  }
}

TEST(array_ref_empty) {
  dense_array_ref<int, 1> null_ref(nullptr, {10});
  ASSERT(null_ref.empty());
  null_ref.set_shape({{3, 3}}, 3);
  ASSERT(null_ref.empty());
}

void f_dense(const dense_array_ref<int, 3>& r) {}
void f_const_dense(const dense_array_ref<const int, 3>& r) {}

TEST(array_ref_conversion) {
  // The correctness of shape conversion is already tested elsewhere, we just
  // want to make sure this compiles here.
  array_ref_of_rank<int, 3> null_ref(nullptr, {10, 20, 30});
  dense_array_ref<int, 3> dense_null_ref(null_ref);
  null_ref = dense_null_ref;
  array_ref_of_rank<const int, 3> const_null_ref(dense_null_ref);

  // Test conversion from array_ref<T*> to array_ref<const T*>.
  f_dense(null_ref);
  f_const_dense(null_ref);
  f_const_dense(const_null_ref);

  array_of_rank<int, 3> a({5, 10, 20});
  f_dense(a);
  f_const_dense(a);
}

TEST(array_ref_crop) {
  dense_array<int, 2> a({8, 9});
  fill_pattern(a);

  auto a_crop1_slice2 = a(range<4, 3>(), 5);
  ASSERT_EQ(a_crop1_slice2.rank(), 1);
  ASSERT_EQ(a_crop1_slice2.x().min(), 4);
  ASSERT_EQ(a_crop1_slice2.x().extent(), 3);
  //check_pattern(a_crop1_slice2);

  auto a_crop1_crop2 = a(range<>{2, 6}, range<3, 4>());
  ASSERT_EQ(a_crop1_crop2.rank(), 2);
  ASSERT_EQ(a_crop1_crop2.x().min(), 2);
  ASSERT_EQ(a_crop1_crop2.x().extent(), 6);
  ASSERT_EQ(a_crop1_crop2.y().min(), 3);
  ASSERT_EQ(a_crop1_crop2.y().extent(), 4);
  check_pattern(a_crop1_crop2);

  auto a_all1_crop2 = a(_, range<3, 4>());
  ASSERT_EQ(a_all1_crop2.rank(), 2);
  ASSERT_EQ(a_all1_crop2.x().min(), 0);
  ASSERT_EQ(a_all1_crop2.x().extent(), 8);
  ASSERT_EQ(a_all1_crop2.y().min(), 3);
  ASSERT_EQ(a_all1_crop2.y().extent(), 4);
  check_pattern(a_all1_crop2);
}

}  // namespace nda
<commit_msg>Add comment about commented test.<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "array.h"
#include "test.h"

#include <cstring>

namespace nda {

TEST(array_ref_indices) {
  int data[100];
  for (int i = 0; i < 100; i++) {
    data[i] = i;
  }

  dense_array_ref<int, 1> ref_1d(data, {100});
  for_all_indices(ref_1d.shape(), [&](int x) {
    ASSERT_EQ(ref_1d(x), x);
  });

  dense_array_ref<int, 2> ref_2d(data, {20, 5});
  ASSERT_EQ(ref_2d.width(), 20);
  ASSERT_EQ(ref_2d.height(), 5);
  ASSERT_EQ(ref_2d.rows(), 20);
  ASSERT_EQ(ref_2d.columns(), 5);
  for_all_indices(ref_2d.shape(), [&](int x, int y) {
    ASSERT_EQ(ref_2d(x, y), y*20 + x);
  });
}

TEST(reinterpret) {
  float eight = 8.0f;
  int eight_int;
  ASSERT_EQ(sizeof(eight), sizeof(eight_int));
  std::memcpy(&eight_int, &eight, sizeof(eight));

  dense_array<int, 3> int_array({4, 5, 6}, eight_int);
  dense_array_ref<float, 3> float_array = reinterpret<float>(int_array);
  ASSERT_EQ(float_array.width(), 4);
  ASSERT_EQ(float_array.height(), 5);
  ASSERT_EQ(float_array.channels(), 6);
  ASSERT_EQ(float_array.rows(), 4);
  ASSERT_EQ(float_array.columns(), 5);
  for_all_indices(int_array.shape(), [&](int x, int y, int z) {
    ASSERT_EQ(int_array(x, y, z), eight_int);
    ASSERT_EQ(float_array(x, y, z), eight);
  });
}

TEST(array_ref_copy) {
  int data[100];
  for (int i = 0; i < 100; i++) {
    data[i] = i;
  }

  array_ref_of_rank<int, 1> evens(data, {dim<>(0, 50, 2)});
  dense_array<int, 1> evens_copy = make_dense_copy(evens);
  for (int i = 0; i < 50; i++) {
    ASSERT_EQ(evens(i), i * 2);
    ASSERT_EQ(evens_copy(i), i * 2);
  }
}

TEST(array_ref_empty) {
  dense_array_ref<int, 1> null_ref(nullptr, {10});
  ASSERT(null_ref.empty());
  null_ref.set_shape({{3, 3}}, 3);
  ASSERT(null_ref.empty());
}

void f_dense(const dense_array_ref<int, 3>& r) {}
void f_const_dense(const dense_array_ref<const int, 3>& r) {}

TEST(array_ref_conversion) {
  // The correctness of shape conversion is already tested elsewhere, we just
  // want to make sure this compiles here.
  array_ref_of_rank<int, 3> null_ref(nullptr, {10, 20, 30});
  dense_array_ref<int, 3> dense_null_ref(null_ref);
  null_ref = dense_null_ref;
  array_ref_of_rank<const int, 3> const_null_ref(dense_null_ref);

  // Test conversion from array_ref<T*> to array_ref<const T*>.
  f_dense(null_ref);
  f_const_dense(null_ref);
  f_const_dense(const_null_ref);

  array_of_rank<int, 3> a({5, 10, 20});
  f_dense(a);
  f_const_dense(a);
}

TEST(array_ref_crop) {
  dense_array<int, 2> a({8, 9});
  fill_pattern(a);

  auto a_crop1_slice2 = a(range<4, 3>(), 5);
  ASSERT_EQ(a_crop1_slice2.rank(), 1);
  ASSERT_EQ(a_crop1_slice2.x().min(), 4);
  ASSERT_EQ(a_crop1_slice2.x().extent(), 3);
  // TODO: This doesn't pass because check_pattern doesn't understand
  // that there is a second dimension to the pattern.
  //check_pattern(a_crop1_slice2);

  auto a_crop1_crop2 = a(range<>{2, 6}, range<3, 4>());
  ASSERT_EQ(a_crop1_crop2.rank(), 2);
  ASSERT_EQ(a_crop1_crop2.x().min(), 2);
  ASSERT_EQ(a_crop1_crop2.x().extent(), 6);
  ASSERT_EQ(a_crop1_crop2.y().min(), 3);
  ASSERT_EQ(a_crop1_crop2.y().extent(), 4);
  check_pattern(a_crop1_crop2);

  auto a_all1_crop2 = a(_, range<3, 4>());
  ASSERT_EQ(a_all1_crop2.rank(), 2);
  ASSERT_EQ(a_all1_crop2.x().min(), 0);
  ASSERT_EQ(a_all1_crop2.x().extent(), 8);
  ASSERT_EQ(a_all1_crop2.y().min(), 3);
  ASSERT_EQ(a_all1_crop2.y().extent(), 4);
  check_pattern(a_all1_crop2);
}

}  // namespace nda
<|endoftext|>


<commit_before>/**
 * @file   measurement_conversion.hpp
 * @author Gabriel Naves da Silva
 * @date   29/06/2015
 *
 * @attention Copyright (C) 2014 UnBall Robot Soccer Team
 *
 * @brief  Measurement conversion system implementation file for vision module
 */

#include <unball/vision/measurement_conversion.hpp>

MeasurementConversion::MeasurementConversion()
{
    has_calculated_parameters_ = false;
    field_metric_width_ = field_metric_height_ = 0;
}

void MeasurementConversion::loadConfig()
{
    ros::param::get("/vision/measurement_conversion/field_width", field_metric_width_);
    ros::param::get("/vision/measurement_conversion/field_height", field_metric_height_);
}

/**
 * Calculates the necessary parameters for unit conversion (from pixel to metric, and vice-versa)
 * @param field_pixel_width The value for the width of the field, given in pixels
 * @param field_pixel_height The value for the height of the field, given in pixels
 */
void MeasurementConversion::calculateConversion(float field_pixel_width, float field_pixel_height)
{
    if (field_pixel_width < 0 or field_pixel_height < 0)
        ROS_ERROR("Invalid field pixel measurements given");

    conversion_parameters_.x = field_metric_width_ / field_pixel_width;
    conversion_parameters_.y = field_metric_height_ / field_pixel_height;

    ROS_DEBUG("Field dimensions: (%f,%f)", field_pixel_width, field_pixel_height);
    ROS_DEBUG("Conversion parameter for the x axis: %f", conversion_parameters_.x);
    ROS_DEBUG("Conversion parameter for the y axis: %f", conversion_parameters_.y);

    has_calculated_parameters_ = true;
}

/**
 * Sets the field center, for conversion from a point to the magnitude and angle notation used by the
 * robot soccer AI system
 * @param field_center the center of the field, in pixels
 */
void MeasurementConversion::setFieldCenter(cv::Point field_center)
{
    ROS_DEBUG("Setting the field center on the measurement conversion system");
    field_center_ = field_center;
}

/**
 * Converts a given pixel coordinate into the magnitude and angle notation used by the robot soccer AI system.
 * @param point_in_pixel The point to convert
 * @return The resulting magnitude and angle relative to the center of the field
 */
cv::Point2f MeasurementConversion::pixelToMagnitudeAndAngle(cv::Point point_in_pixel)
{
    if (not has_calculated_parameters_)
    {
        ROS_ERROR("Trying to make a conversion without calculating the parameters first");
        return cv::Point2f();
    }
    float magnitude, angle;
    magnitude = sqrt(pow(point_in_pixel.x - field_center_.x, 2) + pow(point_in_pixel.y - field_center_.y, 2));
    // TODO(gabri.navess@gmail.com): Find out whether this angle is correct.
    angle = atan2(point_in_pixel.y-field_center_.y, point_in_pixel.x-field_center_.x);
    return cv::Point2f(magnitude, angle);
}

/**
 * Converts a given pixel coordinate into the equivalent metric coordinate
 * @param point_in_pixel The point to convert
 * @return The resulting point
 */
cv::Point2f MeasurementConversion::convertToMetric(cv::Point point_in_pixel)
{
    if (not has_calculated_parameters_)
    {
        ROS_ERROR("Trying to make a conversion without calculating the parameters first");
        return cv::Point2f();
    }
    point_in_pixel.x -= 320;
    point_in_pixel.y -= 240;
    return cv::Point2f(point_in_pixel.x * conversion_parameters_.x,
                       point_in_pixel.y * conversion_parameters_.y);
}

/**
 * Converts a given metric coordinate into the equivalent pixel coordinate
 * @param point_in_metric The point to convert
 * @return The resulting point
 */
cv::Point MeasurementConversion::convertToPixel(cv::Point2f point_in_metric)
{
    if (not has_calculated_parameters_)
    {
        ROS_ERROR("Trying to make a conversion without calculating the parameters first");
        return cv::Point();
    }
    return cv::Point(point_in_metric.x * (1 / conversion_parameters_.x),
                     point_in_metric.y * (1 / conversion_parameters_.y));
}
<commit_msg>corrected y axis in measurement conversion<commit_after>/**
 * @file   measurement_conversion.hpp
 * @author Gabriel Naves da Silva
 * @date   29/06/2015
 *
 * @attention Copyright (C) 2014 UnBall Robot Soccer Team
 *
 * @brief  Measurement conversion system implementation file for vision module
 */

#include <unball/vision/measurement_conversion.hpp>

MeasurementConversion::MeasurementConversion()
{
    has_calculated_parameters_ = false;
    field_metric_width_ = field_metric_height_ = 0;
}

void MeasurementConversion::loadConfig()
{
    ros::param::get("/vision/measurement_conversion/field_width", field_metric_width_);
    ros::param::get("/vision/measurement_conversion/field_height", field_metric_height_);
}

/**
 * Calculates the necessary parameters for unit conversion (from pixel to metric, and vice-versa)
 * @param field_pixel_width The value for the width of the field, given in pixels
 * @param field_pixel_height The value for the height of the field, given in pixels
 */
void MeasurementConversion::calculateConversion(float field_pixel_width, float field_pixel_height)
{
    if (field_pixel_width < 0 or field_pixel_height < 0)
        ROS_ERROR("Invalid field pixel measurements given");

    conversion_parameters_.x = field_metric_width_ / field_pixel_width;
    conversion_parameters_.y = field_metric_height_ / field_pixel_height;

    ROS_DEBUG("Field dimensions: (%f,%f)", field_pixel_width, field_pixel_height);
    ROS_DEBUG("Conversion parameter for the x axis: %f", conversion_parameters_.x);
    ROS_DEBUG("Conversion parameter for the y axis: %f", conversion_parameters_.y);

    has_calculated_parameters_ = true;
}

/**
 * Sets the field center, for conversion from a point to the magnitude and angle notation used by the
 * robot soccer AI system
 * @param field_center the center of the field, in pixels
 */
void MeasurementConversion::setFieldCenter(cv::Point field_center)
{
    ROS_DEBUG("Setting the field center on the measurement conversion system");
    field_center_ = field_center;
}

/**
 * Converts a given pixel coordinate into the magnitude and angle notation used by the robot soccer AI system.
 * @param point_in_pixel The point to convert
 * @return The resulting magnitude and angle relative to the center of the field
 */
cv::Point2f MeasurementConversion::pixelToMagnitudeAndAngle(cv::Point point_in_pixel)
{
    if (not has_calculated_parameters_)
    {
        ROS_ERROR("Trying to make a conversion without calculating the parameters first");
        return cv::Point2f();
    }
    float magnitude, angle;
    magnitude = sqrt(pow(point_in_pixel.x - field_center_.x, 2) + pow(point_in_pixel.y - field_center_.y, 2));
    // TODO(gabri.navess@gmail.com): Find out whether this angle is correct.
    angle = atan2(point_in_pixel.y-field_center_.y, point_in_pixel.x-field_center_.x);
    return cv::Point2f(magnitude, angle);
}

/**
 * Converts a given pixel coordinate into the equivalent metric coordinate
 * @param point_in_pixel The point to convert
 * @return The resulting point
 */
cv::Point2f MeasurementConversion::convertToMetric(cv::Point point_in_pixel)
{
    if (not has_calculated_parameters_)
    {
        ROS_ERROR("Trying to make a conversion without calculating the parameters first");
        return cv::Point2f();
    }
    point_in_pixel.x -= 320;
    point_in_pixel.y -= 240;
    return cv::Point2f(point_in_pixel.x * conversion_parameters_.x,
                       -point_in_pixel.y * conversion_parameters_.y);
}

/**
 * Converts a given metric coordinate into the equivalent pixel coordinate
 * @param point_in_metric The point to convert
 * @return The resulting point
 */
cv::Point MeasurementConversion::convertToPixel(cv::Point2f point_in_metric)
{
    if (not has_calculated_parameters_)
    {
        ROS_ERROR("Trying to make a conversion without calculating the parameters first");
        return cv::Point();
    }
    return cv::Point(point_in_metric.x * (1 / conversion_parameters_.x),
                     point_in_metric.y * (1 / conversion_parameters_.y));
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// File FilterElectrogram.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Outputs virtual electrograms at specific locations.
//
///////////////////////////////////////////////////////////////////////////////

#include <LibUtilities/Memory/NekMemoryManager.hpp>
#include <iomanip>
#include <CardiacEPSolver/Filters/FilterElectrogram.h>

namespace Nektar
{
    std::string FilterElectrogram::className =
            SolverUtils::GetFilterFactory().RegisterCreatorFunction(
                    "Electrogram",
                    FilterElectrogram::create);

    /**
     *
     */
    FilterElectrogram::FilterElectrogram(
            const LibUtilities::SessionReaderSharedPtr &pSession,
            const std::map<std::string, std::string> &pParams)
        : Filter(pSession)
    {
        if (pParams.find("OutputFile") == pParams.end())
        {
            m_outputFile = m_session->GetSessionName();
        }
        else
        {
            ASSERTL0(!(pParams.find("OutputFile")->second.empty()),
                     "Missing parameter 'OutputFile'.");
            m_outputFile = pParams.find("OutputFile")->second;
        }
        if (!(m_outputFile.length() >= 4
              && m_outputFile.substr(m_outputFile.length() - 4) == ".ecg"))
        {
            m_outputFile += ".ecg";
        }

        if (pParams.find("OutputFrequency") == pParams.end())
        {
            m_outputFrequency = 1;
        }
        else
        {
            m_outputFrequency =
                    atoi(pParams.find("OutputFrequency")->second.c_str());
        }

        ASSERTL0(pParams.find("Points") != pParams.end(),
                 "Missing parameter 'Points'.");
        m_electrogramStream.str(pParams.find("Points")->second);
        m_index = 0;
    }

    /**
     *
     */
    FilterElectrogram::~FilterElectrogram()
    {

    }

    /**
     *
     */
    void FilterElectrogram::v_Initialise(
            const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields,
            const NekDouble &time)
    {
        ASSERTL0(!m_electrogramStream.fail(),
                 "No history points in stream.");

        m_index = 0;
        Array<OneD, NekDouble>  gloCoord(3,0.0);
        LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();

        // Read electrogram points
        // Always use dim = 3 to allow electrode to be above surface
        const int dim = 3;
        const NekDouble tol = 1e-06;
        int i = 0;

        while (!m_electrogramStream.fail())
        {
            m_electrogramStream >> gloCoord[0] >> gloCoord[1] >> gloCoord[2];
            if (!m_electrogramStream.fail())
            {
                ASSERTL0(pFields[0]->GetExpIndex(gloCoord, tol) == -1,
                         "Electrogram point must lie outside of domain: ("
                        + boost::lexical_cast<string>(gloCoord[0]) + ","
                        + boost::lexical_cast<string>(gloCoord[1]) + ","
                        + boost::lexical_cast<string>(gloCoord[2]) + ")");

                SpatialDomains::PointGeomSharedPtr vert
                    = MemoryManager<SpatialDomains::PointGeom>
                    ::AllocateSharedPtr(dim, i, gloCoord[0],
                                        gloCoord[1], gloCoord[2]);

                m_electrogramPoints.push_back(vert);
                ++i;
            }
        }

        if (vComm->GetRank() == 0)
        {
            // Open output stream
            m_outputStream.open(m_outputFile.c_str());
            m_outputStream << "# Electrogram data for variables (:";

            for (i = 0; i < pFields.num_elements(); ++i)
            {
                m_outputStream << m_session->GetVariable(i) <<",";
            }

            m_outputStream << ") at points:" << endl;

            for (i = 0; i < m_electrogramPoints.size(); ++i)
            {
                m_electrogramPoints[i]->GetCoords(  gloCoord[0],
                                                gloCoord[1],
                                                gloCoord[2]);

                m_outputStream << "# \t" << i;
                m_outputStream.width(8);
                m_outputStream << gloCoord[0];
                m_outputStream.width(8);
                m_outputStream << gloCoord[1];
                m_outputStream.width(8);
                m_outputStream << gloCoord[2];
                m_outputStream << endl;
            }
        }

        // Compute the distance function for each electrogram point
        const unsigned int nq   = pFields[0]->GetNpoints();
        const unsigned int npts = m_electrogramPoints.size();
        NekDouble px, py, pz;
        m_grad_R_x = Array<OneD, Array<OneD, NekDouble> >(npts);
        m_grad_R_y = Array<OneD, Array<OneD, NekDouble> >(npts);
        m_grad_R_z = Array<OneD, Array<OneD, NekDouble> >(npts);

        Array<OneD, NekDouble> x(nq);
        Array<OneD, NekDouble> y(nq);
        Array<OneD, NekDouble> z(nq);

        Array<OneD, NekDouble> oneOverR(nq);
        for (unsigned int i = 0; i < npts; ++i)
        {
            m_grad_R_x[i] = Array<OneD, NekDouble>(nq);
            m_grad_R_y[i] = Array<OneD, NekDouble>(nq);
            m_grad_R_z[i] = Array<OneD, NekDouble>(nq);

            // Compute 1/R
            m_electrogramPoints[i]->GetCoords(px,py,pz);

            pFields[0]->GetCoords(x,y,z);

            Vmath::Sadd   (nq, -px, x, 1, x, 1);
            Vmath::Sadd   (nq, -py, y, 1, y, 1);
            Vmath::Sadd   (nq, -pz, z, 1, z, 1);
            Vmath::Vvtvvtp(nq, x, 1, x, 1, y, 1, y, 1, oneOverR, 1);
            Vmath::Vvtvp  (nq, z, 1, z, 1, oneOverR, 1, oneOverR, 1);
            Vmath::Vsqrt  (nq, oneOverR, 1, oneOverR, 1);
            Vmath::Sdiv   (nq, 1.0, oneOverR, 1, oneOverR, 1);

            // Compute grad 1/R
            pFields[0]->PhysDeriv(oneOverR, m_grad_R_x[i], m_grad_R_y[i],
                                            m_grad_R_z[i]);
        }

        // Compute electrogram point for initial condition
        v_Update(pFields, time);
    }

    /**
     *
     */
    void FilterElectrogram::v_Update(
            const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields,
            const NekDouble &time)
    {
        // Only output every m_outputFrequency.
        if ((m_index++) % m_outputFrequency)
        {
            return;
        }

        const unsigned int nq = pFields[0]->GetNpoints();
        const unsigned int npoints = m_electrogramPoints.size();
        LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();

        unsigned int i = 0;
        Array<OneD, NekDouble> e(npoints);

        // Compute grad V
        Array<OneD, NekDouble> grad_V_x(nq), grad_V_y(nq), grad_V_z(nq);
        pFields[0]->PhysDeriv(pFields[0]->GetPhys(),
                              grad_V_x, grad_V_y, grad_V_z);

        for (i = 0; i < npoints; ++i)
        {
            // Multiply together
            Array<OneD, NekDouble> output(nq);
            Vmath::Vvtvvtp(nq, m_grad_R_x[i], 1, grad_V_x, 1, m_grad_R_y[i], 1,
                               grad_V_y,      1, output,   1);
            Vmath::Vvtvp  (nq, m_grad_R_z[i], 1, grad_V_z, 1, output, 1,
                               output,        1);

            e[i] = pFields[0]->Integral(output);
        }

        // Exchange history data
        // This could be improved to reduce communication but works for now
        vComm->AllReduce(e, LibUtilities::ReduceSum);

        // Only the root process writes out electrogram data
        if (vComm->GetRank() == 0)
        {
            m_outputStream.width(8);
            m_outputStream << setprecision(6) << time;

            // Write data values point by point
            for (i = 0; i < m_electrogramPoints.size(); ++i)
            {
                m_outputStream.width(25);
                m_outputStream << setprecision(16) << e[i];
            }
            m_outputStream << endl;
        }
    }

    /**
     *
     */
    void FilterElectrogram::v_Finalise(
            const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields,
            const NekDouble &time)
    {
        if (pFields[0]->GetComm()->GetRank() == 0)
        {
            m_outputStream.close();
        }
    }

    /**
     *
     */
    bool FilterElectrogram::v_IsTimeDependent()
    {
        return true;
    }
}
<commit_msg>Removed check in electrogram filter.<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// File FilterElectrogram.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Outputs virtual electrograms at specific locations.
//
///////////////////////////////////////////////////////////////////////////////

#include <LibUtilities/Memory/NekMemoryManager.hpp>
#include <iomanip>
#include <CardiacEPSolver/Filters/FilterElectrogram.h>

namespace Nektar
{
    std::string FilterElectrogram::className =
            SolverUtils::GetFilterFactory().RegisterCreatorFunction(
                    "Electrogram",
                    FilterElectrogram::create);

    /**
     *
     */
    FilterElectrogram::FilterElectrogram(
            const LibUtilities::SessionReaderSharedPtr &pSession,
            const std::map<std::string, std::string> &pParams)
        : Filter(pSession)
    {
        if (pParams.find("OutputFile") == pParams.end())
        {
            m_outputFile = m_session->GetSessionName();
        }
        else
        {
            ASSERTL0(!(pParams.find("OutputFile")->second.empty()),
                     "Missing parameter 'OutputFile'.");
            m_outputFile = pParams.find("OutputFile")->second;
        }
        if (!(m_outputFile.length() >= 4
              && m_outputFile.substr(m_outputFile.length() - 4) == ".ecg"))
        {
            m_outputFile += ".ecg";
        }

        if (pParams.find("OutputFrequency") == pParams.end())
        {
            m_outputFrequency = 1;
        }
        else
        {
            m_outputFrequency =
                    atoi(pParams.find("OutputFrequency")->second.c_str());
        }

        ASSERTL0(pParams.find("Points") != pParams.end(),
                 "Missing parameter 'Points'.");
        m_electrogramStream.str(pParams.find("Points")->second);
        m_index = 0;
    }

    /**
     *
     */
    FilterElectrogram::~FilterElectrogram()
    {

    }

    /**
     *
     */
    void FilterElectrogram::v_Initialise(
            const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields,
            const NekDouble &time)
    {
        ASSERTL0(!m_electrogramStream.fail(),
                 "No history points in stream.");

        m_index = 0;
        Array<OneD, NekDouble>  gloCoord(3,0.0);
        LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();

        // Read electrogram points
        // Always use dim = 3 to allow electrode to be above surface
        const int dim = 3;
        const NekDouble tol = 1e-06;
        int i = 0;

        while (!m_electrogramStream.fail())
        {
            m_electrogramStream >> gloCoord[0] >> gloCoord[1] >> gloCoord[2];
            if (!m_electrogramStream.fail())
            {
                SpatialDomains::PointGeomSharedPtr vert
                    = MemoryManager<SpatialDomains::PointGeom>
                    ::AllocateSharedPtr(dim, i, gloCoord[0],
                                        gloCoord[1], gloCoord[2]);

                m_electrogramPoints.push_back(vert);
                ++i;
            }
        }

        if (vComm->GetRank() == 0)
        {
            // Open output stream
            m_outputStream.open(m_outputFile.c_str());
            m_outputStream << "# Electrogram data for variables (:";

            for (i = 0; i < pFields.num_elements(); ++i)
            {
                m_outputStream << m_session->GetVariable(i) <<",";
            }

            m_outputStream << ") at points:" << endl;

            for (i = 0; i < m_electrogramPoints.size(); ++i)
            {
                m_electrogramPoints[i]->GetCoords(  gloCoord[0],
                                                gloCoord[1],
                                                gloCoord[2]);

                m_outputStream << "# \t" << i;
                m_outputStream.width(8);
                m_outputStream << gloCoord[0];
                m_outputStream.width(8);
                m_outputStream << gloCoord[1];
                m_outputStream.width(8);
                m_outputStream << gloCoord[2];
                m_outputStream << endl;
            }
        }

        // Compute the distance function for each electrogram point
        const unsigned int nq   = pFields[0]->GetNpoints();
        const unsigned int npts = m_electrogramPoints.size();
        NekDouble px, py, pz;
        m_grad_R_x = Array<OneD, Array<OneD, NekDouble> >(npts);
        m_grad_R_y = Array<OneD, Array<OneD, NekDouble> >(npts);
        m_grad_R_z = Array<OneD, Array<OneD, NekDouble> >(npts);

        Array<OneD, NekDouble> x(nq);
        Array<OneD, NekDouble> y(nq);
        Array<OneD, NekDouble> z(nq);

        Array<OneD, NekDouble> oneOverR(nq);
        for (unsigned int i = 0; i < npts; ++i)
        {
            m_grad_R_x[i] = Array<OneD, NekDouble>(nq);
            m_grad_R_y[i] = Array<OneD, NekDouble>(nq);
            m_grad_R_z[i] = Array<OneD, NekDouble>(nq);

            // Compute 1/R
            m_electrogramPoints[i]->GetCoords(px,py,pz);

            pFields[0]->GetCoords(x,y,z);

            Vmath::Sadd   (nq, -px, x, 1, x, 1);
            Vmath::Sadd   (nq, -py, y, 1, y, 1);
            Vmath::Sadd   (nq, -pz, z, 1, z, 1);
            Vmath::Vvtvvtp(nq, x, 1, x, 1, y, 1, y, 1, oneOverR, 1);
            Vmath::Vvtvp  (nq, z, 1, z, 1, oneOverR, 1, oneOverR, 1);
            Vmath::Vsqrt  (nq, oneOverR, 1, oneOverR, 1);
            Vmath::Sdiv   (nq, 1.0, oneOverR, 1, oneOverR, 1);

            // Compute grad 1/R
            pFields[0]->PhysDeriv(oneOverR, m_grad_R_x[i], m_grad_R_y[i],
                                            m_grad_R_z[i]);
        }

        // Compute electrogram point for initial condition
        v_Update(pFields, time);
    }

    /**
     *
     */
    void FilterElectrogram::v_Update(
            const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields,
            const NekDouble &time)
    {
        // Only output every m_outputFrequency.
        if ((m_index++) % m_outputFrequency)
        {
            return;
        }

        const unsigned int nq = pFields[0]->GetNpoints();
        const unsigned int npoints = m_electrogramPoints.size();
        LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();

        unsigned int i = 0;
        Array<OneD, NekDouble> e(npoints);

        // Compute grad V
        Array<OneD, NekDouble> grad_V_x(nq), grad_V_y(nq), grad_V_z(nq);
        pFields[0]->PhysDeriv(pFields[0]->GetPhys(),
                              grad_V_x, grad_V_y, grad_V_z);

        for (i = 0; i < npoints; ++i)
        {
            // Multiply together
            Array<OneD, NekDouble> output(nq);
            Vmath::Vvtvvtp(nq, m_grad_R_x[i], 1, grad_V_x, 1, m_grad_R_y[i], 1,
                               grad_V_y,      1, output,   1);
            Vmath::Vvtvp  (nq, m_grad_R_z[i], 1, grad_V_z, 1, output, 1,
                               output,        1);

            e[i] = pFields[0]->Integral(output);
        }

        // Exchange history data
        // This could be improved to reduce communication but works for now
        vComm->AllReduce(e, LibUtilities::ReduceSum);

        // Only the root process writes out electrogram data
        if (vComm->GetRank() == 0)
        {
            m_outputStream.width(8);
            m_outputStream << setprecision(6) << time;

            // Write data values point by point
            for (i = 0; i < m_electrogramPoints.size(); ++i)
            {
                m_outputStream.width(25);
                m_outputStream << setprecision(16) << e[i];
            }
            m_outputStream << endl;
        }
    }

    /**
     *
     */
    void FilterElectrogram::v_Finalise(
            const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields,
            const NekDouble &time)
    {
        if (pFields[0]->GetComm()->GetRank() == 0)
        {
            m_outputStream.close();
        }
    }

    /**
     *
     */
    bool FilterElectrogram::v_IsTimeDependent()
    {
        return true;
    }
}
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2016 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* 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 version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_COMPONENT_ENGINE_MESHSAMPLER_INL
#define SOFA_COMPONENT_ENGINE_MESHSAMPLER_INL

#include <SofaGeneralEngine/MeshSampler.h>
#include <sofa/helper/gl/template.h>
#include <iostream>

namespace sofa
{

namespace component
{

namespace engine
{

using namespace sofa::helper;
using namespace sofa::defaulttype;
using namespace core::objectmodel;

template <class DataTypes>
MeshSampler<DataTypes>::MeshSampler()
    : DataEngine()
    , number(initData(&number, (unsigned int)1, "number", "Sample number"))
    , position(initData(&position,"position","Input positions."))
    , f_edges(initData(&f_edges,"edges","Input edges for geodesic sampling (Euclidean distances are used if not specified)."))
    , maxIter(initData(&maxIter, (unsigned int)100, "maxIter", "Max number of Lloyd iterations."))
    , outputIndices(initData(&outputIndices,"outputIndices","Computed sample indices."))
    , outputPosition(initData(&outputPosition,"outputPosition","Computed sample coordinates."))
{
}

template <class DataTypes>
void MeshSampler<DataTypes>::init()
{
    addInput(&number);
    addInput(&position);
    addInput(&f_edges);
    addInput(&maxIter);
    addOutput(&outputIndices);
    addOutput(&outputPosition);
    setDirtyValue();
}

template <class DataTypes>
void MeshSampler<DataTypes>::update()
{
    sofa::helper::ReadAccessor< Data< VecCoord > > pos = this->position;

    number.updateIfDirty();
    f_edges.updateIfDirty();
    maxIter.updateIfDirty();

    cleanDirty();

    VVI ngb;    if(this->f_edges.getValue().size()!=0) computeNeighbors(ngb); // one ring neighbors from edges
    VI voronoi;
    VD distances;

    // farthestPointSampling
    farthestPointSampling(distances,voronoi,ngb);

    // Lloyd
    unsigned int count=0;
    while(count<this->maxIter.getValue())
    {
        if(!LLoyd(distances,voronoi,ngb)) break;
        count++;
    }
    if (this->f_printLog.getValue()) std::cout<<this->getName()<<": Lloyd relaxation done in "<<count<<" iterations\n";

    // get export position from indices
    sofa::helper::WriteOnlyAccessor< Data< VI > > ind = this->outputIndices;
    sofa::helper::WriteOnlyAccessor< Data< VecCoord > > outPos = this->outputPosition;
    outPos.resize(ind.size());		for (unsigned int i=0; i<ind.size(); ++i)  outPos[i]=pos[ind[i]];

}

template <class DataTypes>
void MeshSampler<DataTypes>::computeNeighbors(VVI& ngb)
{
    sofa::helper::ReadAccessor< Data< SeqEdges > > edges = this->f_edges;
    unsigned int nbp=this->position.getValue().size();
    ngb.resize(nbp);    for(unsigned int i=0;i<nbp;i++) ngb[i].clear();
    for (unsigned int j = 0; j<edges.size(); j++)
    {
        ngb[edges[j][0]].push_back ( edges[j][1] );
        ngb[edges[j][1]].push_back ( edges[j][0] );
    }
}

template <class DataTypes>
void MeshSampler<DataTypes>::farthestPointSampling(VD& distances,VI& voronoi,const VVI& ngb)
{
    sofa::helper::WriteOnlyAccessor< Data< VI > > ind = this->outputIndices;

    ind.clear();
    ind.push_back(0); // add first point

    computeDistances( distances, voronoi, ngb);

    unsigned int nbp = this->position.getValue().size(), nbc=this->number.getValue();
    if(nbc>nbp) nbc=nbp;

    while(ind.size()<nbc)
    {
        Real dmax=0; ID imax;
        for (unsigned int i=0; i<distances.size(); i++) if(distances[i]>dmax) {dmax=distances[i]; imax=(ID)i;}
        if(dmax==0) break;
        else ind.push_back(imax);
        computeDistances( distances, voronoi, ngb);
    }

    if (this->f_printLog.getValue()) std::cout<<this->getName()<<": farthestPointSampling done\n";
}

template <class DataTypes>
bool MeshSampler<DataTypes>::LLoyd(VD& distances,VI& voronoi,const VVI& ngb)
{
    sofa::helper::WriteOnlyAccessor< Data< VI > > ind = this->outputIndices;
    sofa::helper::ReadAccessor< Data< VecCoord > > pos = this->position;

    unsigned int nbp = pos.size(), nbs = ind.size();

    // update voronoi region centers
    VecCoord center(nbs);
    VI nb(nbs);
    for(unsigned int i=0;i<nbs;i++) { center[i]=Coord(); nb[i]=0;    }
    for(unsigned int i=0;i<nbp;i++) { center[voronoi[i]]+=pos[i]; nb[voronoi[i]]+=1; }
    for(unsigned int i=0;i<nbs;i++) center[i]/=(Real)nb[i];

    // replace each sample by the closest point from the region center
    VD d(nbp);
    for(unsigned int i=0;i<nbp;i++) d[i]=(pos[i]-center[voronoi[i]]).norm2();
    VD dmin(nbs);
    for(unsigned int i=0;i<nbs;i++) dmin[i]=d[ind[i]];
    bool changed=false;
    for(unsigned int i=0;i<nbp;i++) if(d[i]<dmin[voronoi[i]]) { dmin[voronoi[i]]=d[i]; ind[voronoi[i]]=i; changed=true;}

    // update distances
    computeDistances( distances, voronoi, ngb);

    return changed;
}

template <class DataTypes>
void MeshSampler<DataTypes>::computeDistances(VD& distances, VI& voronoi,const VVI& ngb)
{
    sofa::helper::WriteOnlyAccessor< Data< VI > > ind = this->outputIndices;
    sofa::helper::ReadAccessor< Data< VecCoord > > pos = this->position;

    unsigned int nbp = pos.size();
    distances.resize(nbp); for (unsigned int i=0; i<nbp; i++)  distances[i]=std::numeric_limits<Real>::max();
    voronoi.resize(nbp);

    if(this->f_edges.getValue().size()==0)  // use Euclidean distances
    {
        for (unsigned int i=0; i<nbp; i++)
        {
            for (unsigned int j=0; j<ind.size(); j++)
            {
                Real d=(pos[i] - pos[ind[j]]).norm2();
                if(d<distances[i]) { distances[i]=d; voronoi[i]=j;}
            }
        }
    }
    else
    {
        typedef std::pair<Real,ID> DistanceToPoint;
        std::set<DistanceToPoint> q; // priority queue
        typename std::set<DistanceToPoint>::iterator qit;

        for (unsigned int i=0; i<ind.size(); i++)
        {
            q.insert( DistanceToPoint((Real)0,ind[i]) );
            distances[ind[i]]=0;
            voronoi[ind[i]]=i;
        }

        while( !q.empty() )
        {
            DistanceToPoint top = *q.begin();
            q.erase(q.begin());
            ID v = top.second;

            for (unsigned int i=0 ; i<ngb[v].size(); ++i)
            {
                ID v2 = ngb[v][i];

                Real d = distances[v] + (pos[v] - pos[v2]).norm();
                if(distances[v2] > d )
                {
                    qit=q.find(DistanceToPoint(distances[v2],v2));
                    if(qit != q.end()) q.erase(qit);
                    voronoi[v2]=voronoi[v];
                    distances[v2] = d;
                    q.insert( DistanceToPoint(d,v2) );
                }
            }
        }
    }
}

template <class DataTypes>
void MeshSampler<DataTypes>::draw(const core::visual::VisualParams* /*vparams*/)
{

}

} // namespace engine

} // namespace component

} // namespace sofa

#endif
<commit_msg>cleaning MeshSampler logging<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2016 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* 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 version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_COMPONENT_ENGINE_MESHSAMPLER_INL
#define SOFA_COMPONENT_ENGINE_MESHSAMPLER_INL

#include <SofaGeneralEngine/MeshSampler.h>
#include <sofa/helper/gl/template.h>
#include <iostream>

namespace sofa
{

namespace component
{

namespace engine
{

using namespace sofa::helper;
using namespace sofa::defaulttype;
using namespace core::objectmodel;

template <class DataTypes>
MeshSampler<DataTypes>::MeshSampler()
    : DataEngine()
    , number(initData(&number, (unsigned int)1, "number", "Sample number"))
    , position(initData(&position,"position","Input positions."))
    , f_edges(initData(&f_edges,"edges","Input edges for geodesic sampling (Euclidean distances are used if not specified)."))
    , maxIter(initData(&maxIter, (unsigned int)100, "maxIter", "Max number of Lloyd iterations."))
    , outputIndices(initData(&outputIndices,"outputIndices","Computed sample indices."))
    , outputPosition(initData(&outputPosition,"outputPosition","Computed sample coordinates."))
{
}

template <class DataTypes>
void MeshSampler<DataTypes>::init()
{
    addInput(&number);
    addInput(&position);
    addInput(&f_edges);
    addInput(&maxIter);
    addOutput(&outputIndices);
    addOutput(&outputPosition);
    setDirtyValue();
}

template <class DataTypes>
void MeshSampler<DataTypes>::update()
{
    sofa::helper::ReadAccessor< Data< VecCoord > > pos = this->position;

    number.updateIfDirty();
    f_edges.updateIfDirty();
    maxIter.updateIfDirty();

    cleanDirty();

    VVI ngb;    if(this->f_edges.getValue().size()!=0) computeNeighbors(ngb); // one ring neighbors from edges
    VI voronoi;
    VD distances;

    // farthestPointSampling
    farthestPointSampling(distances,voronoi,ngb);

    // Lloyd
    unsigned int count=0;
    while(count<this->maxIter.getValue())
    {
        if(!LLoyd(distances,voronoi,ngb)) break;
        count++;
    }
    if (this->f_printLog.getValue()) sout<<this->getPathName()<<": Lloyd relaxation done in "<<count<<" iterations"<<sendl;

    // get export position from indices
    sofa::helper::WriteOnlyAccessor< Data< VI > > ind = this->outputIndices;
    sofa::helper::WriteOnlyAccessor< Data< VecCoord > > outPos = this->outputPosition;
    outPos.resize(ind.size());		for (unsigned int i=0; i<ind.size(); ++i)  outPos[i]=pos[ind[i]];

}

template <class DataTypes>
void MeshSampler<DataTypes>::computeNeighbors(VVI& ngb)
{
    sofa::helper::ReadAccessor< Data< SeqEdges > > edges = this->f_edges;
    unsigned int nbp=this->position.getValue().size();
    ngb.resize(nbp);    for(unsigned int i=0;i<nbp;i++) ngb[i].clear();
    for (unsigned int j = 0; j<edges.size(); j++)
    {
        ngb[edges[j][0]].push_back ( edges[j][1] );
        ngb[edges[j][1]].push_back ( edges[j][0] );
    }
}

template <class DataTypes>
void MeshSampler<DataTypes>::farthestPointSampling(VD& distances,VI& voronoi,const VVI& ngb)
{
    sofa::helper::WriteOnlyAccessor< Data< VI > > ind = this->outputIndices;

    ind.clear();
    ind.push_back(0); // add first point

    computeDistances( distances, voronoi, ngb);

    unsigned int nbp = this->position.getValue().size(), nbc=this->number.getValue();
    if(nbc>nbp) nbc=nbp;

    while(ind.size()<nbc)
    {
        Real dmax=0; ID imax;
        for (unsigned int i=0; i<distances.size(); i++) if(distances[i]>dmax) {dmax=distances[i]; imax=(ID)i;}
        if(dmax==0) break;
        else ind.push_back(imax);
        computeDistances( distances, voronoi, ngb);
    }

    if (this->f_printLog.getValue()) sout<<this->getPathName()<<": farthestPointSampling done"<<sendl;
}

template <class DataTypes>
bool MeshSampler<DataTypes>::LLoyd(VD& distances,VI& voronoi,const VVI& ngb)
{
    sofa::helper::WriteOnlyAccessor< Data< VI > > ind = this->outputIndices;
    sofa::helper::ReadAccessor< Data< VecCoord > > pos = this->position;

    unsigned int nbp = pos.size(), nbs = ind.size();

    // update voronoi region centers
    VecCoord center(nbs);
    VI nb(nbs);
    for(unsigned int i=0;i<nbs;i++) { center[i]=Coord(); nb[i]=0;    }
    for(unsigned int i=0;i<nbp;i++) { center[voronoi[i]]+=pos[i]; nb[voronoi[i]]+=1; }
    for(unsigned int i=0;i<nbs;i++) center[i]/=(Real)nb[i];

    // replace each sample by the closest point from the region center
    VD d(nbp);
    for(unsigned int i=0;i<nbp;i++) d[i]=(pos[i]-center[voronoi[i]]).norm2();
    VD dmin(nbs);
    for(unsigned int i=0;i<nbs;i++) dmin[i]=d[ind[i]];
    bool changed=false;
    for(unsigned int i=0;i<nbp;i++) if(d[i]<dmin[voronoi[i]]) { dmin[voronoi[i]]=d[i]; ind[voronoi[i]]=i; changed=true;}

    // update distances
    computeDistances( distances, voronoi, ngb);

    return changed;
}

template <class DataTypes>
void MeshSampler<DataTypes>::computeDistances(VD& distances, VI& voronoi,const VVI& ngb)
{
    sofa::helper::WriteOnlyAccessor< Data< VI > > ind = this->outputIndices;
    sofa::helper::ReadAccessor< Data< VecCoord > > pos = this->position;

    unsigned int nbp = pos.size();
    distances.resize(nbp); for (unsigned int i=0; i<nbp; i++)  distances[i]=std::numeric_limits<Real>::max();
    voronoi.resize(nbp);

    if(this->f_edges.getValue().size()==0)  // use Euclidean distances
    {
        for (unsigned int i=0; i<nbp; i++)
        {
            for (unsigned int j=0; j<ind.size(); j++)
            {
                Real d=(pos[i] - pos[ind[j]]).norm2();
                if(d<distances[i]) { distances[i]=d; voronoi[i]=j;}
            }
        }
    }
    else
    {
        typedef std::pair<Real,ID> DistanceToPoint;
        std::set<DistanceToPoint> q; // priority queue
        typename std::set<DistanceToPoint>::iterator qit;

        for (unsigned int i=0; i<ind.size(); i++)
        {
            q.insert( DistanceToPoint((Real)0,ind[i]) );
            distances[ind[i]]=0;
            voronoi[ind[i]]=i;
        }

        while( !q.empty() )
        {
            DistanceToPoint top = *q.begin();
            q.erase(q.begin());
            ID v = top.second;

            for (unsigned int i=0 ; i<ngb[v].size(); ++i)
            {
                ID v2 = ngb[v][i];

                Real d = distances[v] + (pos[v] - pos[v2]).norm();
                if(distances[v2] > d )
                {
                    qit=q.find(DistanceToPoint(distances[v2],v2));
                    if(qit != q.end()) q.erase(qit);
                    voronoi[v2]=voronoi[v];
                    distances[v2] = d;
                    q.insert( DistanceToPoint(d,v2) );
                }
            }
        }
    }
}

template <class DataTypes>
void MeshSampler<DataTypes>::draw(const core::visual::VisualParams* /*vparams*/)
{

}

} // namespace engine

} // namespace component

} // namespace sofa

#endif
<|endoftext|>