~ubuntu-branches/ubuntu/oneiric/kig/oneiric

« back to all changes in this revision

Viewing changes to objects/bezier_type.cc

  • Committer: Bazaar Package Importer
  • Author(s): Harald Sitter
  • Date: 2011-07-10 11:57:38 UTC
  • Revision ID: james.westby@ubuntu.com-20110710115738-gdjnn1kctr49lmy9
Tags: upstream-4.6.90+repack
Import upstream version 4.6.90+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C)  2009  Petr Gajdos <pgajdos@suse.cz>
 
2
 
 
3
// This program is free software; you can redistribute it and/or
 
4
// modify it under the terms of the GNU General Public License
 
5
// as published by the Free Software Foundation; either version 2
 
6
// of the License, or (at your option) any later version.
 
7
 
 
8
// This program is distributed in the hope that it will be useful,
 
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
// GNU General Public License for more details.
 
12
 
 
13
// You should have received a copy of the GNU General Public License
 
14
// along with this program; if not, write to the Free Software
 
15
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
16
// 02110-1301, USA.
 
17
 
 
18
#include "bezier_type.h"
 
19
 
 
20
#include <math.h>
 
21
 
 
22
#include "bogus_imp.h"
 
23
#include "line_imp.h"
 
24
#include "point_imp.h"
 
25
#include "text_imp.h"
 
26
#include "bezier_imp.h"
 
27
#include "object_calcer.h"
 
28
#include "special_imptypes.h"
 
29
 
 
30
#include "../misc/common.h"
 
31
 
 
32
#include <klocale.h>
 
33
#include <cmath>
 
34
#include <vector>
 
35
 
 
36
/*
 
37
 * Bézier curve of degree 2
 
38
 */
 
39
 
 
40
static const char bezier2_constructstatement[] = I18N_NOOP( "Construct a quadratic Bézier curve with this control point" );
 
41
static const char bezier2_constructstatement2[] = I18N_NOOP( "Select a point to be a control point of the new quadratic Bézier curve..." );
 
42
 
 
43
static const struct ArgsParser::spec argsspecBezier2[] =
 
44
{
 
45
  // mp: the central control point is not on the curve
 
46
  { PointImp::stype(), bezier2_constructstatement, bezier2_constructstatement2, true },
 
47
  { PointImp::stype(), bezier2_constructstatement, bezier2_constructstatement2, false },
 
48
  { PointImp::stype(), bezier2_constructstatement, bezier2_constructstatement2, true }
 
49
};
 
50
 
 
51
KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( BezierQuadricType )
 
52
 
 
53
BezierQuadricType::BezierQuadricType()
 
54
  : ArgsParserObjectType( "BezierQuadric", argsspecBezier2, 3 )
 
55
{
 
56
}
 
57
 
 
58
BezierQuadricType::~BezierQuadricType()
 
59
{
 
60
}
 
61
 
 
62
const BezierQuadricType* BezierQuadricType::instance()
 
63
{
 
64
  static const BezierQuadricType s;
 
65
  return &s;
 
66
}
 
67
 
 
68
ObjectImp* BezierQuadricType::calc( const Args& parents, const KigDocument& ) const
 
69
{
 
70
  if ( ! margsparser.checkArgs( parents, 3 ) ) return new InvalidImp;
 
71
  std::vector<Coordinate> points;
 
72
 
 
73
  for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i )
 
74
  {
 
75
    Coordinate point = static_cast<const PointImp*>( *i )->coordinate();
 
76
    points.push_back( point );
 
77
  }
 
78
  return new BezierImp( points );
 
79
}
 
80
 
 
81
const ObjectImpType* BezierQuadricType::resultId() const
 
82
{
 
83
  return BezierImp::stype2();
 
84
}
 
85
 
 
86
bool BezierQuadricType::canMove( const ObjectTypeCalcer& o ) const
 
87
{
 
88
  return isFreelyTranslatable( o );
 
89
}
 
90
 
 
91
bool BezierQuadricType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const
 
92
{
 
93
  std::vector<ObjectCalcer*> parents = o.parents();
 
94
  return parents[0]->isFreelyTranslatable() && 
 
95
         parents[1]->isFreelyTranslatable() &&
 
96
         parents[2]->isFreelyTranslatable();
 
97
}
 
98
 
 
99
void BezierQuadricType::move( ObjectTypeCalcer& o, const Coordinate& to,
 
100
                         const KigDocument& d ) const
 
101
{
 
102
  std::vector<ObjectCalcer*> parents = o.parents();
 
103
  assert( margsparser.checkArgs( parents ) );
 
104
  const Coordinate a = static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
 
105
  const Coordinate b = static_cast<const PointImp*>( parents[1]->imp() )->coordinate();
 
106
  const Coordinate c = static_cast<const PointImp*>( parents[2]->imp() )->coordinate();
 
107
  if ( parents[0]->canMove() )
 
108
    parents[0]->move( to, d );
 
109
  if ( parents[1]->canMove() )
 
110
    parents[1]->move( to + b - a, d );
 
111
  if ( parents[2]->canMove() )
 
112
    parents[2]->move( to + c - a, d );
 
113
}
 
114
 
 
115
const Coordinate BezierQuadricType::moveReferencePoint( const ObjectTypeCalcer& o ) const
 
116
{
 
117
  std::vector<ObjectCalcer*> parents = o.parents();
 
118
  assert( margsparser.checkArgs( parents ) );
 
119
  return static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
 
120
}
 
121
 
 
122
std::vector<ObjectCalcer*> BezierQuadricType::movableParents( const ObjectTypeCalcer& ourobj ) const
 
123
{
 
124
  std::vector<ObjectCalcer*> parents = ourobj.parents();
 
125
  std::set<ObjectCalcer*> ret;
 
126
  std::vector<ObjectCalcer*> tmp = parents[0]->movableParents();
 
127
  ret.insert( tmp.begin(), tmp.end() );
 
128
  tmp = parents[1]->movableParents();
 
129
  ret.insert( tmp.begin(), tmp.end() );
 
130
  tmp = parents[2]->movableParents();
 
131
  ret.insert( tmp.begin(), tmp.end() );
 
132
  ret.insert( parents.begin(), parents.end() );
 
133
  return std::vector<ObjectCalcer*>( ret.begin(), ret.end() );
 
134
}
 
135
 
 
136
/*
 
137
 * Bézier curve of degree 3
 
138
 */
 
139
 
 
140
static const char bezier3_constructstatement[] = I18N_NOOP( "Construct a cubic Bézier curve with this control point" );
 
141
static const char bezier3_constructstatement2[] = I18N_NOOP( "Select a point to be a control point of the new cubic Bézier curve..." );
 
142
 
 
143
static const struct ArgsParser::spec argsspecBezier3[] =
 
144
{
 
145
  { PointImp::stype(), bezier3_constructstatement, bezier3_constructstatement2, true },
 
146
  { PointImp::stype(), bezier3_constructstatement, bezier3_constructstatement2, false },
 
147
  { PointImp::stype(), bezier3_constructstatement, bezier3_constructstatement2, false },
 
148
  { PointImp::stype(), bezier3_constructstatement, bezier3_constructstatement2, true }
 
149
};
 
150
 
 
151
KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( BezierCubicType )
 
152
 
 
153
BezierCubicType::BezierCubicType()
 
154
  : ArgsParserObjectType( "BezierCubic", argsspecBezier3, 4 )
 
155
{
 
156
}
 
157
 
 
158
BezierCubicType::~BezierCubicType()
 
159
{
 
160
}
 
161
 
 
162
const BezierCubicType* BezierCubicType::instance()
 
163
{
 
164
  static const BezierCubicType s;
 
165
  return &s;
 
166
}
 
167
 
 
168
ObjectImp* BezierCubicType::calc( const Args& parents, const KigDocument& ) const
 
169
{
 
170
  if ( ! margsparser.checkArgs( parents, 4 ) ) return new InvalidImp;
 
171
  std::vector<Coordinate> points;
 
172
 
 
173
  for ( Args::const_iterator i = parents.begin(); i != parents.end(); ++i )
 
174
  {
 
175
    Coordinate point = static_cast<const PointImp*>( *i )->coordinate();
 
176
    points.push_back( point );
 
177
  }
 
178
  return new BezierImp( points );
 
179
}
 
180
 
 
181
const ObjectImpType* BezierCubicType::resultId() const
 
182
{
 
183
  return BezierImp::stype3();
 
184
}
 
185
 
 
186
bool BezierCubicType::canMove( const ObjectTypeCalcer& o ) const
 
187
{
 
188
  return isFreelyTranslatable( o );
 
189
}
 
190
 
 
191
bool BezierCubicType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const
 
192
{
 
193
  std::vector<ObjectCalcer*> parents = o.parents();
 
194
  return parents[0]->isFreelyTranslatable() && 
 
195
         parents[1]->isFreelyTranslatable() &&
 
196
         parents[2]->isFreelyTranslatable() &&
 
197
         parents[3]->isFreelyTranslatable();
 
198
}
 
199
 
 
200
void BezierCubicType::move( ObjectTypeCalcer& o, const Coordinate& to,
 
201
                         const KigDocument& d ) const
 
202
{
 
203
  std::vector<ObjectCalcer*> parents = o.parents();
 
204
  assert( margsparser.checkArgs( parents ) );
 
205
  const Coordinate a = static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
 
206
  const Coordinate b = static_cast<const PointImp*>( parents[1]->imp() )->coordinate();
 
207
  const Coordinate c = static_cast<const PointImp*>( parents[2]->imp() )->coordinate();
 
208
  const Coordinate e = static_cast<const PointImp*>( parents[3]->imp() )->coordinate();
 
209
  if ( parents[0]->canMove() )
 
210
    parents[0]->move( to, d );
 
211
  if ( parents[1]->canMove() )
 
212
    parents[1]->move( to + b - a, d );
 
213
  if ( parents[2]->canMove() )
 
214
    parents[2]->move( to + c - a, d );
 
215
  if ( parents[3]->canMove() )
 
216
    parents[3]->move( to + e - a, d );
 
217
}
 
218
 
 
219
const Coordinate BezierCubicType::moveReferencePoint( const ObjectTypeCalcer& o ) const
 
220
{
 
221
  std::vector<ObjectCalcer*> parents = o.parents();
 
222
  assert( margsparser.checkArgs( parents ) );
 
223
  return static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
 
224
}
 
225
 
 
226
std::vector<ObjectCalcer*> BezierCubicType::movableParents( const ObjectTypeCalcer& ourobj ) const
 
227
{
 
228
  std::vector<ObjectCalcer*> parents = ourobj.parents();
 
229
  std::set<ObjectCalcer*> ret;
 
230
  std::vector<ObjectCalcer*> tmp = parents[0]->movableParents();
 
231
  ret.insert( tmp.begin(), tmp.end() );
 
232
  tmp = parents[1]->movableParents();
 
233
  ret.insert( tmp.begin(), tmp.end() );
 
234
  tmp = parents[2]->movableParents();
 
235
  ret.insert( tmp.begin(), tmp.end() );
 
236
  ret.insert( parents.begin(), parents.end() );
 
237
  tmp = parents[3]->movableParents();
 
238
  ret.insert( tmp.begin(), tmp.end() );
 
239
  ret.insert( parents.begin(), parents.end() );
 
240
  return std::vector<ObjectCalcer*>( ret.begin(), ret.end() );
 
241
}
 
242
 
 
243
/*
 
244
 * generic Bézier curve
 
245
 */
 
246
 
 
247
KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( BezierCurveType )
 
248
 
 
249
BezierCurveType::BezierCurveType()
 
250
  : ObjectType( "BezierCurve" )
 
251
{
 
252
}
 
253
 
 
254
BezierCurveType::~BezierCurveType()
 
255
{
 
256
}
 
257
 
 
258
const BezierCurveType* BezierCurveType::instance()
 
259
{
 
260
  static const BezierCurveType s;
 
261
  return &s;
 
262
}
 
263
 
 
264
ObjectImp* BezierCurveType::calc( const Args& parents, const KigDocument& ) const
 
265
{
 
266
  uint count = parents.size();
 
267
  assert (count >= 3);
 
268
//  if ( parents[0] != parents[count] ) return new InvalidImp;
 
269
  std::vector<Coordinate> points;
 
270
 
 
271
  for ( uint i = 0; i < count; ++i )
 
272
  {
 
273
    if ( ! parents[i]->inherits( PointImp::stype() ) ) return new InvalidImp;
 
274
    Coordinate point = static_cast<const PointImp*>( parents[i] )->coordinate();
 
275
    points.push_back( point );
 
276
  }
 
277
  return new BezierImp( points );
 
278
}
 
279
 
 
280
const ObjectImpType* BezierCurveType::resultId() const
 
281
{
 
282
  return BezierImp::stype();
 
283
}
 
284
 
 
285
const ObjectImpType* BezierCurveType::impRequirement( const ObjectImp*, const Args& ) const
 
286
{
 
287
  return PointImp::stype();
 
288
}
 
289
 
 
290
bool BezierCurveType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const
 
291
{
 
292
  // TODO: this should result as true if this is the first or last control point, false otherwise
 
293
  // in the meantime it is better to leave it as false
 
294
  return false;  /* should be true? */
 
295
}
 
296
 
 
297
std::vector<ObjectCalcer*> BezierCurveType::sortArgs( const std::vector<ObjectCalcer*>& args ) const
 
298
{
 
299
  return args;  /* should already be in correct order */
 
300
}
 
301
 
 
302
Args BezierCurveType::sortArgs( const Args& args ) const
 
303
{
 
304
  return args;
 
305
}
 
306
 
 
307
bool BezierCurveType::canMove( const ObjectTypeCalcer& o ) const
 
308
{
 
309
  return isFreelyTranslatable( o );
 
310
}
 
311
 
 
312
bool BezierCurveType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const
 
313
{
 
314
  std::vector<ObjectCalcer*> parents = o.parents();
 
315
  for ( uint i = 0; i < parents.size(); ++i )
 
316
  {
 
317
    if ( !parents[i]->isFreelyTranslatable() ) return false;
 
318
  }
 
319
  return true;
 
320
}
 
321
 
 
322
void BezierCurveType::move( ObjectTypeCalcer& o, const Coordinate& to,
 
323
                         const KigDocument& d ) const
 
324
{
 
325
  std::vector<ObjectCalcer*> parents = o.parents();
 
326
  const Coordinate ref = static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
 
327
  for ( uint i = 0; i < parents.size(); ++i )
 
328
  {
 
329
     const Coordinate a = static_cast<const PointImp*>( parents[i]->imp() )->coordinate();
 
330
     parents[i]->move( to + a - ref, d );
 
331
  }
 
332
}
 
333
 
 
334
const Coordinate BezierCurveType::moveReferencePoint( const ObjectTypeCalcer& o
 
335
) const
 
336
{
 
337
  std::vector<ObjectCalcer*> parents = o.parents();
 
338
  return static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
 
339
}
 
340
 
 
341
std::vector<ObjectCalcer*> BezierCurveType::movableParents( const ObjectTypeCalcer& ourobj ) const
 
342
{
 
343
  std::vector<ObjectCalcer*> parents = ourobj.parents();
 
344
  std::set<ObjectCalcer*> ret;
 
345
  for ( uint i = 0; i < parents.size(); ++i )
 
346
  {
 
347
    std::vector<ObjectCalcer*> tmp = parents[i]->movableParents();
 
348
    ret.insert( tmp.begin(), tmp.end() );
 
349
  }
 
350
  ret.insert( parents.begin(), parents.end() );
 
351
  return std::vector<ObjectCalcer*>( ret.begin(), ret.end() );
 
352
}
 
353
 
 
354
/*
 
355
 * Rational Bézier curve of degree 2
 
356
 */
 
357
 
 
358
static const char rbezier2_constructstatement[] = I18N_NOOP( "Construct a quadratic rational Bézier curve with this control point" );
 
359
static const char rbezier2_constructstatement2[] = I18N_NOOP( "Select three points and three numeric values as weights to construct rational Bézier curve..." );
 
360
static const char rbezier2_constructstatement3[] = I18N_NOOP( "Select this value as weight" );
 
361
 
 
362
 
 
363
static const struct ArgsParser::spec argsspecRationalBezier2[] =
 
364
{
 
365
  { PointImp::stype(), rbezier2_constructstatement, rbezier2_constructstatement2, true },
 
366
  { &weightimptypeinstance, rbezier2_constructstatement3, rbezier2_constructstatement2, false },
 
367
  { PointImp::stype(), rbezier2_constructstatement, rbezier2_constructstatement2, false },
 
368
  { &weightimptypeinstance, rbezier2_constructstatement3, rbezier2_constructstatement2, false },
 
369
  { PointImp::stype(), rbezier2_constructstatement, rbezier2_constructstatement2, true },
 
370
  { &weightimptypeinstance, rbezier2_constructstatement3, rbezier2_constructstatement2, false }
 
371
};
 
372
 
 
373
KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( RationalBezierQuadricType )
 
374
 
 
375
RationalBezierQuadricType::RationalBezierQuadricType()
 
376
  : ArgsParserObjectType( "RationalBezierQuadric", argsspecRationalBezier2, 6 )
 
377
{
 
378
}
 
379
 
 
380
RationalBezierQuadricType::~RationalBezierQuadricType()
 
381
{
 
382
}
 
383
 
 
384
const RationalBezierQuadricType* RationalBezierQuadricType::instance()
 
385
{
 
386
  static const RationalBezierQuadricType s;
 
387
  return &s;
 
388
}
 
389
 
 
390
ObjectImp* RationalBezierQuadricType::calc( const Args& parents, const KigDocument& ) const
 
391
{
 
392
  if ( ! margsparser.checkArgs( parents, 6 ) ) return new InvalidImp;
 
393
  std::vector<Coordinate> points;
 
394
  std::vector<double> weights;
 
395
 
 
396
  for ( uint i = 0; i < 6; i += 2 )
 
397
  {
 
398
    bool valid;
 
399
    Coordinate point = static_cast<const PointImp*>( parents[i] )->coordinate();
 
400
    points.push_back( point );
 
401
    double value = getDoubleFromImp( parents[i+1], valid );
 
402
    if ( ! valid ) return new InvalidImp;
 
403
    weights.push_back( value );
 
404
  }
 
405
 
 
406
  return new RationalBezierImp( points, weights );
 
407
}
 
408
 
 
409
const ObjectImpType* RationalBezierQuadricType::resultId() const
 
410
{
 
411
  return RationalBezierImp::stype2();
 
412
}
 
413
 
 
414
bool RationalBezierQuadricType::canMove( const ObjectTypeCalcer& o ) const
 
415
{
 
416
  return isFreelyTranslatable( o );
 
417
}
 
418
 
 
419
bool RationalBezierQuadricType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const
 
420
{
 
421
  std::vector<ObjectCalcer*> parents = o.parents();
 
422
  return parents[0]->isFreelyTranslatable() && 
 
423
         parents[2]->isFreelyTranslatable() &&
 
424
         parents[4]->isFreelyTranslatable();
 
425
}
 
426
 
 
427
void RationalBezierQuadricType::move( ObjectTypeCalcer& o, const Coordinate& to,
 
428
                                      const KigDocument& d ) const
 
429
{
 
430
  std::vector<ObjectCalcer*> parents = o.parents();
 
431
  assert( margsparser.checkArgs( parents ) );
 
432
  const Coordinate a = static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
 
433
  const Coordinate b = static_cast<const PointImp*>( parents[2]->imp() )->coordinate();
 
434
  const Coordinate c = static_cast<const PointImp*>( parents[4]->imp() )->coordinate();
 
435
 
 
436
  if ( parents[0]->canMove() )
 
437
    parents[0]->move( to, d );
 
438
  if ( parents[2]->canMove() )
 
439
    parents[2]->move( to + b - a, d );
 
440
  if ( parents[4]->canMove() )
 
441
    parents[4]->move( to + c - a, d );
 
442
}
 
443
 
 
444
const Coordinate RationalBezierQuadricType::moveReferencePoint( const ObjectTypeCalcer& o ) const
 
445
{
 
446
  std::vector<ObjectCalcer*> parents = o.parents();
 
447
  assert( margsparser.checkArgs( parents ) );
 
448
  return static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
 
449
}
 
450
 
 
451
std::vector<ObjectCalcer*> RationalBezierQuadricType::movableParents( const ObjectTypeCalcer& ourobj ) const
 
452
{
 
453
  std::vector<ObjectCalcer*> parents = ourobj.parents();
 
454
  std::set<ObjectCalcer*> ret;
 
455
  std::vector<ObjectCalcer*> tmp = parents[0]->movableParents();
 
456
  ret.insert( tmp.begin(), tmp.end() );
 
457
  tmp = parents[2]->movableParents();
 
458
  ret.insert( tmp.begin(), tmp.end() );
 
459
  tmp = parents[4]->movableParents();
 
460
  ret.insert( tmp.begin(), tmp.end() );
 
461
  ret.insert( parents.begin(), parents.end() );
 
462
  return std::vector<ObjectCalcer*>( ret.begin(), ret.end() );
 
463
}
 
464
 
 
465
/*
 
466
 * Rational Bézier curve of degree 3
 
467
 */
 
468
 
 
469
static const char rbezier3_constructstatement[] = I18N_NOOP( "Construct a cubic rational Bézier curve with this control point" );
 
470
static const char rbezier3_constructstatement2[] = I18N_NOOP( "Select three points and three numeric values as weights to construct rational Bézier curve..." );
 
471
static const char rbezier3_constructstatement3[] = I18N_NOOP( "Select this value as weight" );
 
472
 
 
473
 
 
474
static const struct ArgsParser::spec argsspecRationalBezier3[] =
 
475
{
 
476
  { PointImp::stype(), rbezier3_constructstatement, rbezier3_constructstatement2, true },
 
477
  { &weightimptypeinstance, rbezier3_constructstatement3, rbezier3_constructstatement2, false },
 
478
  { PointImp::stype(), rbezier3_constructstatement, rbezier3_constructstatement2, false },
 
479
  { &weightimptypeinstance, rbezier3_constructstatement3, rbezier3_constructstatement2, false },
 
480
  { PointImp::stype(), rbezier3_constructstatement, rbezier3_constructstatement2, false },
 
481
  { &weightimptypeinstance, rbezier3_constructstatement3, rbezier3_constructstatement2, false },
 
482
  { PointImp::stype(), rbezier3_constructstatement, rbezier3_constructstatement2, true },
 
483
  { &weightimptypeinstance, rbezier3_constructstatement3, rbezier3_constructstatement2, false }
 
484
};
 
485
 
 
486
KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( RationalBezierCubicType )
 
487
 
 
488
RationalBezierCubicType::RationalBezierCubicType()
 
489
  : ArgsParserObjectType( "RationalBezierCubic", argsspecRationalBezier3, 8 )
 
490
{
 
491
}
 
492
 
 
493
RationalBezierCubicType::~RationalBezierCubicType()
 
494
{
 
495
}
 
496
 
 
497
const RationalBezierCubicType* RationalBezierCubicType::instance()
 
498
{
 
499
  static const RationalBezierCubicType s;
 
500
  return &s;
 
501
}
 
502
 
 
503
ObjectImp* RationalBezierCubicType::calc( const Args& parents, const KigDocument& ) const
 
504
{
 
505
  if ( ! margsparser.checkArgs( parents, 8 ) ) return new InvalidImp;
 
506
  std::vector<Coordinate> points;
 
507
  std::vector<double> weights;
 
508
 
 
509
  for ( uint i = 0; i < 8; i += 2 )
 
510
  {
 
511
    bool valid;
 
512
    Coordinate point = static_cast<const PointImp*>( parents[i] )->coordinate();
 
513
    points.push_back( point );
 
514
    double value = getDoubleFromImp( parents[i+1], valid );
 
515
    if ( ! valid ) return new InvalidImp;
 
516
    weights.push_back( value );
 
517
  }
 
518
 
 
519
  return new RationalBezierImp( points, weights );
 
520
}
 
521
 
 
522
const ObjectImpType* RationalBezierCubicType::resultId() const
 
523
{
 
524
  return RationalBezierImp::stype3();
 
525
}
 
526
 
 
527
bool RationalBezierCubicType::canMove( const ObjectTypeCalcer& o ) const
 
528
{
 
529
  return isFreelyTranslatable( o );
 
530
}
 
531
 
 
532
bool RationalBezierCubicType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const
 
533
{
 
534
  std::vector<ObjectCalcer*> parents = o.parents();
 
535
  return parents[0]->isFreelyTranslatable() && 
 
536
         parents[2]->isFreelyTranslatable() &&
 
537
         parents[4]->isFreelyTranslatable() &&
 
538
         parents[6]->isFreelyTranslatable();
 
539
}
 
540
 
 
541
void RationalBezierCubicType::move( ObjectTypeCalcer& o, const Coordinate& to,
 
542
                         const KigDocument& d ) const
 
543
{
 
544
  std::vector<ObjectCalcer*> parents = o.parents();
 
545
  assert( margsparser.checkArgs( parents ) );
 
546
  const Coordinate a = static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
 
547
  const Coordinate b = static_cast<const PointImp*>( parents[2]->imp() )->coordinate();
 
548
  const Coordinate c = static_cast<const PointImp*>( parents[4]->imp() )->coordinate();
 
549
  const Coordinate e = static_cast<const PointImp*>( parents[6]->imp() )->coordinate();
 
550
  if ( parents[0]->canMove() )
 
551
    parents[0]->move( to, d );
 
552
  if ( parents[2]->canMove() )
 
553
    parents[2]->move( to + b - a, d );
 
554
  if ( parents[4]->canMove() )
 
555
    parents[4]->move( to + c - a, d );
 
556
  if ( parents[6]->canMove() )
 
557
    parents[6]->move( to + e - a, d );
 
558
}
 
559
 
 
560
const Coordinate RationalBezierCubicType::moveReferencePoint( const ObjectTypeCalcer& o ) const
 
561
{
 
562
  std::vector<ObjectCalcer*> parents = o.parents();
 
563
  assert( margsparser.checkArgs( parents ) );
 
564
  return static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
 
565
}
 
566
 
 
567
std::vector<ObjectCalcer*> RationalBezierCubicType::movableParents( const ObjectTypeCalcer& ourobj ) const
 
568
{
 
569
  std::vector<ObjectCalcer*> parents = ourobj.parents();
 
570
  std::set<ObjectCalcer*> ret;
 
571
  std::vector<ObjectCalcer*> tmp = parents[0]->movableParents();
 
572
  ret.insert( tmp.begin(), tmp.end() );
 
573
  tmp = parents[2]->movableParents();
 
574
  ret.insert( tmp.begin(), tmp.end() );
 
575
  tmp = parents[4]->movableParents();
 
576
  ret.insert( tmp.begin(), tmp.end() );
 
577
  ret.insert( parents.begin(), parents.end() );
 
578
  tmp = parents[6]->movableParents();
 
579
  ret.insert( tmp.begin(), tmp.end() );
 
580
  ret.insert( parents.begin(), parents.end() );
 
581
  return std::vector<ObjectCalcer*>( ret.begin(), ret.end() );
 
582
}
 
583
 
 
584
 
 
585
/*
 
586
 * generic rational Bézier curve
 
587
 */
 
588
 
 
589
KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( RationalBezierCurveType )
 
590
 
 
591
RationalBezierCurveType::RationalBezierCurveType()
 
592
  : ObjectType( "RationalBezierCurve" )
 
593
{
 
594
}
 
595
 
 
596
RationalBezierCurveType::~RationalBezierCurveType()
 
597
{
 
598
}
 
599
 
 
600
const RationalBezierCurveType* RationalBezierCurveType::instance()
 
601
{
 
602
  static const RationalBezierCurveType s;
 
603
  return &s;
 
604
}
 
605
 
 
606
ObjectImp* RationalBezierCurveType::calc( const Args& parents, const KigDocument& ) const
 
607
{
 
608
  uint count = parents.size();
 
609
  std::vector<Coordinate> points;
 
610
  std::vector<double> weights;
 
611
 
 
612
  assert ( count % 2 == 0 );
 
613
 
 
614
  for ( uint i = 0; i < count; i += 2 )
 
615
  {
 
616
    bool valid;
 
617
    Coordinate point = static_cast<const PointImp*>( parents[i] )->coordinate();
 
618
    points.push_back( point );
 
619
    double value = getDoubleFromImp( parents[i+1], valid );
 
620
    if ( ! valid ) return new InvalidImp;
 
621
    weights.push_back( value );
 
622
  }
 
623
 
 
624
  return new RationalBezierImp( points, weights );
 
625
}
 
626
 
 
627
const ObjectImpType* RationalBezierCurveType::resultId() const
 
628
{
 
629
  return RationalBezierImp::stype();
 
630
}
 
631
 
 
632
const ObjectImpType* RationalBezierCurveType::impRequirement( const ObjectImp*, const Args& ) const
 
633
{
 
634
  return PointImp::stype();
 
635
}
 
636
 
 
637
bool RationalBezierCurveType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const
 
638
{
 
639
  // TODO: this should result as true if this is the first or last control point, false otherwise
 
640
  // in the meantime it is better to leave it as false
 
641
  return false;  /* should be true? */
 
642
}
 
643
 
 
644
std::vector<ObjectCalcer*> RationalBezierCurveType::sortArgs( const std::vector<ObjectCalcer*>& args ) const
 
645
{
 
646
  return args;  /* should already be in correct order */
 
647
}
 
648
 
 
649
Args RationalBezierCurveType::sortArgs( const Args& args ) const
 
650
{
 
651
  return args;
 
652
}
 
653
 
 
654
bool RationalBezierCurveType::canMove( const ObjectTypeCalcer& o ) const
 
655
{
 
656
  return isFreelyTranslatable( o );
 
657
}
 
658
 
 
659
bool RationalBezierCurveType::isFreelyTranslatable( const ObjectTypeCalcer& o ) const
 
660
{
 
661
  std::vector<ObjectCalcer*> parents = o.parents();
 
662
  for ( uint i = 0; i < parents.size(); i += 2 )
 
663
  {
 
664
    if ( !parents[i]->isFreelyTranslatable() ) return false;
 
665
  }
 
666
  return true;
 
667
}
 
668
 
 
669
void RationalBezierCurveType::move( ObjectTypeCalcer& o, const Coordinate& to,
 
670
                                 const KigDocument& d ) const
 
671
{
 
672
  std::vector<ObjectCalcer*> parents = o.parents();
 
673
  const Coordinate ref = static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
 
674
  for ( uint i = 0; i < parents.size(); i += 2 )
 
675
  {
 
676
     const Coordinate a = static_cast<const PointImp*>( parents[i]->imp() )->coordinate();
 
677
     parents[i]->move( to + a - ref, d );
 
678
  }
 
679
}
 
680
 
 
681
const Coordinate RationalBezierCurveType::moveReferencePoint( const ObjectTypeCalcer& o
 
682
) const
 
683
{
 
684
  std::vector<ObjectCalcer*> parents = o.parents();
 
685
  return static_cast<const PointImp*>( parents[0]->imp() )->coordinate();
 
686
}
 
687
 
 
688
std::vector<ObjectCalcer*> RationalBezierCurveType::movableParents( const ObjectTypeCalcer& ourobj ) const
 
689
{
 
690
  std::vector<ObjectCalcer*> parents = ourobj.parents();
 
691
  std::set<ObjectCalcer*> ret;
 
692
  for ( uint i = 0; i < parents.size(); i += 2 )
 
693
  {
 
694
    std::vector<ObjectCalcer*> tmp = parents[i]->movableParents();
 
695
    ret.insert( tmp.begin(), tmp.end() );
 
696
  }
 
697
  ret.insert( parents.begin(), parents.end() );
 
698
  return std::vector<ObjectCalcer*>( ret.begin(), ret.end() );
 
699
}
 
700