2 This file is part of Kig, a KDE program for Interactive Geometry...
3 Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 #include "kgeo-filter.h"
23 #include "kgeo-resource.h"
24 #include "filters-common.h"
26 #include "../kig/kig_part.h"
27 #include "../kig/kig_document.h"
28 #include "../objects/angle_type.h"
29 #include "../objects/bogus_imp.h"
30 #include "../objects/circle_imp.h"
31 #include "../objects/circle_type.h"
32 #include "../objects/intersection_types.h"
33 #include "../objects/line_type.h"
34 #include "../objects/object_calcer.h"
35 #include "../objects/object_drawer.h"
36 #include "../objects/object_factory.h"
37 #include "../objects/object_holder.h"
38 #include "../objects/other_type.h"
39 #include "../objects/point_imp.h"
40 #include "../objects/point_type.h"
41 #include "../objects/text_type.h"
42 #include "../objects/transform_types.h"
43 #include "../objects/vector_type.h"
45 #include <ksimpleconfig.h>
50 bool KigFilterKGeo::supportMime( const QString
& mime
)
52 return mime
== "application/x-kgeo";
55 KigDocument
* KigFilterKGeo::load( const QString
& sFrom
)
57 // kgeo uses a KSimpleConfig to save its contents...
58 KSimpleConfig
config ( sFrom
);
60 loadMetrics ( &config
);
61 return loadObjects ( sFrom
, &config
);
64 void KigFilterKGeo::loadMetrics(KSimpleConfig
* c
)
67 xMax
= c
->readNumEntry("XMax", 16);
68 yMax
= c
->readNumEntry("YMax", 11);
69 grid
= c
->readBoolEntry( "Grid", true );
70 axes
= c
->readBoolEntry( "Axes", true );
71 // the rest is not relevant to us (yet ?)...
74 struct KGeoHierarchyElement
77 std::vector
<int> parents
;
80 static void visitElem( std::vector
<KGeoHierarchyElement
>& ret
,
81 const std::vector
<KGeoHierarchyElement
>& elems
,
82 std::vector
<bool>& seen
,
87 for ( uint j
= 0; j
< elems
[i
].parents
.size(); ++j
)
88 visitElem( ret
, elems
, seen
, elems
[i
].parents
[j
] );
89 ret
.push_back( elems
[i
] );
94 static std::vector
<KGeoHierarchyElement
> sortElems( const std::vector
<KGeoHierarchyElement
> elems
)
96 std::vector
<KGeoHierarchyElement
> ret
;
97 std::vector
<bool> seenElems( elems
.size(), false );
98 for ( uint i
= 0; i
< elems
.size(); ++i
)
99 visitElem( ret
, elems
, seenElems
, i
);
103 KigDocument
* KigFilterKGeo::loadObjects( const QString
& file
, KSimpleConfig
* c
)
105 KigDocument
* ret
= new KigDocument();
112 int number
= c
->readNumEntry ("Number");
114 // first we determine the parent relationships, and sort the
115 // elements in an order that we can be sure all of an object's
116 // parents will have been handled before it is handled itself..
117 // ( aka topological sort of the parent relations graph..
118 std::vector
<KGeoHierarchyElement
> elems
;
119 elems
.reserve( number
);
121 for ( int i
= 0; i
< number
; ++i
)
123 KGeoHierarchyElement elem
;
125 group
.setNum( i
+ 1 );
126 group
.prepend( "Object " );
127 c
->setGroup( group
);
129 c
->readListEntry( "Parents", parents
);
130 elems
.push_back( elem
);
131 for ( const char* parent
= parents
.first(); parent
; parent
= parents
.next() )
133 int parentIndex
= QString::fromLatin1( parent
).toInt( &ok
);
134 if ( ! ok
) KIG_FILTER_PARSE_ERROR
;
135 if ( parentIndex
!= 0 )
136 elems
[i
].parents
.push_back( parentIndex
- 1 );
140 std::vector
<KGeoHierarchyElement
> sortedElems
= sortElems( elems
);
141 std::vector
<ObjectHolder
*> os
;
142 os
.resize( number
, 0 );
143 const ObjectFactory
* factory
= ObjectFactory::instance();
145 // now we iterate over the elems again in the newly determined
147 for ( uint i
= 0; i
< sortedElems
.size(); ++i
)
149 const KGeoHierarchyElement
& e
= sortedElems
[i
];
151 group
.setNum( id
+ 1 );
152 group
.prepend( "Object " );
153 c
->setGroup( group
);
154 int objID
= c
->readNumEntry( "Geo" );
156 std::vector
<ObjectCalcer
*> parents
;
157 for ( uint j
= 0; j
< e
.parents
.size(); ++j
)
159 int parentid
= e
.parents
[j
];
160 parents
.push_back( os
[parentid
]->calcer() );
168 // fetch the coordinates...
169 QString strX
= c
->readEntry("QPointX");
170 QString strY
= c
->readEntry("QPointY");
171 double x
= strX
.toDouble(&ok
);
172 if (!ok
) KIG_FILTER_PARSE_ERROR
;
173 double y
= strY
.toDouble(&ok
);
174 if (!ok
) KIG_FILTER_PARSE_ERROR
;
175 Coordinate
m( x
, y
);
176 uint nparents
= parents
.size();
178 o
= factory
->fixedPointCalcer( m
);
179 else if ( nparents
== 1 )
180 o
= factory
->constrainedPointCalcer( parents
[0], m
, *ret
);
182 KIG_FILTER_PARSE_ERROR
;
187 o
= new ObjectTypeCalcer( SegmentABType::instance(), parents
);
192 o
= new ObjectTypeCalcer( CircleBCPType::instance(), parents
);
197 o
= new ObjectTypeCalcer( LineABType::instance(), parents
);
202 // if this is the bisection of two points, first build a segment
204 if ( parents
.size() == 2 )
206 ObjectTypeCalcer
* seg
= new ObjectTypeCalcer( SegmentABType::instance(), parents
);
208 parents
.push_back( seg
);
210 if ( parents
.size() != 1 ) KIG_FILTER_PARSE_ERROR
;
211 o
= factory
->propertyObjectCalcer( parents
[0], "mid-point" );
214 case ID_perpendicular
:
216 o
= new ObjectTypeCalcer( LinePerpendLPType::instance(), parents
);
221 o
= new ObjectTypeCalcer( LineParallelLPType::instance(), parents
);
226 o
= new ObjectTypeCalcer( VectorType::instance(), parents
);
231 o
= new ObjectTypeCalcer( RayABType::instance(), parents
);
236 o
= new ObjectTypeCalcer( TranslatedType::instance(), parents
);
241 o
= new ObjectTypeCalcer( PointReflectionType::instance(), parents
);
246 o
= new ObjectTypeCalcer( LineLineIntersectionType::instance(), parents
);
251 bool frame
= c
->readBoolEntry( "Frame" );
252 double x
= c
->readDoubleNumEntry( "TextRectCenterX" );
253 double y
= c
->readDoubleNumEntry( "TextRectCenterY" );
254 QString text
= c
->readEntry( "TextRectEntry" );
255 double height
= c
->readNumEntry( "TextRectHeight" );
256 double width
= c
->readNumEntry( "TextRectWidth" );
257 // we don't want the center, but the top left..
260 o
= factory
->labelCalcer(
261 text
, Coordinate( x
, y
), frame
, std::vector
<ObjectCalcer
*>(), *ret
);
266 double r
= c
->readDoubleNumEntry( "Radius" );
267 parents
.push_back( new ObjectConstCalcer( new DoubleImp( r
) ) );
268 o
= new ObjectTypeCalcer( CircleBPRType::instance(), parents
);
273 if ( parents
.size() == 3 )
275 ObjectTypeCalcer
* ao
= new ObjectTypeCalcer( AngleType::instance(), parents
);
278 parents
.push_back( ao
);
280 if ( parents
.size() != 1 ) KIG_FILTER_PARSE_ERROR
;
281 ObjectCalcer
* angle
= parents
[0];
284 static_cast<const PointImp
*>( angle
->parents()[1]->imp() )->coordinate();
285 o
= filtersConstructTextObject( c
, angle
, "angle-degrees", *ret
, true );
290 if ( parents
.size() != 2 ) KIG_FILTER_PARSE_ERROR
;
291 ObjectTypeCalcer
* segment
= new ObjectTypeCalcer( SegmentABType::instance(), parents
);
292 segment
->calc( *ret
);
293 Coordinate m
= ( static_cast<const PointImp
*>( parents
[0]->imp() )->coordinate() +
294 static_cast<const PointImp
*>( parents
[1]->imp() )->coordinate() ) / 2;
295 o
= filtersConstructTextObject( m
, segment
, "length", *ret
, true );
300 o
= new ObjectTypeCalcer( AngleType::instance(), parents
);
305 if ( parents
.size() != 1 ) KIG_FILTER_PARSE_ERROR
;
306 const CircleImp
* circle
= static_cast<const CircleImp
*>( parents
[0]->imp() );
307 const Coordinate c
= circle
->center() + Coordinate( circle
->radius(), 0 );
308 o
= filtersConstructTextObject( c
, parents
[0], "surface", *ret
, true );
313 // if parents contains a segment, line, vector or whatever, we
314 // take its parents cause we want points..
315 if ( parents
.size() == 1 ) parents
= parents
[0]->parents();
316 if ( parents
.size() != 2 ) KIG_FILTER_PARSE_ERROR
;
317 const Coordinate c
= (
318 static_cast<const PointImp
*>( parents
[0]->imp() )->coordinate() +
319 static_cast<const PointImp
*>( parents
[1]->imp() )->coordinate() ) / 2;
320 ObjectTypeCalcer
* line
= new ObjectTypeCalcer( LineABType::instance(), parents
);
322 o
= filtersConstructTextObject( c
, line
, "slope", *ret
, true );
325 case ID_circumference
:
327 if ( parents
.size() != 1 ) KIG_FILTER_PARSE_ERROR
;
328 const CircleImp
* c
= static_cast<const CircleImp
*>( parents
[0]->imp() );
329 const Coordinate m
= c
->center() + Coordinate( c
->radius(), 0 );
330 o
= filtersConstructTextObject( m
, parents
[0], "circumference", *ret
, true );
335 // in kig, the rotated object should be last..
336 ObjectCalcer
* t
= parents
[2];
337 parents
[2] = parents
[0];
339 o
= new ObjectTypeCalcer( RotationType::instance(), parents
);
343 KIG_FILTER_PARSE_ERROR
;
347 QColor co
= c
->readColorEntry( "Color" );
350 ObjectDrawer
* d
= new ObjectDrawer( co
);
352 os
[i
] = new ObjectHolder( o
, d
);
354 }; // for loop (creating KGeoHierarchyElements..
356 ret
->addObjects( os
);
357 ret
->setGrid( grid
);
358 ret
->setAxes( axes
);
362 KigFilterKGeo::KigFilterKGeo()
366 KigFilterKGeo::~KigFilterKGeo()
370 KigFilterKGeo
* KigFilterKGeo::instance()
372 static KigFilterKGeo f
;