path.cpp revision cccfdbab6a36d7ea9f8d34125a609db06d870dd6
/** @file
* @brief Path - a sequence of contiguous curves (implementation file)
*//*
* Authors:
* MenTaLguY <mental@rydia.net>
* Marco Cecchetti <mrcekets at gmail.com>
* Krzysztof KosiĆski <tweenk.pl@gmail.com>
*
* Copyright 2007-2014 authors
*
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*/
#include <algorithm>
#include <limits>
using namespace Geom::PathInternal;
namespace Geom {
// this represents an empty interval
: _from(0, 0.0)
, _to(0, 0.0)
, _path_size(1)
, _cross_start(false)
, _reverse(false)
{}
PathInterval::PathInterval(Position const &from, Position const &to, bool cross_start, size_type path_size)
{
if (_reverse) {
}
} else {
}
}
_reverse = false;
_cross_start = false;
}
}
if (_cross_start) {
if (_reverse) {
} else {
}
} else {
if (_reverse) {
} else {
}
}
}
{
// If there is some node further than min_dist (in time coord) from the ends,
// return that node. Otherwise, return the middle.
return result;
}
// If _cross_start, then we can be sure that at least one node is in the domain.
// If dcurve == 0, it actually means that all curves are included in the domain
if (_reverse) {
if (dcurve == 0) {
dcurve = _path_size;
}
if (dcurve == 1) {
if (from_close || to_close) {
if (tmid < 0) {
tmid += 1;
}
return result;
}
return result;
}
if (to_close) {
if (dcurve == 2) {
result.t = 0.5;
} else {
}
}
return result;
} else {
if (dcurve == 0) {
dcurve = _path_size;
}
if (dcurve == 1) {
if (from_close || to_close) {
if (tmid >= 1) {
tmid -= 1;
}
return result;
}
return result;
}
if (from_close) {
if (dcurve == 2) {
result.t = 0.5;
} else {
}
}
return result;
}
return result;
}
PathInterval PathInterval::from_direction(Position const &from, Position const &to, bool reversed, size_type path_size)
{
if (reversed) {
}
} else {
}
}
result._cross_start = false;
} else {
if (reversed) {
} else {
}
}
return result;
}
, _closed(false)
, _exception_on_stitch(true)
{
return;
}
}
_closed = true;
}
{
_unshare();
_closed = false;
}
{
if (empty())
return bounds;
// the closing path segment can be ignored, because it will always lie within the bbox of the rest of the path
}
}
return bounds;
}
{
if (empty())
return bounds;
// the closing path segment can be ignored, because it will always lie within the bbox of the rest of the path
}
}
return bounds;
}
{
unsigned i = 1;
bool degenerate = true;
// pw<d2<>> is always open. so if path is closed, add closing segment as well to pwd2.
if (!it->isDegenerate()) {
degenerate = false;
}
}
if (degenerate) {
// if path only contains degenerate curves, no second cut is added
// so we need to create at least one segment manually
}
return ret;
}
template <typename iter>
for (unsigned i = 0; i < n; i++)
ret++;
return ret;
}
{
if (this == &other)
return true;
return false;
}
{
_unshare();
}
_closing_seg->transform(m);
return *this;
}
clear();
}
_closing_seg->setInitial(p);
_closing_seg->setFinal(p);
}
{
return ret;
}
{
if (rest) {
}
}
{
return pointAt(_getPosition(t));
}
{
return valueAt(_getPosition(t), d);
}
{
}
{
}
{
}
{
for (unsigned i = 0; i <= size(); i++) {
}
return res;
}
{
// TODO: sweepline optimization
// TODO: remove multiple intersections within precision of each other?
}
}
}
return result;
}
int wind = 0;
/* To handle all the edge cases, we consider the maximum Y edge of the bounding box
* as not included in box. This way paths that contain linear horizontal
* segments will be treated correctly. */
// Ray doesn't intersect bbox, so we ignore this segment
continue;
}
/* Ray intersects the curve's bbox, but the point is outside it.
* The winding contribution is exactly the same as that
* of a linear segment with the same initial and final points. */
if (eqbox[Y].lowerContains(p[Y])) {
/* The ray intersects the equivalent linear segment.
* Determine winding contribution based on its derivative. */
wind += 1;
wind -= 1;
} else {
// should never happen, because bounds.height() was not zero
assert(false);
}
}
} else {
// point is inside bbox
}
}
return wind;
}
{
// TODO from and to are not used anywhere.
// rewrite this to simplify.
++sz;
THROW_RANGEERROR("[from,to] interval out of bounds");
}
--si;
st = 1;
}
--ei;
et = 1;
}
for (unsigned int i = 0; i < all_nearest.size(); ++i) {
}
return all_nearest;
}
double dsq;
continue;
}
}
}
return all_t;
}
}
}
}
return all_nearest;
}
{
// return a single nearest time for each curve in this path
}
return np;
}
{
}
{
// naked moveto
ret.curve_index = 0;
ret.t = 0;
if (dist) {
}
return ret;
}
for (size_type i = 0; i < size_default(); ++i) {
Coord t = c.nearestTime(p);
if (d < mindist) {
mindist = d;
ret.curve_index = i;
ret.t = t;
}
}
if (dist) {
}
return ret;
}
{
THROW_RANGEERROR("from and to must be >=0 in Path::appendPortionTo");
}
if (to == 0)
return;
}
if (tf == 0) {
ti--;
tf = 1;
}
return;
}
if (ff != 1.) {
// fromv->setInitial(ret.finalPoint());
}
++ender;
} else {
}
}
{
if (ival.isDegenerate()) {
return;
}
size_type s = size_closed();
if (p_from) {
c->setInitial(*p_from);
}
if (p_to) {
}
} else {
if (p_from) {
}
i = (i + s + di) % s)
{
if (reverse) {
} else {
}
}
if (p_to) {
}
}
}
{
}
return ret;
}
{
_unshare();
}
{
_unshare();
}
{
_unshare();
}
{
if (_exception_on_stitch) {
}
_unshare();
}
}
{
}
{
_unshare();
}
{
}
{
}
{
if (!_closed) return;
_unshare();
}
}
// replace curves between first and last with contents of source,
//
{
// TODO: handle cases where first > last in closed paths?
// special case:
// if do_update replaces the closing segment, we have to regenerate it
// only removing some segments
if ((!_closed && first == _curves->begin()) || (!_closed && last == _curves->end() - 1) || last_beyond_closing_segment) {
// just adjust the closing segment
// do nothing
if (_exception_on_stitch) {
}
}
} else {
// replacing
// special case: replacing everything should work the same in open and closed curves
return;
}
// stitch in front
// not necessary to stitch in front
if (_exception_on_stitch) {
}
source.insert(source.begin(), new StitchSegment(first->initialPoint(), source.front().initialPoint()));
}
// stitch at the end
// repurpose the closing segment as the stitch segment
// do nothing
if (_exception_on_stitch) {
}
}
}
// do not erase the closing segment, adjust it instead
if (last_beyond_closing_segment) {
--last;
}
// adjust closing segment
if (size_open() == 0) {
} else {
}
}
{
} else {
// if we can't freely move the closing segment, we check whether
// the new curve connects with the last non-closing curve
}
}
}
void Path::checkContinuity() const
{
++j;
if (i->finalPoint() != j->initialPoint()) {
}
}
}
}
{
if (t < 0 || t > sz) {
THROW_RANGEERROR("parameter t out of bounds");
}
Coord k;
ret.curve_index = k;
--ret.curve_index;
ret.t = 1;
}
return ret;
}
{
}
return ret;
}
} // end namespace Geom
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :