<commit_before>#include "bookmark.hpp"

#include "../indexer/mercator.hpp"

#include "../coding/file_reader.hpp"
#include "../coding/parse_xml.hpp"  // LoadFromKML
#include "../coding/internal/file_data.hpp"

#include "../platform/platform.hpp"

#include "../base/stl_add.hpp"
#include "../base/string_utils.hpp"

#include "../std/fstream.hpp"
#include "../std/algorithm.hpp"

void BookmarkCategory::AddBookmarkImpl(Bookmark const & bm, double scale)
{
  Bookmark * p = new Bookmark(bm);
  p->SetScale(scale);

  m_bookmarks.push_back(p);
}

void BookmarkCategory::AddBookmark(Bookmark const & bm, double scale)
{
  AddBookmarkImpl(bm, scale);
}

void BookmarkCategory::ReplaceBookmark(size_t index, Bookmark const & bm, double scale)
{
  ASSERT_LESS ( index, m_bookmarks.size(), () );
  if (index < m_bookmarks.size())
  {
    Bookmark * p = new Bookmark(bm);
    p->SetScale(scale);

    Bookmark const * old = m_bookmarks[index];
    // Save creation time stamp
    p->SetTimeStamp(old->GetTimeStamp());
    m_bookmarks[index] = p;

    delete old;
  }
  else
    LOG(LWARNING, ("Trying to replace non-existing bookmark"));
}

BookmarkCategory::~BookmarkCategory()
{
  ClearBookmarks();
}

void BookmarkCategory::ClearBookmarks()
{
  for_each(m_bookmarks.begin(), m_bookmarks.end(), DeleteFunctor());
  m_bookmarks.clear();
}

void BookmarkCategory::DeleteBookmark(size_t index)
{
  if (index < m_bookmarks.size())
  {
    delete m_bookmarks[index];
    m_bookmarks.erase(m_bookmarks.begin() + index);
  }
  else
  {
    LOG(LWARNING, ("Trying to delete non-existing bookmark in category", GetName(), "at index", index));
  }
}

Bookmark const * BookmarkCategory::GetBookmark(size_t index) const
{
  return (index < m_bookmarks.size() ? m_bookmarks[index] : 0);
}

int BookmarkCategory::GetBookmark(m2::PointD const org, double const squareDistance) const
{
  for (size_t i = 0; i < m_bookmarks.size(); ++i)
  {
    if (squareDistance >= org.SquareLength(m_bookmarks[i]->GetOrg()))
      return static_cast<int>(i);
  }
  return -1;
}

namespace
{
  string PointToString(m2::PointD const & org)
  {
    double const lon = MercatorBounds::XToLon(org.x);
    double const lat = MercatorBounds::YToLat(org.y);

    ostringstream ss;
    ss.precision(8);

    ss << lon << "," << lat;
    return ss.str();
  }
}

namespace bookmark_impl
{
  class KMLParser
  {
    // Fixes icons which are not supported by MapsWithMe
    string GetSupportedBMType(string const & s) const
    {
      static char const * icons[] = {
          "placemark-red", "placemark-blue", "placemark-purple",
          "placemark-pink", "placemark-brown", "placemark-green", "placemark-orange"
      };

      // Remove leading '#' symbol
      string const result = s.substr(1);
      for (size_t i = 0; i < ARRAY_SIZE(icons); ++i)
        if (result == icons[i])
          return result;

      // Not recognized symbols are replaced with default one
      LOG(LWARNING, ("Icon", result, "for bookmark", m_name, "is not supported"));
      return icons[0];
    }

    BookmarkCategory & m_category;

    vector<string> m_tags;

    string m_name;
    string m_type;
    string m_description;
    time_t m_timeStamp;

    m2::PointD m_org;
    double m_scale;

    void Reset()
    {
      m_name.clear();
      m_description.clear();
      m_org = m2::PointD(-1000, -1000);
      m_type.clear();
      m_scale = -1.0;
      m_timeStamp = my::INVALID_TIME_STAMP;
    }

    void SetOrigin(string const & s)
    {
      // order in string is: lon, lat, z

      strings::SimpleTokenizer iter(s, ", ");
      if (iter)
      {
        double lon;
        if (strings::to_double(*iter, lon) && MercatorBounds::ValidLon(lon) && ++iter)
        {
          double lat;
          if (strings::to_double(*iter, lat) && MercatorBounds::ValidLat(lat))
            m_org = m2::PointD(MercatorBounds::LonToX(lon), MercatorBounds::LatToY(lat));
          else
            LOG(LWARNING, ("Invalid coordinates", s, "while loading bookmark", m_name));
        }
      }
    }

    bool MakeValid()
    {
      if (MercatorBounds::ValidX(m_org.x) && MercatorBounds::ValidY(m_org.y))
      {
        if (m_name.empty())
          m_name = PointToString(m_org);
        return true;
      }
      return false;
    }

  public:
    KMLParser(BookmarkCategory & cat) : m_category(cat)
    {
      Reset();
    }

    bool Push(string const & name)
    {
      m_tags.push_back(name);
      return true;
    }

    void AddAttr(string const &, string const &) {}

    void Pop(string const & tag)
    {
      ASSERT_EQUAL(m_tags.back(), tag, ());

      if (tag == "Placemark" && MakeValid())
      {
        Bookmark bm(m_org, m_name, m_type);
        bm.SetTimeStamp(m_timeStamp);
        bm.SetDescription(m_description);
        m_category.AddBookmarkImpl(bm, m_scale);
        Reset();
      }
      m_tags.pop_back();
    }

    void CharData(string value)
    {
      strings::Trim(value);

      size_t const count = m_tags.size();
      if (count > 1 && !value.empty())
      {
        string const & currTag = m_tags[count - 1];
        string const & prevTag = m_tags[count - 2];

        if (prevTag == "Document")
        {
          if (currTag == "name")
            m_category.SetName(value);
          else if (currTag == "visibility")
            m_category.SetVisible(value == "0" ? false : true);
        }
        else if (prevTag == "Placemark")
        {
          if (currTag == "name")
            m_name = value;
          else if (currTag == "styleUrl")
            m_type = GetSupportedBMType(value);
          else if (currTag == "description")
            m_description = value;
        }
        else if (count > 3 && m_tags[count-3] == "Placemark")
        {
          if (prevTag == "Point")
          {
            if (currTag == "coordinates")
              SetOrigin(value);
          }
          else if (prevTag == "ExtendedData")
          {
            if (currTag == "mwm:scale")
            {
              if (!strings::to_double(value, m_scale))
                m_scale = -1.0;
            }
          }
          else if (prevTag == "TimeStamp")
          {
            if (currTag == "when")
            {
              m_timeStamp = my::StringToTimestamp(value);
              if (m_timeStamp == my::INVALID_TIME_STAMP)
                LOG(LWARNING, ("Invalid timestamp in Placemark:", value));
            }
          }
        }
      }
    }
  };
}

void BookmarkCategory::LoadFromKML(ReaderPtr<Reader> const & reader)
{
  ReaderSource<ReaderPtr<Reader> > src(reader);
  bookmark_impl::KMLParser parser(*this);
  if (!ParseXML(src, parser, true))
    LOG(LERROR, ("XML read error. Probably, incorrect file encoding."));
}

BookmarkCategory * BookmarkCategory::CreateFromKMLFile(string const & file)
{
  BookmarkCategory * cat = new BookmarkCategory("");
  try
  {
    cat->LoadFromKML(new FileReader(file));
    cat->m_file = file;
  }
  catch (std::exception const & e)
  {
    LOG(LWARNING, ("Error while loading bookmarks from", file, e.what()));
    delete cat;
    cat = 0;
  }
  return cat;
}

namespace
{
char const * kmlHeader =
    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    "<kml xmlns=\"http://earth.google.com/kml/2.2\">\n"
    "<Document>\n"
    "  <Style id=\"placemark-blue\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-blue.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
    "  <Style id=\"placemark-brown\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-brown.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
    "  <Style id=\"placemark-green\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-green.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
    "  <Style id=\"placemark-orange\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-orange.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
    "  <Style id=\"placemark-pink\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-pink.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
    "  <Style id=\"placemark-purple\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-purple.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
    "  <Style id=\"placemark-red\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-red.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
;

char const * kmlFooter =
    "</Document>\n"
    "</kml>\n";
}

namespace
{
  inline void SaveStringWithCDATA(ostream & stream, string const & s)
  {
    // According to kml/xml spec, we need to escape special symbols with CDATA
    if (s.find_first_of("<&") != string::npos)
      stream << "<![CDATA[" << s << "]]>";
    else
      stream << s;
  }
}

void BookmarkCategory::SaveToKML(ostream & s)
{
  s << kmlHeader;

  // Use CDATA if we have special symbols in the name
  s << "  <name>";
  SaveStringWithCDATA(s, GetName());
  s << "</name>\n";

  s << "  <visibility>" << (IsVisible() ? "1" : "0") <<"</visibility>\n";

  for (size_t i = 0; i < m_bookmarks.size(); ++i)
  {
    Bookmark const * bm = m_bookmarks[i];
    s << "  <Placemark>\n";
    s << "    <name>";
    SaveStringWithCDATA(s, bm->GetName());
    s << "</name>\n";

    if (!bm->GetDescription().empty())
    {
      s << "    <description>";
      SaveStringWithCDATA(s, bm->GetDescription());
      s << "</description>\n";
    }

    time_t const timeStamp = bm->GetTimeStamp();
    if (timeStamp != my::INVALID_TIME_STAMP)
    {
      string const strTimeStamp = my::TimestampToString(timeStamp);
      ASSERT_EQUAL(strTimeStamp.size(), 20, ("We always generate fixed length UTC-format timestamp"));
      s << "    <TimeStamp><when>" << strTimeStamp << "</when></TimeStamp>\n";
    }

    s << "    <styleUrl>#" << bm->GetType() << "</styleUrl>\n"
      << "    <Point><coordinates>" << PointToString(bm->GetOrg()) << "</coordinates></Point>\n";

    double const scale = bm->GetScale();
    if (scale != -1.0)
    {
      /// @todo Factor out to separate function to use for other custom params.
      s << "    <ExtendedData xmlns:mwm=\"http://mapswith.me\">\n"
        << "      <mwm:scale>" << bm->GetScale() << "</mwm:scale>\n"
        << "    </ExtendedData>\n";
    }

    s << "  </Placemark>\n";
  }

  s << kmlFooter;
}

namespace
{
  bool IsBadCharForPath(strings::UniChar const & c)
  {
    static strings::UniChar const illegalChars[] = {':', '/', '\\', '<', '>', '\"', '|', '?', '*'};

    for (size_t i = 0; i < ARRAY_SIZE(illegalChars); ++i)
      if (c < ' ' || illegalChars[i] == c)
        return true;

    return false;
  }
}

string BookmarkCategory::GetValidFileName(string const & name)
{
  // Remove not allowed symbols
  strings::UniString uniName = strings::MakeUniString(name);
  strings::UniString::iterator iEnd = remove_if(uniName.begin(), uniName.end(), &IsBadCharForPath);
  if (iEnd != uniName.end())
  {
    // buffer_vector doesn't have erase function - call resize here (it's even better in this case).
    uniName.resize(distance(uniName.begin(), iEnd));
  }

  return (uniName.empty() ? "Bookmarks" : strings::ToUtf8(uniName));
}

string BookmarkCategory::GenerateUniqueFileName(const string & path, string const & name)
{
  size_t counter = 1;
  string suffix;
  while (Platform::IsFileExistsByFullPath(path + name + suffix + ".kml"))
    suffix = strings::to_string(counter++);
  return (path + name + suffix + ".kml");
}

bool BookmarkCategory::SaveToKMLFile()
{
  string oldFile;

  // Get valid file name from category name
  string const name = GetValidFileName(m_name);

  if (!m_file.empty())
  {
    size_t i2 = m_file.find_last_of('.');
    if (i2 == string::npos) i2 = m_file.size();
    size_t i1 = m_file.find_last_of("\\/");
    if (i1 == string::npos) i1 = 0;
    else ++i1;

    // If m_file doesn't match name, assign new m_file for this category and save old file name.
    if (m_file.substr(i1, i2-i1).find(name) != 0)
    {
      oldFile = GenerateUniqueFileName(GetPlatform().WritableDir(), name);
      m_file.swap(oldFile);
    }
  }
  else
    m_file = GenerateUniqueFileName(GetPlatform().WritableDir(), name);

  try
  {
    /// @todo On Windows UTF-8 file names are not supported.
    ofstream of(m_file.c_str());
    SaveToKML(of);
    of.flush();

    if (!of.fail())
    {
      // delete old file
      if (!oldFile.empty())
        VERIFY ( my::DeleteFileX(oldFile), (oldFile, m_file));

      return true;
    }
  }
  catch (std::exception const & e)
  {
    LOG(LWARNING, ("Exception while saving bookmarks:", e.what()));
  }

  LOG(LWARNING, ("Can't save bookmarks category", m_name, "to file", m_file));

  // return old file name in case of error
  if (!oldFile.empty())
    m_file.swap(oldFile);

  return false;
}
<commit_msg>Set default pin-color if no any "styleUrl" in kml.<commit_after>#include "bookmark.hpp"

#include "../indexer/mercator.hpp"

#include "../coding/file_reader.hpp"
#include "../coding/parse_xml.hpp"  // LoadFromKML
#include "../coding/internal/file_data.hpp"

#include "../platform/platform.hpp"

#include "../base/stl_add.hpp"
#include "../base/string_utils.hpp"

#include "../std/fstream.hpp"
#include "../std/algorithm.hpp"

void BookmarkCategory::AddBookmarkImpl(Bookmark const & bm, double scale)
{
  Bookmark * p = new Bookmark(bm);
  p->SetScale(scale);

  m_bookmarks.push_back(p);
}

void BookmarkCategory::AddBookmark(Bookmark const & bm, double scale)
{
  AddBookmarkImpl(bm, scale);
}

void BookmarkCategory::ReplaceBookmark(size_t index, Bookmark const & bm, double scale)
{
  ASSERT_LESS ( index, m_bookmarks.size(), () );
  if (index < m_bookmarks.size())
  {
    Bookmark * p = new Bookmark(bm);
    p->SetScale(scale);

    Bookmark const * old = m_bookmarks[index];
    // Save creation time stamp
    p->SetTimeStamp(old->GetTimeStamp());
    m_bookmarks[index] = p;

    delete old;
  }
  else
    LOG(LWARNING, ("Trying to replace non-existing bookmark"));
}

BookmarkCategory::~BookmarkCategory()
{
  ClearBookmarks();
}

void BookmarkCategory::ClearBookmarks()
{
  for_each(m_bookmarks.begin(), m_bookmarks.end(), DeleteFunctor());
  m_bookmarks.clear();
}

void BookmarkCategory::DeleteBookmark(size_t index)
{
  if (index < m_bookmarks.size())
  {
    delete m_bookmarks[index];
    m_bookmarks.erase(m_bookmarks.begin() + index);
  }
  else
  {
    LOG(LWARNING, ("Trying to delete non-existing bookmark in category", GetName(), "at index", index));
  }
}

Bookmark const * BookmarkCategory::GetBookmark(size_t index) const
{
  return (index < m_bookmarks.size() ? m_bookmarks[index] : 0);
}

int BookmarkCategory::GetBookmark(m2::PointD const org, double const squareDistance) const
{
  for (size_t i = 0; i < m_bookmarks.size(); ++i)
  {
    if (squareDistance >= org.SquareLength(m_bookmarks[i]->GetOrg()))
      return static_cast<int>(i);
  }
  return -1;
}

namespace
{
  string PointToString(m2::PointD const & org)
  {
    double const lon = MercatorBounds::XToLon(org.x);
    double const lat = MercatorBounds::YToLat(org.y);

    ostringstream ss;
    ss.precision(8);

    ss << lon << "," << lat;
    return ss.str();
  }
}

namespace bookmark_impl
{
  class KMLParser
  {
    // Fixes icons which are not supported by MapsWithMe
    string GetSupportedBMType(string const & s) const
    {
      static char const * icons[] = {
          "placemark-red", "placemark-blue", "placemark-purple",
          "placemark-pink", "placemark-brown", "placemark-green", "placemark-orange"
      };

      // Remove leading '#' symbol
      string const result = s.substr(1);
      for (size_t i = 0; i < ARRAY_SIZE(icons); ++i)
        if (result == icons[i])
          return result;

      // Not recognized symbols are replaced with default one
      LOG(LWARNING, ("Icon", result, "for bookmark", m_name, "is not supported"));
      return icons[0];
    }

    BookmarkCategory & m_category;

    vector<string> m_tags;

    string m_name;
    string m_type;
    string m_description;
    time_t m_timeStamp;

    m2::PointD m_org;
    double m_scale;

    void Reset()
    {
      m_name.clear();
      m_description.clear();
      m_org = m2::PointD(-1000, -1000);
      m_type.clear();
      m_scale = -1.0;
      m_timeStamp = my::INVALID_TIME_STAMP;
    }

    void SetOrigin(string const & s)
    {
      // order in string is: lon, lat, z

      strings::SimpleTokenizer iter(s, ", ");
      if (iter)
      {
        double lon;
        if (strings::to_double(*iter, lon) && MercatorBounds::ValidLon(lon) && ++iter)
        {
          double lat;
          if (strings::to_double(*iter, lat) && MercatorBounds::ValidLat(lat))
            m_org = m2::PointD(MercatorBounds::LonToX(lon), MercatorBounds::LatToY(lat));
          else
            LOG(LWARNING, ("Invalid coordinates", s, "while loading bookmark", m_name));
        }
      }
    }

    bool MakeValid()
    {
      if (MercatorBounds::ValidX(m_org.x) && MercatorBounds::ValidY(m_org.y))
      {
        // set default name
        if (m_name.empty())
          m_name = PointToString(m_org);

        // set default pin
        if (m_type.empty())
          m_type = "placemark-red";

        return true;
      }

      return false;
    }

  public:
    KMLParser(BookmarkCategory & cat) : m_category(cat)
    {
      Reset();
    }

    bool Push(string const & name)
    {
      m_tags.push_back(name);
      return true;
    }

    void AddAttr(string const &, string const &) {}

    void Pop(string const & tag)
    {
      ASSERT_EQUAL(m_tags.back(), tag, ());

      if (tag == "Placemark" && MakeValid())
      {
        Bookmark bm(m_org, m_name, m_type);
        bm.SetTimeStamp(m_timeStamp);
        bm.SetDescription(m_description);
        m_category.AddBookmarkImpl(bm, m_scale);
        Reset();
      }
      m_tags.pop_back();
    }

    void CharData(string value)
    {
      strings::Trim(value);

      size_t const count = m_tags.size();
      if (count > 1 && !value.empty())
      {
        string const & currTag = m_tags[count - 1];
        string const & prevTag = m_tags[count - 2];

        if (prevTag == "Document")
        {
          if (currTag == "name")
            m_category.SetName(value);
          else if (currTag == "visibility")
            m_category.SetVisible(value == "0" ? false : true);
        }
        else if (prevTag == "Placemark")
        {
          if (currTag == "name")
            m_name = value;
          else if (currTag == "styleUrl")
            m_type = GetSupportedBMType(value);
          else if (currTag == "description")
            m_description = value;
        }
        else if (count > 3 && m_tags[count-3] == "Placemark")
        {
          if (prevTag == "Point")
          {
            if (currTag == "coordinates")
              SetOrigin(value);
          }
          else if (prevTag == "ExtendedData")
          {
            if (currTag == "mwm:scale")
            {
              if (!strings::to_double(value, m_scale))
                m_scale = -1.0;
            }
          }
          else if (prevTag == "TimeStamp")
          {
            if (currTag == "when")
            {
              m_timeStamp = my::StringToTimestamp(value);
              if (m_timeStamp == my::INVALID_TIME_STAMP)
                LOG(LWARNING, ("Invalid timestamp in Placemark:", value));
            }
          }
        }
      }
    }
  };
}

void BookmarkCategory::LoadFromKML(ReaderPtr<Reader> const & reader)
{
  ReaderSource<ReaderPtr<Reader> > src(reader);
  bookmark_impl::KMLParser parser(*this);
  if (!ParseXML(src, parser, true))
    LOG(LERROR, ("XML read error. Probably, incorrect file encoding."));
}

BookmarkCategory * BookmarkCategory::CreateFromKMLFile(string const & file)
{
  BookmarkCategory * cat = new BookmarkCategory("");
  try
  {
    cat->LoadFromKML(new FileReader(file));
    cat->m_file = file;
  }
  catch (std::exception const & e)
  {
    LOG(LWARNING, ("Error while loading bookmarks from", file, e.what()));
    delete cat;
    cat = 0;
  }
  return cat;
}

namespace
{
char const * kmlHeader =
    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    "<kml xmlns=\"http://earth.google.com/kml/2.2\">\n"
    "<Document>\n"
    "  <Style id=\"placemark-blue\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-blue.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
    "  <Style id=\"placemark-brown\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-brown.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
    "  <Style id=\"placemark-green\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-green.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
    "  <Style id=\"placemark-orange\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-orange.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
    "  <Style id=\"placemark-pink\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-pink.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
    "  <Style id=\"placemark-purple\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-purple.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
    "  <Style id=\"placemark-red\">\n"
    "    <IconStyle>\n"
    "      <Icon>\n"
    "        <href>http://mapswith.me/placemarks/placemark-red.png</href>\n"
    "      </Icon>\n"
    "    </IconStyle>\n"
    "  </Style>\n"
;

char const * kmlFooter =
    "</Document>\n"
    "</kml>\n";
}

namespace
{
  inline void SaveStringWithCDATA(ostream & stream, string const & s)
  {
    // According to kml/xml spec, we need to escape special symbols with CDATA
    if (s.find_first_of("<&") != string::npos)
      stream << "<![CDATA[" << s << "]]>";
    else
      stream << s;
  }
}

void BookmarkCategory::SaveToKML(ostream & s)
{
  s << kmlHeader;

  // Use CDATA if we have special symbols in the name
  s << "  <name>";
  SaveStringWithCDATA(s, GetName());
  s << "</name>\n";

  s << "  <visibility>" << (IsVisible() ? "1" : "0") <<"</visibility>\n";

  for (size_t i = 0; i < m_bookmarks.size(); ++i)
  {
    Bookmark const * bm = m_bookmarks[i];
    s << "  <Placemark>\n";
    s << "    <name>";
    SaveStringWithCDATA(s, bm->GetName());
    s << "</name>\n";

    if (!bm->GetDescription().empty())
    {
      s << "    <description>";
      SaveStringWithCDATA(s, bm->GetDescription());
      s << "</description>\n";
    }

    time_t const timeStamp = bm->GetTimeStamp();
    if (timeStamp != my::INVALID_TIME_STAMP)
    {
      string const strTimeStamp = my::TimestampToString(timeStamp);
      ASSERT_EQUAL(strTimeStamp.size(), 20, ("We always generate fixed length UTC-format timestamp"));
      s << "    <TimeStamp><when>" << strTimeStamp << "</when></TimeStamp>\n";
    }

    s << "    <styleUrl>#" << bm->GetType() << "</styleUrl>\n"
      << "    <Point><coordinates>" << PointToString(bm->GetOrg()) << "</coordinates></Point>\n";

    double const scale = bm->GetScale();
    if (scale != -1.0)
    {
      /// @todo Factor out to separate function to use for other custom params.
      s << "    <ExtendedData xmlns:mwm=\"http://mapswith.me\">\n"
        << "      <mwm:scale>" << bm->GetScale() << "</mwm:scale>\n"
        << "    </ExtendedData>\n";
    }

    s << "  </Placemark>\n";
  }

  s << kmlFooter;
}

namespace
{
  bool IsBadCharForPath(strings::UniChar const & c)
  {
    static strings::UniChar const illegalChars[] = {':', '/', '\\', '<', '>', '\"', '|', '?', '*'};

    for (size_t i = 0; i < ARRAY_SIZE(illegalChars); ++i)
      if (c < ' ' || illegalChars[i] == c)
        return true;

    return false;
  }
}

string BookmarkCategory::GetValidFileName(string const & name)
{
  // Remove not allowed symbols
  strings::UniString uniName = strings::MakeUniString(name);
  strings::UniString::iterator iEnd = remove_if(uniName.begin(), uniName.end(), &IsBadCharForPath);
  if (iEnd != uniName.end())
  {
    // buffer_vector doesn't have erase function - call resize here (it's even better in this case).
    uniName.resize(distance(uniName.begin(), iEnd));
  }

  return (uniName.empty() ? "Bookmarks" : strings::ToUtf8(uniName));
}

string BookmarkCategory::GenerateUniqueFileName(const string & path, string const & name)
{
  size_t counter = 1;
  string suffix;
  while (Platform::IsFileExistsByFullPath(path + name + suffix + ".kml"))
    suffix = strings::to_string(counter++);
  return (path + name + suffix + ".kml");
}

bool BookmarkCategory::SaveToKMLFile()
{
  string oldFile;

  // Get valid file name from category name
  string const name = GetValidFileName(m_name);

  if (!m_file.empty())
  {
    size_t i2 = m_file.find_last_of('.');
    if (i2 == string::npos) i2 = m_file.size();
    size_t i1 = m_file.find_last_of("\\/");
    if (i1 == string::npos) i1 = 0;
    else ++i1;

    // If m_file doesn't match name, assign new m_file for this category and save old file name.
    if (m_file.substr(i1, i2-i1).find(name) != 0)
    {
      oldFile = GenerateUniqueFileName(GetPlatform().WritableDir(), name);
      m_file.swap(oldFile);
    }
  }
  else
    m_file = GenerateUniqueFileName(GetPlatform().WritableDir(), name);

  try
  {
    /// @todo On Windows UTF-8 file names are not supported.
    ofstream of(m_file.c_str());
    SaveToKML(of);
    of.flush();

    if (!of.fail())
    {
      // delete old file
      if (!oldFile.empty())
        VERIFY ( my::DeleteFileX(oldFile), (oldFile, m_file));

      return true;
    }
  }
  catch (std::exception const & e)
  {
    LOG(LWARNING, ("Exception while saving bookmarks:", e.what()));
  }

  LOG(LWARNING, ("Can't save bookmarks category", m_name, "to file", m_file));

  // return old file name in case of error
  if (!oldFile.empty())
    m_file.swap(oldFile);

  return false;
}
<|endoftext|>


<commit_before>#include "Sketch.h"

#include "chr/gl/draw/Sphere.h"

using namespace std;
using namespace chr;
using namespace gl;
using namespace draw;

static constexpr float SUN_EARTH_DISTANCE = 200;
static constexpr float EARTH_MOON_DISTANCE = 27;

void Sketch::setup()
{
  sunBatch
    .setShader(lambertShader)
    .setShaderColor(1, 1, 0.5f, 1);

  earthBatch
    .setShader(lambertShader)
    .setShaderColor(0.5f, 0.67f, 1, 1);

  moonBatch
    .setShader(lambertShader)
    .setShaderColor(0.75f, 0.75f, 0.75f, 1);

  Sphere()
    .setFrontFace(CW)
    .setRadius(45)
    .setSectorCount(60)
    .setStackCount(30)
    .append(sunBatch, Matrix());

  pathBatch
    .setPrimitive(GL_LINE_STRIP)
    .setShader(colorShader)
    .setShaderColor(1, 1, 1, 0.25f);

  createPath();

  // ---

  glEnable(GL_CULL_FACE);
  glEnable(GL_DEPTH_TEST);

  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void Sketch::draw()
{
  glClearColor(0.125f, 0.125f, 0.125f, 1);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // ---

  auto projectionMatrix = glm::perspective(60 * D2R, windowInfo.aspectRatio(), 0.1f, 1000.0f);

  Matrix viewMatrix;
  viewMatrix
    .translate(0, 0, -400)
    .rotateX(22 * D2R);

  State()
    .setShaderMatrix<MVP>(viewMatrix * projectionMatrix)
    .setShaderMatrix<NORMAL>(viewMatrix.getNormalMatrix())
    .apply();

  sunBatch.flush();

  Matrix::Stack stack;
  float t = clock()->getTime();

  earthBatch.clear();
  Sphere()
    .setFrontFace(CW)
    .setRadius(20)
    .setSectorCount(40)
    .setStackCount(20)
    .append(earthBatch, Matrix()
      .rotateY(t * 0.5f)
      .translate(0, 0, SUN_EARTH_DISTANCE)
      .push(stack));
  earthBatch.flush();

  moonBatch.clear();
  Sphere()
    .setFrontFace(CW)
    .setRadius(5)
    .setSectorCount(30)
    .setStackCount(15)
    .append(moonBatch, Matrix()
      .pop(stack)
      .rotateY(t * 2.0f)
      .translate(0, 0, EARTH_MOON_DISTANCE));
  moonBatch.flush();

  pathBatch.flush();
}

void Sketch::createPath()
{
  float radius = SUN_EARTH_DISTANCE;
  float segmentLength = 10;
  int n = ceilf(TWO_PI * radius / segmentLength) + 1;

  for (int i = 0; i < n; i++)
  {
    float d = i * segmentLength / radius;
    pathBatch.addVertex(sinf(-d) * radius, 0, -cosf(-d) * radius);
  }
}
<commit_msg>TestingDrawing3d: Simplification (no need for matrix stack)<commit_after>#include "Sketch.h"

#include "chr/gl/draw/Sphere.h"

using namespace std;
using namespace chr;
using namespace gl;
using namespace draw;

static constexpr float SUN_EARTH_DISTANCE = 200;
static constexpr float EARTH_MOON_DISTANCE = 27;

void Sketch::setup()
{
  sunBatch
    .setShader(lambertShader)
    .setShaderColor(1, 1, 0.5f, 1);

  earthBatch
    .setShader(lambertShader)
    .setShaderColor(0.5f, 0.67f, 1, 1);

  moonBatch
    .setShader(lambertShader)
    .setShaderColor(0.75f, 0.75f, 0.75f, 1);

  Sphere()
    .setFrontFace(CW)
    .setRadius(45)
    .setSectorCount(60)
    .setStackCount(30)
    .append(sunBatch, Matrix());

  pathBatch
    .setPrimitive(GL_LINE_STRIP)
    .setShader(colorShader)
    .setShaderColor(1, 1, 1, 0.25f);

  createPath();

  // ---

  glEnable(GL_CULL_FACE);
  glEnable(GL_DEPTH_TEST);

  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void Sketch::draw()
{
  glClearColor(0.125f, 0.125f, 0.125f, 1);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // ---

  auto projectionMatrix = glm::perspective(60 * D2R, windowInfo.aspectRatio(), 0.1f, 1000.0f);

  Matrix viewMatrix;
  viewMatrix
    .translate(0, 0, -400)
    .rotateX(22 * D2R);

  State()
    .setShaderMatrix<MVP>(viewMatrix * projectionMatrix)
    .setShaderMatrix<NORMAL>(viewMatrix.getNormalMatrix())
    .apply();

  sunBatch.flush();

  Matrix matrix;
  float t = clock()->getTime();

  matrix
    .rotateY(t * 0.5f)
    .translate(0, 0, SUN_EARTH_DISTANCE);

  earthBatch.clear();
  Sphere()
    .setFrontFace(CW)
    .setRadius(20)
    .setSectorCount(40)
    .setStackCount(20)
    .append(earthBatch, matrix);
  earthBatch.flush();

  matrix
    .rotateY(t * 2.0f)
    .translate(0, 0, EARTH_MOON_DISTANCE);

  moonBatch.clear();
  Sphere()
    .setFrontFace(CW)
    .setRadius(5)
    .setSectorCount(30)
    .setStackCount(15)
    .append(moonBatch, matrix);
  moonBatch.flush();

  pathBatch.flush();
}

void Sketch::createPath()
{
  float radius = SUN_EARTH_DISTANCE;
  float segmentLength = 10;
  int n = ceilf(TWO_PI * radius / segmentLength) + 1;

  for (int i = 0; i < n; i++)
  {
    float d = i * segmentLength / radius;
    pathBatch.addVertex(sinf(-d) * radius, 0, -cosf(-d) * radius);
  }
}
<|endoftext|>


<commit_before>/*
 * Tests for the scalar example solving the test equation
 */

#include <cmath>
#include <gtest/gtest.h>
#include <gmock/gmock.h>

#define PFASST_UNIT_TESTING
#include "../examples/scalar/scalar_sdc.cpp"
#undef PFASST_UNIT_TESTING

/*
 * For Lobatto nodes, the resulting method should of order 2*M-2 with M=number of nodes
 * The test below verifies that the code approximately (up to a safety factor) reproduces
 * the theoretically expected rate of convergence
 */
TEST(ConvergenceTest, ScalarSDC)
{
  const complex<double> lambda = complex<double>(-1.0, 1.0);
  const double Tend = 4.0;
  const vector<size_t> nsteps = { 2, 5, 10, 15, 20 };
  size_t nsteps_l = nsteps.size();

  vector<double> err(nsteps.size());
  vector<double> convrate(nsteps.size()-1);

  double dt;

  // Test converge up to 6 nodes: For more nodes, errors are of the order of machine
  // precision and convergence can no longer be monitored
  for ( size_t nnodes = 2; nnodes<=6; ++nnodes)
  {
    // Expect convergence rate of 2*nodes-2 from collocation formula,
    // doing an identical number of iteration should suffice to reach this as each
    // iteration should increase order by one
    size_t niters = 2*nnodes-2;

    for ( size_t i = 0; i<=nsteps_l-1; ++i)
    {
      dt = Tend/double(nsteps[i]);
      err[i] = run_scalar_sdc(nsteps[i], dt, nnodes, niters, lambda);
    }

    for ( size_t i = 0; i<=nsteps_l-2; ++i)
    {
      convrate[i] = log10(err[i+1]/err[i])/log10(double(nsteps[i])/double(nsteps[i+1]));

      EXPECT_THAT(convrate[i],
                  testing::DoubleNear(double(2*nnodes-2), 0.99)) << "Convergence rate at node "
                                                                 << i
                                                                 << " not within expected range";
    }
  }
}

int main(int argc, char** argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>tests: examples: scalar: rewamped to be parameterized<commit_after>/*
 * Tests for the scalar example solving the test equation
 */
#include <cmath>

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

using namespace ::testing;

#define PFASST_UNIT_TESTING
#include "../examples/scalar/scalar_sdc.cpp"
#undef PFASST_UNIT_TESTING

/*
 * parameterized test fixture with number of nodes as parameter
 */
class ConvergenceTest
  : public ::testing::TestWithParam<size_t>
{
  protected:
    size_t nnodes; // parameter

    const complex<double> lambda = complex<double>(-1.0, 1.0);
    const double Tend = 4.0;
    const vector<size_t> nsteps = { 2, 5, 10, 15, 20 };
    size_t nsteps_l;
    vector<double> err;
    vector<double> convrate;
    double dt;
    size_t niters;

  public:
    virtual void SetUp()
    {
      this->nnodes = this->GetParam();
      this->nsteps_l = this->nsteps.size();
      this->err.resize(this->nsteps.size());
      this->convrate.resize(this->nsteps.size());

      // Expect convergence rate of 2*nodes-2 from collocation formula,
      // doing an identical number of iteration should suffice to reach this as each
      // iteration should increase order by one
      this->niters = 2 * nnodes - 2;

      for (size_t i = 0; i <= nsteps_l - 1; ++i) {
        dt = Tend / double(nsteps[i]);
        err[i] = run_scalar_sdc(nsteps[i], dt, nnodes, niters, lambda);
      }
    }

    virtual void TearDown()
    {}
};

/*
 * For Lobatto nodes, the resulting method should of order 2*M-2 with M=number of nodes
 * The test below verifies that the code approximately (up to a safety factor) reproduces
 * the theoretically expected rate of convergence
 */
TEST_P(ConvergenceTest, GaussLobattoNodes)
{
  for (size_t i = 0; i <= nsteps_l - 2; ++i) {
    convrate[i] = log10(err[i+1] / err[i]) / log10(double(nsteps[i]) / double(nsteps[i + 1]));

    EXPECT_THAT(convrate[i],
                testing::DoubleNear(double(2 * nnodes - 2), 0.99)) << "Convergence rate at node "
                                                                   << i
                                                                   << " not within expected range";
  }
}

INSTANTIATE_TEST_CASE_P(ScalarSDC, ConvergenceTest, Range<size_t>(2, 7));

int main(int argc, char** argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#include "dbic++.h"
#include <unistd.h>

/*----------------------------------------------------------------------------------

   To compile:

   g++ -Iinc -Llibs -rdynamic -o example example.cc -ldbic++ -ldl -lpcrecpp -levent -lpthread

----------------------------------------------------------------------------------*/

using namespace std;
using namespace dbi;

char buffer[8192];

void fetchRows(Statement &st) {
    ResultRow r;
    while (r = st.fetchRow()) { }
}

void top() {
    sprintf(buffer, "top -n1 -bp %d | grep %s", getpid(), getlogin());
    FILE *top = popen(buffer, "r");
    fgets(buffer, 8192, top);
    pclose(top);
    buffer[strlen(buffer)-1] = 0;
    printf("%s", buffer);
}

int main(int argc, char *argv[]) {
    string driver(argc > 1 ? argv[1] : "postgresql");

    int rows = argc > 2 ? atoi(argv[2]) : 500;
    int iter = argc > 3 ? atoi(argv[3]) : 10;

    for (int times = 0; times < 50; times++) {
        Handle h (driver, getlogin(), "", "swift");

        printf("-- run %d --\n", times);
        top();

        // create test table
        h.execute("drop table if exists users");
        h.execute("create table users(id serial, name text, email text, created_at timestamp)");

        // insert some test data
        Statement ins (h, "insert into users(name, email, created_at) values(?, ?, now())");

        for (int n = 0; n < rows; n++) {
            sprintf(buffer, "test %d", n);
            ins % buffer;
            ins % "test@example.com";
            ins.execute();
        }

        Statement sel (h, "select id, name, email from users order by id");
        for (int n = 0; n < iter; n++) {
            sel.execute();
            fetchRows(sel);
        }

        Statement upd (h, "update users set name = ?, email = ? where id = ?");
        for (int n = 0; n < iter; n++) {
            sel.execute();
            for (int r = 0; r < sel.rows(); r++) {
                sprintf(buffer, "test %d", r);
                upd % buffer;
                upd % "test@example.com";
                upd % string((const char*)sel.fetchValue(r, 0, 0));
                upd.execute();
            }
        }

        ins.finish();
        sel.finish();
        upd.finish();
        h.close();
    }
}
<commit_msg>Corrected driver memory check instructions.<commit_after>#include "dbic++.h"
#include <unistd.h>

/*----------------------------------------------------------------------------------

   To compile:

   g++ -Iinc -Llibs -rdynamic -o driver driver.cc -ldbic++ -ldl -lpcrecpp -levent -lpthread -luuid

----------------------------------------------------------------------------------*/

using namespace std;
using namespace dbi;

char buffer[8192];

void fetchRows(Statement &st) {
    ResultRow r;
    while (r = st.fetchRow()) { }
}

void top() {
    sprintf(buffer, "top -n1 -bp %d | grep %s", getpid(), getlogin());
    FILE *top = popen(buffer, "r");
    fgets(buffer, 8192, top);
    pclose(top);
    buffer[strlen(buffer)-1] = 0;
    printf("%s", buffer);
}

int main(int argc, char *argv[]) {
    string driver(argc > 1 ? argv[1] : "postgresql");

    int rows = argc > 2 ? atoi(argv[2]) : 500;
    int iter = argc > 3 ? atoi(argv[3]) : 10;

    for (int times = 0; times < 50; times++) {
        Handle h (driver, getlogin(), "", "swift");

        printf("-- run %d --\n", times);
        top();

        // create test table
        h.execute("drop table if exists users");
        h.execute("create table users(id serial, name text, email text, created_at timestamp)");

        // insert some test data
        Statement ins (h, "insert into users(name, email, created_at) values(?, ?, now())");

        for (int n = 0; n < rows; n++) {
            sprintf(buffer, "test %d", n);
            ins % buffer;
            ins % "test@example.com";
            ins.execute();
        }

        Statement sel (h, "select id, name, email from users order by id");
        for (int n = 0; n < iter; n++) {
            sel.execute();
            fetchRows(sel);
        }

        Statement upd (h, "update users set name = ?, email = ? where id = ?");
        for (int n = 0; n < iter; n++) {
            sel.execute();
            for (int r = 0; r < sel.rows(); r++) {
                sprintf(buffer, "test %d", r);
                upd % buffer;
                upd % "test@example.com";
                upd % string((const char*)sel.fetchValue(r, 0, 0));
                upd.execute();
            }
        }

        ins.finish();
        sel.finish();
        upd.finish();
        h.close();
    }
}
<|endoftext|>


<commit_before>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2015 Intel Corporation. All Rights Reserved.
#ifdef RS2_USE_WINUSB_UVC_BACKEND

#if (_MSC_FULL_VER < 180031101)
    #error At least Visual Studio 2013 Update 4 is required to compile this backend
#endif

#include "win7-backend.h"
#include "win7-uvc.h"
#include "win7-usb.h"
#include "win7-hid.h"
#include "../types.h"
#include <mfapi.h>
#include <ks.h>
#include <chrono>
#include <Windows.h>
#include <dbt.h>
#include <cctype> // std::tolower

#ifndef KSCATEGORY_SENSOR_CAMERA
DEFINE_GUIDSTRUCT("24E552D7-6523-47F7-A647-D3465BF1F5CA", KSCATEGORY_SENSOR_CAMERA);
#define KSCATEGORY_SENSOR_CAMERA DEFINE_GUIDNAMED(KSCATEGORY_SENSOR_CAMERA)
#endif // !KSCATEGORY_SENSOR_CAMERA

namespace librealsense
{
    namespace platform
    {
        win7_backend::win7_backend()
        {
        }

        win7_backend::~win7_backend()
        {
            try {

            }
            catch(...)
            {
                // TODO: Write to log
            }
        }

        std::shared_ptr<uvc_device> win7_backend::create_uvc_device(uvc_device_info info) const
        {
            return std::make_shared<retry_controls_work_around>(std::make_shared<win7_uvc_device>(info, shared_from_this()));
        }

        std::shared_ptr<backend> create_backend()
        {
            return std::make_shared<win7_backend>();
        }

        std::vector<uvc_device_info> win7_backend::query_uvc_devices() const
        {
            std::vector<uvc_device_info> devices;

            auto action = [&devices](const uvc_device_info& info)
            {
                devices.push_back(info);
            };

            win7_uvc_device::foreach_uvc_device(action);

            return devices;
        }

        std::shared_ptr<usb_device> win7_backend::create_usb_device(usb_device_info info) const
        {
            return std::make_shared<winusb_bulk_transfer>(info);
        }

        std::vector<usb_device_info> win7_backend::query_usb_devices() const
        {
            const std::vector<std::string> usb_interfaces = {
                "{175695CD-30D9-4F87-8BE3-5A8270F49A31}",
                "{08090549-CE78-41DC-A0FB-1BD66694BB0C}"
            };

            std::vector<usb_device_info> result;
            for (auto&& interface_id : usb_interfaces)
            {
                for (auto&& id : usb_enumerate::query_by_interface(interface_id, "", ""))
                {
                    std::string path(id.begin(), id.end());
                    uint16_t vid, pid, mi; std::string unique_id, device_guid;
                    if (!parse_usb_path(vid, pid, mi, unique_id, device_guid, path)) continue;

                    usb_device_info info{ path, vid, pid, mi, unique_id, usb_undefined };

                    result.push_back(info);
                }
            }

            return result;
        }

        std::shared_ptr<hid_device> win7_backend::create_hid_device(hid_device_info info) const
        {
            throw std::runtime_error("create_hid_device Not supported");
        }

        std::vector<hid_device_info> win7_backend::query_hid_devices() const
        {
            std::vector<hid_device_info> devices;
            // Not supported
            return devices;
        }

        std::shared_ptr<time_service> win7_backend::create_time_service() const
        {
            return std::make_shared<os_time_service>();
        }

        class win_event_device_watcher : public device_watcher
        {
        public:
            win_event_device_watcher(const backend * backend)
            {
                _data._backend = backend;
                _data._stopped = false;
                _data._last = backend_device_group(backend->query_uvc_devices(), backend->query_usb_devices(), backend->query_hid_devices());
            }
            ~win_event_device_watcher() { stop(); }

            void start(device_changed_callback callback) override
            {
                std::lock_guard<std::mutex> lock(_m);
                if (!_data._stopped) throw wrong_api_call_sequence_exception("Cannot start a running device_watcher");
                _data._stopped = false;
                _data._callback = std::move(callback);
                _thread = std::thread([this]() { run(); });
            }

            void stop() override
            {
                std::lock_guard<std::mutex> lock(_m);
                if (!_data._stopped)
                {
                    _data._stopped = true;
                    if (_thread.joinable()) _thread.join();
                }
            }
        private:
            std::thread _thread;
            std::mutex _m;

            struct extra_data {
                const backend * _backend;
                backend_device_group _last;
                device_changed_callback _callback;

                bool _stopped;
                HWND hWnd;
                HDEVNOTIFY hdevnotifyHW, hdevnotifyUVC, hdevnotify_sensor;
            } _data;

            void run()
            {
                WNDCLASS windowClass = {};
                LPCWSTR SzWndClass = TEXT("MINWINAPP");
                windowClass.lpfnWndProc = &on_win_event;
                windowClass.lpszClassName = SzWndClass;
                UnregisterClass(SzWndClass, nullptr);

                if (!RegisterClass(&windowClass))
                    LOG_WARNING("RegisterClass failed.");

                _data.hWnd = CreateWindow(SzWndClass, nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, &_data);
                if (!_data.hWnd)
                    throw winapi_error("CreateWindow failed");

                MSG msg;

                while (!_data._stopped)
                {
                    if (PeekMessage(&msg, _data.hWnd, 0, 0, PM_REMOVE))
                    {
                            TranslateMessage(&msg);
                            DispatchMessage(&msg);
                    }
                    else  // Yield CPU resources, as this is required for connect/disconnect events only
                        std::this_thread::sleep_for(std::chrono::milliseconds(50));
                }

                UnregisterDeviceNotification(_data.hdevnotifyHW);
                UnregisterDeviceNotification(_data.hdevnotifyUVC);
                UnregisterDeviceNotification(_data.hdevnotify_sensor);
                DestroyWindow(_data.hWnd);
            }

            static LRESULT CALLBACK on_win_event(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
            {
                LRESULT lRet = 1;

                switch (message)
                {
                case WM_CREATE:
                    SetWindowLongPtr(hWnd, GWLP_USERDATA, LONG_PTR(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams));
                    if (!DoRegisterDeviceInterfaceToHwnd(hWnd))
                case WM_QUIT:
                {
                    auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
                    data->_stopped = true;
                    break;
                }
                case WM_DEVICECHANGE:
                {
                    //PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE)lParam;
                    // Output some messages to the window.
                    switch (wParam)
                    {
                    case DBT_DEVICEARRIVAL:
                    {
                        auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
                        backend_device_group next(data->_backend->query_uvc_devices(), data->_backend->query_usb_devices(), data->_backend->query_hid_devices());
                        /*if (data->_last != next)*/ data->_callback(data->_last, next);
                        data->_last = next;
                    }
                        break;

                    case DBT_DEVICEREMOVECOMPLETE:
                    {
                        auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
                        auto next = data->_last;
                        std::wstring temp = reinterpret_cast<DEV_BROADCAST_DEVICEINTERFACE*>(lParam)->dbcc_name;
                        std::string path;
                        path.reserve(temp.length());
                        for (wchar_t ch : temp) {
                            if (ch != L'{') path.push_back(std::tolower(((char*)&ch)[0]));
                            else break;
                        }

                        next.uvc_devices.erase(std::remove_if(next.uvc_devices.begin(), next.uvc_devices.end(), [&path](const uvc_device_info& info)
                        { return info.device_path.substr(0, info.device_path.find_first_of("{")) == path; }), next.uvc_devices.end());
                        //                            next.usb_devices.erase(std::remove_if(next.usb_devices.begin(), next.usb_devices.end(), [&path](const usb_device_info& info)
                        //                            { return info.device_path.substr(0, info.device_path.find_first_of("{")) == path; }), next.usb_devices.end());
                        next.usb_devices = data->_backend->query_usb_devices();
                        next.hid_devices.erase(std::remove_if(next.hid_devices.begin(), next.hid_devices.end(), [&path](const hid_device_info& info)
                        { return info.device_path.substr(0, info.device_path.find_first_of("{")) == path; }), next.hid_devices.end());

                        /*if (data->_last != next)*/ data->_callback(data->_last, next);
                        data->_last = next;
                    }
                        break;
                    }
                    break;
                }

                default:
                    // Send all other messages on to the default windows handler.
                    lRet = DefWindowProc(hWnd, message, wParam, lParam);
                    break;
                }

                return lRet;
            }

            static BOOL DoRegisterDeviceInterfaceToHwnd(HWND hWnd)
            {
                auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

                //===========================register HWmonitor events==============================
                const GUID classGuid = { 0x175695cd, 0x30d9, 0x4f87, 0x8b, 0xe3, 0x5a, 0x82, 0x70, 0xf4, 0x9a, 0x31 };
                DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface;
                devBroadcastDeviceInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
                devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
                devBroadcastDeviceInterface.dbcc_classguid = classGuid;
                devBroadcastDeviceInterface.dbcc_reserved = 0;

                data->hdevnotifyHW = RegisterDeviceNotification(hWnd,
                    &devBroadcastDeviceInterface,
                    DEVICE_NOTIFY_WINDOW_HANDLE);
                if (data->hdevnotifyHW == NULL)
                {
                    LOG_WARNING("Register HW events Failed!\n");
                    return FALSE;
                }

                ////===========================register UVC events==============================
                DEV_BROADCAST_DEVICEINTERFACE di = { 0 };
                di.dbcc_size = sizeof(di);
                di.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
                di.dbcc_classguid = KSCATEGORY_CAPTURE;

                data->hdevnotifyUVC = RegisterDeviceNotification(hWnd,
                    &di,
                    DEVICE_NOTIFY_WINDOW_HANDLE);
                if (data->hdevnotifyUVC == nullptr)
                {
                    UnregisterDeviceNotification(data->hdevnotifyHW);
                    LOG_WARNING("Register UVC events Failed!\n");
                    return FALSE;
                }

                ////===========================register UVC sensor camera events==============================
                DEV_BROADCAST_DEVICEINTERFACE di_sensor = { 0 };
                di_sensor.dbcc_size = sizeof(di_sensor);
                di_sensor.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
                di_sensor.dbcc_classguid = KSCATEGORY_SENSOR_CAMERA;

                data->hdevnotify_sensor = RegisterDeviceNotification(hWnd,
                    &di_sensor,
                    DEVICE_NOTIFY_WINDOW_HANDLE);
                if (data->hdevnotify_sensor == nullptr)
                {
                    UnregisterDeviceNotification(data->hdevnotify_sensor);
                    LOG_WARNING("Register UVC events Failed!\n");
                    return FALSE;
                }
                return TRUE;
            }
        };

        std::shared_ptr<device_watcher> win7_backend::create_device_watcher() const
        {
            return std::make_shared<polling_device_watcher>(this);
        }
    }
}

#endif
<commit_msg>Adding faster device_watcher<commit_after>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2015 Intel Corporation. All Rights Reserved.
#ifdef RS2_USE_WINUSB_UVC_BACKEND

#if (_MSC_FULL_VER < 180031101)
    #error At least Visual Studio 2013 Update 4 is required to compile this backend
#endif

#include "win7-backend.h"
#include "win7-uvc.h"
#include "win7-usb.h"
#include "win7-hid.h"
#include "../types.h"
#include <mfapi.h>
#include <ks.h>
#include <chrono>
#include <Windows.h>
#include <dbt.h>
#include <cctype> // std::tolower

#ifndef KSCATEGORY_SENSOR_CAMERA
DEFINE_GUIDSTRUCT("24E552D7-6523-47F7-A647-D3465BF1F5CA", KSCATEGORY_SENSOR_CAMERA);
#define KSCATEGORY_SENSOR_CAMERA DEFINE_GUIDNAMED(KSCATEGORY_SENSOR_CAMERA)
#endif // !KSCATEGORY_SENSOR_CAMERA

namespace librealsense
{
    namespace platform
    {
        win7_backend::win7_backend()
        {
        }

        win7_backend::~win7_backend()
        {
            try {

            }
            catch(...)
            {
                // TODO: Write to log
            }
        }

        std::shared_ptr<uvc_device> win7_backend::create_uvc_device(uvc_device_info info) const
        {
            return std::make_shared<retry_controls_work_around>(std::make_shared<win7_uvc_device>(info, shared_from_this()));
        }

        std::shared_ptr<backend> create_backend()
        {
            return std::make_shared<win7_backend>();
        }

        std::vector<uvc_device_info> win7_backend::query_uvc_devices() const
        {
            std::vector<uvc_device_info> devices;

            auto action = [&devices](const uvc_device_info& info)
            {
                devices.push_back(info);
            };

            win7_uvc_device::foreach_uvc_device(action);

            return devices;
        }

        std::shared_ptr<usb_device> win7_backend::create_usb_device(usb_device_info info) const
        {
            return std::make_shared<winusb_bulk_transfer>(info);
        }

        std::vector<usb_device_info> win7_backend::query_usb_devices() const
        {
            const std::vector<std::string> usb_interfaces = {
                "{175695CD-30D9-4F87-8BE3-5A8270F49A31}",
                "{08090549-CE78-41DC-A0FB-1BD66694BB0C}"
            };

            std::vector<usb_device_info> result;
            for (auto&& interface_id : usb_interfaces)
            {
                for (auto&& id : usb_enumerate::query_by_interface(interface_id, "", ""))
                {
                    std::string path(id.begin(), id.end());
                    uint16_t vid, pid, mi; std::string unique_id, device_guid;
                    if (!parse_usb_path(vid, pid, mi, unique_id, device_guid, path)) continue;

                    usb_device_info info{ path, vid, pid, mi, unique_id, usb_undefined };

                    result.push_back(info);
                }
            }

            return result;
        }

        std::shared_ptr<hid_device> win7_backend::create_hid_device(hid_device_info info) const
        {
            throw std::runtime_error("create_hid_device Not supported");
        }

        std::vector<hid_device_info> win7_backend::query_hid_devices() const
        {
            std::vector<hid_device_info> devices;
            // Not supported
            return devices;
        }

        std::shared_ptr<time_service> win7_backend::create_time_service() const
        {
            return std::make_shared<os_time_service>();
        }

        class win7_event_device_watcher : public device_watcher
        {
        public:
            win7_event_device_watcher(const backend * backend)
            {
                _data._backend = backend;
                _data._stopped = false;
                _data._last = backend_device_group(backend->query_uvc_devices(), backend->query_usb_devices(), backend->query_hid_devices());
            }
            ~win7_event_device_watcher() { stop(); }

            void start(device_changed_callback callback) override
            {
                std::lock_guard<std::mutex> lock(_m);
                if (!_data._stopped) throw wrong_api_call_sequence_exception("Cannot start a running device_watcher");
                _data._stopped = false;
                _data._callback = std::move(callback);
                _thread = std::thread([this]() { run(); });
            }

            void stop() override
            {
                std::lock_guard<std::mutex> lock(_m);
                if (!_data._stopped)
                {
                    _data._stopped = true;
                    if (_thread.joinable()) _thread.join();
                }
            }
        private:
            std::thread _thread;
            std::mutex _m;

            struct extra_data {
                const backend * _backend;
                backend_device_group _last;
                device_changed_callback _callback;

                bool _stopped;
                HWND hWnd;
                HDEVNOTIFY hdevnotifyHW, hdevnotifyUVC, hdevnotify_sensor;
            } _data;

            void run()
            {
                WNDCLASS windowClass = {};
                LPCWSTR SzWndClass = TEXT("MINWINAPP");
                windowClass.lpfnWndProc = &on_win_event;
                windowClass.lpszClassName = SzWndClass;
                UnregisterClass(SzWndClass, nullptr);

                if (!RegisterClass(&windowClass))
                    LOG_WARNING("RegisterClass failed.");

                _data.hWnd = CreateWindow(SzWndClass, nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, &_data);
                if (!_data.hWnd)
                    throw winapi_error("CreateWindow failed");

                MSG msg;

                while (!_data._stopped)
                {
                    if (PeekMessage(&msg, _data.hWnd, 0, 0, PM_REMOVE))
                    {
                            TranslateMessage(&msg);
                            DispatchMessage(&msg);
                    }
                    else  // Yield CPU resources, as this is required for connect/disconnect events only
                        std::this_thread::sleep_for(std::chrono::milliseconds(50));
                }

                UnregisterDeviceNotification(_data.hdevnotifyHW);
                UnregisterDeviceNotification(_data.hdevnotifyUVC);
                UnregisterDeviceNotification(_data.hdevnotify_sensor);
                DestroyWindow(_data.hWnd);
            }

            static LRESULT CALLBACK on_win_event(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
            {
                LRESULT lRet = 1;

                switch (message)
                {
                case WM_CREATE:
                    SetWindowLongPtr(hWnd, GWLP_USERDATA, LONG_PTR(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams));
                    if (!DoRegisterDeviceInterfaceToHwnd(hWnd))
                case WM_QUIT:
                {
                    auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
                    data->_stopped = true;
                    break;
                }
                case WM_DEVICECHANGE:
                {
                    //PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE)lParam;
                    // Output some messages to the window.
                    switch (wParam)
                    {
                    case DBT_DEVICEARRIVAL:
                    {
                        auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
                        backend_device_group next(data->_backend->query_uvc_devices(), data->_backend->query_usb_devices(), data->_backend->query_hid_devices());
                        /*if (data->_last != next)*/ data->_callback(data->_last, next);
                        data->_last = next;
                    }
                        break;

                    case DBT_DEVICEREMOVECOMPLETE:
                    {
                        auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
                        auto next = data->_last;
                        std::wstring temp = reinterpret_cast<DEV_BROADCAST_DEVICEINTERFACE*>(lParam)->dbcc_name;
                        std::string path;
                        path.reserve(temp.length());
                        for (wchar_t ch : temp) {
                            if (ch != L'{') path.push_back(std::tolower(((char*)&ch)[0]));
                            else break;
                        }

                        next.uvc_devices.erase(std::remove_if(next.uvc_devices.begin(), next.uvc_devices.end(), [&path](const uvc_device_info& info)
                        { return info.device_path.substr(0, info.device_path.find_first_of("{")) == path; }), next.uvc_devices.end());
                        //                            next.usb_devices.erase(std::remove_if(next.usb_devices.begin(), next.usb_devices.end(), [&path](const usb_device_info& info)
                        //                            { return info.device_path.substr(0, info.device_path.find_first_of("{")) == path; }), next.usb_devices.end());
                        next.usb_devices = data->_backend->query_usb_devices();
                        next.hid_devices.erase(std::remove_if(next.hid_devices.begin(), next.hid_devices.end(), [&path](const hid_device_info& info)
                        { return info.device_path.substr(0, info.device_path.find_first_of("{")) == path; }), next.hid_devices.end());

                        /*if (data->_last != next)*/ data->_callback(data->_last, next);
                        data->_last = next;
                    }
                        break;
                    }
                    break;
                }

                default:
                    // Send all other messages on to the default windows handler.
                    lRet = DefWindowProc(hWnd, message, wParam, lParam);
                    break;
                }

                return lRet;
            }

            static BOOL DoRegisterDeviceInterfaceToHwnd(HWND hWnd)
            {
                auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

                for (auto guidStr : device_guids)
                {
                    GUID guid;
                    std::wstring guidWStr(guidStr.begin(), guidStr.end());
                    CHECK_HR(CLSIDFromString(guidWStr.c_str(), static_cast<LPCLSID>(&guid)));

                    DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface;
                    devBroadcastDeviceInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
                    devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
                    devBroadcastDeviceInterface.dbcc_classguid = guid;
                    devBroadcastDeviceInterface.dbcc_reserved = 0;

                    data->hdevnotifyHW = RegisterDeviceNotification(hWnd,
                        &devBroadcastDeviceInterface,
                        DEVICE_NOTIFY_WINDOW_HANDLE);
                    if (data->hdevnotifyHW == NULL)
                    {
                        LOG_WARNING("Register HW events Failed!\n");
                        return FALSE;
                    }
                }

                return TRUE;
            }
        };

        std::shared_ptr<device_watcher> win7_backend::create_device_watcher() const
        {
            return std::make_shared<win7_event_device_watcher>(this);
        }
    }
}

#endif
<|endoftext|>


<commit_before>/* @(#)dtkComposerGraphNodeLeaf.cpp ---
 *
 * Author: Nicolas Niclausse
 * Copyright (C) 2012 - Nicolas Niclausse, Inria.
 * Created: 2012/02/14 13:59:57
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "dtkComposerGraphNodeLeaf.h"
#include "dtkComposerNode.h"
#include "dtkComposerNodeLeaf.h"
// #include "dtkComposerNodeLeafData.h"
// #include "dtkComposerNodeLeafProcess.h"
// #include "dtkComposerNodeLeafView.h"
// #include "dtkComposerNodeLeafActor.h"

class dtkComposerGraphNodeLeafPrivate
{
public:
    dtkComposerNodeLeaf *composer_node;

public:
    dtkComposerGraphNode::Kind kind;

};

dtkComposerGraphNodeLeaf::dtkComposerGraphNodeLeaf(dtkComposerNode *cnode, const QString& title) : dtkComposerGraphNode(),d(new dtkComposerGraphNodeLeafPrivate)
{
    d->composer_node = dynamic_cast<dtkComposerNodeLeaf *>(cnode);
    // if (dynamic_cast<dtkComposerNodeLeafProcess *>(cnode))
    //     d->kind = dtkComposerGraphNode::Process;
    // else if (dynamic_cast<dtkComposerNodeLeafView *>(cnode))
    //     d->kind = dtkComposerGraphNode::View;
    // else if (dynamic_cast<dtkComposerNodeLeafData *>(cnode))
    //     d->kind = dtkComposerGraphNode::Data;
    // else if (dynamic_cast<dtkComposerNodeLeafActor *>(cnode))
    //     d->kind = dtkComposerGraphNode::Actor;
    // else
        d->kind = dtkComposerGraphNode::Leaf;

    this->setTitle(title);
}

dtkComposerGraphNode::Kind dtkComposerGraphNodeLeaf::kind(void)
{
    return d->kind;
}

dtkComposerNode *dtkComposerGraphNodeLeaf::wrapee(void)
{
    return d->composer_node;
}

void dtkComposerGraphNodeLeaf::eval(void)
{
    if (d->composer_node == NULL)
        return;

    d->composer_node->run();
    this->setStatus(dtkComposerGraphNode::Done);
}

<commit_msg>restore view type node<commit_after>/* @(#)dtkComposerGraphNodeLeaf.cpp ---
 *
 * Author: Nicolas Niclausse
 * Copyright (C) 2012 - Nicolas Niclausse, Inria.
 * Created: 2012/02/14 13:59:57
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "dtkComposerGraphNodeLeaf.h"
#include "dtkComposerNode.h"
#include "dtkComposerNodeLeaf.h"
#include "dtkComposerNodeMetaData.h"
// #include "dtkComposerNodeLeafData.h"
// #include "dtkComposerNodeLeafProcess.h"
// #include "dtkComposerNodeLeafView.h"
// #include "dtkComposerNodeLeafActor.h"

class dtkComposerGraphNodeLeafPrivate
{
public:
    dtkComposerNodeLeaf *composer_node;

public:
    dtkComposerGraphNode::Kind kind;

};

dtkComposerGraphNodeLeaf::dtkComposerGraphNodeLeaf(dtkComposerNode *cnode, const QString& title) : dtkComposerGraphNode(),d(new dtkComposerGraphNodeLeafPrivate)
{
    dtkComposerNodeMetaData* metaData =cnode->nodeMetaData();

    if(metaData!=NULL && metaData->kind()==dtkComposerNode::View)
        d->kind = dtkComposerGraphNode::View;
    else
        d->kind = dtkComposerGraphNode::Leaf;
    d->composer_node = dynamic_cast<dtkComposerNodeLeaf *>(cnode);

    // if (dynamic_cast<dtkComposerNodeLeafProcess *>(cnode))
    //     d->kind = dtkComposerGraphNode::Process;
    // else if (dynamic_cast<dtkComposerNodeLeafView *>(cnode))
    //     d->kind = dtkComposerGraphNode::View;
    // else if (dynamic_cast<dtkComposerNodeLeafData *>(cnode))
    //     d->kind = dtkComposerGraphNode::Data;
    // else if (dynamic_cast<dtkComposerNodeLeafActor *>(cnode))
    //     d->kind = dtkComposerGraphNode::Actor;
    // else
        //d->kind = dtkComposerGraphNode::Leaf;

    this->setTitle(title);
}

dtkComposerGraphNode::Kind dtkComposerGraphNodeLeaf::kind(void)
{
    return d->kind;
}

dtkComposerNode *dtkComposerGraphNodeLeaf::wrapee(void)
{
    return d->composer_node;
}

void dtkComposerGraphNodeLeaf::eval(void)
{
    if (d->composer_node == NULL)
        return;

    d->composer_node->run();
    this->setStatus(dtkComposerGraphNode::Done);
}

<|endoftext|>


<commit_before>/**
 * @file PrintCtrl.cpp
 *    Definitions for a simple class that augments the streams printing capabilities
 *   (see \ref Cantera::PrintCtrl).
 */
/*
 * $Author$
 * $Revision$
 * $Date$
 */
/*
 * Copywrite 2004 Sandia Corporation. Under the terms of Contract
 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
 * retains certain rights in this software.
 * See file License.txt for licensing information.
 */

#include <cmath>

#include <iostream>
#include <fstream>

#include "PrintCtrl.h"

using namespace std;

namespace Cantera {

  PrintCtrl::PrintCtrl(std::ostream &coutProxy, int Ndec) :
    m_cout(coutProxy),
    m_Ndec(Ndec),
    m_precision(12),
    m_wMin(9),
    m_wMax(19)
  {

  }

  // Print a double using scientific notation
  /*
   * Prints a double using scientific notation in a
   * fixed number of spaces
   *
   *
   *  @param d  double to be printed
   *  @param w  Number of spaces to use
   *  @param p  Precision
   *
   *
   */
  void PrintCtrl::pr_de_c10(const double din, int p, const int wMin,
			    const int wMax) {
    double d = cropAbs10(din, m_Ndec);
    pr_de(d, p, wMin, wMax);
  }

  // Print a double using scientific notation
  /*
   * Prints a double using scientific notation in a
   * fixed number of spaces. Rounding of the last digit is carried out
   * by the standard c++ printing utilities.
   *
   *  @param d  double to be printed
   *  @param w  Number of spaces to use
   *  @param p  Precision
   */
  void PrintCtrl::pr_de(const double d, int sigDigIn, const int wMinIn,
			const int wMaxIn) {
    int p = m_precision;
    if (sigDigIn != -1) {
      p = sigDigIn-1;
      if (p < 0) p = 0;
    }

    int wMin = m_wMin;
    if (wMinIn != -1) {
      wMin = wMinIn;
      if (wMin < 1) wMin = 1;
    }

    int wMax = m_wMax;
    if (wMaxIn != -1) {
      wMax = wMaxIn;
      if (wMax < 1) wMax = 1;
    }

    if (wMin > wMax) wMax = wMin;

    // Have to do the wMax ourselves, since C++ doesn't seem to
    // have a streams manipulator to do this !?!
    double dfabs = fabs(d);
    // This is the normal length assuming no sign and an 1.0E+04
    // formated exponented
    int requestedLength = 6 + p;
    if (d < 0.0) {
      requestedLength++;
    }
    if (dfabs < 9.9999999999E-99) {
      requestedLength++;
    }
    if (dfabs > 9.9999999999E99) {
      requestedLength++;
    }
    if (requestedLength > wMax) {
      p -= (requestedLength - wMax);
      if (p < 0) p = 0;
    }

    // Set to upper case and scientific notation
    m_cout.setf(ios_base::scientific | ios_base::uppercase);
    int wold = m_cout.width(wMin);
    int pold = m_cout.precision(p);

    m_cout << d;
    // Return the precision to the previous value;
    m_cout.precision(pold);
    m_cout.unsetf(ios_base::scientific);

    // Return width to original
    m_cout.width(wold);
  }

  // Croup a double at a certain decade level
  /*
   *    This routine will crop a floating point number at a certain
   *  decade lvl. In other words everything below a power of 10^Ndec
   *  will be deleted.
   *  Note, it currently does not do rounding of the last digit.
   *
   *   @param d Double to be cropped
   *   @param nSig Number of significant digits
   *   example:
   *    d = 1.1305E-15;
   *    Ndec = -16;
   *   This routine will return 1.1E-15
   *
   *    d = 8.0E-17
   *    Ndec = -16
   *   This routine will return 0.0
   */
  double PrintCtrl::cropAbs10(const double d, int Ndec) const {
    if (Ndec < -301 || Ndec > 301) {
      return d;
    }
    double sgn = 1.0;
    if (d < 0.0) sgn = -1.0;
    double dfabs = fabs(d);
    double  pdec = pow(10.0, (double) Ndec);
    if (dfabs < pdec) {
      return 0.0;
    }
    double dl10 = log10(dfabs);
    int N10 = (int) dl10;
    if (dl10 > -0.0) {
      N10 += 1;
    }
    int nsig = N10 - Ndec;
    double retn = cropSigDigits(d, nsig);
    return retn;
  }

  // Crop a double at a certain number of significant digits
  /*
   *  This routine will crop a floating point number at a certain
   *  number of significant digits. Note, it currently does
   *  rounding up of the last digit.
   *
   *  example:
   *    d = 1.0305E-15;
   *    nsig = 3;
   *   This routine will return 1.03E-15
   */
  double PrintCtrl::cropSigDigits(const double d, int nSig) const {
    if (nSig <=0) nSig = 1;
    if (nSig >=10) nSig = 10;
    double sgn = 1.0;
    if (d < 0.0) sgn = -1.0;
    double dfabs = fabs(d);
    double dl10 = log10(dfabs);
    int N10 = (int) dl10;
    if (dl10 > -0.0) {
      N10 += 1;
    }
    int E10 = -N10 + nSig ;
    double pfabs = dfabs * pow(10.0, (double) E10);
    pfabs *= (1.0 + 1.0E-14);
    long int nfabs = (long int) pfabs;
    double remainder = pfabs - nfabs;
    if (remainder > 0.5) {
      nfabs++;
    }
    double paltabs = (double) nfabs;
    double daltabs = paltabs * pow(10.0, (double) -E10);
    return (sgn * daltabs);
  }

  // Set the default value of N decade
  /*
   * @param Ndec new value of Ndec
   *
   * @return returns the old value of Ndec
   */
  int PrintCtrl::setNdec(int Ndec) {
    int nold = m_Ndec;
    m_Ndec = Ndec;
    return nold;
  }

  // Set the default significant digits to output
  /*
   * @param nSigDigits new value of the sig digits
   *
   * @return returns the old value of Ndec
   */
  int PrintCtrl::setSigDigits(int nSigDigits) {
    int nold = m_precision + 1;
    m_precision = nSigDigits - 1;
    if (m_precision < 0) m_precision = 0;
    return nold;
  }

  // Set the default minimum width
  /*
   * @param wmin Default minimum width
   *
   * @return returns the old default
   */
  int PrintCtrl::setWmin(int wmin) {
    int nold = m_wMin;
    m_wMin = wmin;
    return nold;
  }

  // Set the default maximum width
  /*
   * @param wmin Default maximum width
   *
   * @return returns the old default
   */
  int PrintCtrl::setWmax(int wmax) {
    int nold = m_wMax;
    m_wMax = wmax;
    return nold;
  }

}
<commit_msg>Fixed an error in this function<commit_after>/**
 * @file PrintCtrl.cpp
 *    Definitions for a simple class that augments the streams printing capabilities
 *   (see \ref Cantera::PrintCtrl).
 */
/*
 * $Author$
 * $Revision$
 * $Date$
 */
/*
 * Copywrite 2004 Sandia Corporation. Under the terms of Contract
 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
 * retains certain rights in this software.
 * See file License.txt for licensing information.
 */

#include <cmath>

#include <iostream>
#include <fstream>

#include "PrintCtrl.h"

using namespace std;

namespace Cantera {

  PrintCtrl::PrintCtrl(std::ostream &coutProxy, int Ndec) :
    m_cout(coutProxy),
    m_Ndec(Ndec),
    m_precision(12),
    m_wMin(9),
    m_wMax(19)
  {

  }

  // Print a double using scientific notation
  /*
   * Prints a double using scientific notation in a
   * fixed number of spaces
   *
   *
   *  @param d  double to be printed
   *  @param w  Number of spaces to use
   *  @param p  Precision
   *
   *
   */
  void PrintCtrl::pr_de_c10(const double din, int p, const int wMin,
			    const int wMax) {
    double d = cropAbs10(din, m_Ndec);
    pr_de(d, p, wMin, wMax);
  }

  // Print a double using scientific notation
  /*
   * Prints a double using scientific notation in a
   * fixed number of spaces. Rounding of the last digit is carried out
   * by the standard c++ printing utilities.
   *
   *  @param d  double to be printed
   *  @param w  Number of spaces to use
   *  @param p  Precision
   */
  void PrintCtrl::pr_de(const double d, int sigDigIn, const int wMinIn,
			const int wMaxIn) {
    int p = m_precision;
    if (sigDigIn != -1) {
      p = sigDigIn-1;
      if (p < 0) p = 0;
    }

    int wMin = m_wMin;
    if (wMinIn != -1) {
      wMin = wMinIn;
      if (wMin < 1) wMin = 1;
    }

    int wMax = m_wMax;
    if (wMaxIn != -1) {
      wMax = wMaxIn;
      if (wMax < 1) wMax = 1;
    }

    if (wMin > wMax) wMax = wMin;

    // Have to do the wMax ourselves, since C++ doesn't seem to
    // have a streams manipulator to do this !?!
    double dfabs = fabs(d);
    // This is the normal length assuming no sign and an 1.0E+04
    // formated exponented
    int requestedLength = 6 + p;
    if (d < 0.0) {
      requestedLength++;
    }
    if (dfabs < 9.9999999999E-99) {
      requestedLength++;
    }
    if (dfabs > 9.9999999999E99) {
      requestedLength++;
    }
    if (requestedLength > wMax) {
      p -= (requestedLength - wMax);
      if (p < 0) p = 0;
    }

    // Set to upper case and scientific notation
    m_cout.setf(ios_base::scientific | ios_base::uppercase);
    int wold = m_cout.width(wMin);
    int pold = m_cout.precision(p);

    m_cout << d;
    // Return the precision to the previous value;
    m_cout.precision(pold);
    m_cout.unsetf(ios_base::scientific);

    // Return width to original
    m_cout.width(wold);
  }

  // Croup a double at a certain decade level
  /*
   *    This routine will crop a floating point number at a certain
   *  decade lvl. In other words everything below a power of 10^Ndec
   *  will be deleted.
   *  Note, it currently does not do rounding of the last digit.
   *
   *   @param d Double to be cropped
   *   @param nSig Number of significant digits
   *   example:
   *    d = 1.1305E-15;
   *    Ndec = -16;
   *   This routine will return 1.1E-15
   *
   *    d = 8.0E-17
   *    Ndec = -16
   *   This routine will return 0.0
   */
  double PrintCtrl::cropAbs10(const double d, int Ndec) const {
    if (Ndec < -301 || Ndec > 301) {
      return d;
    }
    double sgn = 1.0;
    if (d < 0.0) sgn = -1.0;
    double dfabs = fabs(d);
    double  pdec = pow(10.0, (double) Ndec);
    if (dfabs < pdec) {
      return 0.0;
    }
    double dl10 = log10(dfabs);
    int N10 = (int) dl10;
    if (dl10 > -0.0) {
      N10 += 1;
    }
    int nsig = N10 - Ndec;
    double retn = cropSigDigits(d, nsig);
    return retn;
  }

  // Crop a double at a certain number of significant digits
  /*
   *  This routine will crop a floating point number at a certain
   *  number of significant digits. Note, it currently does
   *  rounding up of the last digit.
   *
   *  example:
   *    d = 1.0305E-15;
   *    nsig = 3;
   *   This routine will return 1.03E-15
   */
  double PrintCtrl::cropSigDigits(const double d, int nSig) const {
    if (nSig <=0) nSig = 1;
    if (nSig >=9) nSig = 9;
    double sgn = 1.0;
    if (d < 0.0) sgn = -1.0;
    double dfabs = fabs(d);
    double dl10 = log10(dfabs);
    int N10 = (int) dl10;
    if (dl10 > -0.0) {
      N10 += 1;
    }
    int E10 = -N10 + nSig ;
    double pfabs = dfabs * pow(10.0, (double) E10);
    pfabs *= (1.0 + 1.0E-14);
    long int nfabs = (long int) pfabs;
    double remainder = pfabs - nfabs;
    if (remainder > 0.5) {
      nfabs++;
    }
    double paltabs = (double) nfabs;
    double daltabs = paltabs * pow(10.0, (double) -E10);
    return (sgn * daltabs);
  }

  // Set the default value of N decade
  /*
   * @param Ndec new value of Ndec
   *
   * @return returns the old value of Ndec
   */
  int PrintCtrl::setNdec(int Ndec) {
    int nold = m_Ndec;
    m_Ndec = Ndec;
    return nold;
  }

  // Set the default significant digits to output
  /*
   * @param nSigDigits new value of the sig digits
   *
   * @return returns the old value of Ndec
   */
  int PrintCtrl::setSigDigits(int nSigDigits) {
    int nold = m_precision + 1;
    m_precision = nSigDigits - 1;
    if (m_precision < 0) m_precision = 0;
    return nold;
  }

  // Set the default minimum width
  /*
   * @param wmin Default minimum width
   *
   * @return returns the old default
   */
  int PrintCtrl::setWmin(int wmin) {
    int nold = m_wMin;
    m_wMin = wmin;
    return nold;
  }

  // Set the default maximum width
  /*
   * @param wmin Default maximum width
   *
   * @return returns the old default
   */
  int PrintCtrl::setWmax(int wmax) {
    int nold = m_wMax;
    m_wMax = wmax;
    return nold;
  }

}
<|endoftext|>


<commit_before>/// Project specific
// This class
#include <Manager/GroundEffectManager.hpp>
// Handles
#include <EntityComponent/EntityHandler.hpp>
// Components
#include <EntityComponent\Components\PressureParticleComponent.hpp>

/// Engine
// Physics
#include <DoremiEngine/Physics/Include/PhysicsModule.hpp>
#include <DoremiEngine/Physics/Include/FluidManager.hpp>

// debug
#include <iostream>
using namespace DirectX;
namespace Doremi
{
    namespace Core
    {

        GroundEffectManager::GroundEffectManager(const DoremiEngine::Core::SharedContext& p_sharedContext)
            : Manager(p_sharedContext, "GroundEffectManager")
        {
        }

        GroundEffectManager::~GroundEffectManager() {}

        void GroundEffectManager::Update(double p_dt)
        {
            EntityHandler& entityHandler = EntityHandler::GetInstance();
            const size_t length = entityHandler.GetLastEntityIndex();
            int mask = (int)ComponentType::PressureParticleSystem;
            for(size_t i = 0; i < length; i++)
            {
                // Check if we have a pressure particle system. TODOXX This will be really funny if we have just ambient particle systems
                if(entityHandler.HasComponents(i, mask))
                {
                    // Merge new positions into already existing positions
                    const vector<XMFLOAT3>& newPositions = m_sharedContext.GetPhysicsModule().GetFluidManager().GetRemovedParticlesPositions(i);
                    m_groundEffectPoints.reserve(m_groundEffectPoints.size() + newPositions.size());
                    m_groundEffectPoints.insert(m_groundEffectPoints.end(), newPositions.begin(), newPositions.end());
                    cout << m_groundEffectPoints.size();
                }
            }
        }

        void GroundEffectManager::OnEvent(Event* p_event) {}
    }
}<commit_msg>Removed debug cout message<commit_after>/// Project specific
// This class
#include <Manager/GroundEffectManager.hpp>
// Handles
#include <EntityComponent/EntityHandler.hpp>
// Components
#include <EntityComponent\Components\PressureParticleComponent.hpp>

/// Engine
// Physics
#include <DoremiEngine/Physics/Include/PhysicsModule.hpp>
#include <DoremiEngine/Physics/Include/FluidManager.hpp>

// debug
#include <iostream>
using namespace DirectX;
namespace Doremi
{
    namespace Core
    {

        GroundEffectManager::GroundEffectManager(const DoremiEngine::Core::SharedContext& p_sharedContext)
            : Manager(p_sharedContext, "GroundEffectManager")
        {
        }

        GroundEffectManager::~GroundEffectManager() {}

        void GroundEffectManager::Update(double p_dt)
        {
            EntityHandler& entityHandler = EntityHandler::GetInstance();
            const size_t length = entityHandler.GetLastEntityIndex();
            int mask = (int)ComponentType::PressureParticleSystem;
            for(size_t i = 0; i < length; i++)
            {
                // Check if we have a pressure particle system. TODOXX This will be really funny if we have just ambient particle systems
                if(entityHandler.HasComponents(i, mask))
                {
                    // Merge new positions into already existing positions
                    const vector<XMFLOAT3>& newPositions = m_sharedContext.GetPhysicsModule().GetFluidManager().GetRemovedParticlesPositions(i);
                    m_groundEffectPoints.reserve(m_groundEffectPoints.size() + newPositions.size());
                    m_groundEffectPoints.insert(m_groundEffectPoints.end(), newPositions.begin(), newPositions.end());
                }
            }
        }

        void GroundEffectManager::OnEvent(Event* p_event) {}
    }
}<|endoftext|>


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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    DiscreteGaussianImageFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

//  Software Guide : BeginLatex
//
//  \piccaption[DiscreteGaussianImageFilter gaussian diagram]{Discretized
//  Gaussian.\label{fig:DiscretizedGaussian}}
//  \parpic(7cm,4cm)[r]{\includegraphics[width=6cm]{DiscreteGaussian.eps}}
//
//  The \doxygen{DiscreteGaussianImageFilter} computes the convolution of the
//  input image with a Gaussian kernel by taking advantage of its separability.
//  A one-dimensional Gaussian function is discretized on a convolution kernel.
//  The size of the kernel is extended until there are enough discrete points
//  in the Gaussian to ensure that a user-provided minimum error is reached.
//  Since the size of the kernel is unkown a priory it is necesary to impose a
//  limit to its growth. The user can then provide a value to be the maximum
//  admisible size of the kernel. The discretization errror is defined as the
//  difference between the area under the discrete Gaussian curve and the area
//  under the continuous Gaussian.
//
//  \index{itk::DiscreteGaussianImageFilter|textbf}
//
//  Software Guide : EndLatex

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkRescaleIntensityImageFilter.h"

//  Software Guide : BeginLatex
//
//  The first step required for using this filter is to include its header file
//
//  \index{itk::DiscreteGaussianImageFilter!header}
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkDiscreteGaussianImageFilter.h"
// Software Guide : EndCodeSnippet

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

  if( argc < 5 )
    {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << "  inputImageFile  outputImageFile  variance  maxKernelWidth " << std::endl;
    return 1;
    }

  //  Software Guide : BeginLatex
  //
  //  Types should be choosen for the pixels of the input and output images.
  //  Image types can be instantiated using the pixel type and dimension.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef    float    InputPixelType;
  typedef    float    OutputPixelType;

  typedef itk::Image< InputPixelType,  2 >   InputImageType;
  typedef itk::Image< OutputPixelType, 2 >   OutputImageType;
  // Software Guide : EndCodeSnippet

  typedef itk::ImageFileReader< InputImageType >  ReaderType;

  //  Software Guide : BeginLatex
  //
  //  The discrete Gaussian filter type is now instantiated using both the
  //  input image and the output image types. Then a filter object is created.
  //
  //  \index{itk::DiscreteGaussianImageFilter!instantiation}
  //  \index{itk::DiscreteGaussianImageFilter!New()}
  //  \index{itk::DiscreteGaussianImageFilter!Pointer}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::DiscreteGaussianImageFilter<
                 InputImageType, OutputImageType >  FilterType;

  FilterType::Pointer filter = FilterType::New();
  // Software Guide : EndCodeSnippet

  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( argv[1] );

  //  Software Guide : BeginLatex
  //
  //  The input image can be obtained from the output of another filter. Here,
  //  an image reader is used as source.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetInput( reader->GetOutput() );
  // Software Guide : EndCodeSnippet

  const double gaussianVariance = atof( argv[3] );

  const unsigned int maxKernelWidth = atoi( argv[4] );

  //  Software Guide : BeginLatex
  //
  //  The filters requires the user to provide a value for the variance
  //  associated with the Gaussian kernel. The method \code{SetVariance()} is
  //  used for this purpose. The Gaussian is dicretized over the pixels of a
  //  convolution kernel. The maximum value of the kernel size can be set by
  //  the user. Note that the combination of variance and kernel-size values
  //  may result in truncating the borders of the discretized Gaussian kernel.
  //
  //  \index{itk::DiscreteGaussianImageFilter!SetVariance()}
  //  \index{itk::DiscreteGaussianImageFilter!SetMaximumKernelWidth()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetVariance( gaussianVariance );

  filter->SetMaximumKernelWidth( maxKernelWidth );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Finally the filter is executed by invoking the \code{Update()} method.
  //
  //  \index{itk::DiscreteGaussianImageFilter!Update()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->Update();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  If the output of this filter has been connected to other filters down the
  //  pipeline, updating any of the downstream filters would have triggered the
  //  execution of this one. For example, a writer could have been used after
  //  the filter.
  //
  //  Software Guide : EndLatex

  typedef unsigned char WritePixelType;

  typedef itk::Image< WritePixelType, 2 > WriteImageType;

  typedef itk::RescaleIntensityImageFilter<
               OutputImageType, WriteImageType > RescaleFilterType;

  RescaleFilterType::Pointer rescaler = RescaleFilterType::New();

  rescaler->SetOutputMinimum(   0 );
  rescaler->SetOutputMaximum( 255 );

  typedef itk::ImageFileWriter< WriteImageType >  WriterType;

  WriterType::Pointer writer = WriterType::New();

  writer->SetFileName( argv[2] );

  // Software Guide : BeginCodeSnippet
  rescaler->SetInput( filter->GetOutput() );
  writer->SetInput( rescaler->GetOutput() );
  writer->Update();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  // \begin{figure}
  // \center
  // \includegraphics[width=6cm]{BrainProtonDensitySlice.eps}
  // \includegraphics[width=6cm]{DiscreteGaussianImageFilterOutput.eps}
  // \caption[DiscreteGaussianImageFilter output]{Effect of the
  // DiscreteGaussianImageFilter on a slice from a MRI Proton Density image  of
  // the brain.}
  // \label{fig:DiscreteGaussianImageFilterInputOutput}
  // \end{figure}
  //
  //  Figure \ref{fig:DiscreteGaussianImageFilterInputOutput} illustrates the
  //  effect of this filter on a MRI proton density image of the brain.
  //
  //  Since this filter actually computes the convolution with the Gaussian
  //  kernel, it is not desirable to use large values of the variance since the
  //  appropriate approximation will require large kernels and incurr in
  //  prohibitive computational times.
  //
  //  Software Guide : EndLatex

  return 0;

}

<commit_msg>FIX: Corrected some typos in the text.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    DiscreteGaussianImageFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

//  Software Guide : BeginLatex
//
//  \piccaption[DiscreteGaussianImageFilter gaussian diagram]{Discretized
//  Gaussian.\label{fig:DiscretizedGaussian}}
//  \parpic(7cm,4cm)[r]{\includegraphics[width=6cm]{DiscreteGaussian.eps}}
//
//  The \doxygen{DiscreteGaussianImageFilter} computes the convolution
//  of the input image with a Gaussian kernel by taking advantage of
//  its separability.  A one-dimensional Gaussian function is
//  discretized on a convolution kernel.  The size of the kernel is
//  extended until there are enough discrete points in the Gaussian to
//  ensure that a user-provided maximum error is not exceeded.  Since
//  the size of the kernel is unkown a priori it is necesary to impose
//  a limit to its growth. The user can thus provide a value to be the
//  maximum admissible size of the kernel. The discretization errror
//  is defined as the difference between the area under the discrete
//  Gaussian curve (which has finite support) and the area under the
//  continuous Gaussian.
//
//  \index{itk::DiscreteGaussianImageFilter|textbf}
//
//  Software Guide : EndLatex

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkRescaleIntensityImageFilter.h"

//  Software Guide : BeginLatex
//
//  The first step required for using this filter is to include its header file
//
//  \index{itk::DiscreteGaussianImageFilter!header}
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkDiscreteGaussianImageFilter.h"
// Software Guide : EndCodeSnippet

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

  if( argc < 5 )
    {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << "  inputImageFile  outputImageFile  variance  maxKernelWidth " << std::endl;
    return 1;
    }

  //  Software Guide : BeginLatex
  //
  //  Types should be choosen for the pixels of the input and output images.
  //  Image types can be instantiated using the pixel type and dimension.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef    float    InputPixelType;
  typedef    float    OutputPixelType;

  typedef itk::Image< InputPixelType,  2 >   InputImageType;
  typedef itk::Image< OutputPixelType, 2 >   OutputImageType;
  // Software Guide : EndCodeSnippet

  typedef itk::ImageFileReader< InputImageType >  ReaderType;

  //  Software Guide : BeginLatex
  //
  //  The discrete Gaussian filter type is now instantiated using both the
  //  input image and the output image types. Then a filter object is created.
  //
  //  \index{itk::DiscreteGaussianImageFilter!instantiation}
  //  \index{itk::DiscreteGaussianImageFilter!New()}
  //  \index{itk::DiscreteGaussianImageFilter!Pointer}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef itk::DiscreteGaussianImageFilter<
                 InputImageType, OutputImageType >  FilterType;

  FilterType::Pointer filter = FilterType::New();
  // Software Guide : EndCodeSnippet

  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( argv[1] );

  //  Software Guide : BeginLatex
  //
  //  The input image can be obtained from the output of another filter. Here,
  //  an image reader is used as source.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetInput( reader->GetOutput() );
  // Software Guide : EndCodeSnippet

  const double gaussianVariance = atof( argv[3] );

  const unsigned int maxKernelWidth = atoi( argv[4] );

  //  Software Guide : BeginLatex
  //
  //  The filters requires the user to provide a value for the variance
  //  associated with the Gaussian kernel. The method \code{SetVariance()} is
  //  used for this purpose. The Gaussian is dicretized over the pixels of a
  //  convolution kernel. The maximum value of the kernel size can be set by
  //  the user. Note that the combination of variance and kernel-size values
  //  may result in truncating the borders of the discretized Gaussian kernel.
  //
  //  \index{itk::DiscreteGaussianImageFilter!SetVariance()}
  //  \index{itk::DiscreteGaussianImageFilter!SetMaximumKernelWidth()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetVariance( gaussianVariance );

  filter->SetMaximumKernelWidth( maxKernelWidth );
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Finally the filter is executed by invoking the \code{Update()} method.
  //
  //  \index{itk::DiscreteGaussianImageFilter!Update()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->Update();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  If the output of this filter has been connected to other filters down the
  //  pipeline, updating any of the downstream filters would have triggered the
  //  execution of this one. For example, a writer could have been used after
  //  the filter.
  //
  //  Software Guide : EndLatex

  typedef unsigned char WritePixelType;

  typedef itk::Image< WritePixelType, 2 > WriteImageType;

  typedef itk::RescaleIntensityImageFilter<
               OutputImageType, WriteImageType > RescaleFilterType;

  RescaleFilterType::Pointer rescaler = RescaleFilterType::New();

  rescaler->SetOutputMinimum(   0 );
  rescaler->SetOutputMaximum( 255 );

  typedef itk::ImageFileWriter< WriteImageType >  WriterType;

  WriterType::Pointer writer = WriterType::New();

  writer->SetFileName( argv[2] );

  // Software Guide : BeginCodeSnippet
  rescaler->SetInput( filter->GetOutput() );
  writer->SetInput( rescaler->GetOutput() );
  writer->Update();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  // \begin{figure}
  // \center
  // \includegraphics[width=6cm]{BrainProtonDensitySlice.eps}
  // \includegraphics[width=6cm]{DiscreteGaussianImageFilterOutput.eps}
  // \caption[DiscreteGaussianImageFilter output]{Effect of the
  // DiscreteGaussianImageFilter on a slice from a MRI Proton Density image  of
  // the brain.}
  // \label{fig:DiscreteGaussianImageFilterInputOutput}
  // \end{figure}
  //
  //  Figure \ref{fig:DiscreteGaussianImageFilterInputOutput} illustrates the
  //  effect of this filter on a MRI proton density image of the brain.
  //
  //  Since this filter actually computes the convolution with the Gaussian
  //  kernel, it is not desirable to use large values of the variance since the
  //  appropriate approximation will require large kernels and incurr in
  //  prohibitive computational times.
  //
  //  Software Guide : EndLatex

  return 0;

}

<|endoftext|>