<commit_before>#ifndef FEATURE_MATCHING_HOUGH_HH
#define FEATURE_MATCHING_HOUGH_HH

#include <vpp/core/keypoint_trajectory.hh>
#include <vpp/core/keypoint_container.hh>
#include <vpp/core/symbols.hh>
#include <vpp/algorithms/descriptor_matcher.hh>
#include "track.hh"
#include "vpp/algorithms/Line_tracker_4_sfm/miscellanous/define.hh"

namespace vpp {

float val_diff = 0;
int nb_diff = 0;

struct feature_matching_hough_ctx {
    feature_matching_hough_ctx(box2d domain) : keypoints(domain), frame_id(0) {}

    // Keypoint container.
    // ctx.keypoint[i] to access the ith keypoint.
    keypoint_container<keypoint<int>, int> keypoints;

    // Trajectory container.
    // ctx.trajectory[i].position_at_frame(j) to access the ith keypoint position at frame j.
    std::vector<keypoint_trajectory> trajectories;

    std::vector<track> list_track;

    // Current frame id.
    int frame_id;
};

feature_matching_hough_ctx feature_matching_hough_init(box2d domain);

template <typename... OPTS>
void feature_matching_hough_update_three_first(feature_matching_hough_ctx& ftx,
                                               std::vector<float>& frame1,
                                               std::vector<float>& frame2,
                                               image2d<uchar> &frame_gradient,image2d<uchar> &frame_point,
                                               int type_video,image2d<uchar> img,
                                               int T_theta,int rhomax,bool first, Type_output type_sortie,
                                               int &id_trackers,Type_Lines type_line,Frequence freq,std::vector<vint2>& old_vects,
                                               int wkf,
                                               OPTS... options);

template <typename... OPTS>
void feature_matching_hough_update_three_first_3_frames(feature_matching_hough_ctx& ftx,
                                                        std::vector<float>& frame1,
                                                        std::vector<float>& frame2,
                                                        std::vector<float>& frame3,
                                                        int nb_matcher,
                                                        image2d<uchar> &frame_grad,
                                                        image2d<uchar> &frame_point,
                                                        std::vector<vint2>& new_values1,
                                                        int type_video,
                                                        image2d<uchar> img,
                                                        int T_theta,int rhomax,bool first,
                                                        Type_output type_sortie,int &id_trackers,
                                                        Type_Lines type_line,Frequence freq,std::list<vint2>& old_vects,
                                                        //float precision_runtime_balance = 0,
                                                        OPTS... options);

template <typename... OPTS>
void feature_matching_hough_update_three_first_mat(feature_matching_hough_ctx& ftx,
                                               std::vector<float>& frame1,
                                               std::vector<float>& frame2,
                                               Mat &frame_grad,Sclare_rho scale,
                                               int type_video,image2d<uchar> img, Mat &img_ori,
                                               int T_theta,int rhomax,bool first,
                                               Type_output type_sortie,int &id_trackers,
                                               Type_Lines type_line,Frequence freq,std::list<vint2>& old_vects,
                                               //float precision_runtime_balance = 0,
                                               OPTS... options);

template <typename... OPTS>
void feature_matching_hough_update_local(feature_matching_hough_ctx& ftx,
                                    std::vector<float>& frame1,
                                    std::vector<float>& frame2,int type_video,image2d<vuchar1> img,
                                   int T_theta,int rhomax,bool first, std::vector<vint2>& old_values,
                                   int &id_trackers,
                                   //float precision_runtime_balance = 0,
                                   OPTS... options);

float Distance_between_curve_L1(std::vector<float> frame1, std::vector<float>  frame2, int taille);

float Distance_between_curve_L2(std::vector<float> frame1, std::vector<float>  frame2,  int taille_theta, int taille_rho);

float sum_vector(std::vector<float> a);

float mean_vector(std::vector<float> a);

float sqsum(std::vector<float> a);

float stdev(std::vector<float> nums);

std::vector<float> operator-(std::vector<float> a, float b);

std::vector<float> operator*(std::vector<float> a, std::vector<float> b);

float pearsoncoeff(std::vector<float> X, std::vector<float> Y);

float Correlation_Matrix_Pearson(Eigen::MatrixXd M1,Eigen::MatrixXd M2,int taille);

std::vector<int> getDuplicata(feature_matching_hough_ctx ftx);

inline
float computeDistanceHoughSpace(float rhomax,float rho_p,float theta_p,float rho_q,float theta_q);

void brute_force_matching(std::vector<vint2> descriptor1, std::vector<vint2> descriptor2,std::vector<int>& matches,int type);
}

#include "feature_matching_hough.hpp"

#endif // FEATURE_MATCHING_HOUGH_HH
<commit_msg>Tracking through N frames<commit_after>#ifndef FEATURE_MATCHING_HOUGH_HH
#define FEATURE_MATCHING_HOUGH_HH

#include <vpp/core/keypoint_trajectory.hh>
#include <vpp/core/keypoint_container.hh>
#include <vpp/core/symbols.hh>
#include <vpp/algorithms/descriptor_matcher.hh>
#include "track.hh"
#include "vpp/algorithms/Line_tracker_4_sfm/miscellanous/define.hh"

namespace vpp {

struct feature_matching_hough_ctx {
    feature_matching_hough_ctx(box2d domain) : keypoints(domain), frame_id(0) {}

    // Keypoint container.
    // ctx.keypoint[i] to access the ith keypoint.
    keypoint_container<keypoint<int>, int> keypoints;

    // Trajectory container.
    // ctx.trajectory[i].position_at_frame(j) to access the ith keypoint position at frame j.
    std::vector<keypoint_trajectory> trajectories;

    std::vector<track> list_track;

    // Current frame id.
    int frame_id;
};

feature_matching_hough_ctx feature_matching_hough_init(box2d domain);

template <typename... OPTS>
void feature_matching_hough_update_three_first(feature_matching_hough_ctx& ftx,
                                               std::vector<float>& frame1,
                                               std::vector<float>& frame2,
                                               image2d<uchar> &frame_grad,
                                               image2d<uchar> &frame_point,
                                               Sclare_rho scale,
                                               int type_video,image2d<uchar> img,
                                               int T_theta,int rhomax,bool first,
                                               Type_output type_sortie,int &id_trackers,
                                               Type_Lines type_line,Frequence freq,
                                               std::vector<vint2>& old_clusters,
                                               int wkf,
                                               OPTS... options);

template <typename... OPTS>
void feature_matching_hough_update_N_first(feature_matching_hough_ctx& ftx,
                                               std::vector<float>& frame1,
                                               std::vector<float>& frame2,
                                               image2d<uchar> &frame_grad,
                                               image2d<uchar> &frame_point,
                                               Sclare_rho scale,
                                               int type_video,image2d<uchar> img,
                                               int T_theta,int rhomax,bool first,
                                               Type_output type_sortie,int &id_trackers,
                                               Type_Lines type_line,Frequence freq,
                                               std::vector<vint2>& old_clusters,
                                               int wkf,int N, std::list<image2d<uchar>> liste_images,
                                               OPTS... options);

float Distance_between_curve_L1(std::vector<float> frame1, std::vector<float>  frame2, int taille);

float Distance_between_curve_L2(std::vector<float> frame1, std::vector<float>  frame2,  int taille_theta, int taille_rho);

float sum_vector(std::vector<float> a);

float mean_vector(std::vector<float> a);

float sqsum(std::vector<float> a);

float stdev(std::vector<float> nums);

std::vector<float> operator-(std::vector<float> a, float b);

std::vector<float> operator*(std::vector<float> a, std::vector<float> b);

float pearsoncoeff(std::vector<float> X, std::vector<float> Y);

float Correlation_Matrix_Pearson(Eigen::MatrixXd M1,Eigen::MatrixXd M2,int taille);

std::vector<int> getDuplicata(feature_matching_hough_ctx ftx);

inline
float computeDistanceHoughSpace(float rhomax,float rho_p,float theta_p,float rho_q,float theta_q);

void brute_force_matching(std::vector<vint2> descriptor1, std::vector<vint2> descriptor2,std::vector<int>& matches,int type);
}

#include "feature_matching_hough.hpp"

#endif // FEATURE_MATCHING_HOUGH_HH
<|endoftext|>


<commit_before>#include <set>

#include "dg/analysis/ReachingDefinitions/RDMap.h"
#include "dg/analysis/ReachingDefinitions/ReachingDefinitions.h"
#include "dg/analysis/BBlocksBuilder.h"

namespace dg {
namespace analysis {
namespace rd {

RDNode UNKNOWN_MEMLOC;
RDNode *UNKNOWN_MEMORY = &UNKNOWN_MEMLOC;

void ReachingDefinitionsGraph::buildBBlocks() {
    assert(getRoot() && "No root node");

    BBlocksBuilder<RDBBlock> builder;
    _bblocks = std::move(builder.buildAndGetBlocks(getRoot()));
}

bool ReachingDefinitionsAnalysis::processNode(RDNode *node)
{
    bool changed = false;

    // merge maps from predecessors
    for (RDNode *n : node->predecessors)
        changed |= node->def_map.merge(&n->def_map,
                                       &node->overwrites /* strong update */,
                                       options.strongUpdateUnknown,
                                       *options.maxSetSize, /* max size of set of reaching definition
                                                              of one definition site */
                                       false /* merge unknown */);

    return changed;
}

void ReachingDefinitionsAnalysis::run()
{
    assert(getRoot() && "Do not have root");

    std::vector<RDNode *> to_process = getNodes(getRoot());
    std::vector<RDNode *> changed;

    // do fixpoint
    do {
        unsigned last_processed_num = to_process.size();
        changed.clear();

        for (RDNode *cur : to_process) {
            if (processNode(cur))
                changed.push_back(cur);
        }

        if (!changed.empty()) {
            to_process.clear();
            to_process = getNodes(changed /* starting set */,
                                  last_processed_num /* expected num */);

            // since changed was not empty,
            // the to_process must not be empty too
            assert(!to_process.empty());
        }
    } while (!changed.empty());
}

std::vector<RDNode *>
SSAReachingDefinitionsAnalysis::readValue(RDBBlock *block,
                                          RDNode *node,
                                          const DefSite& ds,
                                          bool addDefuse) {
    // add def-use edges to known definitions
    if (addDefuse) {
        auto defs = block->definitions.get(ds);
        node->defuse = decltype(node->defuse)(defs.begin(), defs.end());
    }

    std::vector<RDNode *> phis;
    // find out which bytes are not covered yet
    // and add phi nodes for these intervals
    auto uncovered = block->definitions.undefinedIntervals(ds);
    for (auto& interval : uncovered) {
        phis.emplace_back(graph.create(RDNodeType::PHI));
        phis.back()->addOverwrites(ds.target,
                                   interval.start,
                                   interval.length());
        if (addDefuse)
            node->defuse.push_back(phis.back());
    }

    return phis;
}

std::set<RDNode *>
SSAReachingDefinitionsAnalysis::performLvn() {
    std::set<RDNode *> allphis;

    for (RDBBlock *block : graph.blocks()) {
        // new phi nodes
        std::vector<RDNode *> phis;

        // perform Lvn for one block
        for (RDNode *node : block->getNodes()) {
            // strong update
            for (auto& ds : node->overwrites) {
                block->definitions.update(ds, node);
            }

            // weak update
            for (auto& ds : node->defs) {
                // since this is just weak update,
                // look for the previous definitions of 'ds'
                // and if there are none, add a PHI node
                auto newphis = readValue(block, node, ds,
                                         false /* do not add def-def edges */);
                phis.insert(phis.end(), newphis.begin(), newphis.end());

                block->definitions.add(ds, node);
                block->definitions.add(ds, newphis);
            }

            // is this node a use? If so then update def-use edges
            for (auto& ds : node->uses) {
                auto newphis = readValue(block, node, ds);
                phis.insert(phis.end(), newphis.begin(), newphis.end());

                // we added new phi nodes and those act as definitions,
                // so register new definitions
                block->definitions.add(ds, newphis);
            }
        }

        // add all the new phi nodes to the current block
        for (auto phi : phis) {
            block->prependAndUpdateCFG(phi);
            allphis.insert(phi);
        }
    }

    return allphis;
}

void SSAReachingDefinitionsAnalysis::performGvn(std::set<RDNode *>& phis) {
    while(!phis.empty()) {
        RDNode *phi = *(phis.begin());
        phis.erase(phis.begin());

        auto block = phi->getBBlock();
        for (auto I = block->pred_begin(), E = block->pred_end(); I != E; ++I) {
            assert(phi->overwrites.size() == 1);
            const auto& ds = *(phi->overwrites.begin());
            auto newphis = readValue(*I, phi, ds);

            for (auto phi : newphis) {
                I->prependAndUpdateCFG(phi);
                // queue the new phi for processing
                phis.insert(phi);
            }
        }

    }
}

} // namespace rd
} // namespace analysis
} // namespace dg
<commit_msg>RDA: fix adding new definitions in GVN<commit_after>#include <set>

#include "dg/analysis/ReachingDefinitions/RDMap.h"
#include "dg/analysis/ReachingDefinitions/ReachingDefinitions.h"
#include "dg/analysis/BBlocksBuilder.h"

namespace dg {
namespace analysis {
namespace rd {

RDNode UNKNOWN_MEMLOC;
RDNode *UNKNOWN_MEMORY = &UNKNOWN_MEMLOC;

void ReachingDefinitionsGraph::buildBBlocks() {
    assert(getRoot() && "No root node");

    BBlocksBuilder<RDBBlock> builder;
    _bblocks = std::move(builder.buildAndGetBlocks(getRoot()));
}

bool ReachingDefinitionsAnalysis::processNode(RDNode *node)
{
    bool changed = false;

    // merge maps from predecessors
    for (RDNode *n : node->predecessors)
        changed |= node->def_map.merge(&n->def_map,
                                       &node->overwrites /* strong update */,
                                       options.strongUpdateUnknown,
                                       *options.maxSetSize, /* max size of set of reaching definition
                                                              of one definition site */
                                       false /* merge unknown */);

    return changed;
}

void ReachingDefinitionsAnalysis::run()
{
    assert(getRoot() && "Do not have root");

    std::vector<RDNode *> to_process = getNodes(getRoot());
    std::vector<RDNode *> changed;

    // do fixpoint
    do {
        unsigned last_processed_num = to_process.size();
        changed.clear();

        for (RDNode *cur : to_process) {
            if (processNode(cur))
                changed.push_back(cur);
        }

        if (!changed.empty()) {
            to_process.clear();
            to_process = getNodes(changed /* starting set */,
                                  last_processed_num /* expected num */);

            // since changed was not empty,
            // the to_process must not be empty too
            assert(!to_process.empty());
        }
    } while (!changed.empty());
}

std::vector<RDNode *>
SSAReachingDefinitionsAnalysis::readValue(RDBBlock *block,
                                          RDNode *node,
                                          const DefSite& ds,
                                          bool addDefuse) {
    // add def-use edges to known definitions
    if (addDefuse) {
        auto defs = block->definitions.get(ds);
        node->defuse = decltype(node->defuse)(defs.begin(), defs.end());
    }

    std::vector<RDNode *> phis;
    // find out which bytes are not covered yet
    // and add phi nodes for these intervals
    auto uncovered = block->definitions.undefinedIntervals(ds);
    for (auto& interval : uncovered) {
        phis.emplace_back(graph.create(RDNodeType::PHI));
        phis.back()->addOverwrites(ds.target,
                                   interval.start,
                                   interval.length());
        if (addDefuse)
            node->defuse.push_back(phis.back());
    }

    return phis;
}

std::set<RDNode *>
SSAReachingDefinitionsAnalysis::performLvn() {
    std::set<RDNode *> allphis;

    for (RDBBlock *block : graph.blocks()) {
        // new phi nodes
        std::vector<RDNode *> phis;

        // perform Lvn for one block
        for (RDNode *node : block->getNodes()) {
            // strong update
            for (auto& ds : node->overwrites) {
                block->definitions.update(ds, node);
            }

            // weak update
            for (auto& ds : node->defs) {
                // since this is just weak update,
                // look for the previous definitions of 'ds'
                // and if there are none, add a PHI node
                auto newphis = readValue(block, node, ds,
                                         false /* do not add def-def edges */);
                phis.insert(phis.end(), newphis.begin(), newphis.end());

                block->definitions.add(ds, node);
                block->definitions.add(ds, newphis);
            }

            // is this node a use? If so then update def-use edges
            for (auto& ds : node->uses) {
                auto newphis = readValue(block, node, ds);
                phis.insert(phis.end(), newphis.begin(), newphis.end());

                // we added new phi nodes and those act as definitions,
                // so register new definitions
                block->definitions.add(ds, newphis);
            }
        }

        // add all the new phi nodes to the current block
        for (auto phi : phis) {
            block->prependAndUpdateCFG(phi);
            allphis.insert(phi);
        }
    }

    return allphis;
}

void SSAReachingDefinitionsAnalysis::performGvn(std::set<RDNode *>& phis) {
    while(!phis.empty()) {
        RDNode *phi = *(phis.begin());
        phis.erase(phis.begin());

        auto block = phi->getBBlock();
        for (auto I = block->pred_begin(), E = block->pred_end(); I != E; ++I) {
            assert(phi->overwrites.size() == 1);
            const auto& ds = *(phi->overwrites.begin());
            auto newphis = readValue(*I, phi, ds);
            assert(newphis.size() <= 1);

            // update phi nodes and block definitions
            for (auto phi : newphis) {
                I->prependAndUpdateCFG(phi);
                assert(I->definitions.get(ds).empty());
                I->definitions.update(ds, phi);
                // queue the new phi for processing
                phis.insert(phi);
            }
        }

    }
}

} // namespace rd
} // namespace analysis
} // namespace dg
<|endoftext|>


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

#include "ModelCommand.h"

#include <app/InteractionModelEngine.h>
#include <inttypes.h>

using namespace ::chip;

CHIP_ERROR ModelCommand::RunCommand()
{
    ChipLogProgress(chipTool, "Sending command to node 0x%" PRIx64, mNodeId);
    return CurrentCommissioner().GetConnectedDevice(mNodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback);
}

void ModelCommand::OnDeviceConnectedFn(void * context, ChipDevice * device)
{
    ModelCommand * command = reinterpret_cast<ModelCommand *>(context);
    VerifyOrReturn(command != nullptr, ChipLogError(chipTool, "OnDeviceConnectedFn: context is null"));
    command->SendCommand(device, command->mEndPointId);
}

void ModelCommand::OnDeviceConnectionFailureFn(void * context, PeerId peerId, CHIP_ERROR err)
{
    LogErrorOnFailure(err);

    ModelCommand * command = reinterpret_cast<ModelCommand *>(context);
    VerifyOrReturn(command != nullptr, ChipLogError(chipTool, "OnDeviceConnectionFailureFn: context is null"));
    command->SetCommandExitStatus(err);
}
<commit_msg>[chip-tool] When sending a command fails for some reasons, chip-tool ignore the error (#13690)<commit_after>/*
 *   Copyright (c) 2020 Project CHIP Authors
 *   All rights reserved.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */

#include "ModelCommand.h"

#include <app/InteractionModelEngine.h>
#include <inttypes.h>

using namespace ::chip;

CHIP_ERROR ModelCommand::RunCommand()
{
    ChipLogProgress(chipTool, "Sending command to node 0x%" PRIx64, mNodeId);
    return CurrentCommissioner().GetConnectedDevice(mNodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback);
}

void ModelCommand::OnDeviceConnectedFn(void * context, ChipDevice * device)
{
    ModelCommand * command = reinterpret_cast<ModelCommand *>(context);
    VerifyOrReturn(command != nullptr, ChipLogError(chipTool, "OnDeviceConnectedFn: context is null"));

    CHIP_ERROR err = command->SendCommand(device, command->mEndPointId);
    VerifyOrReturn(CHIP_NO_ERROR == err, command->SetCommandExitStatus(err));
}

void ModelCommand::OnDeviceConnectionFailureFn(void * context, PeerId peerId, CHIP_ERROR err)
{
    LogErrorOnFailure(err);

    ModelCommand * command = reinterpret_cast<ModelCommand *>(context);
    VerifyOrReturn(command != nullptr, ChipLogError(chipTool, "OnDeviceConnectionFailureFn: context is null"));
    command->SetCommandExitStatus(err);
}
<|endoftext|>


<commit_before>//
//     Copyright (C) Pixar. All rights reserved.
//
//     This license governs use of the accompanying software. If you
//     use the software, you accept this license. If you do not accept
//     the license, do not use the software.
//
//     1. Definitions
//     The terms "reproduce," "reproduction," "derivative works," and
//     "distribution" have the same meaning here as under U.S.
//     copyright law.  A "contribution" is the original software, or
//     any additions or changes to the software.
//     A "contributor" is any person or entity that distributes its
//     contribution under this license.
//     "Licensed patents" are a contributor's patent claims that read
//     directly on its contribution.
//
//     2. Grant of Rights
//     (A) Copyright Grant- Subject to the terms of this license,
//     including the license conditions and limitations in section 3,
//     each contributor grants you a non-exclusive, worldwide,
//     royalty-free copyright license to reproduce its contribution,
//     prepare derivative works of its contribution, and distribute
//     its contribution or any derivative works that you create.
//     (B) Patent Grant- Subject to the terms of this license,
//     including the license conditions and limitations in section 3,
//     each contributor grants you a non-exclusive, worldwide,
//     royalty-free license under its licensed patents to make, have
//     made, use, sell, offer for sale, import, and/or otherwise
//     dispose of its contribution in the software or derivative works
//     of the contribution in the software.
//
//     3. Conditions and Limitations
//     (A) No Trademark License- This license does not grant you
//     rights to use any contributor's name, logo, or trademarks.
//     (B) If you bring a patent claim against any contributor over
//     patents that you claim are infringed by the software, your
//     patent license from such contributor to the software ends
//     automatically.
//     (C) If you distribute any portion of the software, you must
//     retain all copyright, patent, trademark, and attribution
//     notices that are present in the software.
//     (D) If you distribute any portion of the software in source
//     code form, you may do so only under this license by including a
//     complete copy of this license with your distribution. If you
//     distribute any portion of the software in compiled or object
//     code form, you may only do so under a license that complies
//     with this license.
//     (E) The software is licensed "as-is." You bear the risk of
//     using it. The contributors give no express warranties,
//     guarantees or conditions. You may have additional consumer
//     rights under your local laws which this license cannot change.
//     To the extent permitted under your local laws, the contributors
//     exclude the implied warranties of merchantability, fitness for
//     a particular purpose and non-infringement.
//
#include <string.h>
#include <stdio.h>
#include "hud.h"
#include "font_image.h"

Hud::Hud() : _visible(true), _windowWidth(0), _windowHeight(0), _requiresRebuildStatic(true)
{
}

Hud::~Hud()
{
}

void
Hud::Init(int width, int height)
{
    _windowWidth = width;
    _windowHeight = height;
}

int
Hud::GetWidth() const
{
    return _windowWidth;
}

int
Hud::GetHeight() const
{
    return _windowHeight;
}

void
Hud::Clear()
{
    _radioButtons.clear();
    _checkBoxes.clear();
    _vboSource.clear();
    _requiresRebuildStatic = true;
}

bool
Hud::KeyDown(int key)
{
    for (std::vector<RadioButton>::iterator it = _radioButtons.begin();
        it != _radioButtons.end(); ++it) {

        if (key == it->shortcut) {
            int nextLocalIndex = it->localIndex;
            if (it->sharedShortcut) {
                // find checked radio button in this group
                int maxLocalIndex = 0;
                for (std::vector<RadioButton>::iterator it2 = _radioButtons.begin();
                     it2 != _radioButtons.end(); ++it2) {

                    if (it2->group == it->group) {
                        maxLocalIndex = std::max(maxLocalIndex, it2->localIndex);
                        if (it2->checked) {
                            nextLocalIndex = it2->localIndex+1;
                        }
                    }
                }
                if(nextLocalIndex > maxLocalIndex) nextLocalIndex = 0;
            }
            for (std::vector<RadioButton>::iterator it2 = _radioButtons.begin();
                 it2 != _radioButtons.end(); ++it2) {
                if (it2->group == it->group) {
                    if (it2->localIndex == nextLocalIndex) {
                        it2->checked = true;
                        it2->callback(it2->callbackData);
                    } else {
                        it2->checked = false;
                    }
                }
            }
            _requiresRebuildStatic = true;
            return true;
        }
    }
    for (std::vector<CheckBox>::iterator it = _checkBoxes.begin();
         it != _checkBoxes.end(); ++it) {

        if (key == it->shortcut) {
            it->checked = !it->checked;
            it->callback(it->checked, it->callbackData);
            _requiresRebuildStatic = true;
            return true;
        }
    }

    return false;
}

bool
Hud::MouseClick(int x, int y)
{
    for (std::vector<RadioButton>::iterator it = _radioButtons.begin();
        it != _radioButtons.end(); ++it) {

        int bx = it->x > 0 ? it->x : _windowWidth + it->x;
        int by = it->y > 0 ? it->y : _windowHeight + it->y;

        if (x >= bx && y >= by &&
            x <= (bx + it->w) && y <= (by + it->h)) {
            for (std::vector<RadioButton>::iterator it2 = _radioButtons.begin();
                 it2 != _radioButtons.end(); ++it2) {

                if (it2->group == it->group && it != it2) it2->checked = false;
            }
            it->checked = true;
            it->callback(it->callbackData);
            _requiresRebuildStatic = true;
            return true;
        }
    }
    for (std::vector<CheckBox>::iterator it = _checkBoxes.begin();
        it != _checkBoxes.end(); ++it) {

        int bx = it->x > 0 ? it->x : _windowWidth + it->x;
        int by = it->y > 0 ? it->y : _windowHeight + it->y;

        if (x >= bx && y >= by &&
            x <= (bx + it->w) && y <= (by + it->h)) {
            it->checked = !it->checked;
            it->callback(it->checked, it->callbackData);
            _requiresRebuildStatic = true;
            return true;
        }
    }
    return false;
}

void
Hud::AddCheckBox(const char *label, bool checked, int x, int y,
                   CheckBoxCallback callback, int data, int shortcut)
{
    CheckBox cb;
    cb.label = label;
    cb.checked = checked;
    cb.x = x;
    cb.y = y;
    cb.w = (int)(strlen(label)+1) * FONT_CHAR_WIDTH;
    cb.h = FONT_CHAR_HEIGHT;
    cb.callback = callback;
    cb.callbackData = data;
    cb.shortcut = shortcut;

    _checkBoxes.push_back(cb);
    _requiresRebuildStatic = true;
}

void
Hud::AddRadioButton(int group, const char *label, bool checked, int x, int y,
                      RadioButtonCallback callback, int data, int shortcut)
{
    RadioButton rb;
    rb.group = group;
    rb.label = label;
    rb.checked = checked;
    rb.x = x;
    rb.y = y;
    rb.w = (int)(strlen(label)+1) * FONT_CHAR_WIDTH;
    rb.h = FONT_CHAR_HEIGHT;
    rb.callback = callback;
    rb.callbackData = data;
    rb.shortcut = shortcut;
    rb.sharedShortcut = false;
    rb.localIndex = 0;

    for (std::vector<RadioButton>::iterator it = _radioButtons.begin();
         it != _radioButtons.end(); ++it) {
        if (it->group == group) {
            rb.localIndex = it->localIndex+1;
            if (it->shortcut == shortcut) {
                it->sharedShortcut = true;
                rb.sharedShortcut = true;
            }
        }
    }

    _radioButtons.push_back(rb);
    _requiresRebuildStatic = true;
}

int
Hud::drawChar(std::vector<float> &vboSource, int x, int y, float r, float g, float b, char ch) const
{
    const float w = 1.0f/FONT_TEXTURE_COLUMNS;
    const float h = 1.0f/FONT_TEXTURE_ROWS;

    float u = (ch%FONT_TEXTURE_COLUMNS)/(float)FONT_TEXTURE_COLUMNS;
    float v = (ch/FONT_TEXTURE_COLUMNS)/(float)FONT_TEXTURE_ROWS;

    vboSource.push_back(float(x)); vboSource.push_back(float(y));
    vboSource.push_back(r); vboSource.push_back(g); vboSource.push_back(b);
    vboSource.push_back(u); vboSource.push_back(v);

    vboSource.push_back(float(x)); vboSource.push_back(float(y+FONT_CHAR_HEIGHT));
    vboSource.push_back(r); vboSource.push_back(g); vboSource.push_back(b);
    vboSource.push_back(u); vboSource.push_back(v+h);

    vboSource.push_back(float(x+FONT_CHAR_WIDTH)); vboSource.push_back(float(y));
    vboSource.push_back(r);                 vboSource.push_back(g); vboSource.push_back(b);
    vboSource.push_back(u+w);               vboSource.push_back(v);

    vboSource.push_back(float(x+FONT_CHAR_WIDTH)); vboSource.push_back(float(y));
    vboSource.push_back(r);                 vboSource.push_back(g); vboSource.push_back(b);
    vboSource.push_back(u+w);               vboSource.push_back(v);

    vboSource.push_back(float(x)); vboSource.push_back(float(y+FONT_CHAR_HEIGHT));
    vboSource.push_back(r); vboSource.push_back(g); vboSource.push_back(b);
    vboSource.push_back(u); vboSource.push_back(v+h);

    vboSource.push_back(float(x+FONT_CHAR_WIDTH)); vboSource.push_back(float(y+FONT_CHAR_HEIGHT));
    vboSource.push_back(r);                 vboSource.push_back(g); vboSource.push_back(b);
    vboSource.push_back(u+w);               vboSource.push_back(v+h);

    return x + FONT_CHAR_WIDTH;
}

int
Hud::drawString(std::vector<float> &vboSource, int x, int y, float r, float g, float b, const char *c) const
{
    while(*c) {
        int ch = (*c) & 0x7f;
        x = drawChar(vboSource, x, y, r, g, b, ch);
        c++;
    }
    return x;
}

void
Hud::DrawString(int x, int y, const char *fmt, ...)
{
    char buf[1024];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    va_end(args);

    x = x > 0 ? x : _windowWidth + x;
    y = y > 0 ? y : _windowHeight + y;

    drawString(_vboSource, x, y, 1, 1, 1, buf);
}

void
Hud::DrawString(int x, int y, float r, float g, float b, const char *fmt, ...)
{
    char buf[1024];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    va_end(args);

    x = x > 0 ? x : _windowWidth + x;
    y = y > 0 ? y : _windowHeight + y;

    drawString(_vboSource, x, y, r, g, b, buf);
}

void
Hud::Rebuild(int width, int height)
{
    _requiresRebuildStatic = false;
    _windowWidth = width;
    _windowHeight = height;
}

bool
Hud::Flush()
{
    if (!_visible) {
        _vboSource.clear();
        return false;
    }

    if (_requiresRebuildStatic)
        Rebuild(_windowWidth, _windowHeight);

    return true;
}

bool
Hud::IsVisible() const
{
    return _visible;
}

void
Hud::SetVisible(bool visible)
{
    _visible = visible;
}

const std::vector<Hud::RadioButton> &
Hud::getRadioButtons() const
{
    return _radioButtons;
}
const std::vector<Hud::CheckBox> &
Hud::getCheckBoxes() const
{
    return _checkBoxes;
}

std::vector<float> &
Hud::getVboSource()
{
    return _vboSource;
}
<commit_msg>bail out of Rebuild call if the VBO / VAO have not been allocated yet.<commit_after>//
//     Copyright (C) Pixar. All rights reserved.
//
//     This license governs use of the accompanying software. If you
//     use the software, you accept this license. If you do not accept
//     the license, do not use the software.
//
//     1. Definitions
//     The terms "reproduce," "reproduction," "derivative works," and
//     "distribution" have the same meaning here as under U.S.
//     copyright law.  A "contribution" is the original software, or
//     any additions or changes to the software.
//     A "contributor" is any person or entity that distributes its
//     contribution under this license.
//     "Licensed patents" are a contributor's patent claims that read
//     directly on its contribution.
//
//     2. Grant of Rights
//     (A) Copyright Grant- Subject to the terms of this license,
//     including the license conditions and limitations in section 3,
//     each contributor grants you a non-exclusive, worldwide,
//     royalty-free copyright license to reproduce its contribution,
//     prepare derivative works of its contribution, and distribute
//     its contribution or any derivative works that you create.
//     (B) Patent Grant- Subject to the terms of this license,
//     including the license conditions and limitations in section 3,
//     each contributor grants you a non-exclusive, worldwide,
//     royalty-free license under its licensed patents to make, have
//     made, use, sell, offer for sale, import, and/or otherwise
//     dispose of its contribution in the software or derivative works
//     of the contribution in the software.
//
//     3. Conditions and Limitations
//     (A) No Trademark License- This license does not grant you
//     rights to use any contributor's name, logo, or trademarks.
//     (B) If you bring a patent claim against any contributor over
//     patents that you claim are infringed by the software, your
//     patent license from such contributor to the software ends
//     automatically.
//     (C) If you distribute any portion of the software, you must
//     retain all copyright, patent, trademark, and attribution
//     notices that are present in the software.
//     (D) If you distribute any portion of the software in source
//     code form, you may do so only under this license by including a
//     complete copy of this license with your distribution. If you
//     distribute any portion of the software in compiled or object
//     code form, you may only do so under a license that complies
//     with this license.
//     (E) The software is licensed "as-is." You bear the risk of
//     using it. The contributors give no express warranties,
//     guarantees or conditions. You may have additional consumer
//     rights under your local laws which this license cannot change.
//     To the extent permitted under your local laws, the contributors
//     exclude the implied warranties of merchantability, fitness for
//     a particular purpose and non-infringement.
//
#include <string.h>
#include <stdio.h>
#include "hud.h"
#include "font_image.h"

Hud::Hud() : _visible(true), _windowWidth(0), _windowHeight(0), _requiresRebuildStatic(true)
{
}

Hud::~Hud()
{
}

void
Hud::Init(int width, int height)
{
    _windowWidth = width;
    _windowHeight = height;
}

int
Hud::GetWidth() const
{
    return _windowWidth;
}

int
Hud::GetHeight() const
{
    return _windowHeight;
}

void
Hud::Clear()
{
    _radioButtons.clear();
    _checkBoxes.clear();
    _vboSource.clear();
    _requiresRebuildStatic = true;
}

bool
Hud::KeyDown(int key)
{
    for (std::vector<RadioButton>::iterator it = _radioButtons.begin();
        it != _radioButtons.end(); ++it) {

        if (key == it->shortcut) {
            int nextLocalIndex = it->localIndex;
            if (it->sharedShortcut) {
                // find checked radio button in this group
                int maxLocalIndex = 0;
                for (std::vector<RadioButton>::iterator it2 = _radioButtons.begin();
                     it2 != _radioButtons.end(); ++it2) {

                    if (it2->group == it->group) {
                        maxLocalIndex = std::max(maxLocalIndex, it2->localIndex);
                        if (it2->checked) {
                            nextLocalIndex = it2->localIndex+1;
                        }
                    }
                }
                if(nextLocalIndex > maxLocalIndex) nextLocalIndex = 0;
            }
            for (std::vector<RadioButton>::iterator it2 = _radioButtons.begin();
                 it2 != _radioButtons.end(); ++it2) {
                if (it2->group == it->group) {
                    if (it2->localIndex == nextLocalIndex) {
                        it2->checked = true;
                        it2->callback(it2->callbackData);
                    } else {
                        it2->checked = false;
                    }
                }
            }
            _requiresRebuildStatic = true;
            return true;
        }
    }
    for (std::vector<CheckBox>::iterator it = _checkBoxes.begin();
         it != _checkBoxes.end(); ++it) {

        if (key == it->shortcut) {
            it->checked = !it->checked;
            it->callback(it->checked, it->callbackData);
            _requiresRebuildStatic = true;
            return true;
        }
    }

    return false;
}

bool
Hud::MouseClick(int x, int y)
{
    for (std::vector<RadioButton>::iterator it = _radioButtons.begin();
        it != _radioButtons.end(); ++it) {

        int bx = it->x > 0 ? it->x : _windowWidth + it->x;
        int by = it->y > 0 ? it->y : _windowHeight + it->y;

        if (x >= bx && y >= by &&
            x <= (bx + it->w) && y <= (by + it->h)) {
            for (std::vector<RadioButton>::iterator it2 = _radioButtons.begin();
                 it2 != _radioButtons.end(); ++it2) {

                if (it2->group == it->group && it != it2) it2->checked = false;
            }
            it->checked = true;
            it->callback(it->callbackData);
            _requiresRebuildStatic = true;
            return true;
        }
    }
    for (std::vector<CheckBox>::iterator it = _checkBoxes.begin();
        it != _checkBoxes.end(); ++it) {

        int bx = it->x > 0 ? it->x : _windowWidth + it->x;
        int by = it->y > 0 ? it->y : _windowHeight + it->y;

        if (x >= bx && y >= by &&
            x <= (bx + it->w) && y <= (by + it->h)) {
            it->checked = !it->checked;
            it->callback(it->checked, it->callbackData);
            _requiresRebuildStatic = true;
            return true;
        }
    }
    return false;
}

void
Hud::AddCheckBox(const char *label, bool checked, int x, int y,
                   CheckBoxCallback callback, int data, int shortcut)
{
    CheckBox cb;
    cb.label = label;
    cb.checked = checked;
    cb.x = x;
    cb.y = y;
    cb.w = (int)(strlen(label)+1) * FONT_CHAR_WIDTH;
    cb.h = FONT_CHAR_HEIGHT;
    cb.callback = callback;
    cb.callbackData = data;
    cb.shortcut = shortcut;

    _checkBoxes.push_back(cb);
    _requiresRebuildStatic = true;
}

void
Hud::AddRadioButton(int group, const char *label, bool checked, int x, int y,
                      RadioButtonCallback callback, int data, int shortcut)
{
    RadioButton rb;
    rb.group = group;
    rb.label = label;
    rb.checked = checked;
    rb.x = x;
    rb.y = y;
    rb.w = (int)(strlen(label)+1) * FONT_CHAR_WIDTH;
    rb.h = FONT_CHAR_HEIGHT;
    rb.callback = callback;
    rb.callbackData = data;
    rb.shortcut = shortcut;
    rb.sharedShortcut = false;
    rb.localIndex = 0;

    for (std::vector<RadioButton>::iterator it = _radioButtons.begin();
         it != _radioButtons.end(); ++it) {
        if (it->group == group) {
            rb.localIndex = it->localIndex+1;
            if (it->shortcut == shortcut) {
                it->sharedShortcut = true;
                rb.sharedShortcut = true;
            }
        }
    }

    _radioButtons.push_back(rb);
    _requiresRebuildStatic = true;
}

int
Hud::drawChar(std::vector<float> &vboSource, int x, int y, float r, float g, float b, char ch) const
{
    const float w = 1.0f/FONT_TEXTURE_COLUMNS;
    const float h = 1.0f/FONT_TEXTURE_ROWS;

    float u = (ch%FONT_TEXTURE_COLUMNS)/(float)FONT_TEXTURE_COLUMNS;
    float v = (ch/FONT_TEXTURE_COLUMNS)/(float)FONT_TEXTURE_ROWS;

    vboSource.push_back(float(x)); vboSource.push_back(float(y));
    vboSource.push_back(r); vboSource.push_back(g); vboSource.push_back(b);
    vboSource.push_back(u); vboSource.push_back(v);

    vboSource.push_back(float(x)); vboSource.push_back(float(y+FONT_CHAR_HEIGHT));
    vboSource.push_back(r); vboSource.push_back(g); vboSource.push_back(b);
    vboSource.push_back(u); vboSource.push_back(v+h);

    vboSource.push_back(float(x+FONT_CHAR_WIDTH)); vboSource.push_back(float(y));
    vboSource.push_back(r);                 vboSource.push_back(g); vboSource.push_back(b);
    vboSource.push_back(u+w);               vboSource.push_back(v);

    vboSource.push_back(float(x+FONT_CHAR_WIDTH)); vboSource.push_back(float(y));
    vboSource.push_back(r);                 vboSource.push_back(g); vboSource.push_back(b);
    vboSource.push_back(u+w);               vboSource.push_back(v);

    vboSource.push_back(float(x)); vboSource.push_back(float(y+FONT_CHAR_HEIGHT));
    vboSource.push_back(r); vboSource.push_back(g); vboSource.push_back(b);
    vboSource.push_back(u); vboSource.push_back(v+h);

    vboSource.push_back(float(x+FONT_CHAR_WIDTH)); vboSource.push_back(float(y+FONT_CHAR_HEIGHT));
    vboSource.push_back(r);                 vboSource.push_back(g); vboSource.push_back(b);
    vboSource.push_back(u+w);               vboSource.push_back(v+h);

    return x + FONT_CHAR_WIDTH;
}

int
Hud::drawString(std::vector<float> &vboSource, int x, int y, float r, float g, float b, const char *c) const
{
    while(*c) {
        int ch = (*c) & 0x7f;
        x = drawChar(vboSource, x, y, r, g, b, ch);
        c++;
    }
    return x;
}

void
Hud::DrawString(int x, int y, const char *fmt, ...)
{
    char buf[1024];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    va_end(args);

    x = x > 0 ? x : _windowWidth + x;
    y = y > 0 ? y : _windowHeight + y;

    drawString(_vboSource, x, y, 1, 1, 1, buf);
}

void
Hud::DrawString(int x, int y, float r, float g, float b, const char *fmt, ...)
{
    char buf[1024];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    va_end(args);

    x = x > 0 ? x : _windowWidth + x;
    y = y > 0 ? y : _windowHeight + y;

    drawString(_vboSource, x, y, r, g, b, buf);
}

void
Hud::Rebuild(int width, int height)
{
    _requiresRebuildStatic = false;
    _windowWidth = width;
    _windowHeight = height;
}

bool
Hud::Flush()
{
    if (!_visible) {
        _vboSource.clear();
        return false;
    }

    if (_requiresRebuildStatic)
        Rebuild(_windowWidth, _windowHeight);

    return true;
}

bool
Hud::IsVisible() const
{
    return _visible;
}

void
Hud::SetVisible(bool visible)
{
    _visible = visible;
}

const std::vector<Hud::RadioButton> &
Hud::getRadioButtons() const
{
    return _radioButtons;
}
const std::vector<Hud::CheckBox> &
Hud::getCheckBoxes() const
{
    return _checkBoxes;
}

std::vector<float> &
Hud::getVboSource()
{
    return _vboSource;
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#include <Ancona/Framework/EntityFramework/SystemManager.hpp>
#include <Ancona/Core2D/Systems/Drawable/DrawableSystem.hpp>
#include <Ancona/Core2D/Systems/Drawable/ShapeDrawable.hpp>
#include <Ancona/Core2D/Systems/Drawable/ImageDrawable.hpp>
#include <Ancona/Platformer/Physics/PlatformPhysicsSystem.hpp>
#include <Ancona/Core2D/Systems/Drawable/AnimatedDrawable.hpp>

using namespace ild;

TEST(DrawableSystem, ShapeDrawableSize)
{
    sf::RectangleShape * sfRectShape = new sf::RectangleShape(sf::Vector2f(50.0f, 50.0f));
    ShapeDrawable shape(sfRectShape, 0, "shape");

    ASSERT_EQ(shape.size(), sf::Vector2f(50.0f, 50.0f));

    shape.scale(sf::Vector2f(2.0f, 2.0f));
    ASSERT_EQ(shape.size(), sf::Vector2f(100.0f, 100.0f));

    shape.scale(sf::Vector2f(1.3f, 1.0f));
    ASSERT_EQ(shape.size(), sf::Vector2f(65.0f, 50.0f));
}

TEST(DrawableSystem, ImageDrawableSize)
{
    SystemManager manager;
    sf::RenderWindow renderWindow;
    Entity entity = manager.CreateEntity();

    DrawableSystem & drawable = *(new DrawableSystem("drawable", renderWindow, manager));
    CameraSystem & camera = *(new CameraSystem("camera", manager));
    PlatformPhysicsSystem & physics = *(new PlatformPhysicsSystem("physics", manager));

    sf::View view;
    drawable.defaultCamera(camera.CreateComponent(manager.CreateEntity(), view, 0, &drawable, 1.0f));

    sf::Texture * texture = new sf::Texture();
    texture->create(50, 50);
    ImageDrawable * image = new ImageDrawable(texture, 0, "image");
    physics.CreateComponent(entity);
    drawable.CreateComponent(entity, image, &physics);

    manager.Update(1, UpdateStep::Draw);

    ASSERT_EQ(image->size(), sf::Vector2f(50.0f, 50.0f));

    image->scale(sf::Vector2f(2.0f, 2.0f));
    ASSERT_EQ(image->size(), sf::Vector2f(100.0f, 100.0f));

    image->scale(sf::Vector2f(1.3f, 1.0f));
    ASSERT_EQ(image->size(), sf::Vector2f(65.0f, 50.0f));
}

TEST(DrawableSystem, ContainerDrawable)
{
    ContainerDrawable containerDrawable(0, "container");
    ShapeDrawable * shape1 = new ShapeDrawable(new sf::RectangleShape(sf::Vector2f(50.0f, 50.0f)), 0, "shape1");
    containerDrawable.AddDrawable(shape1);

    ASSERT_EQ(containerDrawable.size(), sf::Vector2f(50.0f, 50.0f));

    shape1->positionOffset(sf::Vector2f(-50.0f, 0.0f));
    ShapeDrawable * shape2 = new ShapeDrawable(new sf::RectangleShape(sf::Vector2f(50.0f, 50.0f)), 0, "shape2");
    containerDrawable.AddDrawable(shape2);

    ASSERT_EQ(containerDrawable.size(), sf::Vector2f(100.0f, 50.0f));

    shape2->scale(sf::Vector2f(2.0f, 2.0f));

    ASSERT_EQ(containerDrawable.size(), sf::Vector2f(125.0f, 100.0f));

    ASSERT_EQ(containerDrawable.FindDrawable("shape2"), shape2);
    containerDrawable.RemoveDrawable("shape2");
    ASSERT_EQ(containerDrawable.FindDrawable("shape2"), nullptr);

    ASSERT_EQ(containerDrawable.size(), sf::Vector2f(50.0f, 50.0f));

    shape1->scale(sf::Vector2f(0.5f, 0.5f));

    ASSERT_EQ(containerDrawable.size(), sf::Vector2f(25.0f, 25.0f));

}

TEST(DrawableSystem, AnimatedDrawable)
{
    AnimatedDrawable animatedDrawable(0, "animatedDrawable", 1);
    ShapeDrawable * shape1 = new ShapeDrawable(new sf::RectangleShape(sf::Vector2f(50.0f, 50.0f)), 0, "shape1");
    animatedDrawable.AddFrame(shape1);

    ASSERT_EQ(animatedDrawable.size(), sf::Vector2f(50.0f, 50.0f));

    ASSERT_EQ(animatedDrawable.FindDrawable("shape1"), shape1);
    animatedDrawable.RemoveFrame("shape1");
    ASSERT_EQ(animatedDrawable.FindDrawable("shape1"), nullptr);
}<commit_msg>add scaling assert test for AnimatedDrawable<commit_after>#include <gtest/gtest.h>

#include <Ancona/Framework/EntityFramework/SystemManager.hpp>
#include <Ancona/Core2D/Systems/Drawable/DrawableSystem.hpp>
#include <Ancona/Core2D/Systems/Drawable/ShapeDrawable.hpp>
#include <Ancona/Core2D/Systems/Drawable/ImageDrawable.hpp>
#include <Ancona/Platformer/Physics/PlatformPhysicsSystem.hpp>
#include <Ancona/Core2D/Systems/Drawable/AnimatedDrawable.hpp>

using namespace ild;

TEST(DrawableSystem, ShapeDrawableSize)
{
    sf::RectangleShape * sfRectShape = new sf::RectangleShape(sf::Vector2f(50.0f, 50.0f));
    ShapeDrawable shape(sfRectShape, 0, "shape");

    ASSERT_EQ(shape.size(), sf::Vector2f(50.0f, 50.0f));

    shape.scale(sf::Vector2f(2.0f, 2.0f));
    ASSERT_EQ(shape.size(), sf::Vector2f(100.0f, 100.0f));

    shape.scale(sf::Vector2f(1.3f, 1.0f));
    ASSERT_EQ(shape.size(), sf::Vector2f(65.0f, 50.0f));
}

TEST(DrawableSystem, ImageDrawableSize)
{
    SystemManager manager;
    sf::RenderWindow renderWindow;
    Entity entity = manager.CreateEntity();

    DrawableSystem & drawable = *(new DrawableSystem("drawable", renderWindow, manager));
    CameraSystem & camera = *(new CameraSystem("camera", manager));
    PlatformPhysicsSystem & physics = *(new PlatformPhysicsSystem("physics", manager));

    sf::View view;
    drawable.defaultCamera(camera.CreateComponent(manager.CreateEntity(), view, 0, &drawable, 1.0f));

    sf::Texture * texture = new sf::Texture();
    texture->create(50, 50);
    ImageDrawable * image = new ImageDrawable(texture, 0, "image");
    physics.CreateComponent(entity);
    drawable.CreateComponent(entity, image, &physics);

    manager.Update(1, UpdateStep::Draw);

    ASSERT_EQ(image->size(), sf::Vector2f(50.0f, 50.0f));

    image->scale(sf::Vector2f(2.0f, 2.0f));
    ASSERT_EQ(image->size(), sf::Vector2f(100.0f, 100.0f));

    image->scale(sf::Vector2f(1.3f, 1.0f));
    ASSERT_EQ(image->size(), sf::Vector2f(65.0f, 50.0f));
}

TEST(DrawableSystem, ContainerDrawable)
{
    ContainerDrawable containerDrawable(0, "container");
    ShapeDrawable * shape1 = new ShapeDrawable(new sf::RectangleShape(sf::Vector2f(50.0f, 50.0f)), 0, "shape1");
    containerDrawable.AddDrawable(shape1);

    ASSERT_EQ(containerDrawable.size(), sf::Vector2f(50.0f, 50.0f));

    shape1->positionOffset(sf::Vector2f(-50.0f, 0.0f));
    ShapeDrawable * shape2 = new ShapeDrawable(new sf::RectangleShape(sf::Vector2f(50.0f, 50.0f)), 0, "shape2");
    containerDrawable.AddDrawable(shape2);

    ASSERT_EQ(containerDrawable.size(), sf::Vector2f(100.0f, 50.0f));

    shape2->scale(sf::Vector2f(2.0f, 2.0f));

    ASSERT_EQ(containerDrawable.size(), sf::Vector2f(125.0f, 100.0f));

    ASSERT_EQ(containerDrawable.FindDrawable("shape2"), shape2);
    containerDrawable.RemoveDrawable("shape2");
    ASSERT_EQ(containerDrawable.FindDrawable("shape2"), nullptr);

    ASSERT_EQ(containerDrawable.size(), sf::Vector2f(50.0f, 50.0f));

    shape1->scale(sf::Vector2f(0.5f, 0.5f));

    ASSERT_EQ(containerDrawable.size(), sf::Vector2f(25.0f, 25.0f));

}

TEST(DrawableSystem, AnimatedDrawable)
{
    AnimatedDrawable animatedDrawable(0, "animatedDrawable", 1);
    ShapeDrawable * shape1 = new ShapeDrawable(new sf::RectangleShape(sf::Vector2f(50.0f, 50.0f)), 0, "shape1");
    animatedDrawable.AddFrame(shape1);

    ASSERT_EQ(animatedDrawable.size(), sf::Vector2f(50.0f, 50.0f));

    shape1->scale(sf::Vector2f(2.0f, 2.0f));

    ASSERT_EQ(animatedDrawable.size(), sf::Vector2f(100.0f, 100.0f));

    ASSERT_EQ(animatedDrawable.FindDrawable("shape1"), shape1);
    animatedDrawable.RemoveFrame("shape1");
    ASSERT_EQ(animatedDrawable.FindDrawable("shape1"), nullptr);
}<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <CoreServices/CoreServices.h>
#include <sys/xattr.h>

#include <boost/filesystem.hpp>
#include <boost/property_tree/json_parser.hpp>

#include <osquery/filesystem.h>
#include <osquery/logger.h>
#include <osquery/sql.h>
#include <osquery/tables.h>

#include "osquery/core/conversions.h"

namespace osquery {
namespace tables {

// Structure of any OS X extended attribute
struct XAttrAttribute {
  std::string attribute_data;
  int return_value;
  int buffer_length;
};

const std::string kMetadataXattr = "com.apple.metadata:kMDItemWhereFroms";
const std::string kQuarantineXattr = "com.apple.quarantine";

const std::map<std::string, std::string> kQuarantineKeys = {
    {"quarantine_agent", "LSQuarantineAgentName"},
    {"quarantine_type", "LSQuarantineType"},
    {"quarantine_timestamp", "LSQuarantineTimeStamp"},
    {"quarantine_event_id", "LSQuarantineEventIdentifier"},
    {"quarantine_sender", "LSQuarantineSenderName"},
    {"quarantine_data_url", "LSQuarantineDataURL"},
    {"quarantine_origin_url", "LSQuarantineOriginURL"}};

// Pull the requested extended attribute from the path and return
// the XAttrAttribute structure
struct XAttrAttribute getAttribute(const std::string &path,
                                   const std::string &attribute) {
  struct XAttrAttribute x_att;
  x_att.buffer_length =
      getxattr(path.c_str(), attribute.c_str(), nullptr, (size_t)0, 0, 0);
  char *buffer = (char *)malloc(x_att.buffer_length);
  if (buffer == nullptr) {
    return x_att;
  }

  x_att.return_value = getxattr(path.c_str(), attribute.c_str(), buffer,
                                x_att.buffer_length, 0, 0);

  if (x_att.return_value != -1) {
    x_att.attribute_data = std::string(buffer, x_att.buffer_length);
  } else {
    x_att.attribute_data = std::string("");
    x_att.buffer_length = 0;
  }
  free(buffer);
  return x_att;
}

// Pull the list of all the extended attributes for a path
std::vector<std::string> parseExtendedAttributeList(const std::string &path) {
  std::vector<std::string> attributes;
  ssize_t value = listxattr(path.c_str(), nullptr, (size_t)0, 0);
  char *content = (char *)malloc(value);
  if (content == nullptr) {
    return attributes;
  }

  ssize_t ret = listxattr(path.c_str(), content, value, 0);
  if (ret == 0) {
    return attributes;
  }

  char *stable = content;
  do {
    attributes.push_back(std::string(content));
    content += attributes.back().size() + 1;
  } while (content - stable < value);
  free(stable);
  return attributes;
}

void setRow(QueryData &results,
            const std::string &path,
            const std::string &key,
            const std::string &value) {
  Row r;
  r["path"] = path;
  r["directory"] = boost::filesystem::path(path).parent_path().string();
  r["key"] = key;
  auto value_printable = isPrintable(value);
  r["value"] = (value_printable) ? value : base64Encode(value);
  r["base64"] = (value_printable) ? INTEGER(0) : INTEGER(1);
  results.push_back(r);
}

void parseWhereFrom(QueryData &results, const std::string &path) {

  CFStringRef CFPath = CFStringCreateWithCString(
      kCFAllocatorDefault, path.c_str(), kCFStringEncodingUTF8);

  MDItemRef metadata = MDItemCreate(kCFAllocatorDefault, CFPath);
  CFRelease(CFPath);

  if (metadata == nullptr) {
    VLOG(1) << "Metadata for " << path << " is null";
    return;
  }

  CFTypeRef attributes;
  attributes = MDItemCopyAttribute(metadata, kMDItemWhereFroms);
  CFRelease(metadata);

  if (attributes == nullptr) {
    VLOG(1) << "No attributes found for " << path;
    return;
  }

  CFArrayRef attribs = (CFArrayRef)attributes;
  CFIndex count = CFArrayGetCount(attribs);

  for (CFIndex i = 0; i < count; i++) {
    CFStringRef attribute = (CFStringRef)CFArrayGetValueAtIndex(attribs, i);
    auto where_from_attribute = stringFromCFString(attribute);
    if (!where_from_attribute.empty()) {
      setRow(results, path, "where_from", where_from_attribute);
    }
  }

  CFRelease(attributes);
}

void extractQuarantineProperty(const std::string &table_key_name,
                               CFTypeRef property,
                               const std::string &path,
                               QueryData &results) {
  std::string value;
  if (CFGetTypeID(property) == CFStringGetTypeID()) {
    value = stringFromCFString((CFStringRef)property);
  } else if (CFGetTypeID(property) == CFDateGetTypeID()) {
    auto unix_time = CFDateGetAbsoluteTime((CFDateRef)property) +
                     kCFAbsoluteTimeIntervalSince1970;
    value = INTEGER(std::llround(unix_time));
  } else if (CFGetTypeID(property) == CFURLGetTypeID()) {
    value = stringFromCFString(CFURLGetString((CFURLRef)property));
  }
  setRow(results, path, table_key_name, value);
}

void parseQuarantineFile(QueryData &results, const std::string &path) {
  CFURLRef url = CFURLCreateFromFileSystemRepresentation(
      kCFAllocatorDefault, (const UInt8 *)path.c_str(), path.length(), false);

  if (url == nullptr) {
    VLOG(1) << "Error obtaining CFURLRef for " << path;
    VLOG(1) << "Unable to fetch quarantine data";
    return;
  }

  CFTypeRef quarantine_properties = nullptr;
  // This is the non-10.10-symbolic version of kCFURLQuarantinePropertiesKey.
  CFStringRef qp_key = CFSTR("NSURLQuarantinePropertiesKey");
  CFURLCopyResourcePropertyForKey(url, qp_key, &quarantine_properties, nullptr);
  CFRelease(qp_key);

  if (quarantine_properties == nullptr) {
    VLOG(1) << "Error retrieving quarantine properties for " << path;
    CFRelease(url);
    return;
  }

  CFTypeRef property = nullptr;
  for (const auto &kv : kQuarantineKeys) {
    CFStringRef key = CFStringCreateWithCString(
        kCFAllocatorDefault, kv.second.c_str(), kCFStringEncodingUTF8);
    if (key != nullptr) {
      if (CFDictionaryGetValueIfPresent(
              (CFDictionaryRef)quarantine_properties, key, &property)) {
        extractQuarantineProperty(kv.first, property, path, results);
      }
      CFRelease(key);
    }
  }

  CFRelease(quarantine_properties);
  CFRelease(url);
}

// Process a file and extract all attribute information, parsed or not.
void getFileData(QueryData &results, const std::string &path) {
  std::vector<std::string> attributes = parseExtendedAttributeList(path);
  for (const auto &attribute : attributes) {
    struct XAttrAttribute x_att = getAttribute(path, attribute);

    if (attribute == kMetadataXattr) {
      parseWhereFrom(results, path);
    } else if (attribute == kQuarantineXattr) {
      parseQuarantineFile(results, path);
    } else {
      setRow(results, path, attribute, x_att.attribute_data);
    }
  }
}

QueryData genXattr(QueryContext &context) {
  QueryData results;
  auto paths = context.constraints["path"].getAll(EQUALS);

  for (const auto &path_string : paths) {
    boost::filesystem::path path = path_string;
    // Folders can have extended attributes too
    if (!(boost::filesystem::is_regular_file(path) ||
          boost::filesystem::is_directory(path))) {
      continue;
    }
    getFileData(results, path.string());
  }

  auto directories = context.constraints["directory"].getAll(EQUALS);
  for (const auto &directory : directories) {
    if (!boost::filesystem::is_directory(directory)) {
      continue;
    }
    std::vector<std::string> files;
    listFilesInDirectory(directory, files);

    for (auto &file : files) {
      getFileData(results, file);
    }
  }
  return results;
}
}
}
<commit_msg>implement LIKEs for extended attributes table (#3541)<commit_after>/*
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <CoreServices/CoreServices.h>
#include <sys/xattr.h>

#include <boost/filesystem.hpp>
#include <boost/property_tree/json_parser.hpp>

#include <osquery/filesystem.h>
#include <osquery/logger.h>
#include <osquery/sql.h>
#include <osquery/tables.h>

#include "osquery/core/conversions.h"

namespace fs = boost::filesystem;

namespace osquery {
namespace tables {

// Structure of any OS X extended attribute
struct XAttrAttribute {
  std::string attribute_data;
  int return_value;
  int buffer_length;
};

const std::string kMetadataXattr = "com.apple.metadata:kMDItemWhereFroms";
const std::string kQuarantineXattr = "com.apple.quarantine";

const std::map<std::string, std::string> kQuarantineKeys = {
    {"quarantine_agent", "LSQuarantineAgentName"},
    {"quarantine_type", "LSQuarantineType"},
    {"quarantine_timestamp", "LSQuarantineTimeStamp"},
    {"quarantine_event_id", "LSQuarantineEventIdentifier"},
    {"quarantine_sender", "LSQuarantineSenderName"},
    {"quarantine_data_url", "LSQuarantineDataURL"},
    {"quarantine_origin_url", "LSQuarantineOriginURL"}};

// Pull the requested extended attribute from the path and return
// the XAttrAttribute structure
struct XAttrAttribute getAttribute(const std::string& path,
                                   const std::string& attribute) {
  struct XAttrAttribute x_att;
  x_att.buffer_length =
      getxattr(path.c_str(), attribute.c_str(), nullptr, (size_t)0, 0, 0);
  char* buffer = (char*)malloc(x_att.buffer_length);
  if (buffer == nullptr) {
    return x_att;
  }

  x_att.return_value = getxattr(
      path.c_str(), attribute.c_str(), buffer, x_att.buffer_length, 0, 0);

  if (x_att.return_value != -1) {
    x_att.attribute_data = std::string(buffer, x_att.buffer_length);
  } else {
    x_att.attribute_data = std::string("");
    x_att.buffer_length = 0;
  }
  free(buffer);
  return x_att;
}

// Pull the list of all the extended attributes for a path
std::vector<std::string> parseExtendedAttributeList(const std::string& path) {
  std::vector<std::string> attributes;
  ssize_t value = listxattr(path.c_str(), nullptr, (size_t)0, 0);
  char* content = (char*)malloc(value);
  if (content == nullptr) {
    return attributes;
  }

  ssize_t ret = listxattr(path.c_str(), content, value, 0);
  if (ret == 0) {
    return attributes;
  }

  char* stable = content;
  do {
    attributes.push_back(std::string(content));
    content += attributes.back().size() + 1;
  } while (content - stable < value);
  free(stable);
  return attributes;
}

void setRow(QueryData& results,
            const std::string& path,
            const std::string& key,
            const std::string& value) {
  Row r;
  r["path"] = path;
  r["directory"] = boost::filesystem::path(path).parent_path().string();
  r["key"] = key;
  auto value_printable = isPrintable(value);
  r["value"] = (value_printable) ? value : base64Encode(value);
  r["base64"] = (value_printable) ? INTEGER(0) : INTEGER(1);
  results.push_back(r);
}

void parseWhereFrom(QueryData& results, const std::string& path) {
  CFStringRef CFPath = CFStringCreateWithCString(
      kCFAllocatorDefault, path.c_str(), kCFStringEncodingUTF8);

  MDItemRef metadata = MDItemCreate(kCFAllocatorDefault, CFPath);
  CFRelease(CFPath);

  if (metadata == nullptr) {
    VLOG(1) << "Metadata for " << path << " is null";
    return;
  }

  CFTypeRef attributes;
  attributes = MDItemCopyAttribute(metadata, kMDItemWhereFroms);
  CFRelease(metadata);

  if (attributes == nullptr) {
    VLOG(1) << "No attributes found for " << path;
    return;
  }

  CFArrayRef attribs = (CFArrayRef)attributes;
  CFIndex count = CFArrayGetCount(attribs);

  for (CFIndex i = 0; i < count; i++) {
    CFStringRef attribute = (CFStringRef)CFArrayGetValueAtIndex(attribs, i);
    auto where_from_attribute = stringFromCFString(attribute);
    if (!where_from_attribute.empty()) {
      setRow(results, path, "where_from", where_from_attribute);
    }
  }

  CFRelease(attributes);
}

void extractQuarantineProperty(const std::string& table_key_name,
                               CFTypeRef property,
                               const std::string& path,
                               QueryData& results) {
  std::string value;
  if (CFGetTypeID(property) == CFStringGetTypeID()) {
    value = stringFromCFString((CFStringRef)property);
  } else if (CFGetTypeID(property) == CFDateGetTypeID()) {
    auto unix_time = CFDateGetAbsoluteTime((CFDateRef)property) +
                     kCFAbsoluteTimeIntervalSince1970;
    value = INTEGER(std::llround(unix_time));
  } else if (CFGetTypeID(property) == CFURLGetTypeID()) {
    value = stringFromCFString(CFURLGetString((CFURLRef)property));
  }
  setRow(results, path, table_key_name, value);
}

void parseQuarantineFile(QueryData& results, const std::string& path) {
  CFURLRef url = CFURLCreateFromFileSystemRepresentation(
      kCFAllocatorDefault, (const UInt8*)path.c_str(), path.length(), false);

  if (url == nullptr) {
    VLOG(1) << "Error obtaining CFURLRef for " << path;
    VLOG(1) << "Unable to fetch quarantine data";
    return;
  }

  CFTypeRef quarantine_properties = nullptr;
  // This is the non-10.10-symbolic version of kCFURLQuarantinePropertiesKey.
  CFStringRef qp_key = CFSTR("NSURLQuarantinePropertiesKey");
  CFURLCopyResourcePropertyForKey(url, qp_key, &quarantine_properties, nullptr);
  CFRelease(qp_key);

  if (quarantine_properties == nullptr) {
    VLOG(1) << "Error retrieving quarantine properties for " << path;
    CFRelease(url);
    return;
  }

  CFTypeRef property = nullptr;
  for (const auto& kv : kQuarantineKeys) {
    CFStringRef key = CFStringCreateWithCString(
        kCFAllocatorDefault, kv.second.c_str(), kCFStringEncodingUTF8);
    if (key != nullptr) {
      if (CFDictionaryGetValueIfPresent(
              (CFDictionaryRef)quarantine_properties, key, &property)) {
        extractQuarantineProperty(kv.first, property, path, results);
      }
      CFRelease(key);
    }
  }

  CFRelease(quarantine_properties);
  CFRelease(url);
}

// Process a file and extract all attribute information, parsed or not.
void getFileData(QueryData& results, const std::string& path) {
  std::vector<std::string> attributes = parseExtendedAttributeList(path);
  for (const auto& attribute : attributes) {
    struct XAttrAttribute x_att = getAttribute(path, attribute);

    if (attribute == kMetadataXattr) {
      parseWhereFrom(results, path);
    } else if (attribute == kQuarantineXattr) {
      parseQuarantineFile(results, path);
    } else {
      setRow(results, path, attribute, x_att.attribute_data);
    }
  }
}

QueryData genXattr(QueryContext& context) {
  QueryData results;
  // Resolve file paths for EQUALS and LIKE operations.
  auto paths = context.constraints["path"].getAll(EQUALS);
  context.expandConstraints(
      "path",
      LIKE,
      paths,
      ([&](const std::string& pattern, std::set<std::string>& out) {
        std::vector<std::string> patterns;
        auto status =
            resolveFilePattern(pattern, patterns, GLOB_ALL | GLOB_NO_CANON);
        if (status.ok()) {
          for (const auto& resolved : patterns) {
            out.insert(resolved);
          }
        }
        return status;
      }));

  for (const auto& path_string : paths) {
    boost::filesystem::path path = path_string;
    // Folders can have extended attributes too
    if (!(boost::filesystem::is_regular_file(path) ||
          boost::filesystem::is_directory(path))) {
      continue;
    }
    getFileData(results, path.string());
  }

  // Resolve directories for EQUALS and LIKE operations.
  auto directories = context.constraints["directory"].getAll(EQUALS);
  context.expandConstraints(
      "directory",
      LIKE,
      directories,
      ([&](const std::string& pattern, std::set<std::string>& out) {
        std::vector<std::string> patterns;
        auto status =
            resolveFilePattern(pattern, patterns, GLOB_FOLDERS | GLOB_NO_CANON);
        if (status.ok()) {
          for (const auto& resolved : patterns) {
            out.insert(resolved);
          }
        }
        return status;
      }));

  // Now loop through constraints using the directory column constraint.
  for (const auto& directory_string : directories) {
    if (!isReadable(directory_string) || !isDirectory(directory_string)) {
      continue;
    }

    std::vector<std::string> files;
    if (listFilesInDirectory(directory_string, files).ok()) {
      for (const auto& file : files) {
        getFileData(results, file);
      }
    }
  }
  return results;
}
}
}
<|endoftext|>


<commit_before>//---------------------------------------------------------------------------//
/*
  Copyright (c) 2012, Stuart R. Slattery
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are
  met:

  *: Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

  *: Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.

  *: Neither the name of the University of Wisconsin - Madison nor the
  names of its contributors may be used to endorse or promote products
  derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//---------------------------------------------------------------------------//
/*!
 * \brief DTK_ParallelSearch.cpp
 * \author Stuart R. Slattery
 * \brief Parallel search.
 */
//---------------------------------------------------------------------------//

#include "DTK_ParallelSearch.hpp"
#include "DTK_DBC.hpp"

#include <Tpetra_Distributor.hpp>
#include <Teuchos_Comm.hpp>

namespace DataTransferKit
{
//---------------------------------------------------------------------------//
// Constructor.
ParallelSearch::ParallelSearch(
    const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
    const int physical_dimension,
    const EntityIterator& domain_iterator,
    const Teuchos::RCP<EntityLocalMap>& domain_local_map,
    const Teuchos::ParameterList& parameters )
    : d_comm( comm )
    , d_physical_dim( physical_dimension )
    , d_track_missed_range_entities( false )
    , d_missed_range_entity_ids( 0 )
{
    // Set the parameters with the local map.
    domain_local_map->setParameters( parameters );

    // Determine if we are tracking missed range entities.
    if ( parameters.isParameter("Track Missed Range Entities") )
    {
	d_track_missed_range_entities =
	    parameters.get<bool>("Track Missed Range Entities");
    }

    // Build a coarse global search as this object must be collective across
    // the communicator.
    d_coarse_global_search = Teuchos::rcp(
	new CoarseGlobalSearch(d_comm, physical_dimension,
			       domain_iterator, parameters) );

    // Only do the local search if there are local domain entities.
    d_empty_domain = ( 0 == domain_iterator.size() );
    if ( !d_empty_domain )
    {
	d_coarse_local_search = Teuchos::rcp(
	    new CoarseLocalSearch(domain_iterator, domain_local_map, parameters) );
	d_fine_local_search = Teuchos::rcp(
	    new FineLocalSearch(domain_local_map) );
    }
}

//---------------------------------------------------------------------------//
// Search the domain with the range entity centroids and construct the
// graph. This will update the state of the object.
void ParallelSearch::search(
    const EntityIterator& range_iterator,
    const Teuchos::RCP<EntityLocalMap>& range_local_map,
    const Teuchos::ParameterList& parameters )
{
    // Set the parameters with the local map.
    range_local_map->setParameters( parameters );

    // Empty range flag.
    d_empty_range = ( 0 == range_iterator.size() );

    // Reset the state of the object.
    d_range_owner_ranks.clear();
    d_domain_to_range_map.clear();
    d_range_to_domain_map.clear();
    d_parametric_coords.clear();

    // Perform a coarse global search to redistribute the range entities.
    Teuchos::Array<EntityId> range_entity_ids;
    Teuchos::Array<int> range_owner_ranks;
    Teuchos::Array<double> range_centroids;
    d_coarse_global_search->search(
	range_iterator, range_local_map, parameters,
	range_entity_ids, range_owner_ranks, range_centroids );

    // If needed, extract the range entities that were missed during the
    // coarse global search.
    Teuchos::Array<EntityId> found_range_entity_ids;
    Teuchos::Array<int> found_range_ranks;
    Teuchos::Array<EntityId> missed_range_entity_ids;
    Teuchos::Array<int> missed_range_ranks;
    if ( d_track_missed_range_entities )
    {
	missed_range_entity_ids = Teuchos::Array<EntityId>(
	    d_coarse_global_search->getMissedRangeEntityIds() );
	missed_range_ranks.assign( missed_range_entity_ids.size(),
				   d_comm->getRank() );
    }

    // Only do the local search if there are local domain entities.
    Teuchos::Array<int> export_range_ranks;
    Teuchos::Array<EntityId> export_data;
    if ( !d_empty_domain )
    {
	// For each range centroid, perform a local search.
	int num_range = range_entity_ids.size();
	Teuchos::Array<Entity> domain_neighbors;
	Teuchos::Array<Entity> domain_parents;
	Teuchos::Array<double> reference_coordinates;
	Teuchos::Array<double> local_coords( d_physical_dim );
	int num_parents = 0;
	for ( int n = 0; n < num_range; ++n )
	{
	    // Perform a coarse local search to get the nearest domain
	    // entities to the point.
	    d_coarse_local_search->search(
		range_centroids(d_physical_dim*n,d_physical_dim),
		parameters,
		domain_neighbors );

	    // Perform a fine local search to get the entities the point maps
	    // to.
	    d_fine_local_search->search(
		domain_neighbors,
		range_centroids(d_physical_dim*n,d_physical_dim),
		parameters,
		domain_parents,
		reference_coordinates );

	    // Store the potentially multiple parametric realizations of the
	    // point.
	    std::unordered_map<EntityId,Teuchos::Array<double> > ref_map;
	    num_parents = domain_parents.size();
	    for ( int p = 0; p < num_parents; ++p )
	    {
		// Store the range data in the domain parallel decomposition.
		local_coords().assign(
		    reference_coordinates(d_physical_dim*p,d_physical_dim) );
		d_range_owner_ranks.emplace(
		    range_entity_ids[n], range_owner_ranks[n] );
		d_domain_to_range_map.emplace(
		    domain_parents[p].id(), range_entity_ids[n] );
		ref_map.emplace(
		    domain_parents[p].id(), local_coords );

		// Extract the data to communicate back to the range parallel
		// decomposition.
		export_range_ranks.push_back( range_owner_ranks[n] );
		export_data.push_back( range_entity_ids[n] );
		export_data.push_back( domain_parents[p].id() );
		export_data.push_back(
		    Teuchos::as<EntityId>(d_comm->getRank()) );
	    }

	    // If we found parents for the point, store them.
	    if ( num_parents > 0 )
	    {
		d_parametric_coords.emplace( range_entity_ids[n], ref_map );

		// If we are tracking missed entities, also track those that
		// we found so we can determine if an entity was found after
		// being sent to multiple destinations.
		if ( d_track_missed_range_entities )
		{
		    found_range_entity_ids.push_back( range_entity_ids[n] );
		    found_range_ranks.push_back( range_owner_ranks[n] );
		}
	    }

	    // Otherwise, if we are tracking missed entities report this.
	    else if ( d_track_missed_range_entities )
	    {
		missed_range_entity_ids.push_back( range_entity_ids[n] );
		missed_range_ranks.push_back( range_owner_ranks[n] );
	    }
	}
    }

    // Back-communicate the domain entities in which we found each range
    // entity to complete the mapping.
    Tpetra::Distributor domain_to_range_dist( d_comm );
    int num_import =
	domain_to_range_dist.createFromSends( export_range_ranks() );
    Teuchos::Array<EntityId> domain_data( 3*num_import );
    Teuchos::ArrayView<const EntityId> export_data_view = export_data();
    domain_to_range_dist.doPostsAndWaits( export_data_view, 3, domain_data() );

    // Store the domain data in the range parallel decomposition.
    for ( int i = 0; i < num_import; ++i )
    {
	d_domain_owner_ranks.emplace(
	    domain_data[3*i+1], domain_data[3*i+2] );
	d_range_to_domain_map.emplace(
	    domain_data[3*i], domain_data[3*i+1] );
    }

    // If we are tracking missed entities, back-communicate the missing entities
    // and found entities to determine which entities are actually missing.
    if ( d_track_missed_range_entities )
    {
	// Back-communicate the missing entities.
	Tpetra::Distributor missed_range_dist( d_comm );
	int num_import_missed =
	    missed_range_dist.createFromSends( missed_range_ranks() );
	Teuchos::Array<EntityId> import_missed( num_import_missed );
	Teuchos::ArrayView<const EntityId> missed_view =
	    missed_range_entity_ids();
	missed_range_dist.doPostsAndWaits( missed_view, 1, import_missed() );

	// Back-communicate the found entities.
	Tpetra::Distributor found_range_dist( d_comm );
	int num_import_found =
	    found_range_dist.createFromSends( found_range_ranks() );
	Teuchos::Array<EntityId> import_found( num_import_found );
	Teuchos::ArrayView<const EntityId> found_view =
	    found_range_entity_ids();
	found_range_dist.doPostsAndWaits( found_view, 1, import_found() );

	// Intersect the found and missed entities to determine if there are any
	// that were found on one process but missed on another.
	std::sort( import_missed.begin(), import_missed.end() );
	std::sort( import_found.begin(), import_found.end() );
	Teuchos::Array<EntityId> false_positive_missed(
	    import_missed.size() + import_found.size() );
	auto false_positive_end =
	    std::set_intersection( import_missed.begin(), import_missed.end(),
				   import_found.begin(), import_found.end(),
				   false_positive_missed.begin() );

	// Create a list of missed entities without the false positives.
	d_missed_range_entity_ids.resize( num_import_missed );
	auto missed_range_end = std::set_difference(
	    import_missed.begin(), import_missed.end(),
	    false_positive_missed.begin(), false_positive_end,
	    d_missed_range_entity_ids.begin() );

	// Create a unique list of missed entities without the false positives.
	std::sort( d_missed_range_entity_ids.begin(), missed_range_end );
	auto missed_range_unique_end = std::unique(
	    d_missed_range_entity_ids.begin(), missed_range_end );
	d_missed_range_entity_ids.resize(
	    std::distance(d_missed_range_entity_ids.begin(),
			  missed_range_unique_end) );
#if HAVE_DTK_DBC
  unsigned long long int n_entities = d_missed_range_entity_ids.size() +
    num_import_found;
  DTK_REQUIRE( n_entities == range_iterator.size() );
#endif
    }
}

//---------------------------------------------------------------------------//
// Given a domain entity id, get the ids of the range entities that mapped to it.
void ParallelSearch::getRangeEntitiesFromDomain(
    const EntityId domain_id,
    Teuchos::Array<EntityId>& range_ids ) const
{
    DTK_REQUIRE( !d_empty_domain );
    auto domain_pair = d_domain_to_range_map.equal_range( domain_id );
    range_ids.resize( std::distance(domain_pair.first,domain_pair.second) );
    auto range_it = range_ids.begin();
    for ( auto domain_it = domain_pair.first;
	  domain_it != domain_pair.second;
	  ++domain_it, ++range_it )
    {
	*range_it = domain_it->second;
    }
}

//---------------------------------------------------------------------------//
// Given a range entity id, get the ids of the domain entities that it mapped to.
void ParallelSearch::getDomainEntitiesFromRange(
    const EntityId range_id,
    Teuchos::Array<EntityId>& domain_ids ) const
{
    DTK_REQUIRE( !d_empty_range );
    auto range_pair = d_range_to_domain_map.equal_range( range_id );
    domain_ids.resize( std::distance(range_pair.first,range_pair.second) );
    auto domain_it = domain_ids.begin();
    for ( auto range_it = range_pair.first;
	  range_it != range_pair.second;
	  ++range_it, ++domain_it )
    {
	*domain_it = range_it->second;
    }
}

//---------------------------------------------------------------------------//
// Get the owner rank of a given range entity.
int ParallelSearch::rangeEntityOwnerRank( const EntityId range_id ) const
{
    DTK_REQUIRE( !d_empty_domain );
    DTK_REQUIRE( d_range_owner_ranks.count(range_id) );
    return d_range_owner_ranks.find(range_id)->second;
}

//---------------------------------------------------------------------------//
// Get the owner rank of a given domain entity.
int ParallelSearch::domainEntityOwnerRank( const EntityId domain_id ) const
{
    DTK_REQUIRE( !d_empty_range );
    DTK_REQUIRE( d_domain_owner_ranks.count(domain_id) );
    return d_domain_owner_ranks.find(domain_id)->second;
}

//---------------------------------------------------------------------------//
// Get the parametric coordinates of the range entities in the domain entities.
void ParallelSearch::rangeParametricCoordinatesInDomain(
    const EntityId domain_id,
    const EntityId range_id,
    Teuchos::ArrayView<const double>& parametric_coords ) const
{
    DTK_REQUIRE( !d_empty_domain );
    DTK_REQUIRE( d_parametric_coords.count(range_id) );
    DTK_REQUIRE( d_parametric_coords.find(range_id)->second.count(domain_id) );
    parametric_coords =
	d_parametric_coords.find(range_id)->second.find(domain_id)->second;
}

//---------------------------------------------------------------------------//
// Return the ids of the range entities that were not mapped during the last
// setup phase (i.e. those that are guaranteed to not receive data from the
// transfer).
Teuchos::ArrayView<const EntityId>
ParallelSearch::getMissedRangeEntityIds() const
{
    return d_missed_range_entity_ids();
}

//---------------------------------------------------------------------------//

} // end namespace DataTransferKit

//---------------------------------------------------------------------------//
// end DTK_ParallelSearch.cpp
//---------------------------------------------------------------------------//
<commit_msg>Impose unicity before getting the difference of two vectors.<commit_after>//---------------------------------------------------------------------------//
/*
  Copyright (c) 2012, Stuart R. Slattery
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are
  met:

  *: Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

  *: Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.

  *: Neither the name of the University of Wisconsin - Madison nor the
  names of its contributors may be used to endorse or promote products
  derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//---------------------------------------------------------------------------//
/*!
 * \brief DTK_ParallelSearch.cpp
 * \author Stuart R. Slattery
 * \brief Parallel search.
 */
//---------------------------------------------------------------------------//

#include "DTK_ParallelSearch.hpp"
#include "DTK_DBC.hpp"

#include <Tpetra_Distributor.hpp>

namespace DataTransferKit
{
//---------------------------------------------------------------------------//
// Constructor.
ParallelSearch::ParallelSearch(
    const Teuchos::RCP<const Teuchos::Comm<int> >& comm,
    const int physical_dimension,
    const EntityIterator& domain_iterator,
    const Teuchos::RCP<EntityLocalMap>& domain_local_map,
    const Teuchos::ParameterList& parameters )
    : d_comm( comm )
    , d_physical_dim( physical_dimension )
    , d_track_missed_range_entities( false )
    , d_missed_range_entity_ids( 0 )
{
    // Set the parameters with the local map.
    domain_local_map->setParameters( parameters );

    // Determine if we are tracking missed range entities.
    if ( parameters.isParameter("Track Missed Range Entities") )
    {
	d_track_missed_range_entities =
	    parameters.get<bool>("Track Missed Range Entities");
    }

    // Build a coarse global search as this object must be collective across
    // the communicator.
    d_coarse_global_search = Teuchos::rcp(
	new CoarseGlobalSearch(d_comm, physical_dimension,
			       domain_iterator, parameters) );

    // Only do the local search if there are local domain entities.
    d_empty_domain = ( 0 == domain_iterator.size() );
    if ( !d_empty_domain )
    {
	d_coarse_local_search = Teuchos::rcp(
	    new CoarseLocalSearch(domain_iterator, domain_local_map, parameters) );
	d_fine_local_search = Teuchos::rcp(
	    new FineLocalSearch(domain_local_map) );
    }
}

//---------------------------------------------------------------------------//
// Search the domain with the range entity centroids and construct the
// graph. This will update the state of the object.
void ParallelSearch::search(
    const EntityIterator& range_iterator,
    const Teuchos::RCP<EntityLocalMap>& range_local_map,
    const Teuchos::ParameterList& parameters )
{
    // Set the parameters with the local map.
    range_local_map->setParameters( parameters );

    // Empty range flag.
    d_empty_range = ( 0 == range_iterator.size() );

    // Reset the state of the object.
    d_range_owner_ranks.clear();
    d_domain_to_range_map.clear();
    d_range_to_domain_map.clear();
    d_parametric_coords.clear();

    // Perform a coarse global search to redistribute the range entities.
    Teuchos::Array<EntityId> range_entity_ids;
    Teuchos::Array<int> range_owner_ranks;
    Teuchos::Array<double> range_centroids;
    d_coarse_global_search->search(
	range_iterator, range_local_map, parameters,
	range_entity_ids, range_owner_ranks, range_centroids );

    // If needed, extract the range entities that were missed during the
    // coarse global search.
    Teuchos::Array<EntityId> found_range_entity_ids;
    Teuchos::Array<int> found_range_ranks;
    Teuchos::Array<EntityId> missed_range_entity_ids;
    Teuchos::Array<int> missed_range_ranks;
    if ( d_track_missed_range_entities )
    {
	missed_range_entity_ids = Teuchos::Array<EntityId>(
	    d_coarse_global_search->getMissedRangeEntityIds() );
	missed_range_ranks.assign( missed_range_entity_ids.size(),
				   d_comm->getRank() );
    }

    // Only do the local search if there are local domain entities.
    Teuchos::Array<int> export_range_ranks;
    Teuchos::Array<EntityId> export_data;
    if ( !d_empty_domain )
    {
	// For each range centroid, perform a local search.
	int num_range = range_entity_ids.size();
	Teuchos::Array<Entity> domain_neighbors;
	Teuchos::Array<Entity> domain_parents;
	Teuchos::Array<double> reference_coordinates;
	Teuchos::Array<double> local_coords( d_physical_dim );
	int num_parents = 0;
	for ( int n = 0; n < num_range; ++n )
	{
	    // Perform a coarse local search to get the nearest domain
	    // entities to the point.
	    d_coarse_local_search->search(
		range_centroids(d_physical_dim*n,d_physical_dim),
		parameters,
		domain_neighbors );

	    // Perform a fine local search to get the entities the point maps
	    // to.
	    d_fine_local_search->search(
		domain_neighbors,
		range_centroids(d_physical_dim*n,d_physical_dim),
		parameters,
		domain_parents,
		reference_coordinates );

	    // Store the potentially multiple parametric realizations of the
	    // point.
	    std::unordered_map<EntityId,Teuchos::Array<double> > ref_map;
	    num_parents = domain_parents.size();
	    for ( int p = 0; p < num_parents; ++p )
	    {
		// Store the range data in the domain parallel decomposition.
		local_coords().assign(
		    reference_coordinates(d_physical_dim*p,d_physical_dim) );
		d_range_owner_ranks.emplace(
		    range_entity_ids[n], range_owner_ranks[n] );
		d_domain_to_range_map.emplace(
		    domain_parents[p].id(), range_entity_ids[n] );
		ref_map.emplace(
		    domain_parents[p].id(), local_coords );

		// Extract the data to communicate back to the range parallel
		// decomposition.
		export_range_ranks.push_back( range_owner_ranks[n] );
		export_data.push_back( range_entity_ids[n] );
		export_data.push_back( domain_parents[p].id() );
		export_data.push_back(
		    Teuchos::as<EntityId>(d_comm->getRank()) );
	    }

	    // If we found parents for the point, store them.
	    if ( num_parents > 0 )
	    {
		d_parametric_coords.emplace( range_entity_ids[n], ref_map );

		// If we are tracking missed entities, also track those that
		// we found so we can determine if an entity was found after
		// being sent to multiple destinations.
		if ( d_track_missed_range_entities )
		{
		    found_range_entity_ids.push_back( range_entity_ids[n] );
		    found_range_ranks.push_back( range_owner_ranks[n] );
		}
	    }

	    // Otherwise, if we are tracking missed entities report this.
	    else if ( d_track_missed_range_entities )
	    {
		missed_range_entity_ids.push_back( range_entity_ids[n] );
		missed_range_ranks.push_back( range_owner_ranks[n] );
	    }
	}
    }

    // Back-communicate the domain entities in which we found each range
    // entity to complete the mapping.
    Tpetra::Distributor domain_to_range_dist( d_comm );
    int num_import =
	domain_to_range_dist.createFromSends( export_range_ranks() );
    Teuchos::Array<EntityId> domain_data( 3*num_import );
    Teuchos::ArrayView<const EntityId> export_data_view = export_data();
    domain_to_range_dist.doPostsAndWaits( export_data_view, 3, domain_data() );

    // Store the domain data in the range parallel decomposition.
    for ( int i = 0; i < num_import; ++i )
    {
	d_domain_owner_ranks.emplace(
	    domain_data[3*i+1], domain_data[3*i+2] );
	d_range_to_domain_map.emplace(
	    domain_data[3*i], domain_data[3*i+1] );
    }

    // If we are tracking missed entities, back-communicate the missing entities
    // and found entities to determine which entities are actually missing.
    if ( d_track_missed_range_entities )
    {
	// Back-communicate the missing entities.
	Tpetra::Distributor missed_range_dist( d_comm );
	int num_import_missed =
	    missed_range_dist.createFromSends( missed_range_ranks() );
	Teuchos::Array<EntityId> import_missed( num_import_missed );
	Teuchos::ArrayView<const EntityId> missed_view =
	    missed_range_entity_ids();
	missed_range_dist.doPostsAndWaits( missed_view, 1, import_missed() );

	// Back-communicate the found entities.
	Tpetra::Distributor found_range_dist( d_comm );
	int num_import_found =
	    found_range_dist.createFromSends( found_range_ranks() );
	Teuchos::Array<EntityId> import_found( num_import_found );
	Teuchos::ArrayView<const EntityId> found_view =
	    found_range_entity_ids();
	found_range_dist.doPostsAndWaits( found_view, 1, import_found() );

	// Intersect the found and missed entities to determine if there are any
	// that were found on one process but missed on another.
	std::sort( import_missed.begin(), import_missed.end() );
	std::sort( import_found.begin(), import_found.end() );
	Teuchos::Array<EntityId> false_positive_missed(
	    import_missed.size() + import_found.size() );
	auto false_positive_end =
	    std::set_intersection( import_missed.begin(), import_missed.end(),
				   import_found.begin(), import_found.end(),
				   false_positive_missed.begin() );

  // Create a unique list of missed entities
	std::sort( import_missed.begin(), import_missed.end() );
  auto import_missed_unique_end = std::unique(
      import_missed.begin(), import_missed.end());
  import_missed.resize(std::distance(import_missed.begin(), import_missed_unique_end));

	// Create a list of missed entities without the false positives.
	d_missed_range_entity_ids.resize( num_import_missed );
	auto missed_range_end = std::set_difference(
	    import_missed.begin(), import_missed.end(),
	    false_positive_missed.begin(), false_positive_end,
	    d_missed_range_entity_ids.begin() );
	d_missed_range_entity_ids.resize(
	    std::distance(d_missed_range_entity_ids.begin(),
			  missed_range_end) );

#if HAVE_DTK_DBC
  unsigned long long int n_entities = d_missed_range_entity_ids.size() +
    num_import_found;
  DTK_REQUIRE( n_entities == range_iterator.size() );
#endif
    }
}

//---------------------------------------------------------------------------//
// Given a domain entity id, get the ids of the range entities that mapped to it.
void ParallelSearch::getRangeEntitiesFromDomain(
    const EntityId domain_id,
    Teuchos::Array<EntityId>& range_ids ) const
{
    DTK_REQUIRE( !d_empty_domain );
    auto domain_pair = d_domain_to_range_map.equal_range( domain_id );
    range_ids.resize( std::distance(domain_pair.first,domain_pair.second) );
    auto range_it = range_ids.begin();
    for ( auto domain_it = domain_pair.first;
	  domain_it != domain_pair.second;
	  ++domain_it, ++range_it )
    {
	*range_it = domain_it->second;
    }
}

//---------------------------------------------------------------------------//
// Given a range entity id, get the ids of the domain entities that it mapped to.
void ParallelSearch::getDomainEntitiesFromRange(
    const EntityId range_id,
    Teuchos::Array<EntityId>& domain_ids ) const
{
    DTK_REQUIRE( !d_empty_range );
    auto range_pair = d_range_to_domain_map.equal_range( range_id );
    domain_ids.resize( std::distance(range_pair.first,range_pair.second) );
    auto domain_it = domain_ids.begin();
    for ( auto range_it = range_pair.first;
	  range_it != range_pair.second;
	  ++range_it, ++domain_it )
    {
	*domain_it = range_it->second;
    }
}

//---------------------------------------------------------------------------//
// Get the owner rank of a given range entity.
int ParallelSearch::rangeEntityOwnerRank( const EntityId range_id ) const
{
    DTK_REQUIRE( !d_empty_domain );
    DTK_REQUIRE( d_range_owner_ranks.count(range_id) );
    return d_range_owner_ranks.find(range_id)->second;
}

//---------------------------------------------------------------------------//
// Get the owner rank of a given domain entity.
int ParallelSearch::domainEntityOwnerRank( const EntityId domain_id ) const
{
    DTK_REQUIRE( !d_empty_range );
    DTK_REQUIRE( d_domain_owner_ranks.count(domain_id) );
    return d_domain_owner_ranks.find(domain_id)->second;
}

//---------------------------------------------------------------------------//
// Get the parametric coordinates of the range entities in the domain entities.
void ParallelSearch::rangeParametricCoordinatesInDomain(
    const EntityId domain_id,
    const EntityId range_id,
    Teuchos::ArrayView<const double>& parametric_coords ) const
{
    DTK_REQUIRE( !d_empty_domain );
    DTK_REQUIRE( d_parametric_coords.count(range_id) );
    DTK_REQUIRE( d_parametric_coords.find(range_id)->second.count(domain_id) );
    parametric_coords =
	d_parametric_coords.find(range_id)->second.find(domain_id)->second;
}

//---------------------------------------------------------------------------//
// Return the ids of the range entities that were not mapped during the last
// setup phase (i.e. those that are guaranteed to not receive data from the
// transfer).
Teuchos::ArrayView<const EntityId>
ParallelSearch::getMissedRangeEntityIds() const
{
    return d_missed_range_entity_ids();
}

//---------------------------------------------------------------------------//

} // end namespace DataTransferKit

//---------------------------------------------------------------------------//
// end DTK_ParallelSearch.cpp
//---------------------------------------------------------------------------//
<|endoftext|>