<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libkeynote project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <cmath>
#include <deque>

#include <boost/bind.hpp>

#include "KNPath.h"
#include "KNShape.h"
#include "KNTransformation.h"
#include "KNTypes.h"

using std::deque;

namespace libkeynote
{

namespace
{

struct Point
{
  double x;
  double y;

  Point();
  Point(double x_, double y_);
};

Point::Point()
  : x(0)
  , y(0)
{
}

Point::Point(const double x_, const double y_)
  : x(x_)
  , y(y_)
{
}

bool operator==(const Point &left, const Point &right)
{
  return (left.x == right.x) && (left.y == right.y);
}

bool operator!=(const Point &left, const Point &right)
{
  return !(left == right);
}

}

namespace
{

using namespace transformations;

deque<Point> rotatePoint(const Point &point, const unsigned n)
{
  deque<Point> points;


  const double angle = 2 * M_PI / n;

  points.push_back(point);
  for (unsigned i = 1; i < n; ++i)
  {
    Point pt(point);
    const KNTransformation rot(rotate(i * angle));
    rot(pt.x, pt.y);
    points.push_back(pt);
  }

  return points;
}

deque<Point> drawArrowHalf(const double headWidth, const double stemThickness)
{
  // user space canvas: [0:1] x [0:1]

  deque<Point> points;
  points.push_back(Point(0, stemThickness));
  points.push_back(Point(1 - headWidth, stemThickness));
  points.push_back(Point(1 - headWidth, 1));
  points.push_back(Point(1, 0));

  return points;
}

KNPathPtr_t makePolyLine(const deque<Point> inputPoints, bool close = true)
{
  KNPathPtr_t path;

// need at least 2 points to make a polyline
  if (inputPoints.size() < 2)
    return path;

  // remove multiple points
  deque<Point> points;
  {
    deque<Point>::const_iterator first = inputPoints.begin();
    deque<Point>::const_iterator last = first;
    do
    {
      last = adjacent_find(first, inputPoints.end());
      copy(first, last, back_inserter(points));
      // skip the range of adjacent, equal points
      first = adjacent_find(last, inputPoints.end(), boost::bind(operator!=, _1, _2));
      if (inputPoints.end() != first)
        ++first;
    }
    while (first != inputPoints.end());
  }

  // close path if the first and last points are equal
  if (points.front() == points.back())
  {
    points.pop_back();
    close = true;
  }

// ... but there must be at least 3 points to make a closed path
  if (points.size() < 3)
    close = false;

// need at least 2 points to make a polyline
  if (points.size() < 2)
    return path;

  deque<Point>::const_iterator it = points.begin();
  path->appendMoveTo(it->x, it->y);
  ++it;
  for (; it != points.end(); ++it)
    path->appendLineTo(it->x, it->y);

  if (close)
    path->appendClose();

  return path;
}

struct TransformPoint
{
  TransformPoint(const KNTransformation &tr)
    : m_tr(tr)
  {
  }

  void operator()(Point &point) const
  {
    m_tr(point.x, point.y);
  }

private:
  const KNTransformation &m_tr;
};

void transform(deque<Point> &points, const KNTransformation &tr)
{
  for_each(points.begin(), points.end(), TransformPoint(tr));
}

}

KNShape::KNShape()
  : geometry()
  , style()
  , path()
  , text()
{
}

KNObjectPtr_t makeObject(const KNShapePtr_t &shape)
{
  // TODO: implement me
  (void) shape;
  return KNObjectPtr_t();
}

KNPathPtr_t makePolygonPath(const KNSize &size, const unsigned edges)
{
  // user space canvas: [-1:1] x [-1:1]

  deque<Point> points = rotatePoint(Point(0, -1), edges);

  transform(points, translate(0, 1) * scale(0.5, 0.5) * scale(size.width, size.height));
  const KNPathPtr_t path = makePolyLine(points);

  return path;
}

KNPathPtr_t makeRoundedRectanglePath(const KNSize &size, const double radius)
{
  // TODO: implement me
  (void) size;
  (void) radius;
  return KNPathPtr_t();
}

KNPathPtr_t makeArrowPath(const KNSize &size, const double headWidth, const double stemThickness)
{
  deque<Point> points = drawArrowHalf(headWidth, stemThickness);

  // mirror around the x axis<commit_msg>shuffle code around a bit<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libkeynote project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <cmath>
#include <deque>

#include <boost/bind.hpp>

#include "KNPath.h"
#include "KNShape.h"
#include "KNTransformation.h"
#include "KNTypes.h"

using std::deque;

namespace libkeynote
{

KNShape::KNShape()
  : geometry()
  , style()
  , path()
  , text()
{
}

KNObjectPtr_t makeObject(const KNShapePtr_t &shape)
{
  // TODO: implement me
  (void) shape;
  return KNObjectPtr_t();
}

namespace
{

struct Point
{
  double x;
  double y;

  Point();
  Point(double x_, double y_);
};

Point::Point()
  : x(0)
  , y(0)
{
}

Point::Point(const double x_, const double y_)
  : x(x_)
  , y(y_)
{
}

bool operator==(const Point &left, const Point &right)
{
  return (left.x == right.x) && (left.y == right.y);
}

bool operator!=(const Point &left, const Point &right)
{
  return !(left == right);
}

}

namespace
{

using namespace transformations;

deque<Point> rotatePoint(const Point &point, const unsigned n)
{
  deque<Point> points;


  const double angle = 2 * M_PI / n;

  points.push_back(point);
  for (unsigned i = 1; i < n; ++i)
  {
    Point pt(point);
    const KNTransformation rot(rotate(i * angle));
    rot(pt.x, pt.y);
    points.push_back(pt);
  }

  return points;
}

deque<Point> drawArrowHalf(const double headWidth, const double stemThickness)
{
  // user space canvas: [0:1] x [0:1]

  deque<Point> points;
  points.push_back(Point(0, stemThickness));
  points.push_back(Point(1 - headWidth, stemThickness));
  points.push_back(Point(1 - headWidth, 1));
  points.push_back(Point(1, 0));

  return points;
}

KNPathPtr_t makePolyLine(const deque<Point> inputPoints, bool close = true)
{
  KNPathPtr_t path;

// need at least 2 points to make a polyline
  if (inputPoints.size() < 2)
    return path;

  // remove multiple points
  deque<Point> points;
  {
    deque<Point>::const_iterator first = inputPoints.begin();
    deque<Point>::const_iterator last = first;
    do
    {
      last = adjacent_find(first, inputPoints.end());
      copy(first, last, back_inserter(points));
      // skip the range of adjacent, equal points
      first = adjacent_find(last, inputPoints.end(), boost::bind(operator!=, _1, _2));
      if (inputPoints.end() != first)
        ++first;
    }
    while (first != inputPoints.end());
  }

  // close path if the first and last points are equal
  if (points.front() == points.back())
  {
    points.pop_back();
    close = true;
  }

// ... but there must be at least 3 points to make a closed path
  if (points.size() < 3)
    close = false;

// need at least 2 points to make a polyline
  if (points.size() < 2)
    return path;

  deque<Point>::const_iterator it = points.begin();
  path->appendMoveTo(it->x, it->y);
  ++it;
  for (; it != points.end(); ++it)
    path->appendLineTo(it->x, it->y);

  if (close)
    path->appendClose();

  return path;
}

struct TransformPoint
{
  TransformPoint(const KNTransformation &tr)
    : m_tr(tr)
  {
  }

  void operator()(Point &point) const
  {
    m_tr(point.x, point.y);
  }

private:
  const KNTransformation &m_tr;
};

void transform(deque<Point> &points, const KNTransformation &tr)
{
  for_each(points.begin(), points.end(), TransformPoint(tr));
}

}

KNPathPtr_t makePolygonPath(const KNSize &size, const unsigned edges)
{
  // user space canvas: [-1:1] x [-1:1]

  deque<Point> points = rotatePoint(Point(0, -1), edges);

  transform(points, translate(0, 1) * scale(0.5, 0.5) * scale(size.width, size.height));
  const KNPathPtr_t path = makePolyLine(points);

  return path;
}

KNPathPtr_t makeRoundedRectanglePath(const KNSize &size, const double radius)
{
  // TODO: implement me
  (void) size;
  (void) radius;
  return KNPathPtr_t();
}

KNPathPtr_t makeArrowPath(const KNSize &size, const double headWidth, const double stemThickness)
{
  deque<Point> points = drawArrowHalf(headWidth, stemThickness);

  // mirror around the x axis
{'fraction_non_alphanumeric': 0.14572983203217413, 'fraction_numerical': 0.009462976105985333, 'mean_word_length': 3.557951482479784, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '71073', 'n_tokens_mistral': 3120, 'n_tokens_neox': 3005, 'n_words': 827}