<commit_before>/***********************************************************************************************************************
**
** Copyright (c) 2011, 2015 ETH Zurich
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
** following conditions are met:
**
**    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
**      disclaimer.
**    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
**      following disclaimer in the documentation and/or other materials provided with the distribution.
**    * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
**      derived from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***********************************************************************************************************************/

#include "ClangAstConsumer.h"

#include "OOModel/src/elements/StatementItemList.h"
#include "OOModel/src/elements/CommentStatementItem.h"

namespace CppImport {

CppImport::Comment::Comment(clang::RawComment* rawComment, const clang::SourceManager& sourceManager)
	: rawComment_{rawComment}
{
	text_ = QString::fromStdString(rawComment->getRawText(sourceManager).str());
	auto presumedLocationStart = sourceManager.getPresumedLoc(rawComment->getLocStart());
	fileName_ = presumedLocationStart.getFilename();
	lineStart_ = presumedLocationStart.getLine();
	lineEnd_ = sourceManager.getPresumedLineNumber(rawComment->getLocEnd());
}

void CppImport::Comment::setNode(Model::Node* node)
{
	// assert that the client can only associate the comment with a node once.
	Q_ASSERT(node && !node_);
	node_ = node;
}

void Comment::insertIntoItemList(OOModel::StatementItemList* itemList, int index)
{
	setNode(itemList);
	commentStatementItem_ = new OOModel::CommentStatementItem{};
	commentStatementItem_->setCommentNode(new Comments::CommentNode{text()});

	if (index >= 0)
		itemList->insert(index, commentStatementItem_);
	else
		itemList->append(commentStatementItem_);
}

void Comment::removeFromItemList()
{
	Q_ASSERT(commentStatementItem_);
	auto itemList = DCast<OOModel::StatementItemList>(node());
	Q_ASSERT(itemList);

	itemList->remove(commentStatementItem_);

	// in this special case the client can afterwards reassociate the comment.
	node_ = nullptr;

	SAFE_DELETE(commentStatementItem_);
	commentStatementItem_ = nullptr;
}

QString Comment::text()
{
	auto lines = text_.split('\n');
	if (!lines.first().startsWith("/*"))
	{
		static QRegularExpression singleLineRegex{"^\\s*//\\s*([^\\s].*)$"};
		for (auto i = 0; i < lines.size(); i++)
		{
			auto match = singleLineRegex.match(lines[i]);
			if (match.hasMatch()) lines[i] = match.captured(1);
		}
	}
	else
	{
		static QRegularExpression firstLineRegex{"^/\\*+<?\\s?(.*)$"};
		auto match = firstLineRegex.match(lines.first());
		if (match.hasMatch()) lines[0] = match.captured(1);

		static QRegularExpression middleLineRegex{"^\\s*\\*\\s(.*)$"};
		for (auto i = 1; i < lines.size(); i++)
		{
			match = middleLineRegex.match(lines[i]);
			if (match.hasMatch()) lines[i] = match.captured(1);
		}

		static QRegularExpression lastLineRegex{"^(.*)\\*/\\s*$"};
		match = lastLineRegex.match(lines.last());
		if (match.hasMatch())
		{
			auto captured = match.captured(1);
			while (captured.endsWith('*')) captured = captured.left(captured.size() - 1);
			lines[lines.size() - 1] = captured;
		}

		for (auto i = 1; i < lines.size() - 1; i++) if (lines[i].trimmed() == "*") lines[i] = "";
		if (lines.first().trimmed().isEmpty()) lines.removeFirst();
		if (lines.last().trimmed().isEmpty()) lines.removeLast();
	}
	return lines.join('\n');
}

}
<commit_msg>change regex to drop at most one space after //<commit_after>/***********************************************************************************************************************
**
** Copyright (c) 2011, 2015 ETH Zurich
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
** following conditions are met:
**
**    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
**      disclaimer.
**    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
**      following disclaimer in the documentation and/or other materials provided with the distribution.
**    * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
**      derived from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***********************************************************************************************************************/

#include "ClangAstConsumer.h"

#include "OOModel/src/elements/StatementItemList.h"
#include "OOModel/src/elements/CommentStatementItem.h"

namespace CppImport {

CppImport::Comment::Comment(clang::RawComment* rawComment, const clang::SourceManager& sourceManager)
	: rawComment_{rawComment}
{
	text_ = QString::fromStdString(rawComment->getRawText(sourceManager).str());
	auto presumedLocationStart = sourceManager.getPresumedLoc(rawComment->getLocStart());
	fileName_ = presumedLocationStart.getFilename();
	lineStart_ = presumedLocationStart.getLine();
	lineEnd_ = sourceManager.getPresumedLineNumber(rawComment->getLocEnd());
}

void CppImport::Comment::setNode(Model::Node* node)
{
	// assert that the client can only associate the comment with a node once.
	Q_ASSERT(node && !node_);
	node_ = node;
}

void Comment::insertIntoItemList(OOModel::StatementItemList* itemList, int index)
{
	setNode(itemList);
	commentStatementItem_ = new OOModel::CommentStatementItem{};
	commentStatementItem_->setCommentNode(new Comments::CommentNode{text()});

	if (index >= 0)
		itemList->insert(index, commentStatementItem_);
	else
		itemList->append(commentStatementItem_);
}

void Comment::removeFromItemList()
{
	Q_ASSERT(commentStatementItem_);
	auto itemList = DCast<OOModel::StatementItemList>(node());
	Q_ASSERT(itemList);

	itemList->remove(commentStatementItem_);

	// in this special case the client can afterwards reassociate the comment.
	node_ = nullptr;

	SAFE_DELETE(commentStatementItem_);
	commentStatementItem_ = nullptr;
}

QString Comment::text()
{
	auto lines = text_.split('\n');
	if (!lines.first().startsWith("/*"))
	{
		static QRegularExpression singleLineRegex{"^\\s*//\\s?(.*)$"};
		for (auto i = 0; i < lines.size(); i++)
		{
			auto match = singleLineRegex.match(lines[i]);
			if (match.hasMatch()) lines[i] = match.captured(1);
		}
	}
	else
	{
		static QRegularExpression firstLineRegex{"^/\\*+<?\\s?(.*)$"};
		auto match = firstLineRegex.match(lines.first());
		if (match.hasMatch()) lines[0] = match.captured(1);

		static QRegularExpression middleLineRegex{"^\\s*\\*\\s(.*)$"};
		for (auto i = 1; i < lines.size(); i++)
		{
			match = middleLineRegex.match(lines[i]);
			if (match.hasMatch()) lines[i] = match.captured(1);
		}

		static QRegularExpression lastLineRegex{"^(.*)\\*/\\s*$"};
		match = lastLineRegex.match(lines.last());
		if (match.hasMatch())
		{
			auto captured = match.captured(1);
			while (captured.endsWith('*')) captured = captured.left(captured.size() - 1);
			lines[lines.size() - 1] = captured;
		}

		for (auto i = 1; i < lines.size() - 1; i++) if (lines[i].trimmed() == "*") lines[i] = "";
		if (lines.first().trimmed().isEmpty()) lines.removeFirst();
		if (lines.last().trimmed().isEmpty()) lines.removeLast();
	}
	return lines.join('\n');
}

}
<|endoftext|>


<commit_before>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999 Stefan Seefeld <seefelds@magellan.umontreal.ca>
 * Copyright (C) 1999 Graydon Hoare <graydon@pobox.com>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */

#include "Warsaw/config.hh"
#include "Warsaw/Transform.hh"
#include "Drawing/openGL/GLQuadric.hh"
#include "Drawing/openGL/GLDrawingKit.hh"
// #include "Warsaw/Text.hh"
#include "Berlin/Logger.hh"
#include "Berlin/Plugin.hh"

#include <GL/glu.h>
#include <strstream>
#include <iostream>

GLDrawingKit::GLDrawingKit()
  : drawable(GGI::drawable()), tr(new TransformImpl), cl(new RegionImpl), tx(0), textures(100), images(500)
{
  tr->_obj_is_ready(_boa());
  cl->_obj_is_ready(_boa());

  context = GGIMesaCreateContext();
  if (!context)
    {
      cerr << "GGIMesaCreateContext() failed" << endl;
      exit(4);
    }
  if (GGIMesaSetVisual(context, drawable->visual(), GL_TRUE, GL_FALSE))
    {
      cerr << "GGIMesaSetVisual() failed" << endl;
      exit(7);
    }
  GGIMesaMakeCurrent(context);
  glViewport(0, 0, drawable->width(), drawable->height());
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0, drawable->width()/drawable->resolution(xaxis), drawable->height()/drawable->resolution(yaxis), 0, -1000.0, 1000.0);
  glTranslatef(0.375, 0.375, 0.);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glShadeModel(GL_SMOOTH);
  glDisable(GL_LIGHTING);
  glFrontFace(GL_CW);
  glEnable(GL_ALPHA_TEST);
  glEnable(GL_SCISSOR_TEST);
  glScissor(0, 0, drawable->width(), drawable->height());
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

GLDrawingKit::~GLDrawingKit()
{
  GGIMesaDestroyContext(context);
  cl->_dispose();
  tr->_dispose();
}

void GLDrawingKit::setTransformation(Transform_ptr t)
{
  tr->copy(t);
  Transform::Matrix &matrix = tr->matrix();
  GLdouble glmatrix[16] = {matrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0],
			   matrix[0][1], matrix[1][1], matrix[2][1], matrix[3][1],
			   matrix[0][2], matrix[1][2], matrix[2][2], matrix[3][2],
			   matrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]};
  glLoadMatrixd(glmatrix);
}

void GLDrawingKit::setClipping(Region_ptr r)
{
  cl->copy(r);
  PixelCoord x = static_cast<PixelCoord>(cl->lower.x*drawable->resolution(xaxis) + 0.5);
  PixelCoord y = static_cast<PixelCoord>((drawable->height()/drawable->resolution(yaxis) - cl->upper.y)*drawable->resolution(yaxis) + 0.5);
  PixelCoord w = static_cast<PixelCoord>((cl->upper.x - cl->lower.x)*drawable->resolution(xaxis) + 0.5);
  PixelCoord h = static_cast<PixelCoord>((cl->upper.y - cl->lower.y)*drawable->resolution(yaxis) + 0.5);
  glScissor(x, y, w, h);
}

void GLDrawingKit::setForeground(const Color &c)
{
  fg = c;
  glColor4d(fg.red, fg.green, fg.blue, fg.alpha);
}

void GLDrawingKit::setPointSize(Coord s)
{
  ps = s;
  // FIXME !: glPointSize uses pixel units !
  glPointSize(ps);
}

void GLDrawingKit::setLineWidth(Coord w)
{
  lw = w;
  // FIXME !: glLineWidth uses pixel units !
  glLineWidth(lw);
}

void GLDrawingKit::setLineEndstyle(DrawingKit::Endstyle style)
{
  es = style;
}

void GLDrawingKit::setSurfaceFillstyle(DrawingKit::Fillstyle style)
{
  if (fs == textured) glDisable(GL_TEXTURE_2D);
  fs = style;
  if (fs == textured) glEnable(GL_TEXTURE_2D);
}

void GLDrawingKit::setTexture(Raster_ptr t)
{
  tx = CORBA::is_nil(t) ? 0 : textures.lookup(t);
  if (tx) glBindTexture(GL_TEXTURE_2D, tx->texture);
}

// void GLDrawingKit::clear(Coord l, Coord t, Coord r, Coord b)
// {
//   glColor4d(0., 0., 0., 1.);
//   glRectf(l, t, r, b);
// }

void GLDrawingKit::drawPath(const Path &path)
{
  if (fs == solid)
    {
      glBegin(GL_POLYGON);
      for (unsigned long i = 0; i < path.length(); i++) glVertex3f(path[i].x, path[i].y, path[i].z);
      glEnd();
    }
  else if (fs == textured)
    {
      cerr << "sorry, implementation for textured polygons not finished..." << endl;
//       GLTexture *gltextures = textures.lookup(tx);
      glBegin(GL_POLYGON);
      for (unsigned long i = 0; i < path.length(); i++) glVertex3f(path[i].x, path[i].y, path[i].z);
      glEnd();
    }
  else
    {
      glBegin(GL_LINE_STRIP);
      // line strips (no final connecting line)
      for (unsigned long i = 0; i < path.length(); i++) glVertex3f(path[i].x, path[i].y, path[i].z);
      glEnd();
    }
}

void GLDrawingKit::drawRect(const Vertex &lower, const Vertex &upper)
{
  if (fs == solid) glRectf(lower.x, lower.y, upper.x, upper.y);
  else if (fs == textured)
    {
      double w = (upper.x - lower.x)/(tx->width * 10.);
      double h = (upper.y - lower.y)/(tx->height * 10.);
      glBegin(GL_POLYGON);
      glTexCoord2f(0., 0.); glVertex2d(lower.x, lower.y);
      glTexCoord2f(w, 0.);  glVertex2d(upper.x, lower.y);
      glTexCoord2f(w, h);   glVertex2d(upper.x, upper.y);
      glTexCoord2f(0., h);  glVertex2d(lower.x, upper.y);
      glEnd();
    }
  else
    {
      glBegin(GL_LINE_LOOP);
      glVertex2d(lower.x, lower.y);
      glVertex2d(upper.x, lower.y);
      glVertex2d(upper.x, upper.y);
      glVertex2d(lower.x, upper.y);
      glEnd();
    }
}

void GLDrawingKit::drawEllipse(const Vertex &lower, const Vertex &upper)
{
  glPushMatrix();
  glScaled(upper.x - lower.x, upper.y - lower.y, upper.z - lower.z);
  glTranslated(lower.x, lower.y, lower.z);
  GLQuadric quadric(fs, GLQuadric::out);
  quadric.disk(0., 1., 360., 100.);
  glPopMatrix();
}

void GLDrawingKit::drawImage(Raster_ptr raster)
{
  GLImage *glimage = images.lookup(Raster::_duplicate(raster));
  GLint tbackup = -1;
  if (fs == textured) glGetIntegerv(GL_TEXTURE_BINDING_2D, &tbackup);
  else glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, glimage->texture);
  glColor4f(1., 1., 1., 1.);
  glBegin(GL_POLYGON);
  Path path;
  path.length(4);
  Coord width = glimage->width*10.;
  Coord height = glimage->height*10.;
  path[0].x = path[0].y = path[0].z = 0.;
  path[1].x = width, path[1].y = path[1].z = 0.;
  path[2].x = width, path[2].y = height, path[2].z = 0.;
  path[3].x = 0, path[3].y = height, path[3].z = 0.;
  glTexCoord2f(0., 0.);                   glVertex3f(path[3].x, path[3].y, path[3].z);
  glTexCoord2f(glimage->s, 0.);           glVertex3f(path[2].x, path[2].y, path[2].z);
  glTexCoord2f(glimage->s, glimage->t);   glVertex3f(path[1].x, path[1].y, path[1].z);
  glTexCoord2f(0., glimage->t);           glVertex3f(path[0].x, path[0].y, path[0].z);
  glEnd();
  if (fs != textured) glDisable(GL_TEXTURE_2D);
  else glBindTexture(GL_TEXTURE_2D, tbackup);
}

CORBA::ULong GLDrawingKit::fontSize() { return 16; }
CORBA::ULong GLDrawingKit::fontWeight() { return 100;}
Unistring* GLDrawingKit::fontFamily()
{
  static Unistring name = Unicode::toCORBA(Unicode::String("GNU Unifont"));
  return &name;
}
Unistring* GLDrawingKit::fontSubFamily() { return 0; }
Unistring* GLDrawingKit::fontFullName() { return 0; }
Unistring* GLDrawingKit::fontStyle()
{
  static Unistring name = Unicode::toCORBA(Unicode::String("monospace"));
  return &name;
}

FontMetrics GLDrawingKit::metrics()
{
  FontMetrics m;
  return m;
}

CORBA::Any *GLDrawingKit::getFontAttr(const Unistring &name)
{
  return new CORBA::Any();
}

void GLDrawingKit::setFontSize(CORBA::ULong) {}
void GLDrawingKit::setFontWeight(CORBA::ULong) {}
void GLDrawingKit::setFontFamily(const Unistring&) {}
void GLDrawingKit::setFontSubFamily(const Unistring&) {}
void GLDrawingKit::setFontFullName(const Unistring&) {}
void GLDrawingKit::setFontStyle(const Unistring&) {}
void GLDrawingKit::setFontAttr(const NVPair & nvp) {}

void GLDrawingKit::allocateText(const Unistring & s, Graphic::Requisition & req)
{
  unifont.allocateText(s,req);
}

void GLDrawingKit::drawText(const Unistring &us)
{
  /*
   * the real thing to do would be to use the current trafo and
   * look up glyphs of appropriate pixel sizes within the current
   * font.   -stefan
   */
  Vertex origin = {0., 0., 0.};
  tr->transformVertex(origin);
  unifont.drawText(us, origin);
}

EXPORT_PLUGIN(GLDrawingKit, interface(DrawingKit))
<commit_msg>DrawingKit compiles again<commit_after>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999 Stefan Seefeld <seefelds@magellan.umontreal.ca>
 * Copyright (C) 1999 Graydon Hoare <graydon@pobox.com>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */

#include "Warsaw/config.hh"
#include "Warsaw/Transform.hh"
#include "Drawing/openGL/GLQuadric.hh"
#include "Drawing/openGL/GLDrawingKit.hh"
// #include "Warsaw/Text.hh"
#include "Berlin/Logger.hh"
#include "Berlin/Plugin.hh"

#include <GL/glu.h>
#include <strstream>
#include <iostream>

GLDrawingKit::GLDrawingKit()
  : drawable(GGI::drawable()), tr(new TransformImpl), cl(new RegionImpl), tx(0), textures(100), images(500)
{
  tr->_obj_is_ready(_boa());
  cl->_obj_is_ready(_boa());

  context = GGIMesaCreateContext();
  if (!context)
    {
      cerr << "GGIMesaCreateContext() failed" << endl;
      exit(4);
    }
  if (GGIMesaSetVisual(context, drawable->visual(), GL_TRUE, GL_FALSE))
    {
      cerr << "GGIMesaSetVisual() failed" << endl;
      exit(7);
    }
  GGIMesaMakeCurrent(context);
  glViewport(0, 0, drawable->width(), drawable->height());
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0, drawable->width()/drawable->resolution(xaxis), drawable->height()/drawable->resolution(yaxis), 0, -1000.0, 1000.0);
  glTranslatef(0.375, 0.375, 0.);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glShadeModel(GL_SMOOTH);
  glDisable(GL_LIGHTING);
  glFrontFace(GL_CW);
  glEnable(GL_ALPHA_TEST);
  glEnable(GL_SCISSOR_TEST);
  glScissor(0, 0, drawable->width(), drawable->height());
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

GLDrawingKit::~GLDrawingKit()
{
  GGIMesaDestroyContext(context);
  cl->_dispose();
  tr->_dispose();
}

void GLDrawingKit::setTransformation(Transform_ptr t)
{
  tr->copy(t);
  Transform::Matrix &matrix = tr->matrix();
  GLdouble glmatrix[16] = {matrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0],
			   matrix[0][1], matrix[1][1], matrix[2][1], matrix[3][1],
			   matrix[0][2], matrix[1][2], matrix[2][2], matrix[3][2],
			   matrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]};
  glLoadMatrixd(glmatrix);
}

void GLDrawingKit::setClipping(Region_ptr r)
{
  cl->copy(r);
  PixelCoord x = static_cast<PixelCoord>(cl->lower.x*drawable->resolution(xaxis) + 0.5);
  PixelCoord y = static_cast<PixelCoord>((drawable->height()/drawable->resolution(yaxis) - cl->upper.y)*drawable->resolution(yaxis) + 0.5);
  PixelCoord w = static_cast<PixelCoord>((cl->upper.x - cl->lower.x)*drawable->resolution(xaxis) + 0.5);
  PixelCoord h = static_cast<PixelCoord>((cl->upper.y - cl->lower.y)*drawable->resolution(yaxis) + 0.5);
  glScissor(x, y, w, h);
}

void GLDrawingKit::setForeground(const Color &c)
{
  fg = c;
  glColor4d(fg.red, fg.green, fg.blue, fg.alpha);
}

void GLDrawingKit::setPointSize(Coord s)
{
  ps = s;
  // FIXME !: glPointSize uses pixel units !
  glPointSize(ps);
}

void GLDrawingKit::setLineWidth(Coord w)
{
  lw = w;
  // FIXME !: glLineWidth uses pixel units !
  glLineWidth(lw);
}

void GLDrawingKit::setLineEndstyle(DrawingKit::Endstyle style)
{
  es = style;
}

void GLDrawingKit::setSurfaceFillstyle(DrawingKit::Fillstyle style)
{
  if (fs == textured) glDisable(GL_TEXTURE_2D);
  fs = style;
  if (fs == textured) glEnable(GL_TEXTURE_2D);
}

void GLDrawingKit::setTexture(Raster_ptr t)
{
  tx = CORBA::is_nil(t) ? 0 : textures.lookup(Raster::_duplicate(t));
  if (tx) glBindTexture(GL_TEXTURE_2D, tx->texture);
}

// void GLDrawingKit::clear(Coord l, Coord t, Coord r, Coord b)
// {
//   glColor4d(0., 0., 0., 1.);
//   glRectf(l, t, r, b);
// }

void GLDrawingKit::drawPath(const Path &path)
{
  if (fs == solid)
    {
      glBegin(GL_POLYGON);
      for (unsigned long i = 0; i < path.length(); i++) glVertex3f(path[i].x, path[i].y, path[i].z);
      glEnd();
    }
  else if (fs == textured)
    {
      cerr << "sorry, implementation for textured polygons not finished..." << endl;
//       GLTexture *gltextures = textures.lookup(tx);
      glBegin(GL_POLYGON);
      for (unsigned long i = 0; i < path.length(); i++) glVertex3f(path[i].x, path[i].y, path[i].z);
      glEnd();
    }
  else
    {
      glBegin(GL_LINE_STRIP);
      // line strips (no final connecting line)
      for (unsigned long i = 0; i < path.length(); i++) glVertex3f(path[i].x, path[i].y, path[i].z);
      glEnd();
    }
}

void GLDrawingKit::drawRect(const Vertex &lower, const Vertex &upper)
{
  if (fs == solid) glRectf(lower.x, lower.y, upper.x, upper.y);
  else if (fs == textured)
    {
      double w = (upper.x - lower.x)/(tx->width * 10.);
      double h = (upper.y - lower.y)/(tx->height * 10.);
      glBegin(GL_POLYGON);
      glTexCoord2f(0., 0.); glVertex2d(lower.x, lower.y);
      glTexCoord2f(w, 0.);  glVertex2d(upper.x, lower.y);
      glTexCoord2f(w, h);   glVertex2d(upper.x, upper.y);
      glTexCoord2f(0., h);  glVertex2d(lower.x, upper.y);
      glEnd();
    }
  else
    {
      glBegin(GL_LINE_LOOP);
      glVertex2d(lower.x, lower.y);
      glVertex2d(upper.x, lower.y);
      glVertex2d(upper.x, upper.y);
      glVertex2d(lower.x, upper.y);
      glEnd();
    }
}

void GLDrawingKit::drawEllipse(const Vertex &lower, const Vertex &upper)
{
  glPushMatrix();
  glScaled(upper.x - lower.x, upper.y - lower.y, upper.z - lower.z);
  glTranslated(lower.x, lower.y, lower.z);
  GLQuadric quadric(fs, GLQuadric::out);
  quadric.disk(0., 1., 360., 100.);
  glPopMatrix();
}

void GLDrawingKit::drawImage(Raster_ptr raster)
{
  GLImage *glimage = images.lookup(Raster::_duplicate(raster));
  GLint tbackup = -1;
  if (fs == textured) glGetIntegerv(GL_TEXTURE_BINDING_2D, &tbackup);
  else glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, glimage->texture);
  glColor4f(1., 1., 1., 1.);
  glBegin(GL_POLYGON);
  Path path;
  path.length(4);
  Coord width = glimage->width*10.;
  Coord height = glimage->height*10.;
  path[0].x = path[0].y = path[0].z = 0.;
  path[1].x = width, path[1].y = path[1].z = 0.;
  path[2].x = width, path[2].y = height, path[2].z = 0.;
  path[3].x = 0, path[3].y = height, path[3].z = 0.;
  glTexCoord2f(0., 0.);                   glVertex3f(path[3].x, path[3].y, path[3].z);
  glTexCoord2f(glimage->s, 0.);           glVertex3f(path[2].x, path[2].y, path[2].z);
  glTexCoord2f(glimage->s, glimage->t);   glVertex3f(path[1].x, path[1].y, path[1].z);
  glTexCoord2f(0., glimage->t);           glVertex3f(path[0].x, path[0].y, path[0].z);
  glEnd();
  if (fs != textured) glDisable(GL_TEXTURE_2D);
  else glBindTexture(GL_TEXTURE_2D, tbackup);
}

CORBA::ULong GLDrawingKit::fontSize() { return 16; }
CORBA::ULong GLDrawingKit::fontWeight() { return 100;}
Unistring *GLDrawingKit::fontFamily()
{
  Unistring *name = new Unistring(Unicode::toCORBA(Unicode::String("GNU Unifont")));
  return name;
}
Unistring* GLDrawingKit::fontSubFamily() { return 0; }
Unistring* GLDrawingKit::fontFullName() { return 0; }
Unistring* GLDrawingKit::fontStyle()
{
  Unistring *name = new Unistring(Unicode::toCORBA(Unicode::String("monospace")));
  return name;
}

FontMetrics GLDrawingKit::metrics()
{
  FontMetrics m;
  return m;
}

CORBA::Any *GLDrawingKit::getFontAttr(const Unistring &name)
{
  return new CORBA::Any();
}

void GLDrawingKit::setFontSize(CORBA::ULong) {}
void GLDrawingKit::setFontWeight(CORBA::ULong) {}
void GLDrawingKit::setFontFamily(const Unistring&) {}
void GLDrawingKit::setFontSubFamily(const Unistring&) {}
void GLDrawingKit::setFontFullName(const Unistring&) {}
void GLDrawingKit::setFontStyle(const Unistring&) {}
void GLDrawingKit::setFontAttr(const NVPair & nvp) {}

void GLDrawingKit::allocateText(const Unistring & s, Graphic::Requisition & req)
{
  unifont.allocateText(s,req);
}

void GLDrawingKit::drawText(const Unistring &us)
{
  /*
   * the real thing to do would be to use the current trafo and
   * look up glyphs of appropriate pixel sizes within the current
   * font.   -stefan
   */
  Vertex origin = {0., 0., 0.};
  tr->transformVertex(origin);
  unifont.drawText(us, origin);
}

EXPORT_PLUGIN(GLDrawingKit, interface(DrawingKit))
<|endoftext|>


<commit_before><commit_msg>Call base class Tick function in RTSCharacter.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2012 Bram van der Kroef
 *
 * This file is part of LESS CSS Compiler.
 *
 * LESS CSS Compiler is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * LESS CSS Compiler is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LESS CSS Compiler.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Bram van der Kroef <bram@vanderkroef.net>
 */

#include "NumberValue.h"

NumberValue::NumberValue(Token* token) {
  tokens.push(token);

  switch(token->type) {
  case Token::NUMBER:
    type = NUMBER;
    break;
  case Token::PERCENTAGE:
    type = PERCENTAGE;
    break;
  case Token::DIMENSION:
    type = DIMENSION;
    break;
  default:
    throw new ValueException("Token used for Value that isn't a number, percentage or dimension");
  }
}

NumberValue::~NumberValue() {
}

void NumberValue::verifyUnits(NumberValue* v) {
  if (type == Value::DIMENSION &&
      v->type == Value::DIMENSION &&
      getUnit().compare(v->getUnit()) != 0) {

    if (v->convert(getUnit())) {
      return;
    } else
      throw new ValueException("Can't do math on dimensions with different units.");
  }
}

bool NumberValue::convert(string unit) {
  UnitValue::UnitGroup group = UnitValue::getUnitGroup(unit);
  double value = getValue();

  if (UnitValue::getUnitGroup(getUnit()) == group) {

    switch(group) {
    case UnitValue::LENGTH:
      value = UnitValue::lengthToPx(value, getUnit());
      setValue(UnitValue::pxToLength(value, unit));
      setUnit(unit);
      return true;

    case UnitValue::TIME:
      value = UnitValue::timeToMs(value, getUnit());
      setValue(UnitValue::msToTime(value, unit));
      setUnit(unit);
      return true;

    case UnitValue::ANGLE:
      value = UnitValue::angleToRad(value, getUnit());
      setValue(UnitValue::radToAngle(value, unit));
      setUnit(unit);
      return true;

    default:
      break;
    }
  }
  return false;
}

Value* NumberValue::add(Value* v) {
  Token* t;
  StringValue* s;

  if (isNumber(v)) {
    if (type == NUMBER)
      setType(v);
    else
      verifyUnits((NumberValue*)v);

    setValue(getValue() + ((NumberValue*)v)->getValue());
    return this;

  } else if (v->type == COLOR) {
    return v->add(this);

  } else if (v->type == STRING) {
    t = this->tokens.front()->clone();
    t->type = Token::STRING;
    s = new StringValue(t, ((StringValue*)v)->getQuotes());
    s->add(v);
    return s;
  } else {
    throw new ValueException("Unsupported type.");
  }
}
Value* NumberValue::substract(Value* v) {
  if (isNumber(v)) {
    if (type == NUMBER)
      setType(v);
    else
      verifyUnits((NumberValue*)v);

    setValue(getValue() - ((NumberValue*)v)->getValue());
    return this;
  } else
    throw new ValueException("You can only substract a *number* from a number.");
}
Value* NumberValue::multiply(Value* v) {
  if (isNumber(v)) {
    if (type == NUMBER)
      setType(v);
    else
      verifyUnits((NumberValue*)v);
    setValue(getValue() * ((NumberValue*)v)->getValue());
    return this;
  } else if (v->type == COLOR ||
             v->type == STRING) {
    return v->multiply(this);
  } else {
    throw new ValueException("Unsupported type.");
  }
}

Value* NumberValue::divide(Value* v) {
  if (isNumber(v)) {
    if (type == NUMBER)
      setType(v);
    else
      verifyUnits((NumberValue*)v);
    setValue(getValue() / ((NumberValue*)v)->getValue());
    return this;
  } else
    throw new ValueException("You can only divide a number by a *number*.");
}
int NumberValue::compare(Value* v) {
  if (isNumber(v)) {
    verifyUnits((NumberValue*)v);
    return getValue() - ((NumberValue*)v)->getValue();
  } else {
    throw new ValueException("You can only compare a number with a *number*.");
  }
}

void NumberValue::setType(Value* v) {
  NumberValue* n;

  if (isNumber(v)) {

    n = static_cast<NumberValue*>(v);

    type = n->type;
    if (n->type == DIMENSION)
      setUnit(n->getUnit());
    else if (n->type == PERCENTAGE)
      tokens.front()->type = Token::PERCENTAGE;
    else if (n->type == NUMBER) {
      setUnit("");
      tokens.front()->type = Token::NUMBER;
    }
  }
}

double NumberValue::getValue() {
  string number;
  istringstream stm;
  double ret;
  char c;

  for (unsigned int i = 0; i < tokens.front()->str.size(); i++) {
    c = tokens.front()->str[i];
    if (!isdigit(c) && c != '.' && c != '-') {
      number = tokens.front()->str.substr(0, i);
      break;
    }
  }
  if (number == "")
    number = tokens.front()->str;
  stm.str(number);
  stm >>ret;
  return ret;
}
string NumberValue::getUnit () {
  char c;
  unsigned int i;

  for (i = 0; i < tokens.front()->str.size(); i++) {
    c = tokens.front()->str[i];
    if (!isdigit(c) && c != '.' && c != '-')
      return tokens.front()->str.substr(i);
  }
  return string("");
}

void NumberValue::setUnit(string unit) {
  ostringstream stm;
  stm << getValue();
  stm << unit;
  type = DIMENSION;
  tokens.front()->type = Token::DIMENSION;
  tokens.front()->str = stm.str();
}

void NumberValue::setValue(double d) {
  ostringstream stm;
  stm << d;
  if (type == DIMENSION)
    stm << getUnit();
  else if (type == PERCENTAGE)
    stm << "%";
  tokens.front()->str = stm.str();
}

bool NumberValue::isNumber(Value* val) {
  return (val->type == Value::NUMBER ||
          val->type == Value::DIMENSION ||
          val->type == Value::PERCENTAGE);
}

void NumberValue::loadFunctions(FunctionLibrary* lib) {
  lib->push("unit", ".U?", &NumberValue::unit);
  lib->push("ceil", ".", &NumberValue::ceil);
  lib->push("floor", ".", &NumberValue::floor);
  lib->push("percentage", "N", &NumberValue::percentage);
  lib->push("round", ".", &NumberValue::round);
  lib->push("sqrt", ".", &NumberValue::sqrt);
  lib->push("abs", ".", &NumberValue::abs);
  lib->push("sin", ".", &NumberValue::sin);
  lib->push("asin", "N", &NumberValue::asin);
  lib->push("cos", ".", &NumberValue::cos);
  lib->push("acos", "N", &NumberValue::acos);
  lib->push("tan", ".", &NumberValue::tan);
  lib->push("atan", "N", &NumberValue::atan);
  lib->push("pi", "", &NumberValue::pi);
  lib->push("pow", ".N", &NumberValue::pow);
  lib->push("mod", "..", &NumberValue::mod);
  lib->push("convert", "..", &NumberValue::convert);
}

// DIMENSION unit(DIMENSION, UNIT)
Value* NumberValue::unit(vector<Value*> arguments) {
  if (arguments[0]->type == Value::NUMBER ||
      arguments[0]->type == Value::DIMENSION) {
    if (arguments.size() > 1) {
      ((NumberValue*)arguments[0])
        ->setUnit(((UnitValue*)arguments[1])->getUnit());
    } else
      ((NumberValue*)arguments[0])->setUnit("");
    return arguments[0];
  } else
    throw new ValueException("argument 1 has to be a number or dimension");
}
Value* NumberValue::ceil(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("ceil() only works on numeric values");

  double val = ((NumberValue*)args[0])->getValue();
  ((NumberValue*)args[0])->setValue(std::ceil(val));
  return args[0];
}
Value* NumberValue::floor(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("floor() only works on numeric values");

  double val = ((NumberValue*)args[0])->getValue();
  ((NumberValue*)args[0])->setValue(std::floor(val));
  return args[0];
}
Value* NumberValue::percentage(vector<Value*> args) {
  double val = ((NumberValue*)args[0])->getValue();
  ((NumberValue*)args[0])->setValue(val * 100);
  ((NumberValue*)args[0])->type = Value::PERCENTAGE;
  return args[0];
}
Value* NumberValue::round(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("round() only works on numeric values");

  double val = ((NumberValue*)args[0])->getValue();
  double decimalplaces = 0;

  if (args.size() > 1)
    decimalplaces = ((NumberValue*)args[0])->getValue();

  val = val * std::pow(10, decimalplaces);
  val = std::floor(val + 0.5);
  val = val / std::pow(10, decimalplaces);
  ((NumberValue*)args[0])->setValue(val);
  return args[0];
}
Value* NumberValue::sqrt(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("sqrt() only works on numeric values");

  double val = ((NumberValue*)args[0])->getValue();
  ((NumberValue*)args[0])->setValue(std::sqrt(val));
  return args[0];
}
Value* NumberValue::abs(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("abs() only works on numeric values");

  double val = ((NumberValue*)args[0])->getValue();
  ((NumberValue*)args[0])->setValue(fabs(val));
  return args[0];
}

Value* NumberValue::sin(vector<Value*> args) {
  if (args[0]->type != Value::NUMBER &&
      args[0]->type != Value::DIMENSION) {
    throw new ValueException("sin() only works on numbers or dimensions");
  }

  NumberValue* arg = ((NumberValue*)args[0]);
  double val = arg->getValue();

  if (arg->type == Value::DIMENSION) {
    if(arg->getUnit().compare("rad") != 0 &&
       arg->getUnit().compare("deg") != 0 &&
       arg->getUnit().compare("grad") != 0 &&
       arg->getUnit().compare("turn") != 0) {
      throw new ValueException("sin() requires rad, deg, grad or turn units.");
    }
    val = UnitValue::angleToRad(val, arg->getUnit());
  }

  arg->setValue(std::sin(val));
  arg->type = Value::NUMBER;
  arg->setUnit("");
  return arg;
}
Value* NumberValue::asin(vector<Value*> args) {
  NumberValue* arg = ((NumberValue*)args[0]);

  arg->setValue(std::asin(arg->getValue()));
  arg->setUnit("rad");
  arg->type = Value::DIMENSION;
  return arg;
}
Value* NumberValue::cos(vector<Value*> args) {
  if (args[0]->type != Value::NUMBER &&
      args[0]->type != Value::DIMENSION) {
    throw new ValueException("cos() only works on numbers or dimensions");
  }
  NumberValue* arg = ((NumberValue*)args[0]);
  double val = arg->getValue();

  if (arg->type == Value::DIMENSION) {
    if(arg->getUnit().compare("rad") != 0 &&
       arg->getUnit().compare("deg") != 0 &&
       arg->getUnit().compare("grad") != 0 &&
       arg->getUnit().compare("turn") != 0) {
      throw new ValueException("cos() requires rad, deg, grad or turn units.");
    }
    val = UnitValue::angleToRad(val, arg->getUnit());
  }

  arg->setValue(std::cos(val));
  arg->type = Value::NUMBER;
  arg->setUnit("");
  return arg;
}
Value* NumberValue::acos(vector<Value*> args) {
  NumberValue* arg = ((NumberValue*)args[0]);

  arg->setValue(std::acos(arg->getValue()));
  arg->setUnit("rad");
  arg->type = Value::DIMENSION;
  return arg;
}
Value* NumberValue::tan(vector<Value*> args) {
  if (args[0]->type != Value::NUMBER &&
      args[0]->type != Value::DIMENSION) {
    throw new ValueException("tan() only works on numbers or dimensions");
  }
  NumberValue* arg = ((NumberValue*)args[0]);
  double val = arg->getValue();

  if (arg->type == Value::DIMENSION) {
    if(arg->getUnit().compare("rad") != 0 &&
       arg->getUnit().compare("deg") != 0 &&
       arg->getUnit().compare("grad") != 0 &&
       arg->getUnit().compare("turn") != 0) {
      throw new ValueException("tan() requires rad, deg, grad or turn units.");
    }
    val = UnitValue::angleToRad(val, arg->getUnit());
  }

  arg->setValue(std::tan(val));
  arg->type = Value::NUMBER;
  arg->setUnit("");
  return arg;
}
Value* NumberValue::atan(vector<Value*> args) {
  NumberValue* arg = ((NumberValue*)args[0]);

  arg->setValue(std::atan(arg->getValue()));
  arg->setUnit("rad");
  arg->type = Value::DIMENSION;
  return arg;
}
Value* NumberValue::pi(vector<Value*> args) {
  (void)args;
  return new NumberValue(new Token("3.141592653589793", Token::NUMBER));
}
Value* NumberValue::pow(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("pow() only works on numeric values");

  double val = ((NumberValue*)args[0])->getValue();
  double exp = ((NumberValue*)args[1])->getValue();
  ((NumberValue*)args[0])->setValue(std::pow(val, exp));
  return args[0];
}
Value* NumberValue::mod(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]) ||
      !NumberValue::isNumber(args[1]))
    throw new ValueException("mod() only works on numeric values");

  double val1 = ((NumberValue*)args[0])->getValue();
  double val2 = ((NumberValue*)args[1])->getValue();
  ((NumberValue*)args[0])->setValue(std::fmod(val1, val2));
  return args[0];
}
Value* NumberValue::convert(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("convert() only works on numeric values");
  if (args[1]->type != Value::STRING &&
      args[1]->type != Value::UNIT) {
    throw new ValueException("convert() requires a unit \
(or unit as a string)");
  }

  NumberValue* val = (NumberValue*)args[0];
  string unit;

  if (args[1]->type == Value::STRING)
    unit = ((StringValue*)args[1])->getString();
  else
    unit.append(((UnitValue*)args[1])->getUnit());

  val->convert(unit);
  return val;
}
<commit_msg>Fixed NumberValue so that it doesn't set it's Token type to DIMENSION when it's a NUMBER.<commit_after>/*
 * Copyright 2012 Bram van der Kroef
 *
 * This file is part of LESS CSS Compiler.
 *
 * LESS CSS Compiler is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * LESS CSS Compiler is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LESS CSS Compiler.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Bram van der Kroef <bram@vanderkroef.net>
 */

#include "NumberValue.h"

NumberValue::NumberValue(Token* token) {
  tokens.push(token);

  switch(token->type) {
  case Token::NUMBER:
    type = NUMBER;
    break;
  case Token::PERCENTAGE:
    type = PERCENTAGE;
    break;
  case Token::DIMENSION:
    type = DIMENSION;
    break;
  default:
    throw new ValueException("Token used for Value that isn't a number, percentage or dimension");
  }
}

NumberValue::~NumberValue() {
}

void NumberValue::verifyUnits(NumberValue* v) {
  if (type == Value::DIMENSION &&
      v->type == Value::DIMENSION &&
      getUnit().compare(v->getUnit()) != 0) {

    if (v->convert(getUnit())) {
      return;
    } else
      throw new ValueException("Can't do math on dimensions with different units.");
  }
}

bool NumberValue::convert(string unit) {
  UnitValue::UnitGroup group = UnitValue::getUnitGroup(unit);
  double value = getValue();

  if (UnitValue::getUnitGroup(getUnit()) == group) {

    switch(group) {
    case UnitValue::LENGTH:
      value = UnitValue::lengthToPx(value, getUnit());
      setValue(UnitValue::pxToLength(value, unit));
      setUnit(unit);
      return true;

    case UnitValue::TIME:
      value = UnitValue::timeToMs(value, getUnit());
      setValue(UnitValue::msToTime(value, unit));
      setUnit(unit);
      return true;

    case UnitValue::ANGLE:
      value = UnitValue::angleToRad(value, getUnit());
      setValue(UnitValue::radToAngle(value, unit));
      setUnit(unit);
      return true;

    default:
      break;
    }
  }
  return false;
}

Value* NumberValue::add(Value* v) {
  Token* t;
  StringValue* s;

  if (isNumber(v)) {
    if (type == NUMBER)
      setType(v);
    else
      verifyUnits((NumberValue*)v);

    setValue(getValue() + ((NumberValue*)v)->getValue());
    return this;

  } else if (v->type == COLOR) {
    return v->add(this);

  } else if (v->type == STRING) {
    t = this->tokens.front()->clone();
    t->type = Token::STRING;
    s = new StringValue(t, ((StringValue*)v)->getQuotes());
    s->add(v);
    return s;
  } else {
    throw new ValueException("Unsupported type.");
  }
}
Value* NumberValue::substract(Value* v) {
  if (isNumber(v)) {
    if (type == NUMBER)
      setType(v);
    else
      verifyUnits((NumberValue*)v);

    setValue(getValue() - ((NumberValue*)v)->getValue());
    return this;
  } else
    throw new ValueException("You can only substract a *number* from a number.");
}
Value* NumberValue::multiply(Value* v) {
  if (isNumber(v)) {
    if (type == NUMBER)
      setType(v);
    else
      verifyUnits((NumberValue*)v);
    setValue(getValue() * ((NumberValue*)v)->getValue());
    return this;
  } else if (v->type == COLOR ||
             v->type == STRING) {
    return v->multiply(this);
  } else {
    throw new ValueException("Unsupported type.");
  }
}

Value* NumberValue::divide(Value* v) {
  if (isNumber(v)) {
    if (type == NUMBER)
      setType(v);
    else
      verifyUnits((NumberValue*)v);
    setValue(getValue() / ((NumberValue*)v)->getValue());
    return this;
  } else
    throw new ValueException("You can only divide a number by a *number*.");
}
int NumberValue::compare(Value* v) {
  if (isNumber(v)) {
    verifyUnits((NumberValue*)v);
    return getValue() - ((NumberValue*)v)->getValue();
  } else {
    throw new ValueException("You can only compare a number with a *number*.");
  }
}

void NumberValue::setType(Value* v) {
  NumberValue* n;

  if (isNumber(v)) {

    n = (NumberValue*)v;

    type = n->type;
    if (n->type == DIMENSION)
      setUnit(n->getUnit());
    else if (n->type == PERCENTAGE)
      tokens.front()->type = Token::PERCENTAGE;
    else if (n->type == NUMBER) {
      setUnit("");
    }
  }
}

double NumberValue::getValue() {
  string number;
  istringstream stm;
  double ret;
  char c;

  for (unsigned int i = 0; i < tokens.front()->str.size(); i++) {
    c = tokens.front()->str[i];
    if (!isdigit(c) && c != '.' && c != '-') {
      number = tokens.front()->str.substr(0, i);
      break;
    }
  }
  if (number == "")
    number = tokens.front()->str;
  stm.str(number);
  stm >>ret;
  return ret;
}
string NumberValue::getUnit () {
  char c;
  unsigned int i;

  for (i = 0; i < tokens.front()->str.size(); i++) {
    c = tokens.front()->str[i];
    if (!isdigit(c) && c != '.' && c != '-')
      return tokens.front()->str.substr(i);
  }
  return string("");
}

void NumberValue::setUnit(string unit) {
  ostringstream stm;
  stm << getValue();
  stm << unit;
  tokens.front()->str = stm.str();

  if (unit.length() == 0) {
    type = NUMBER;
    tokens.front()->type = Token::NUMBER;
  } else {
    type = DIMENSION;
    tokens.front()->type = Token::DIMENSION;
  }
}

void NumberValue::setValue(double d) {
  ostringstream stm;
  stm << d;
  if (type == DIMENSION)
    stm << getUnit();
  else if (type == PERCENTAGE)
    stm << "%";
  tokens.front()->str = stm.str();
}

bool NumberValue::isNumber(Value* val) {
  return (val->type == Value::NUMBER ||
          val->type == Value::DIMENSION ||
          val->type == Value::PERCENTAGE);
}

void NumberValue::loadFunctions(FunctionLibrary* lib) {
  lib->push("unit", ".U?", &NumberValue::unit);
  lib->push("ceil", ".", &NumberValue::ceil);
  lib->push("floor", ".", &NumberValue::floor);
  lib->push("percentage", "N", &NumberValue::percentage);
  lib->push("round", ".", &NumberValue::round);
  lib->push("sqrt", ".", &NumberValue::sqrt);
  lib->push("abs", ".", &NumberValue::abs);
  lib->push("sin", ".", &NumberValue::sin);
  lib->push("asin", "N", &NumberValue::asin);
  lib->push("cos", ".", &NumberValue::cos);
  lib->push("acos", "N", &NumberValue::acos);
  lib->push("tan", ".", &NumberValue::tan);
  lib->push("atan", "N", &NumberValue::atan);
  lib->push("pi", "", &NumberValue::pi);
  lib->push("pow", ".N", &NumberValue::pow);
  lib->push("mod", "..", &NumberValue::mod);
  lib->push("convert", "..", &NumberValue::convert);
}

// DIMENSION unit(DIMENSION, UNIT)
Value* NumberValue::unit(vector<Value*> arguments) {
  if (arguments[0]->type == Value::NUMBER ||
      arguments[0]->type == Value::DIMENSION) {
    if (arguments.size() > 1) {
      ((NumberValue*)arguments[0])
        ->setUnit(((UnitValue*)arguments[1])->getUnit());
    } else
      ((NumberValue*)arguments[0])->setUnit("");
    return arguments[0];
  } else
    throw new ValueException("argument 1 has to be a number or dimension");
}
Value* NumberValue::ceil(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("ceil() only works on numeric values");

  double val = ((NumberValue*)args[0])->getValue();
  ((NumberValue*)args[0])->setValue(std::ceil(val));
  return args[0];
}
Value* NumberValue::floor(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("floor() only works on numeric values");

  double val = ((NumberValue*)args[0])->getValue();
  ((NumberValue*)args[0])->setValue(std::floor(val));
  return args[0];
}
Value* NumberValue::percentage(vector<Value*> args) {
  double val = ((NumberValue*)args[0])->getValue();
  ((NumberValue*)args[0])->setValue(val * 100);
  ((NumberValue*)args[0])->type = Value::PERCENTAGE;
  return args[0];
}
Value* NumberValue::round(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("round() only works on numeric values");

  double val = ((NumberValue*)args[0])->getValue();
  double decimalplaces = 0;

  if (args.size() > 1)
    decimalplaces = ((NumberValue*)args[0])->getValue();

  val = val * std::pow(10, decimalplaces);
  val = std::floor(val + 0.5);
  val = val / std::pow(10, decimalplaces);
  ((NumberValue*)args[0])->setValue(val);
  return args[0];
}
Value* NumberValue::sqrt(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("sqrt() only works on numeric values");

  double val = ((NumberValue*)args[0])->getValue();
  ((NumberValue*)args[0])->setValue(std::sqrt(val));
  return args[0];
}
Value* NumberValue::abs(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("abs() only works on numeric values");

  double val = ((NumberValue*)args[0])->getValue();
  ((NumberValue*)args[0])->setValue(fabs(val));
  return args[0];
}

Value* NumberValue::sin(vector<Value*> args) {
  if (args[0]->type != Value::NUMBER &&
      args[0]->type != Value::DIMENSION) {
    throw new ValueException("sin() only works on numbers or dimensions");
  }

  NumberValue* arg = ((NumberValue*)args[0]);
  double val = arg->getValue();

  if (arg->type == Value::DIMENSION) {
    if(arg->getUnit().compare("rad") != 0 &&
       arg->getUnit().compare("deg") != 0 &&
       arg->getUnit().compare("grad") != 0 &&
       arg->getUnit().compare("turn") != 0) {
      throw new ValueException("sin() requires rad, deg, grad or turn units.");
    }
    val = UnitValue::angleToRad(val, arg->getUnit());
  }

  arg->setValue(std::sin(val));
  arg->type = Value::NUMBER;
  arg->setUnit("");
  return arg;
}
Value* NumberValue::asin(vector<Value*> args) {
  NumberValue* arg = ((NumberValue*)args[0]);

  arg->setValue(std::asin(arg->getValue()));
  arg->setUnit("rad");
  arg->type = Value::DIMENSION;
  return arg;
}
Value* NumberValue::cos(vector<Value*> args) {
  if (args[0]->type != Value::NUMBER &&
      args[0]->type != Value::DIMENSION) {
    throw new ValueException("cos() only works on numbers or dimensions");
  }
  NumberValue* arg = ((NumberValue*)args[0]);
  double val = arg->getValue();

  if (arg->type == Value::DIMENSION) {
    if(arg->getUnit().compare("rad") != 0 &&
       arg->getUnit().compare("deg") != 0 &&
       arg->getUnit().compare("grad") != 0 &&
       arg->getUnit().compare("turn") != 0) {
      throw new ValueException("cos() requires rad, deg, grad or turn units.");
    }
    val = UnitValue::angleToRad(val, arg->getUnit());
  }

  arg->setValue(std::cos(val));
  arg->type = Value::NUMBER;
  arg->setUnit("");
  return arg;
}
Value* NumberValue::acos(vector<Value*> args) {
  NumberValue* arg = ((NumberValue*)args[0]);

  arg->setValue(std::acos(arg->getValue()));
  arg->setUnit("rad");
  arg->type = Value::DIMENSION;
  return arg;
}
Value* NumberValue::tan(vector<Value*> args) {
  if (args[0]->type != Value::NUMBER &&
      args[0]->type != Value::DIMENSION) {
    throw new ValueException("tan() only works on numbers or dimensions");
  }
  NumberValue* arg = ((NumberValue*)args[0]);
  double val = arg->getValue();

  if (arg->type == Value::DIMENSION) {
    if(arg->getUnit().compare("rad") != 0 &&
       arg->getUnit().compare("deg") != 0 &&
       arg->getUnit().compare("grad") != 0 &&
       arg->getUnit().compare("turn") != 0) {
      throw new ValueException("tan() requires rad, deg, grad or turn units.");
    }
    val = UnitValue::angleToRad(val, arg->getUnit());
  }

  arg->setValue(std::tan(val));
  arg->type = Value::NUMBER;
  arg->setUnit("");
  return arg;
}
Value* NumberValue::atan(vector<Value*> args) {
  NumberValue* arg = ((NumberValue*)args[0]);

  arg->setValue(std::atan(arg->getValue()));
  arg->setUnit("rad");
  arg->type = Value::DIMENSION;
  return arg;
}
Value* NumberValue::pi(vector<Value*> args) {
  (void)args;
  return new NumberValue(new Token("3.141592653589793", Token::NUMBER));
}
Value* NumberValue::pow(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("pow() only works on numeric values");

  double val = ((NumberValue*)args[0])->getValue();
  double exp = ((NumberValue*)args[1])->getValue();
  ((NumberValue*)args[0])->setValue(std::pow(val, exp));
  return args[0];
}
Value* NumberValue::mod(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]) ||
      !NumberValue::isNumber(args[1]))
    throw new ValueException("mod() only works on numeric values");

  double val1 = ((NumberValue*)args[0])->getValue();
  double val2 = ((NumberValue*)args[1])->getValue();
  ((NumberValue*)args[0])->setValue(std::fmod(val1, val2));
  return args[0];
}
Value* NumberValue::convert(vector<Value*> args) {
  if (!NumberValue::isNumber(args[0]))
    throw new ValueException("convert() only works on numeric values");
  if (args[1]->type != Value::STRING &&
      args[1]->type != Value::UNIT) {
    throw new ValueException("convert() requires a unit \
(or unit as a string)");
  }

  NumberValue* val = (NumberValue*)args[0];
  string unit;

  if (args[1]->type == Value::STRING)
    unit = ((StringValue*)args[1])->getString();
  else
    unit.append(((UnitValue*)args[1])->getUnit());

  val->convert(unit);
  return val;
}
<|endoftext|>


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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkNarrowBandCurvesLevelSetImageFilterTest.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.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
#include "itkNarrowBandCurvesLevelSetImageFilter.h"

#include "itkImage.h"
#include "itkImageRegionIterator.h"
#include "itkCastImageFilter.h"
#include "itkGradientMagnitudeRecursiveGaussianImageFilter.h"
#include "itkSigmoidImageFilter.h"
#include "itkFastMarchingImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkSimilarityIndexImageFilter.h"

/* Uncomment to write out image files */
/*
#include "itkRescaleIntensityImageFilter.h"
#include "itkImageFileWriter.h"
*/

int itkNarrowBandCurvesLevelSetImageFilterTest(int, char* [] )
{

  const   unsigned int    ImageDimension = 2;
  typedef unsigned char   PixelType;
  typedef float           InternalPixelType;

  typedef itk::Image<PixelType,ImageDimension> ImageType;
  typedef itk::Image<InternalPixelType,ImageDimension> InternalImageType;

  ImageType::SizeType imageSize;
  imageSize[0] = 64;
  imageSize[1] = 64;

  ImageType::RegionType imageRegion;
  imageRegion.SetSize( imageSize );

  /**
   * Create an input image.
   * A light square on a dark background.
   */
  PixelType background = 0;
  PixelType foreground = 190;

  ImageType::Pointer inputImage = ImageType::New();
  inputImage->SetRegions( imageRegion );
  inputImage->Allocate();
  inputImage->FillBuffer( background );

  ImageType::IndexType squareStart;
  squareStart.Fill( 10 );
  ImageType::SizeType squareSize;
  squareSize.Fill( 30 );
  ImageType::RegionType squareRegion;
  squareRegion.SetIndex( squareStart );
  squareRegion.SetSize( squareSize );

  typedef itk::ImageRegionIterator<ImageType> Iterator;
  Iterator it( inputImage, squareRegion );
  it.GoToBegin();
  while( !it.IsAtEnd() )
    {
    it.Set( foreground );
    ++it;
    }

  /**
   * Create an edge potential map.
   * First compute the image gradient magnitude using a derivative of gaussian filter.
   * Then apply a sigmoid function to the gradient magnitude.
   */
  typedef itk::CastImageFilter< ImageType, InternalImageType > CastFilterType;
  CastFilterType::Pointer caster = CastFilterType::New();
  caster->SetInput( inputImage );

  typedef itk::GradientMagnitudeRecursiveGaussianImageFilter< InternalImageType,
    InternalImageType > GradientImageType;

  GradientImageType::Pointer gradMagnitude = GradientImageType::New();
  gradMagnitude->SetInput( caster->GetOutput() );
  gradMagnitude->SetSigma( 1.0 );

  typedef itk::SigmoidImageFilter< InternalImageType, InternalImageType >
    SigmoidFilterType;
  SigmoidFilterType::Pointer sigmoid = SigmoidFilterType::New();
  sigmoid->SetOutputMinimum( 0.0 );
  sigmoid->SetOutputMaximum( 1.0 );
  sigmoid->SetAlpha( -0.4 );
  sigmoid->SetBeta( 2.5 );
  sigmoid->SetInput( gradMagnitude->GetOutput() );

  /**
   * Create an initial level.
   * Use fast marching to create an signed distance from a seed point.
   */
  typedef itk::FastMarchingImageFilter<InternalImageType> FastMarchingFilterType;
  FastMarchingFilterType::Pointer fastMarching = FastMarchingFilterType::New();

  typedef FastMarchingFilterType::NodeContainer NodeContainer;
  typedef FastMarchingFilterType::NodeType      NodeType;

  NodeContainer::Pointer seeds = NodeContainer::New();

  // Choose an initial contour that overlaps the square to be segmented.
  InternalImageType::IndexType seedPosition;
  seedPosition[0] = 23;
  seedPosition[1] = 23;

  NodeType node;
  node.SetValue( -15 );
  node.SetIndex( seedPosition );

  seeds->Initialize();
  seeds->InsertElement( 0, node );

  fastMarching->SetTrialPoints( seeds );
  fastMarching->SetSpeedConstant( 1.0 );
  fastMarching->SetOutputSize( imageSize );

  /**
   * Set up and run the shape detection filter
   */
  typedef itk::NarrowBandCurvesLevelSetImageFilter<
    InternalImageType, InternalImageType > CurvesFilterType;

  CurvesFilterType::Pointer curvesFilter = CurvesFilterType::New();

  // set the initial level set
  curvesFilter->SetInput( fastMarching->GetOutput() );

  // set the edge potential image
  curvesFilter->SetFeatureImage( sigmoid->GetOutput() );

  // set the weights between the propagation, curvature and advection terms
  curvesFilter->SetPropagationScaling( 0.8 );
  curvesFilter->SetCurvatureScaling( 0.3 );
  curvesFilter->SetAdvectionScaling( 0.5 );

  // set the convergence criteria
  curvesFilter->SetMaximumRMSError( 0.03 );
  curvesFilter->SetMaximumIterations( 50 );

  curvesFilter->SetNumberOfThreads(2);

  /**
   * Threshold the output level set to display the final contour.
   */
  typedef itk::BinaryThresholdImageFilter< InternalImageType, ImageType >
    ThresholdFilterType;
  ThresholdFilterType::Pointer thresholder = ThresholdFilterType::New();

  thresholder->SetInput( curvesFilter->GetOutput() );
  thresholder->SetLowerThreshold( -1e+10 );
  thresholder->SetUpperThreshold( 0.0 );
  thresholder->SetOutsideValue( 0 );
  thresholder->SetInsideValue( 255 );

  /**
   * Compute overlap between the true shape and the segmented shape
   */
  typedef itk::SimilarityIndexImageFilter< ImageType, ImageType >
    OverlapCalculatorType;
  OverlapCalculatorType::Pointer overlap = OverlapCalculatorType::New();

  overlap->SetInput1( inputImage );
  overlap->SetInput2( thresholder->GetOutput() );
  overlap->Update();

  /** Printout useful information from the shape detection filter. */
  std::cout << "Max. no. iterations: " << curvesFilter->GetMaximumIterations() << std::endl;
  std::cout << "No. elpased iterations: " << curvesFilter->GetElapsedIterations() << std::endl;
  std::cout << "Overlap: " << overlap->GetSimilarityIndex() << std::endl;

  /**
   * Uncomment to write out image files.
   */
  /*
  typedef itk::ImageFileWriter< ImageType > WriterType;
  WriterType::Pointer writer = WriterType::New();

  typedef itk::RescaleIntensityImageFilter< InternalImageType,
    ImageType > RescaleFilterType;
  RescaleFilterType::Pointer rescaler = RescaleFilterType::New();

  writer->SetFileName( "inputImage.png" );
  writer->SetInput( inputImage );
  writer->Update();

  rescaler->SetInput( gradMagnitude->GetOutput() );
  rescaler->SetOutputMinimum( 0 );
  rescaler->SetOutputMaximum( 255 );
  writer->SetFileName( "gradMagnitude.png" );
  writer->SetInput( rescaler->GetOutput() );
  writer->Update();

  rescaler->SetInput( sigmoid->GetOutput() );
  writer->SetFileName( "edgePotential.png" );
  writer->Update();

  writer->SetInput( thresholder->GetOutput() );
  writer->SetFileName( "outputLevelSet.png" );
  writer->Update();

  thresholder->SetInput( fastMarching->GetOutput() );
  writer->SetInput( thresholder->GetOutput() );
  writer->SetFileName( "initialLevelSet.png" );
  writer->Update();
  */

  // Check if overlap is above threshold
  if ( overlap->GetSimilarityIndex() > 0.90 )
    {
    std::cout << "Overlap exceed threshold." << std::endl;
    }
  else
    {
    std::cout << "Overlap below threshold." << std::endl;
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
    }

  // Test case when PropagationScaling is zero
  curvesFilter->SetPropagationScaling( 0.0 );
  curvesFilter->SetCurvatureScaling( 1.0 );
  curvesFilter->SetAdvectionScaling( 0.0 );
  curvesFilter->Update();

  std::cout << "Test Passed. " << std::endl;
  return EXIT_SUCCESS;
}

<commit_msg>FIX: propagation and curvature scaling adjusted<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkNarrowBandCurvesLevelSetImageFilterTest.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.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
#include "itkNarrowBandCurvesLevelSetImageFilter.h"

#include "itkImage.h"
#include "itkImageRegionIterator.h"
#include "itkCastImageFilter.h"
#include "itkGradientMagnitudeRecursiveGaussianImageFilter.h"
#include "itkSigmoidImageFilter.h"
#include "itkFastMarchingImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkSimilarityIndexImageFilter.h"

/* Uncomment to write out image files */
/*
#include "itkRescaleIntensityImageFilter.h"
#include "itkImageFileWriter.h"
*/

int itkNarrowBandCurvesLevelSetImageFilterTest(int, char* [] )
{

  const   unsigned int    ImageDimension = 2;
  typedef unsigned char   PixelType;
  typedef float           InternalPixelType;

  typedef itk::Image<PixelType,ImageDimension> ImageType;
  typedef itk::Image<InternalPixelType,ImageDimension> InternalImageType;

  ImageType::SizeType imageSize;
  imageSize[0] = 64;
  imageSize[1] = 64;

  ImageType::RegionType imageRegion;
  imageRegion.SetSize( imageSize );

  /**
   * Create an input image.
   * A light square on a dark background.
   */
  PixelType background = 0;
  PixelType foreground = 190;

  ImageType::Pointer inputImage = ImageType::New();
  inputImage->SetRegions( imageRegion );
  inputImage->Allocate();
  inputImage->FillBuffer( background );

  ImageType::IndexType squareStart;
  squareStart.Fill( 10 );
  ImageType::SizeType squareSize;
  squareSize.Fill( 30 );
  ImageType::RegionType squareRegion;
  squareRegion.SetIndex( squareStart );
  squareRegion.SetSize( squareSize );

  typedef itk::ImageRegionIterator<ImageType> Iterator;
  Iterator it( inputImage, squareRegion );
  it.GoToBegin();
  while( !it.IsAtEnd() )
    {
    it.Set( foreground );
    ++it;
    }

  /**
   * Create an edge potential map.
   * First compute the image gradient magnitude using a derivative of gaussian filter.
   * Then apply a sigmoid function to the gradient magnitude.
   */
  typedef itk::CastImageFilter< ImageType, InternalImageType > CastFilterType;
  CastFilterType::Pointer caster = CastFilterType::New();
  caster->SetInput( inputImage );

  typedef itk::GradientMagnitudeRecursiveGaussianImageFilter< InternalImageType,
    InternalImageType > GradientImageType;

  GradientImageType::Pointer gradMagnitude = GradientImageType::New();
  gradMagnitude->SetInput( caster->GetOutput() );
  gradMagnitude->SetSigma( 1.0 );

  typedef itk::SigmoidImageFilter< InternalImageType, InternalImageType >
    SigmoidFilterType;
  SigmoidFilterType::Pointer sigmoid = SigmoidFilterType::New();
  sigmoid->SetOutputMinimum( 0.0 );
  sigmoid->SetOutputMaximum( 1.0 );
  sigmoid->SetAlpha( -0.4 );
  sigmoid->SetBeta( 2.5 );
  sigmoid->SetInput( gradMagnitude->GetOutput() );

  /**
   * Create an initial level.
   * Use fast marching to create an signed distance from a seed point.
   */
  typedef itk::FastMarchingImageFilter<InternalImageType> FastMarchingFilterType;
  FastMarchingFilterType::Pointer fastMarching = FastMarchingFilterType::New();

  typedef FastMarchingFilterType::NodeContainer NodeContainer;
  typedef FastMarchingFilterType::NodeType      NodeType;

  NodeContainer::Pointer seeds = NodeContainer::New();

  // Choose an initial contour that overlaps the square to be segmented.
  InternalImageType::IndexType seedPosition;
  seedPosition[0] = 23;
  seedPosition[1] = 23;

  NodeType node;
  node.SetValue( -15 );
  node.SetIndex( seedPosition );

  seeds->Initialize();
  seeds->InsertElement( 0, node );

  fastMarching->SetTrialPoints( seeds );
  fastMarching->SetSpeedConstant( 1.0 );
  fastMarching->SetOutputSize( imageSize );

  /**
   * Set up and run the shape detection filter
   */
  typedef itk::NarrowBandCurvesLevelSetImageFilter<
    InternalImageType, InternalImageType > CurvesFilterType;

  CurvesFilterType::Pointer curvesFilter = CurvesFilterType::New();

  // set the initial level set
  curvesFilter->SetInput( fastMarching->GetOutput() );

  // set the edge potential image
  curvesFilter->SetFeatureImage( sigmoid->GetOutput() );

  // set the weights between the propagation, curvature and advection terms
  curvesFilter->SetPropagationScaling( 0.3 );
  curvesFilter->SetCurvatureScaling( 0.5 );
  curvesFilter->SetAdvectionScaling( 0.5 );

  // set the convergence criteria
  curvesFilter->SetMaximumRMSError( 0.03 );
  curvesFilter->SetMaximumIterations( 50 );

  curvesFilter->SetNumberOfThreads(2);

  /**
   * Threshold the output level set to display the final contour.
   */
  typedef itk::BinaryThresholdImageFilter< InternalImageType, ImageType >
    ThresholdFilterType;
  ThresholdFilterType::Pointer thresholder = ThresholdFilterType::New();

  thresholder->SetInput( curvesFilter->GetOutput() );
  thresholder->SetLowerThreshold( -1e+10 );
  thresholder->SetUpperThreshold( 0.0 );
  thresholder->SetOutsideValue( 0 );
  thresholder->SetInsideValue( 255 );

  /**
   * Compute overlap between the true shape and the segmented shape
   */
  typedef itk::SimilarityIndexImageFilter< ImageType, ImageType >
    OverlapCalculatorType;
  OverlapCalculatorType::Pointer overlap = OverlapCalculatorType::New();

  overlap->SetInput1( inputImage );
  overlap->SetInput2( thresholder->GetOutput() );
  overlap->Update();

  /** Printout useful information from the shape detection filter. */
  std::cout << "Max. no. iterations: " << curvesFilter->GetMaximumIterations() << std::endl;
  std::cout << "No. elpased iterations: " << curvesFilter->GetElapsedIterations() << std::endl;
  std::cout << "Overlap: " << overlap->GetSimilarityIndex() << std::endl;

  /**
   * Uncomment to write out image files.
   */
  /*
  typedef itk::ImageFileWriter< ImageType > WriterType;
  WriterType::Pointer writer = WriterType::New();

  typedef itk::RescaleIntensityImageFilter< InternalImageType,
    ImageType > RescaleFilterType;
  RescaleFilterType::Pointer rescaler = RescaleFilterType::New();

  writer->SetFileName( "inputImage.png" );
  writer->SetInput( inputImage );
  writer->Update();

  rescaler->SetInput( gradMagnitude->GetOutput() );
  rescaler->SetOutputMinimum( 0 );
  rescaler->SetOutputMaximum( 255 );
  writer->SetFileName( "gradMagnitude.png" );
  writer->SetInput( rescaler->GetOutput() );
  writer->Update();

  rescaler->SetInput( sigmoid->GetOutput() );
  writer->SetFileName( "edgePotential.png" );
  writer->Update();

  writer->SetInput( thresholder->GetOutput() );
  writer->SetFileName( "outputLevelSet.png" );
  writer->Update();

  thresholder->SetInput( fastMarching->GetOutput() );
  writer->SetInput( thresholder->GetOutput() );
  writer->SetFileName( "initialLevelSet.png" );
  writer->Update();
  */

  // Check if overlap is above threshold
  if ( overlap->GetSimilarityIndex() > 0.90 )
    {
    std::cout << "Overlap exceed threshold." << std::endl;
    }
  else
    {
    std::cout << "Overlap below threshold." << std::endl;
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
    }

  // Test case when PropagationScaling is zero
  curvesFilter->SetPropagationScaling( 0.0 );
  curvesFilter->SetCurvatureScaling( 1.0 );
  curvesFilter->SetAdvectionScaling( 0.0 );
  curvesFilter->Update();

  std::cout << "Test Passed. " << std::endl;
  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#include "vast/configuration.h"
#include "vast/file_system.h"
#include "vast/logger.h"
#include "vast/string.h"
#include "vast/type_info.h"
#include "vast/detail/type_manager.h"

namespace vast {

std::string configuration::banner() const
{
  std::stringstream ss;
  ss << " _   _____   __________\n"
        "| | / / _ | / __/_  __/\n"
        "| |/ / __ |_\\ \\  / /\n"
        "|___/_/ |_/___/ /_/  " << VAST_VERSION;

  return ss.str();
}

void configuration::initialize()
{
  auto& general = create_block("general options");
  general.add('c', "config", "configuration file");
  general.add('h', "help", "display this help");
  general.add('d', "directory", "VAST directory").init("vast");
  general.add('z', "advanced", "show advanced options");

  auto min = 0;
  auto max = VAST_LOG_LEVEL;
  auto range = '[' + std::to_string(min) + '-' + std::to_string(max) + ']';

  auto& log = create_block("logger options", "log");
  log.add('v', "console-verbosity", "console verbosity " + range)
     .init(std::min(3, max));
  log.add('V', "file-verbosity", "log file verbosity " + range)
     .init(std::min(4, max));
  log.add("no-colors", "don't use colors for console output");
  log.add("function-names", "log function names");

  auto& advanced = create_block("advanced options");
  advanced.add('P', "profile",
               "enable getrusage profiling at a given interval (seconds)")
          .single();
#ifdef VAST_USE_PERFTOOLS_CPU_PROFILER
  advanced.add("profile-cpu", "also enable Google perftools CPU profiling");
#endif
#ifdef VAST_USE_PERFTOOLS_HEAP_PROFILER
  advanced.add("profile-heap", "also enable Google perftools heap profiling");
#endif
#ifdef VAST_HAVE_BROCCOLI
  advanced.add("broccoli-messages", "enable broccoli debug messages");
  advanced.add("broccoli-calltrace", "enable broccoli function call tracing");
#endif
  advanced.visible(false);

  auto& actor = create_block("actor options");
#ifdef VAST_HAVE_EDITLINE
  actor.add('C', "console-actor", "spawn the console client actor");
#endif
  actor.add('a', "all-server", "spawn all server actors");
  actor.add('A', "archive-actor", "spawn the archive");
  actor.add('I', "ingestor-actor", "spawn the ingestor");
  actor.add('R', "receiver-actor", "spawn the receiver");
  actor.add('S', "search-actor", "spawn the search");
  actor.add('T', "tracker-actor", "spawn the ID tracker");
  actor.add('X', "index-actor", "spawn the index");
  actor.visible(false);

  auto& schema = create_block("schema options", "schema");
  schema.add('s', "file", "schema file").single();
  schema.add("print", "print the parsed event schema");
  schema.visible(false);

  auto& ingest = create_block("ingest options", "ingest");
  ingest.add("max-events-per-chunk", "maximum number of events per chunk")
        .init(5000);
  ingest.add("max-segment-size", "maximum segment size in MB").init(128);
  ingest.add("batch-size", "number of events to ingest in one run").init(4000);
  ingest.add("file-name", "path to file to ingest").single();
  ingest.add("file-type", "file type of the file to ingest").init("bro2");
  ingest.add("time-field", "field to extract event timestamp from").init(-1);
  ingest.add("submit", "send orphaned segments on startup");
#ifdef VAST_HAVE_BROCCOLI
  ingest.add("broccoli-host", "hostname/address of the broccoli source")
        .init("127.0.0.1");
  ingest.add("broccoli-port", "port of the broccoli source").init(42000);
  ingest.add("broccoli-events", "list of events for broccoli to subscribe to")
        .multi();
#endif
  ingest.visible(false);

  auto& receiver = create_block("receiver options", "receiver");
  receiver.add("host", "hostname/address of the receiver").init("127.0.0.1");
  receiver.add("port", "TCP port of the receiver").init(42000);
  receiver.visible(false);

  auto& archive = create_block("archive options", "archive");
  archive.add("host", "hostname/address of the archive").init("127.0.0.1");
  archive.add("port", "TCP port of the archive").init(42003);
  archive.add("max-segments", "maximum number of segments to keep in memory")
         .init(500);
  archive.visible(false);

  auto& index = create_block("index options", "index");
  index.add("host", "hostname/address of the archive").init("127.0.0.1");
  index.add("port", "TCP port of the index").init(42004);
  index.add("partition", "name of the partition to append to").single();
  index.add("batch-size", "number of events to index in one run").init(5000);
  index.add("rebuild", "rebuild indexes from archive");
  index.visible(false);

  auto& tracker = create_block("ID tracker options", "tracker");
  tracker.add("host", "hostname/address of the tracker").init("127.0.0.1");
  tracker.add("port", "TCP port of the ID tracker").init(42002);
  tracker.visible(false);

  auto& search = create_block("search options", "search");
  search.add("host", "hostname/address of the archive").init("127.0.0.1");
  search.add("port", "TCP port of the search").init(42001);
  search.visible(false);

  add_dependency("schema.print", "schema.file");

#ifdef VAST_HAVE_EDITLINE
  add_conflict("console-actor", "all-server");
  add_conflict("console-actor", "tracker-actor");
  add_conflict("console-actor", "archive-actor");
  add_conflict("console-actor", "index-actor");
  add_conflict("console-actor", "ingestor-actor");
  add_conflict("console-actor", "search-actor");
#endif

  add_dependency("ingest.time-field", "ingestor-actor");
  add_dependency("ingest.submit", "ingestor-actor");
  add_dependency("ingest.file-name", "ingestor-actor");
  add_dependency("ingest.file-type", "ingest.file-name");
  add_dependencies("index.partition", {"index-actor", "all-server"});
  add_conflict("index.rebuild", "index.partition");
}

} // namespace vast
<commit_msg>Add colors to command line help banner.<commit_after>#include "vast/configuration.h"
#include "vast/file_system.h"
#include "vast/logger.h"
#include "vast/string.h"
#include "vast/type_info.h"
#include "vast/detail/type_manager.h"
#include "vast/util/color.h"

namespace vast {

std::string configuration::banner() const
{
  std::stringstream ss;
  auto colorize = ! check("log.no-colors");
  if (colorize)
    ss << util::color::red;

  ss << "     _   _____   __________\n"
        "    | | / / _ | / __/_  __/\n"
        "    | |/ / __ |_\\ \\  / /\n"
        "    |___/_/ |_/___/ /_/  ";

  if (colorize)
    ss << util::color::yellow;

  ss << VAST_VERSION;

  if (colorize)
    ss << util::color::reset;

  return ss.str();
}

void configuration::initialize()
{
  auto& general = create_block("general options");
  general.add('c', "config", "configuration file");
  general.add('h', "help", "display this help");
  general.add('d', "directory", "VAST directory").init("vast");
  general.add('z', "advanced", "show advanced options");

  auto min = 0;
  auto max = VAST_LOG_LEVEL;
  auto range = '[' + std::to_string(min) + '-' + std::to_string(max) + ']';

  auto& log = create_block("logger options", "log");
  log.add('v', "console-verbosity", "console verbosity " + range)
     .init(std::min(3, max));
  log.add('V', "file-verbosity", "log file verbosity " + range)
     .init(std::min(4, max));
  log.add("no-colors", "don't use colors for console output");
  log.add("function-names", "log function names");

  auto& advanced = create_block("advanced options");
  advanced.add('P', "profile",
               "enable getrusage profiling at a given interval (seconds)")
          .single();
#ifdef VAST_USE_PERFTOOLS_CPU_PROFILER
  advanced.add("profile-cpu", "also enable Google perftools CPU profiling");
#endif
#ifdef VAST_USE_PERFTOOLS_HEAP_PROFILER
  advanced.add("profile-heap", "also enable Google perftools heap profiling");
#endif
#ifdef VAST_HAVE_BROCCOLI
  advanced.add("broccoli-messages", "enable broccoli debug messages");
  advanced.add("broccoli-calltrace", "enable broccoli function call tracing");
#endif
  advanced.visible(false);

  auto& actor = create_block("actor options");
#ifdef VAST_HAVE_EDITLINE
  actor.add('C', "console-actor", "spawn the console client actor");
#endif
  actor.add('a', "all-server", "spawn all server actors");
  actor.add('A', "archive-actor", "spawn the archive");
  actor.add('I', "ingestor-actor", "spawn the ingestor");
  actor.add('R', "receiver-actor", "spawn the receiver");
  actor.add('S', "search-actor", "spawn the search");
  actor.add('T', "tracker-actor", "spawn the ID tracker");
  actor.add('X', "index-actor", "spawn the index");
  actor.visible(false);

  auto& schema = create_block("schema options", "schema");
  schema.add('s', "file", "schema file").single();
  schema.add("print", "print the parsed event schema");
  schema.visible(false);

  auto& ingest = create_block("ingest options", "ingest");
  ingest.add("max-events-per-chunk", "maximum number of events per chunk")
        .init(5000);
  ingest.add("max-segment-size", "maximum segment size in MB").init(128);
  ingest.add("batch-size", "number of events to ingest in one run").init(4000);
  ingest.add("file-name", "path to file to ingest").single();
  ingest.add("file-type", "file type of the file to ingest").init("bro2");
  ingest.add("time-field", "field to extract event timestamp from").init(-1);
  ingest.add("submit", "send orphaned segments on startup");
#ifdef VAST_HAVE_BROCCOLI
  ingest.add("broccoli-host", "hostname/address of the broccoli source")
        .init("127.0.0.1");
  ingest.add("broccoli-port", "port of the broccoli source").init(42000);
  ingest.add("broccoli-events", "list of events for broccoli to subscribe to")
        .multi();
#endif
  ingest.visible(false);

  auto& receiver = create_block("receiver options", "receiver");
  receiver.add("host", "hostname/address of the receiver").init("127.0.0.1");
  receiver.add("port", "TCP port of the receiver").init(42000);
  receiver.visible(false);

  auto& archive = create_block("archive options", "archive");
  archive.add("host", "hostname/address of the archive").init("127.0.0.1");
  archive.add("port", "TCP port of the archive").init(42003);
  archive.add("max-segments", "maximum number of segments to keep in memory")
         .init(500);
  archive.visible(false);

  auto& index = create_block("index options", "index");
  index.add("host", "hostname/address of the archive").init("127.0.0.1");
  index.add("port", "TCP port of the index").init(42004);
  index.add("partition", "name of the partition to append to").single();
  index.add("batch-size", "number of events to index in one run").init(5000);
  index.add("rebuild", "rebuild indexes from archive");
  index.visible(false);

  auto& tracker = create_block("ID tracker options", "tracker");
  tracker.add("host", "hostname/address of the tracker").init("127.0.0.1");
  tracker.add("port", "TCP port of the ID tracker").init(42002);
  tracker.visible(false);

  auto& search = create_block("search options", "search");
  search.add("host", "hostname/address of the archive").init("127.0.0.1");
  search.add("port", "TCP port of the search").init(42001);
  search.visible(false);

  add_dependency("schema.print", "schema.file");

#ifdef VAST_HAVE_EDITLINE
  add_conflict("console-actor", "all-server");
  add_conflict("console-actor", "tracker-actor");
  add_conflict("console-actor", "archive-actor");
  add_conflict("console-actor", "index-actor");
  add_conflict("console-actor", "ingestor-actor");
  add_conflict("console-actor", "search-actor");
#endif

  add_dependency("ingest.time-field", "ingestor-actor");
  add_dependency("ingest.submit", "ingestor-actor");
  add_dependency("ingest.file-name", "ingestor-actor");
  add_dependency("ingest.file-type", "ingest.file-name");
  add_dependencies("index.partition", {"index-actor", "all-server"});
  add_conflict("index.rebuild", "index.partition");
}

} // namespace vast
<|endoftext|>