diff --git a/icons/22-actions-segment_golden_point.png b/icons/22-actions-segment_golden_point.png new file mode 100644 index 00000000..e69de29b diff --git a/icons/32-actions-segment_golden_point.png b/icons/32-actions-segment_golden_point.png new file mode 100644 index 00000000..e69de29b diff --git a/icons/CMakeLists.txt b/icons/CMakeLists.txt index a28ecbea..446cf1f1 100644 --- a/icons/CMakeLists.txt +++ b/icons/CMakeLists.txt @@ -1,279 +1,282 @@ ecm_install_icons(ICONS 32-actions-square.png 22-actions-intersection.png 22-actions-centerofcurvature.png 22-actions-rbezier4.png sc-actions-conicasymptotes.svgz 22-actions-point.png 32-actions-coniclineintersection.png 32-actions-translation.png 32-actions-tangent.png sc-actions-conicb5p.svgz 22-actions-rbezier3.png sc-actions-square.svgz sc-actions-bisection.svgz 32-actions-perpendicular.png 22-actions-perpendicular.png 32-actions-circlebps.png sc-actions-segment_midpoint.svgz + sc-actions-segment_golden_point.svgz 32-actions-genericaffinity.png sc-actions-bezier4.svgz 32-actions-ellipsebffp.png 22-actions-convexhull.png sc-actions-circlelineintersection.svgz 32-actions-inversion.png sc-actions-equilateralhyperbolab4p.svgz sc-actions-bezier3.svgz 16-actions-kig_xfig.png 32-actions-directrix.png sc-actions-distance.svgz 22-actions-similitude.png 22-actions-bezierN.png 32-actions-rbezier4.png 22-actions-inversion.png 22-actions-distance.png 32-actions-rotation.png 32-actions-segmentaxis.png sc-actions-paint.svgz 22-actions-bisection.png 32-actions-hexagonbcv.png sc-actions-sizer.svgz 32-actions-curvelineintersection.png 32-actions-convexhull.png sc-actions-centerofcurvature.svgz sc-actions-inversion.svgz 32-actions-locus.png 32-actions-areaCircle.png sc-actions-harmonichomology.svgz 22-actions-kig_polygon.png 22-actions-vectordifference.png sc-actions-rbezier3.svgz 22-actions-hexagonbcv.png 32-actions-kig_polygon.png 32-actions-triangle.png 32-actions-rbezierN.png sc-actions-hyperbolabffp.svgz 32-actions-pointOnLine.png 22-actions-line.png 22-actions-segment.png 22-actions-circlelineintersection.png 22-actions-circlebpd.png 32-actions-bezier4.png 32-actions-bisection.png sc-actions-curvelineintersection.svgz 32-actions-vector.png 22-actions-vector.png 32-actions-stretch.png 22-actions-vectorsum.png 22-actions-arc_center.png 22-actions-arc.png 22-actions-view_fit_to_page.png sc-actions-parallel.svgz 32-actions-python.png sc-actions-circlebcp.svgz 22-actions-polygonvertices.png sc-actions-perpendicular.svgz sc-actions-line.svgz 32-actions-parallel.png 32-actions-arc.png 32-actions-openpolygon.png 22-actions-segmentaxis.png sc-actions-tangent.svgz 32-actions-testcollinear.png sc-actions-test.svgz 32-actions-kig_numericvalue.png 32-actions-attacher.png sc-actions-baseCircle.svgz 32-actions-w.png 22-actions-angle_bisector.png 32-actions-equitriangle.png 22-actions-attacher.png sc-actions-attacher.svgz 32-actions-genericprojectivity.png 32-actions-circlebcl.png sc-actions-rbezierN.svgz sc-actions-testdistance.svgz 22-actions-harmonichomology.png 32-actions-conicasymptotes.png 22-actions-coniclineintersection.png 22-actions-slope.png sc-actions-testorthogonal.svgz 32-actions-angle_bisector.png 22-actions-circlebcl.png 32-actions-arc_center.png 22-actions-controlpolygon.png sc-actions-hexagonbcv.svgz sc-actions-segmentaxis.svgz 32-actions-parabolabtp.png sc-actions-vectordifference.svgz sc-actions-areaCircle.svgz 22-actions-baseCircle.png 32-actions-linebyvector.png 22-actions-sizer.png 22-actions-bezier3.png sc-actions-conicsradicalline.svgz 22-actions-square.png 22-actions-genericaffinity.png 32-actions-testcontains.png 22-actions-segment_midpoint.png + 22-actions-segment_golden_point.png 32-actions-kig_text.png 22-actions-conicasymptotes.png 22-actions-directrix.png sc-actions-circlebpd.svgz 22-actions-locus.png 22-actions-ray.png sc-actions-polygonsides.svgz 22-actions-w.png 22-actions-circumference.png sc-actions-centralsymmetry.svgz 32-actions-bezierN.png 32-actions-circumference.png 32-actions-point.png 22-actions-equilateralhyperbolab4p.png 32-actions-paint.png sc-actions-directrix.svgz 22-actions-python.png 22-actions-testdistance.png 22-actions-conicsradicalline.png 32-actions-halflinebyvector.png 22-actions-areaCircle.png sc-actions-kig_numericvalue.svgz sc-actions-halflinebyvector.svgz 22-actions-paint.png 22-actions-bezier4.png 32-actions-projection.png 22-actions-triangle.png 22-actions-openpolygon.png 32-actions-rbezier3.png 22-actions-parallel.png sc-actions-parabolabtp.svgz 22-actions-testparallel.png 22-actions-polygonsides.png 32-actions-circlebtp.png sc-actions-genericprojectivity.svgz 32-actions-scale.png 32-actions-beziercurves.png 32-actions-vectordifference.png sc-actions-python.svgz 22-actions-pointOnLine.png sc-actions-equitriangle.svgz 22-actions-angle.png 32-actions-hyperbolabffp.png 22-actions-pointxy.png 32-actions-polygonvertices.png 22-actions-hyperbolabffp.png 32-actions-controlpolygon.png 32-actions-slope.png sc-actions-linebyvector.svgz sc-actions-arc.svgz sc-actions-ray.svgz 22-actions-beziercurves.png 22-actions-testcontains.png 22-actions-ellipsebffp.png 22-actions-stretch.png sc-actions-scale.svgz sc-actions-intersection.svgz 22-actions-kig_text.png sc-actions-point.svgz sc-actions-similitude.svgz sc-actions-vector.svgz sc-actions-coniclineintersection.svgz 22-actions-translation.png 32-actions-bezier3.png 22-actions-radicalline.png 32-actions-vectorsum.png 32-actions-centerofcurvature.png sc-actions-openpolygon.svgz sc-actions-circlebcl.svgz 22-actions-rbezierN.png 32-actions-polygonsides.png sc-actions-locus.svgz 22-actions-tangent.png 32-actions-sizer.png 32-actions-harmonichomology.png 22-actions-testcollinear.png 22-actions-en.png 32-actions-conicb5p.png 32-actions-distance.png 22-actions-circlebtp.png 22-actions-kig_numericvalue.png sc-actions-vectorsum.svgz 32-actions-line.png 32-actions-testdistance.png sc-actions-kig_text.svgz 32-actions-angle.png sc-actions-angle.svgz sc-actions-controlpolygon.svgz 22-actions-parabolabtp.png sc-actions-w.svgz 22-actions-test.png 22-actions-curvelineintersection.png 32-actions-test.png 22-actions-equitriangle.png 32-actions-mirrorpoint.png 32-actions-centralsymmetry.png sc-actions-mirrorpoint.svgz sc-actions-triangle.svgz sc-actions-genericaffinity.svgz sc-actions-segment.svgz sc-actions-bezierN.svgz sc-actions-radicalline.svgz 32-actions-segment_midpoint.png + 32-actions-segment_golden_point.png sc-actions-slope.svgz 32-actions-ray.png 22-actions-projection.png 32-actions-testparallel.png sc-actions-translation.svgz sc-actions-pointxy.svgz 22-actions-circlebcp.png 32-actions-segment.png sc-actions-convexhull.svgz sc-actions-testcontains.svgz sc-actions-en.svgz sc-actions-arc_center.svgz 22-actions-genericprojectivity.png 22-actions-testorthogonal.png 22-actions-rotation.png sc-actions-pointOnLine.svgz sc-actions-beziercurves.svgz 32-actions-pointxy.png 22-actions-mirrorpoint.png 32-actions-equilateralhyperbolab4p.png sc-actions-kig_polygon.svgz 32-actions-en.png 22-actions-scale.png 32-actions-angle_size.png 32-actions-testorthogonal.png 22-actions-centralsymmetry.png 32-actions-baseCircle.png sc-actions-angle_size.svgz sc-actions-circlebtp.svgz 32-actions-circlelineintersection.png 32-actions-circlebcp.png 22-actions-angle_size.png 22-actions-linebyvector.png sc-actions-rotation.svgz 22-actions-conicb5p.png 32-actions-intersection.png sc-actions-circlebps.svgz 32-actions-conicsradicalline.png sc-actions-testparallel.svgz sc-actions-stretch.svgz 22-actions-circlebps.png 32-actions-similitude.png sc-actions-projection.svgz sc-actions-circumference.svgz sc-actions-ellipsebffp.svgz sc-actions-angle_bisector.svgz sc-actions-polygonvertices.svgz 32-actions-radicalline.png 22-actions-halflinebyvector.png sc-actions-rbezier4.svgz 32-actions-circlebpd.png sc-actions-testcollinear.svgz DESTINATION ${CMAKE_INSTALL_DATADIR}/kig/icons THEME hicolor ) diff --git a/icons/sc-actions-segment_golden_point.svgz b/icons/sc-actions-segment_golden_point.svgz new file mode 100644 index 00000000..e69de29b diff --git a/kig/kigpartui.rc b/kig/kigpartui.rc index a99f2466..b6e3323e 100644 --- a/kig/kigpartui.rc +++ b/kig/kigpartui.rc @@ -1,322 +1,323 @@ &File &Edit &View &Objects &Points - + + &Lines &Circles && Arcs Poly&gons &Vectors && Segments Co&nics && Cubics More Conics Cu&bics &Bézier curves &Angles &Transformations &Differential geometry T&ests &Other &Types &Tools Main Toolbar Points Lines Vectors && Segments Circles && Arcs Conics Angles Transformations Other Objects View diff --git a/misc/builtin_stuff.cc b/misc/builtin_stuff.cc index e1de877d..f2a3d5d5 100644 --- a/misc/builtin_stuff.cc +++ b/misc/builtin_stuff.cc @@ -1,717 +1,743 @@ // Copyright (C) 2003 Dominique Devriese // This program 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 2 // of the License, or (at your option) any later version. // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301, USA. #include "builtin_stuff.h" #include #include "object_constructor.h" #include "lists.h" #include "special_constructors.h" #include "guiaction.h" #include "../objects/angle_type.h" #include "../objects/arc_type.h" #include "../objects/circle_type.h" #include "../objects/conic_types.h" #include "../objects/cubic_type.h" #include "../objects/intersection_types.h" #include "../objects/inversion_type.h" #include "../objects/line_imp.h" #include "../objects/line_type.h" #include "../objects/object_imp.h" #include "../objects/other_imp.h" #include "../objects/other_type.h" #include "../objects/point_type.h" #include "../objects/tests_type.h" #include "../objects/transform_types.h" #include "../objects/vector_type.h" #include "../objects/polygon_type.h" #include "../objects/bezier_type.h" void setupBuiltinStuff() { static bool done = false; if ( ! done ) { ObjectConstructorList* ctors = ObjectConstructorList::instance(); GUIActionList* actions = GUIActionList::instance(); ObjectConstructor* c = 0; // point by coords... c = new SimpleObjectTypeConstructor( PointByCoordsType::instance(), I18N_NOOP( "Point by Numeric Labels" ), I18N_NOOP( "A point whose coordinates are given by two numeric labels" ), "pointxy" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_point_by_coords" ) ); // segment... c = new SimpleObjectTypeConstructor( SegmentABType::instance(), I18N_NOOP( "Segment" ), I18N_NOOP( "A segment constructed from its start and end point" ), "segment" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_segment", Qt::Key_S ) ); // segment axis... c = new SimpleObjectTypeConstructor( SegmentAxisType::instance(), I18N_NOOP( "Segment Axis" ), I18N_NOOP( "The perpendicular line through a given segment's mid point." ), "segmentaxis" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_segment_axis" ) ); // line by two points.. c = new SimpleObjectTypeConstructor( LineABType::instance(), I18N_NOOP( "Line by Two Points" ), I18N_NOOP( "A line constructed through two points"), "line" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_linettp", Qt::Key_L ) ); // ray by two points.. c = new SimpleObjectTypeConstructor( RayABType::instance(), I18N_NOOP( "Half-Line" ), I18N_NOOP( "A half-line by its start point, and another point somewhere on it." ), "ray" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_ray", Qt::Key_R ) ); // perpendicular line c = new SimpleObjectTypeConstructor( LinePerpendLPType::instance(), I18N_NOOP( "Perpendicular" ), I18N_NOOP( "A line constructed through a point, perpendicular to another line or segment." ), "perpendicular" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_lineperpend" ) ); // parallel line c = new SimpleObjectTypeConstructor( LineParallelLPType::instance(), I18N_NOOP( "Parallel" ), I18N_NOOP( "A line constructed through a point, and parallel to another line or segment" ), "parallel" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_lineparallel" ) ); // circle c = new SimpleObjectTypeConstructor( CircleBCPType::instance(), I18N_NOOP( "Circle by Center && Point" ), I18N_NOOP( "A circle constructed by its center and a point that pertains to it" ), "circlebcp" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_circlebcp", Qt::Key_C ) ); c = new SimpleObjectTypeConstructor( CircleBTPType::instance(), I18N_NOOP( "Circle by Three Points" ), I18N_NOOP( "A circle constructed through three points" ), "circlebtp" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_circlebtp" ) ); c = new SimpleObjectTypeConstructor( CircleBPRType::instance(), I18N_NOOP( "Circle by Point && Radius" ), I18N_NOOP( "A circle defined by its center and the length of the radius" ), "circlebps" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_circlebpr" ) ); // declare this object static to this function, so it gets deleted // at the end of the program, without us having to wonder about // deleting it.. We don't want to register this // object-constructor, because that way, "construct the bisector" // would appear twice in the angle popup menu: once as the generic // construct a property stuff, and once because of this ctor.. // we only register the guiaction, cause it makes sense to have a // toolbar icon for this.. static PropertyObjectConstructor anglebisectionctor( AngleImp::stype(), I18N_NOOP( "Construct Bisector of This Angle" ), I18N_NOOP( "Select the angle you want to construct the bisector of..." ), I18N_NOOP( "Angle Bisector" ), I18N_NOOP( "The bisector of an angle" ), "angle_bisector", "angle-bisector" ); actions->add( new ConstructibleAction( &anglebisectionctor, "objects_new_angle_bisector" ) ); // conic stuff c = new SimpleObjectTypeConstructor( ConicB5PType::instance(), I18N_NOOP( "Conic by Five Points" ), I18N_NOOP( "A conic constructed through five points" ), "conicb5p" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_conicb5p" ) ); c = new SimpleObjectTypeConstructor( ConicBAAPType::instance(), I18N_NOOP( "Hyperbola by Asymptotes && Point" ), I18N_NOOP( "A hyperbola with given asymptotes through a point" ), "conicbaap" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_conicbaap" ) ); c = new SimpleObjectTypeConstructor( EllipseBFFPType::instance(), I18N_NOOP( "Ellipse by Focuses && Point" ), // focuses is used in preference to foci I18N_NOOP( "An ellipse constructed by its focuses and a point that pertains to it" ), "ellipsebffp" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_ellipsebffp" ) ); c = new SimpleObjectTypeConstructor( HyperbolaBFFPType::instance(), I18N_NOOP( "Hyperbola by Focuses && Point" ), // focuses is used in preference to foci I18N_NOOP( "A hyperbola constructed by its focuses and a point that pertains to it" ), "hyperbolabffp" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_hyperbolabffp" ) ); c = new SimpleObjectTypeConstructor( ConicBDFPType::instance(), I18N_NOOP( "Conic by Directrix, Focus && Point" ), I18N_NOOP( "A conic with given directrix and focus, through a point" ), "conicbdfp" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_conicbdfp" ) ); c = new SimpleObjectTypeConstructor( ParabolaBTPType::instance(), I18N_NOOP( "Vertical Parabola by Three Points" ), I18N_NOOP( "A vertical parabola constructed through three points" ), "parabolabtp" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_parabolabtp" ) ); c = new SimpleObjectTypeConstructor( CubicB9PType::instance(), I18N_NOOP( "Cubic Curve by Nine Points" ), I18N_NOOP( "A cubic curve constructed through nine points" ), "cubicb9p" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_cubicb9p" ) ); c = new SimpleObjectTypeConstructor( ConicPolarPointType::instance(), I18N_NOOP( "Polar Point of a Line" ), I18N_NOOP( "The polar point of a line with respect to a conic." ), "polarpoint" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_pointpolar" ) ); c = new SimpleObjectTypeConstructor( ConicPolarLineType::instance(), I18N_NOOP( "Polar Line of a Point" ), I18N_NOOP( "The polar line of a point with respect to a conic." ), "polarline" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_linepolar" ) ); c = new SimpleObjectTypeConstructor( CubicNodeB6PType::instance(), I18N_NOOP( "Cubic Curve with Node by Six Points" ), I18N_NOOP( "A cubic curve with a nodal point at the origin through six points" ), "cubicnodeb6p" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_cubicnodeb6p" ) ); c = new SimpleObjectTypeConstructor( CubicCuspB4PType::instance(), I18N_NOOP( "Cubic Curve with Cusp by Four Points" ), I18N_NOOP( "A cubic curve with a horizontal cusp at the origin through four points" ), "cubiccuspb4p" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_cubiccuspb4p" ) ); c = new SimpleObjectTypeConstructor( VerticalCubicB4PType::instance(), I18N_NOOP( "Cubic Function by Four Points" ), I18N_NOOP( "A cubic function through four points" ), "verticalcubicb4p" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_verticalcubicb4p" ) ); c = new SimpleObjectTypeConstructor( ConicDirectrixType::instance(), I18N_NOOP( "Directrix of a Conic" ), I18N_NOOP( "The directrix line of a conic." ), "directrix" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_linedirectrix" ) ); c = new SimpleObjectTypeConstructor( AngleType::instance(), I18N_NOOP( "Angle by Three Points" ), I18N_NOOP( "An angle defined by three points" ), "angle" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_angle", Qt::Key_A ) ); c = new SimpleObjectTypeConstructor( EquilateralHyperbolaB4PType::instance(), I18N_NOOP( "Equilateral Hyperbola by Four Points" ), I18N_NOOP( "An equilateral hyperbola constructed through four points" ), "equilateralhyperbolab4p" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_equilateralhyperbolab4p" ) ); { // now for the Mid Point action. It does both the mid point of // a segment, and the mid point of two points. The midpoint of // two segments just shows the mid point property, and therefore // doesn't need to be added to the ctors, because there are // already facilities to construct an object's properties.. // therefore, we add only an mpotp to the ctors, and add the // merged constructor only to the actions.. ctors->add( new MidPointOfTwoPointsConstructor() ); ObjectConstructor* mpotp = new MidPointOfTwoPointsConstructor(); ObjectConstructor* mpos = new PropertyObjectConstructor( SegmentImp::stype(), I18N_NOOP( "Construct the midpoint of this segment" ), "", "", "", "", "mid-point" ); // make this a static object, so it gets deleted at the end of // the program. static MergeObjectConstructor m( I18N_NOOP( "Mid Point" ), I18N_NOOP( "The midpoint of a segment or two other points" ), "bisection" ); m.merge( mpotp ); m.merge( mpos ); actions->add( new ConstructibleAction( &m, "objects_new_midpoint", Qt::Key_M ) ); }; + { + // now for the Golden Ratio Point action. It does both the golden ratio point of + // a segment, and the golden ratio point of two points. The golden ratio point of + // two segments just shows the golden ratio point property, and therefore + // doesn't need to be added to the ctors, because there are + // already facilities to construct an object's properties.. + // therefore, we add only an mpotp to the ctors, and add the + // merged constructor only to the actions.. + ctors->add( new GoldenPointOfTwoPointsConstructor() ); + + ObjectConstructor* mpotp = new GoldenPointOfTwoPointsConstructor(); + ObjectConstructor* mpos = new PropertyObjectConstructor( + SegmentImp::stype(), I18N_NOOP( "Construct the golden ratio point of this segment" ), + "", "", "", "", "golden-point" ); + + // make this a static object, so it gets deleted at the end of + // the program. + static MergeObjectConstructor m( + I18N_NOOP( "Golden Ratio Point" ), + I18N_NOOP( "The golden ratio point of a segment or two other points" ), + "segment_golden_point" ); + m.merge( mpotp ); + m.merge( mpos ); + actions->add( new ConstructibleAction( &m, "objects_new_golden_point", Qt::Key_G ) ); + }; + c = new SimpleObjectTypeConstructor( VectorType::instance(), I18N_NOOP( "Vector" ), I18N_NOOP( "Construct a vector from two given points." ), "vector" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_vector", Qt::Key_V ) ); c = new SimpleObjectTypeConstructor( VectorSumType::instance(), I18N_NOOP( "Vector Sum" ), I18N_NOOP( "Construct the vector sum of two vectors." ), "vectorsum" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_vectorsum", 0 ) ); c = new SimpleObjectTypeConstructor( LineByVectorType::instance(), I18N_NOOP( "Line by Vector" ), I18N_NOOP( "Construct the line by a given vector though a given point." ), "linebyvector" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_linebyvector", 0 ) ); c = new SimpleObjectTypeConstructor( HalflineByVectorType::instance(), I18N_NOOP( "Half-Line by Vector" ), I18N_NOOP( "Construct the half-line by a given vector starting at given point." ), "halflinebyvector" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_halflinebyvector", 0 ) ); c = new SimpleObjectTypeConstructor( ArcBTPType::instance(), I18N_NOOP( "Arc by Three Points" ), I18N_NOOP( "Construct an arc through three points." ), "arc" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_arcbtp" ) ); c = new SimpleObjectTypeConstructor( ConicArcBCTPType::instance(), I18N_NOOP( "Conic Arc by Center and Three Points" ), I18N_NOOP( "Construct a conic arc with given center through three points." ), "conicarc" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_conicarcbctp" ) ); c = new SimpleObjectTypeConstructor( ConicArcB5PType::instance(), I18N_NOOP( "Conic Arc by Five Points" ), I18N_NOOP( "Construct a conic arc through five points." ), "conicarc" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_conicarcb5p" ) ); c = new SimpleObjectTypeConstructor( ArcBCPAType::instance(), I18N_NOOP( "Arc by Center, Angle && Point" ), I18N_NOOP( "Construct an arc by its center and a given angle, " "starting at a given point" ), "arcbcpa" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_arcbcpa" ) ); c = new SimpleObjectTypeConstructor( ParabolaBDPType::instance(), I18N_NOOP( "Parabola by Directrix && Focus" ), I18N_NOOP( "A parabola defined by its directrix and focus" ), "parabolabdp" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_parabolabdp" ) ); // Transformation stuff.. // c = new SimpleObjectTypeConstructor( // CircularInversionType::instance(), // I18N_NOOP( "Invert" ), // I18N_NOOP( "The inversion of an object with respect to a circle" ), // "inversion" ); // ctors->add( c ); // actions->add( new ConstructibleAction( c, "objects_new_inversion" ) ); c = new InversionConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_inversion" ) ); c = new SimpleObjectTypeConstructor( TranslatedType::instance(), I18N_NOOP( "Translate" ), I18N_NOOP( "The translation of an object by a vector" ), "translation" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_translation" ) ); c = new SimpleObjectTypeConstructor( PointReflectionType::instance(), I18N_NOOP( "Reflect in Point" ), I18N_NOOP( "An object reflected in a point" ), "centralsymmetry" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_pointreflection" ) ); c = new SimpleObjectTypeConstructor( LineReflectionType::instance(), I18N_NOOP( "Reflect in Line" ), I18N_NOOP( "An object reflected in a line" ), "mirrorpoint" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_linereflection" ) ); c = new SimpleObjectTypeConstructor( RotationType::instance(), I18N_NOOP( "Rotate" ), I18N_NOOP( "An object rotated by an angle around a point" ), "rotation" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_rotation" ) ); c = new SimpleObjectTypeConstructor( ScalingOverCenterType::instance(), I18N_NOOP( "Scale" ), I18N_NOOP( "Scale an object over a point, by the ratio given by the length of a segment" ), "scale" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_scalingovercenter" ) ); c = new SimpleObjectTypeConstructor( ScalingOverLineType::instance(), I18N_NOOP( "Scale over Line" ), I18N_NOOP( "An object scaled over a line, by the ratio given by the length of a segment" ), "stretch" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_scalingoverline" ) ); c = new SimpleObjectTypeConstructor( ScalingOverCenter2Type::instance(), I18N_NOOP( "Scale (ratio given by two segments)" ), I18N_NOOP( "Scale an object over a point, by the ratio given by the length of two segments" ), "scale" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_scalingovercenter2" ) ); c = new SimpleObjectTypeConstructor( ScalingOverLine2Type::instance(), I18N_NOOP( "Scale over Line (ratio given by two segments)" ), I18N_NOOP( "An object scaled over a line, by the ratio given by the length of two segments" ), "stretch" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_scalingoverline2" ) ); c = new SimpleObjectTypeConstructor( SimilitudeType::instance(), I18N_NOOP( "Apply Similitude" ), I18N_NOOP( "Apply a similitude to an object (the sequence of a scaling and rotation around a center)" ), "similitude" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_similitude" ) ); c = new SimpleObjectTypeConstructor( HarmonicHomologyType::instance(), I18N_NOOP( "Harmonic Homology" ), I18N_NOOP( "The harmonic homology with a given center and a given axis (this is a projective transformation)" ), "harmonichomology" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_harmonichomology" ) ); c = new GenericAffinityConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_genericaffinity" ) ); c = new GenericProjectivityConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_genericprojectivity" ) ); c = new SimpleObjectTypeConstructor( CastShadowType::instance(), I18N_NOOP( "Draw Projective Shadow" ), I18N_NOOP( "The shadow of an object with a given light source and projection plane (indicated by a line)" ), "castshadow" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_castshadow" ) ); // c = new SimpleObjectTypeConstructor( // ProjectiveRotationType::instance(), // I18N_NOOP( "Rotate Projectively" ), // I18N_NOOP( "An object projectively rotated by an angle and a half-line" ), // "projectiverotation" ); // ctors->add( c ); // actions->add( new ConstructibleAction( c, "objects_new_projectiverotation" ) ); c = new MultiObjectTypeConstructor( ConicAsymptoteType::instance(), I18N_NOOP( "Asymptotes of a Hyperbola" ), I18N_NOOP( "The two asymptotes of a hyperbola." ), "conicasymptotes", -1, 1 ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_lineconicasymptotes" ) ); c = new ConicRadicalConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_lineconicradical") ); /* ----------- start polygons --------- */ c = new SimpleObjectTypeConstructor( TriangleB3PType::instance(), I18N_NOOP( "Triangle by Its Vertices" ), I18N_NOOP( "Construct a triangle given its three vertices." ), "triangle" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_trianglebtp" ) ); c = new PolygonBNPTypeConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_polygonbnp" )); c = new OpenPolygonTypeConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_openpolygon" )); c = new PolygonBCVConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_polygonbcv" ) ); c = new PolygonVertexTypeConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_polygonvertices" )); c = new PolygonSideTypeConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_polygonsides" )); c = new SimpleObjectTypeConstructor( ConvexHullType::instance(), I18N_NOOP( "Convex Hull" ), I18N_NOOP( "A polygon that corresponds to the convex hull of another polygon" ), "convexhull" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_convexhull" ) ); /* ----------- end polygons --------- */ /* ----------- start bezier --------- */ c = new SimpleObjectTypeConstructor( BezierQuadricType::instance(), I18N_NOOP( "Bézier Quadratic by its Control Points" ), I18N_NOOP( "Construct a Bézier quadratic given its three control points." ), "bezier3" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_bezierquadratic" ) ); c = new SimpleObjectTypeConstructor( BezierCubicType::instance(), I18N_NOOP( "Bézier Cubic by its Control Points" ), I18N_NOOP( "Construct a Bézier cubic given its four control points." ), "bezier4" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_beziercubic" ) ); c = new BezierCurveTypeConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_beziercurve" )); c = new SimpleObjectTypeConstructor( RationalBezierQuadricType::instance(), I18N_NOOP( "Rational Bézier Quadratic by its Control Points" ), I18N_NOOP( "Construct a Rational Bézier quadratic given its three control points." ), "rbezier3" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_rationalbezierquadratic" ) ); c = new SimpleObjectTypeConstructor( RationalBezierCubicType::instance(), I18N_NOOP( "Rational Bézier Cubic by its Control Points" ), I18N_NOOP( "Construct a Rational Bézier cubic given its four control points." ), "rbezier4" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_rationalbeziercubic" ) ); c = new RationalBezierCurveTypeConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_rationalbeziercurve" )); /* ----------- end bezier ----------- */ c = new LocusConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_locus" ) ); // tests c = new TestConstructor( AreParallelType::instance(), I18N_NOOP( "Parallel Test" ), I18N_NOOP( "Test whether two given lines are parallel" ), "testparallel" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_areparallel" ) ); c = new TestConstructor( AreOrthogonalType::instance(), I18N_NOOP( "Orthogonal Test" ), I18N_NOOP( "Test whether two given lines are orthogonal" ), "testorthogonal" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_areorthogonal" ) ); c = new TestConstructor( AreCollinearType::instance(), I18N_NOOP( "Collinear Test" ), I18N_NOOP( "Test whether three given points are collinear" ), "testcollinear" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_arecollinear" ) ); c = new TestConstructor( ContainsTestType::instance(), I18N_NOOP( "Contains Test" ), I18N_NOOP( "Test whether a given curve contains a given point" ), "testcontains" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_containstest" ) ); c = new TestConstructor( InPolygonTestType::instance(), I18N_NOOP( "In Polygon Test" ), I18N_NOOP( "Test whether a given polygon contains a given point" ), "test" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_inpolygontest" ) ); c = new TestConstructor( ConvexPolygonTestType::instance(), I18N_NOOP( "Convex Polygon Test" ), I18N_NOOP( "Test whether a given polygon is convex" ), "test" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_convexpolygontest" ) ); c = new TestConstructor( ExistenceTestType::instance(), I18N_NOOP( "Existence Test" ), I18N_NOOP( "Test whether a given object is constructible" ), "test" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_existencetest" ) ); c = new TestConstructor( SameDistanceType::instance(), I18N_NOOP( "Distance Test" ), I18N_NOOP( "Test whether a given point have the same distance from a given point " "and from another given point" ), "testdistance" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_distancetest" ) ); c = new TestConstructor( VectorEqualityTestType::instance(), I18N_NOOP( "Vector Equality Test" ), I18N_NOOP( "Test whether two vectors are equal" ), "test" ); // "testequal" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_vectorequalitytest" ) ); c = new MeasureTransportConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_measuretransport" )); // c = new SimpleObjectTypeConstructor( // MeasureTransportType::instance(), // I18N_NOOP( "Measure Transport" ), // I18N_NOOP( "Transport the measure of a segment or arc over a line or circle." ), // "measuretransport" ); // ctors->add( c ); // actions->add( new ConstructibleAction( c, "objects_new_measuretransport" ) ); c = new SimpleObjectTypeConstructor( ProjectedPointType::instance(), I18N_NOOP( "Point Projection" ), I18N_NOOP( "Project a point on a line" ), "projection" ); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_projection" ) ); // the generic intersection constructor.. c = new GenericIntersectionConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_intersection", Qt::Key_I ) ); // the generic tangent constructor c = new TangentConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_tangent", Qt::Key_T ) ); // the generic center of curvature constructor c = new CocConstructor(); ctors->add( c ); actions->add( new ConstructibleAction( c, "objects_new_centerofcurvature" ) ); actions->add( new ConstructPointAction( "objects_new_normalpoint" ) ); actions->add( new ConstructTextLabelAction( "objects_new_textlabel" ) ); actions->add( new AddFixedPointAction( "objects_new_point_xy" ) ); actions->add( new ConstructNumericLabelAction( "objects_new_numericlabel" ) ); #ifdef KIG_ENABLE_PYTHON_SCRIPTING #include "../scripting/script-common.h" actions->add( new NewScriptAction( I18N_NOOP( "Python Script" ), I18N_NOOP( "Construct a new Python script." ), "objects_new_script_python", ScriptType::Python ) ); #endif #if 0 actions->add( new TestAction( "test_stuff" ) ); #endif }; done = true; } diff --git a/misc/special_constructors.cc b/misc/special_constructors.cc index 8b096cf6..794e8ce5 100644 --- a/misc/special_constructors.cc +++ b/misc/special_constructors.cc @@ -1,2317 +1,2377 @@ // Copyright (C) 2003 Dominique Devriese // This program 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 2 // of the License, or (at your option) any later version. // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301, USA. #include "special_constructors.h" #include #include "calcpaths.h" #include "common.h" #include "conic-common.h" #include "guiaction.h" #include "kigpainter.h" #include "../kig/kig_part.h" #include "../kig/kig_document.h" #include "../modes/construct_mode.h" #include "../objects/special_imptypes.h" #include "../objects/bogus_imp.h" #include "../objects/centerofcurvature_type.h" #include "../objects/circle_imp.h" #include "../objects/conic_imp.h" #include "../objects/conic_types.h" #include "../objects/cubic_imp.h" #include "../objects/intersection_types.h" #include "../objects/inversion_type.h" #include "../objects/line_imp.h" #include "../objects/line_type.h" #include "../objects/locus_imp.h" #include "../objects/object_calcer.h" #include "../objects/object_drawer.h" #include "../objects/object_factory.h" #include "../objects/object_holder.h" #include "../objects/object_imp.h" #include "../objects/object_type.h" #include "../objects/other_imp.h" #include "../objects/other_type.h" #include "../objects/point_imp.h" #include "../objects/point_type.h" #include "../objects/polygon_imp.h" #include "../objects/polygon_type.h" #include "../objects/bezier_imp.h" #include "../objects/bezier_type.h" #include "../objects/tangent_type.h" #include "../objects/text_imp.h" #include "../objects/transform_types.h" #include #include #include #include /* * conic-line and circle-circle intersection (with search for already computed * intersections) * the previous "ConicLineIntersectionConstructor" is now * dead code, which could be remove in the future */ TwoOrOneIntersectionConstructor::TwoOrOneIntersectionConstructor( const ArgsParserObjectType* t_std, const ArgsParserObjectType* t_special, const char* iconfile, const struct ArgsParser::spec argsspecv[] ) : StandardConstructorBase( "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", iconfile, margsparser ), mtype_std( t_std ), mtype_special( t_special ), margsparser( argsspecv, 2 ) { } TwoOrOneIntersectionConstructor::~TwoOrOneIntersectionConstructor() { } void TwoOrOneIntersectionConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& doc ) const { Args args; if ( parents.size() != 2 ) return; transform( parents.begin(), parents.end(), back_inserter( args ), std::mem_fun( &ObjectCalcer::imp ) ); for ( int i = -1; i <= 1; i += 2 ) { IntImp param( i ); args.push_back( ¶m ); ObjectImp* data = mtype_std->calc( args, doc ); drawer.draw( *data, p, true ); delete data; args.pop_back(); } } std::vector removeDuplicatedPoints( std::vector points ) { std::vector ret; for ( std::vector::iterator i = points.begin(); i != points.end(); ++i ) { for ( std::vector::iterator j = ret.begin(); j != ret.end(); ++j ) { if ( coincidentPoints( (*i)->imp(), (*j)->imp() ) ) break; } ret.push_back( *i ); } return ret; } bool coincidentPoints( const ObjectImp* p1, const ObjectImp* p2 ) { const PointImp* pt1 = dynamic_cast( p1 ); if ( !pt1 ) return false; const PointImp* pt2 = dynamic_cast( p2 ); if ( !pt2 ) return false; Coordinate diff = pt1->coordinate() - pt2->coordinate(); if ( diff.squareLength() < 1e-12 ) return true; return false; } std::vector TwoOrOneIntersectionConstructor::build( const std::vector& parents, KigDocument& doc, KigWidget& ) const { std::vector ret; assert( parents.size() == 2 ); std::vector points = doc.findIntersectionPoints( parents[0], parents[1] ); std::vector uniquepoints = removeDuplicatedPoints( points ); if ( uniquepoints.size() == 1 ) { std::vector args( parents ); args.push_back( uniquepoints[0] ); ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype_special, args ) ) ); return ret; } for ( int i = -1; i <= 1; i += 2 ) { ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( i ) ); std::vector args( parents ); args.push_back( d ); ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype_std, args ) ) ); } return ret; } void TwoOrOneIntersectionConstructor::plug( KigPart*, KigGUIAction* ) { } bool TwoOrOneIntersectionConstructor::isTransform() const { return false; } ThreeTwoOneIntersectionConstructor::ThreeTwoOneIntersectionConstructor( const ArgsParserObjectType* t_std, const ArgsParserObjectType* t_special, const char* iconfile, const struct ArgsParser::spec argsspecv[] ) : StandardConstructorBase( "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", iconfile, margsparser ), mtype_std( t_std ), mtype_special( t_special ), margsparser( argsspecv, 2 ) { } ThreeTwoOneIntersectionConstructor::~ThreeTwoOneIntersectionConstructor() { } void ThreeTwoOneIntersectionConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& doc ) const { Args args; if ( parents.size() != 2 ) return; transform( parents.begin(), parents.end(), back_inserter( args ), std::mem_fun( &ObjectCalcer::imp ) ); for ( int i = 1; i <= 3; i += 1 ) { IntImp param( i ); args.push_back( ¶m ); ObjectImp* data = mtype_std->calc( args, doc ); drawer.draw( *data, p, true ); delete data; args.pop_back(); } } std::vector ThreeTwoOneIntersectionConstructor::build( const std::vector& parents, KigDocument& doc, KigWidget& ) const { std::vector ret; assert( parents.size() == 2 ); std::vector points = doc.findIntersectionPoints( parents[0], parents[1] ); std::vector uniquepoints = removeDuplicatedPoints( points ); if ( uniquepoints.size() == 2 ) { std::vector args( parents ); args.push_back( uniquepoints[0] ); args.push_back( uniquepoints[1] ); ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype_special, args ) ) ); return ret; } if ( uniquepoints.size() == 1 ) { for ( int i = -1; i <= 1; i += 2 ) { std::vector args( parents ); args.push_back( uniquepoints[0] ); ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( i ) ); args.push_back( d ); ret.push_back( new ObjectHolder( new ObjectTypeCalcer( CubicLineTwoIntersectionType::instance(), args ) ) ); args.clear(); } return ret; } for ( int i = 1; i <= 3; i += 1 ) { ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( i ) ); std::vector args( parents ); args.push_back( d ); ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype_std, args ) ) ); } return ret; } void ThreeTwoOneIntersectionConstructor::plug( KigPart*, KigGUIAction* ) { } bool ThreeTwoOneIntersectionConstructor::isTransform() const { return false; } /* * conic-conic intersection */ class ConicConicIntersectionConstructor : public StandardConstructorBase { protected: ArgsParser mparser; public: ConicConicIntersectionConstructor(); ~ConicConicIntersectionConstructor(); void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const Q_DECL_OVERRIDE; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const Q_DECL_OVERRIDE; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; }; class ConicLineIntersectionConstructor : public MultiObjectTypeConstructor { public: ConicLineIntersectionConstructor(); ~ConicLineIntersectionConstructor(); }; class ArcLineIntersectionConstructor : public MultiObjectTypeConstructor { public: ArcLineIntersectionConstructor(); ~ArcLineIntersectionConstructor(); }; ConicRadicalConstructor::ConicRadicalConstructor() : StandardConstructorBase( I18N_NOOP( "Radical Lines for Conics" ), I18N_NOOP( "The lines constructed through the intersections " "of two conics. This is also defined for " "non-intersecting conics." ), "conicsradicalline", mparser ), mtype( ConicRadicalType::instance() ), mparser( mtype->argsParser().without( IntImp::stype() ) ) { } ConicRadicalConstructor::~ConicRadicalConstructor() { } void ConicRadicalConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& doc ) const { if ( parents.size() == 2 && parents[0]->imp()->inherits( ConicImp::stype() ) && parents[1]->imp()->inherits( ConicImp::stype() ) ) { Args args; std::transform( parents.begin(), parents.end(), std::back_inserter( args ), std::mem_fun( &ObjectCalcer::imp ) ); for ( int i = -1; i < 2; i += 2 ) { IntImp root( i ); IntImp zeroindex( 1 ); args.push_back( &root ); args.push_back( &zeroindex ); ObjectImp* data = mtype->calc( args, doc ); drawer.draw( *data, p, true ); delete data; data = 0; args.pop_back(); args.pop_back(); }; }; } std::vector ConicRadicalConstructor::build( const std::vector& os, KigDocument&, KigWidget& ) const { using namespace std; std::vector ret; ObjectCalcer* zeroindexcalcer = new ObjectConstCalcer( new IntImp( 1 ) ); for ( int i = -1; i < 2; i += 2 ) { std::vector args; std::copy( os.begin(), os.end(), back_inserter( args ) ); args.push_back( new ObjectConstCalcer( new IntImp( i ) ) ); // we use only one zeroindex dataobject, so that if you switch one // radical line around, then the other switches along.. args.push_back( zeroindexcalcer ); ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) ); }; return ret; } static const struct ArgsParser::spec argsspecpp[] = { { PointImp::stype(), I18N_NOOP( "Moving Point" ), I18N_NOOP( "Select the moving point, which will be moved around while drawing the locus..." ), false }, { PointImp::stype(), I18N_NOOP( "Following Point" ), I18N_NOOP( "Select the following point, whose locations the locus will be drawn through..." ), true } }; LocusConstructor::LocusConstructor() : StandardConstructorBase( I18N_NOOP( "Locus" ), I18N_NOOP( "A locus" ), "locus", margsparser ), margsparser( argsspecpp, 2 ) { } LocusConstructor::~LocusConstructor() { } void LocusConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const { // this function is rather ugly, but it is necessary to do it this // way in order to play nice with Kig's design.. if ( parents.size() != 2 ) return; const ObjectTypeCalcer* constrained = dynamic_cast( parents.front() ); const ObjectCalcer* moving = parents.back(); if ( ! constrained || ! constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) { // moving is in fact the constrained point.. swap them.. moving = parents.front(); constrained = dynamic_cast( parents.back() ); assert( constrained ); }; assert( constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ); const ObjectImp* oimp = constrained->parents().back()->imp(); if( !oimp->inherits( CurveImp::stype() ) ) oimp = constrained->parents().front()->imp(); assert( oimp->inherits( CurveImp::stype() ) ); const CurveImp* cimp = static_cast( oimp ); ObjectHierarchy hier( constrained, moving ); LocusImp limp( cimp->copy(), hier ); drawer.draw( limp, p, true ); } int LocusConstructor::wantArgs( const std::vector& os, const KigDocument&, const KigWidget& ) const { int ret = margsparser.check( os ); if ( ret == ArgsParser::Invalid ) return ret; else if ( os.size() != 2 ) return ret; if ( dynamic_cast( os.front() ) && static_cast( os.front() )->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) { std::set children = getAllChildren( os.front() ); return children.find( os.back() ) != children.end() ? ret : ArgsParser::Invalid; } if ( dynamic_cast( os.back() ) && static_cast( os.back() )->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) { std::set children = getAllChildren( os.back() ); return children.find( os.front() ) != children.end() ? ret : ArgsParser::Invalid; } return ArgsParser::Invalid; } std::vector LocusConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const { std::vector ret; assert( parents.size() == 2 ); ObjectTypeCalcer* constrained = dynamic_cast( parents.front() ); ObjectCalcer* moving = parents.back(); if ( ! constrained || ! constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) { // moving is in fact the constrained point.. swap them.. moving = parents.front(); constrained = dynamic_cast( parents.back() ); assert( constrained ); }; assert( constrained->type()->inherits( ObjectType::ID_ConstrainedPointType ) ); ret.push_back( ObjectFactory::instance()->locus( constrained, moving ) ); return ret; } QString LocusConstructor::useText( const ObjectCalcer& o, const std::vector& os, const KigDocument&, const KigWidget& ) const { if ( dynamic_cast( &o ) && static_cast( o ).type()->inherits( ObjectType::ID_ConstrainedPointType ) && ( os.empty() || !dynamic_cast( os[0] ) || !static_cast( os[0] )->type()->inherits( ObjectType::ID_ConstrainedPointType ) ) ) return i18n( "Moving Point" ); else return i18n( "Dependent Point" ); } void ConicRadicalConstructor::plug( KigPart*, KigGUIAction* ) { } void LocusConstructor::plug( KigPart*, KigGUIAction* ) { } bool ConicRadicalConstructor::isTransform() const { return mtype->isTransform(); } bool LocusConstructor::isTransform() const { return false; } /* * generic sequence of points constructor */ PointSequenceConstructor::PointSequenceConstructor( const char* descname, const char* desc, const char* iconfile, const ObjectType* type ) : mdescname( descname ), mdesc( desc ), miconfile( iconfile ), mtype( type ) { } const QString PointSequenceConstructor::descriptiveName() const { return i18n( mdescname ); } const QString PointSequenceConstructor::description() const { return i18n( mdesc ); } const QByteArray PointSequenceConstructor::iconFileName( const bool ) const { return miconfile; } void PointSequenceConstructor::handleArgs( const std::vector& os, KigPart& d, KigWidget& v ) const { std::vector bos = build( os, d.document(), v ); for ( std::vector::iterator i = bos.begin(); i != bos.end(); ++i ) { (*i)->calc( d.document() ); } d.addObjects( bos ); } void PointSequenceConstructor::handlePrelim( KigPainter& p, const std::vector& os, const KigDocument& d, const KigWidget& ) const { uint count = os.size(); if ( count < 2 ) return; for ( uint i = 0; i < count; i++ ) { assert ( os[i]->imp()->inherits( PointImp::stype() ) ); } std::vector args = os; p.setBrushStyle( Qt::NoBrush ); p.setBrushColor( Qt::red ); p.setPen( QPen ( Qt::red, 1) ); p.setWidth( -1 ); // -1 means the default width for the object being // drawn.. ObjectDrawer drawer( Qt::red ); drawprelim( drawer, p, args, d ); } std::vector PointSequenceConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const { uint count = parents.size() - 1; assert ( count >= 3 ); std::vector args; for ( uint i = 0; i < count; ++i ) args.push_back( parents[i] ); ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, args ); ObjectHolder* h = new ObjectHolder( calcer ); std::vector ret; ret.push_back( h ); return ret; } void PointSequenceConstructor::plug( KigPart*, KigGUIAction* ) { } bool PointSequenceConstructor::isTransform() const { return false; } /* * generic polygon constructor */ PolygonBNPTypeConstructor::PolygonBNPTypeConstructor() : PointSequenceConstructor( I18N_NOOP( "Polygon by Its Vertices" ), I18N_NOOP( "Construct a polygon by giving its vertices" ), "kig_polygon", PolygonBNPType::instance() ) { } PolygonBNPTypeConstructor::~PolygonBNPTypeConstructor() { } bool PolygonBNPTypeConstructor::isAlreadySelectedOK( const std::vector& os, const uint& pos ) const { if ( pos == 0 && os.size() >= 3 ) return true; return false; } int PolygonBNPTypeConstructor::wantArgs( const std::vector& os, const KigDocument&, const KigWidget& ) const { int count=os.size() - 1; for ( int i = 0; i <= count; i++ ) { if ( ! ( os[i]->imp()->inherits( PointImp::stype() ) ) ) return ArgsParser::Invalid; } if ( count < 3 ) return ArgsParser::Valid; if ( os[0] == os[count] ) return ArgsParser::Complete; return ArgsParser::Valid; } QString PolygonBNPTypeConstructor::useText( const ObjectCalcer&, const std::vector& os, const KigDocument&, const KigWidget& ) const { if ( os.size() > 3 ) return i18n("... with this vertex (click on the first vertex to terminate construction)"); else return i18n("Construct a polygon with this vertex"); } QString PolygonBNPTypeConstructor::selectStatement( const std::vector&, const KigDocument&, const KigWidget& ) const { return i18n("Select a point to be a vertex of the new polygon..."); } void PolygonBNPTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const { if ( parents.size() < 2 ) return; std::vector points; for ( uint i = 0; i < parents.size(); ++i ) { const Coordinate vertex = static_cast( parents[i]->imp() )->coordinate(); points.push_back( vertex ); } if ( parents.size() == 2 ) { SegmentImp segment = SegmentImp( points[0], points[1] ); drawer.draw( segment, p, true ); } else { FilledPolygonImp polygon = FilledPolygonImp( points ); drawer.draw( polygon, p, true ); } } /* * open polygon (polyline) constructor */ OpenPolygonTypeConstructor::OpenPolygonTypeConstructor() : PointSequenceConstructor( I18N_NOOP( "Open Polygon (Polygonal Line)" ), I18N_NOOP( "Construct an open polygon" ), "openpolygon", OpenPolygonType::instance() ) { } OpenPolygonTypeConstructor::~OpenPolygonTypeConstructor() { } bool OpenPolygonTypeConstructor::isAlreadySelectedOK( const std::vector& os, const uint& pos ) const { if ( pos == os.size() - 1 && os.size() >= 2 ) return true; return false; } int OpenPolygonTypeConstructor::wantArgs( const std::vector& os, const KigDocument&, const KigWidget& ) const { int count=os.size() - 1; for ( int i = 0; i <= count; i++ ) { if ( ! ( os[i]->imp()->inherits( PointImp::stype() ) ) ) return ArgsParser::Invalid; } if ( count < 2 ) return ArgsParser::Valid; if ( os[count] == os[count - 1] ) return ArgsParser::Complete; return ArgsParser::Valid; } QString OpenPolygonTypeConstructor::useText( const ObjectCalcer&, const std::vector& os, const KigDocument&, const KigWidget& ) const { if ( os.size() > 2 ) return i18n("... with this vertex (click again on the last vertex to terminate construction)"); else return i18n("Construct a polygonal line with this vertex"); } QString OpenPolygonTypeConstructor::selectStatement( const std::vector&, const KigDocument&, const KigWidget& ) const { return i18n("Select a point to be a vertex of the new polygonal line..."); } void OpenPolygonTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const { if ( parents.size() < 2 ) return; std::vector points; for ( uint i = 0; i < parents.size(); ++i ) { const Coordinate vertex = static_cast( parents[i]->imp() )->coordinate(); points.push_back( vertex ); } if ( parents.size() == 2 ) { SegmentImp segment = SegmentImp( points[0], points[1] ); drawer.draw( segment, p, true ); } else { OpenPolygonalImp polygon = OpenPolygonalImp( points ); drawer.draw( polygon, p, true ); } } /* * construction of polygon vertices */ static const struct ArgsParser::spec argsspecpv[] = { { FilledPolygonImp::stype(), I18N_NOOP( "Polygon" ), I18N_NOOP( "Construct the vertices of this polygon..." ), true } }; PolygonVertexTypeConstructor::PolygonVertexTypeConstructor() : StandardConstructorBase( I18N_NOOP( "Vertices of a Polygon" ), I18N_NOOP( "The vertices of a polygon." ), "polygonvertices", margsparser ), mtype( PolygonVertexType::instance() ), margsparser( argsspecpv, 1 ) { } PolygonVertexTypeConstructor::~PolygonVertexTypeConstructor() { } void PolygonVertexTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const { if ( parents.size() != 1 ) return; const FilledPolygonImp* polygon = dynamic_cast( parents.front()->imp() ); const std::vector points = polygon->points(); int sides = points.size(); for ( int i = 0; i < sides; ++i ) { PointImp point = PointImp( points[i] ); drawer.draw( point, p, true ); } } std::vector PolygonVertexTypeConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const { std::vector ret; assert( parents.size() == 1 ); const FilledPolygonImp* polygon = dynamic_cast( parents.front()->imp() ); const std::vector points = polygon->points(); int sides = points.size(); for ( int i = 0; i < sides; ++i ) { ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( i ) ); std::vector args( parents ); args.push_back( d ); ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) ); } return ret; } void PolygonVertexTypeConstructor::plug( KigPart*, KigGUIAction* ) { } bool PolygonVertexTypeConstructor::isTransform() const { return false; } /* * construction of polygon sides */ static const struct ArgsParser::spec argsspecps[] = { { FilledPolygonImp::stype(), I18N_NOOP( "Polygon" ), I18N_NOOP( "Construct the sides of this polygon..." ), false } }; PolygonSideTypeConstructor::PolygonSideTypeConstructor() : StandardConstructorBase( I18N_NOOP( "Sides of a Polygon" ), I18N_NOOP( "The sides of a polygon." ), "polygonsides", margsparser ), mtype( PolygonSideType::instance() ), margsparser( argsspecps, 1 ) { } PolygonSideTypeConstructor::~PolygonSideTypeConstructor() { } void PolygonSideTypeConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const { if ( parents.size() != 1 ) return; const FilledPolygonImp* polygon = dynamic_cast( parents.front()->imp() ); const std::vector points = polygon->points(); uint sides = points.size(); for ( uint i = 0; i < sides; ++i ) { uint nexti = ( i + 1 < sides )?(i + 1):0; SegmentImp segment = SegmentImp( points[i], points[nexti] ); drawer.draw( segment, p, true ); } } std::vector PolygonSideTypeConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const { std::vector ret; assert( parents.size() == 1 ); const FilledPolygonImp* polygon = dynamic_cast( parents.front()->imp() ); const std::vector points = polygon->points(); uint sides = points.size(); for ( uint i = 0; i < sides; ++i ) { ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( i ) ); std::vector args( parents ); args.push_back( d ); ret.push_back( new ObjectHolder( new ObjectTypeCalcer( mtype, args ) ) ); } return ret; } void PolygonSideTypeConstructor::plug( KigPart*, KigGUIAction* ) { } bool PolygonSideTypeConstructor::isTransform() const { return false; } /* * polygon by center and vertex */ PolygonBCVConstructor::PolygonBCVConstructor() : mtype( PolygonBCVType::instance() ) { } PolygonBCVConstructor::~PolygonBCVConstructor() { } const QString PolygonBCVConstructor::descriptiveName() const { return i18n("Regular Polygon with Given Center"); } const QString PolygonBCVConstructor::description() const { return i18n("Construct a regular polygon with a given center and vertex"); } const QByteArray PolygonBCVConstructor::iconFileName( const bool ) const { return "hexagonbcv"; } bool PolygonBCVConstructor::isAlreadySelectedOK( const std::vector&, const uint& ) const { return false; } int PolygonBCVConstructor::wantArgs( const std::vector& os, const KigDocument&, const KigWidget& ) const { if ( os.size() > 3 ) return ArgsParser::Invalid; uint imax = ( os.size() <= 2) ? os.size() : 2; for ( uint i = 0; i < imax; ++i ) if ( ! ( os[i]->imp()->inherits( PointImp::stype() ) ) ) return ArgsParser::Invalid; if ( os.size() < 3 ) return ArgsParser::Valid; if ( ! ( os[2]->imp()->inherits( BogusPointImp::stype() ) ) ) return ArgsParser::Invalid; return ArgsParser::Complete; } void PolygonBCVConstructor::handleArgs( const std::vector& os, KigPart& d, KigWidget& v ) const { std::vector bos = build( os, d.document(), v ); for ( std::vector::iterator i = bos.begin(); i != bos.end(); ++i ) { (*i)->calc( d.document() ); } d.addObjects( bos ); } void PolygonBCVConstructor::handlePrelim( KigPainter& p, const std::vector& os, const KigDocument& d, const KigWidget& ) const { if ( os.size() < 2 ) return; for ( uint i = 0; i < 2; i++ ) { assert ( os[i]->imp()->inherits( PointImp::stype() ) ); } Coordinate c = static_cast( os[0]->imp() )->coordinate(); Coordinate v = static_cast( os[1]->imp() )->coordinate(); int nsides = 6; bool moreinfo = false; int winding = 0; // 0 means allow winding > 1 if ( os.size() == 3 ) { assert ( os[2]->imp()->inherits( BogusPointImp::stype() ) ); Coordinate cntrl = static_cast( os[2]->imp() )->coordinate(); nsides = computeNsides( c, v, cntrl, winding ); moreinfo = true; } std::vector args; args.push_back( os[0] ); args.push_back( os[1] ); ObjectConstCalcer* ns = new ObjectConstCalcer( new IntImp( nsides ) ); args.push_back( ns ); if ( winding > 1 ) { ns = new ObjectConstCalcer( new IntImp( winding ) ); args.push_back( ns ); } p.setBrushStyle( Qt::NoBrush ); p.setBrushColor( Qt::red ); p.setPen( QPen ( Qt::red, 1) ); p.setWidth( -1 ); // -1 means the default width for the object being // drawn.. ObjectDrawer drawer( Qt::red ); drawprelim( drawer, p, args, d ); if ( moreinfo ) { p.setPointStyle( Kig::RoundEmpty ); p.setWidth( 6 ); double ro = 1.0/(2.5); Coordinate where = getRotatedCoord( c, (1-ro)*c+ro*v, 4*M_PI/5.0 ); PointImp ptn = PointImp( where ); TextImp text = TextImp( "(5,2)", where, false ); ptn.draw( p ); text.draw( p ); for ( int i = 3; i < 9; ++i ) { where = getRotatedCoord( c, v, 2.0*M_PI/i ); ptn = PointImp( where ); ptn.draw( p ); if ( i > 5 ) continue; text = TextImp( QString( "(%1)" ).arg(i), where, false ); text.draw( p ); } p.setStyle( Qt::DotLine ); p.setWidth( 1 ); double radius = ( v - c ).length(); CircleImp circle = CircleImp( c, radius ); circle.draw( p ); for ( int i = 2; i < 5; i++ ) { ro = 1.0/(i+0.5); CircleImp circle = CircleImp( c, ro*radius ); circle.draw( p ); } } delete_all( args.begin() + 2, args.end() ); } std::vector PolygonBCVConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const { assert ( parents.size() == 3 ); std::vector args; Coordinate c = static_cast( parents[0]->imp() )->coordinate(); Coordinate v = static_cast( parents[1]->imp() )->coordinate(); Coordinate cntrl = static_cast( parents[2]->imp() )->coordinate(); args.push_back( parents[0] ); args.push_back( parents[1] ); int winding = 0; int nsides = computeNsides( c, v, cntrl, winding ); ObjectConstCalcer* d = new ObjectConstCalcer( new IntImp( nsides ) ); args.push_back( d ); if ( winding > 1 ) { d = new ObjectConstCalcer( new IntImp( winding ) ); args.push_back( d ); } ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, args ); ObjectHolder* h = new ObjectHolder( calcer ); std::vector ret; ret.push_back( h ); return ret; } QString PolygonBCVConstructor::useText( const ObjectCalcer&, const std::vector& os, const KigDocument&, const KigWidget& ) const { switch ( os.size() ) { case 1: return i18n( "Construct a regular polygon with this center" ); break; case 2: return i18n( "Construct a regular polygon with this vertex" ); break; case 3: Coordinate c = static_cast( os[0]->imp() )->coordinate(); Coordinate v = static_cast( os[1]->imp() )->coordinate(); Coordinate cntrl = static_cast( os[2]->imp() )->coordinate(); int winding = 0; int nsides = computeNsides( c, v, cntrl, winding ); if ( winding > 1 ) { QString result = i18n( "Adjust the number of sides (%1/%2)", nsides, winding ); return result; } else { QString result = i18n( "Adjust the number of sides (%1)", nsides ); return result; } break; } return ""; } QString PolygonBCVConstructor::selectStatement( const std::vector& os, const KigDocument&, const KigWidget& ) const { switch ( os.size() ) { case 1: return i18n( "Select the center of the new polygon..." ); break; case 2: return i18n( "Select a vertex for the new polygon..." ); break; case 3: return i18n( "Move the cursor to get the desired number of sides..." ); break; } return ""; } void PolygonBCVConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& doc ) const { if ( parents.size() < 3 || parents.size() > 4 ) return; assert ( parents[0]->imp()->inherits( PointImp::stype() ) && parents[1]->imp()->inherits( PointImp::stype() ) && parents[2]->imp()->inherits( IntImp::stype() ) ); if ( parents.size() == 4 ) assert ( parents[3]->imp()->inherits( IntImp::stype() ) ); Args args; std::transform( parents.begin(), parents.end(), std::back_inserter( args ), std::mem_fun( &ObjectCalcer::imp ) ); ObjectImp* data = mtype->calc( args, doc ); drawer.draw( *data, p, true ); delete data; data = 0; } void PolygonBCVConstructor::plug( KigPart*, KigGUIAction* ) { } bool PolygonBCVConstructor::isTransform() const { return false; } Coordinate PolygonBCVConstructor::getRotatedCoord( const Coordinate& c, const Coordinate& v, double alpha ) const { double cosalpha = cos(alpha); double sinalpha = sin(alpha); double dx = v.x - c.x; double dy = v.y - c.y; return c + Coordinate( cosalpha*dx - sinalpha*dy, sinalpha*dx + cosalpha*dy ); } int PolygonBCVConstructor::computeNsides ( const Coordinate& c, const Coordinate& v, const Coordinate& cntrl, int& winding ) const { Coordinate lvect = v - c; Coordinate rvect = cntrl - c; double angle = atan2( rvect.y, rvect.x ) - atan2( lvect.y, lvect.x ); angle = fabs( angle/(2*M_PI) ); while ( angle > 1 ) angle -= 1; if ( angle > 0.5 ) angle = 1 - angle; double realsides = 1.0/angle; // this is bigger that 2 if ( angle == 0. ) realsides = 3; if ( winding <= 0 ) // free to compute winding { winding = 1; double ratio = lvect.length()/rvect.length(); winding = int ( ratio ); if ( winding < 1 ) winding = 1; if ( winding > 50 ) winding = 50; } int nsides = int( winding*realsides + 0.5 ); // nsides/winding should be reduced! if ( nsides > 100 ) nsides = 100; // well, 100 seems large enough! if ( nsides < 3 ) nsides = 3; while ( !relativePrimes ( nsides, winding ) ) ++nsides; return nsides; } /* * generic Bézier curve constructor */ BezierCurveTypeConstructor::BezierCurveTypeConstructor() : PointSequenceConstructor( I18N_NOOP( "Bézier Curve by its Control Points" ), I18N_NOOP( "Construct a Bézier curve by giving its control points" ), "bezierN", BezierCurveType::instance() ) { } BezierCurveTypeConstructor::~BezierCurveTypeConstructor() { } bool BezierCurveTypeConstructor::isAlreadySelectedOK( const std::vector& os, const uint& pos ) const { if ( pos == os.size() - 1 && os.size() >= 3 ) return true; return false; } int BezierCurveTypeConstructor::wantArgs( const std::vector& os, const KigDocument&, const KigWidget& ) const { int count=os.size() - 1; for ( int i = 0; i <= count; i++ ) { if ( ! ( os[i]->imp()->inherits( PointImp::stype() ) ) ) return ArgsParser::Invalid; } if ( count < 3 ) return ArgsParser::Valid; if ( os[count] == os[count - 1] ) return ArgsParser::Complete; return ArgsParser::Valid; } QString BezierCurveTypeConstructor::useText( const ObjectCalcer&, const std::vector& os, const KigDocument&, const KigWidget& ) const { if ( os.size() > 3 ) return i18n("... with this control point (click again on the last control point to terminate construction)"); else return i18n("Construct a Bézier curve with this control point"); } QString BezierCurveTypeConstructor::selectStatement( const std::vector&, const KigDocument&, const KigWidget& ) const { return i18n("Select a point to be a control point of the new Bézier curve..."); } void BezierCurveTypeConstructor::drawprelim( const ObjectDrawer& , KigPainter& p, const std::vector& parents, const KigDocument& ) const { if ( parents.size() < 2 ) return; std::vector points; for ( uint i = 0; i < parents.size(); ++i ) { const Coordinate vertex = static_cast( parents[i]->imp() )->coordinate(); points.push_back( vertex ); } BezierImp B = BezierImp( points ); B.draw( p ); } /* * generic rational Bézier curve constructor */ RationalBezierCurveTypeConstructor::RationalBezierCurveTypeConstructor() { } RationalBezierCurveTypeConstructor::~RationalBezierCurveTypeConstructor() { } const QString RationalBezierCurveTypeConstructor::descriptiveName() const { return i18n( "Rational Bézier Curve by its Control Points" ); } const QString RationalBezierCurveTypeConstructor::description() const { return i18n( "Construct a Bézier curve by giving its control points and positive weights" ); } const QByteArray RationalBezierCurveTypeConstructor::iconFileName( const bool ) const { return "rbezierN"; } bool RationalBezierCurveTypeConstructor::isAlreadySelectedOK( const std::vector& os, const uint& pos ) const { if ( pos % 2 == 1 ) return true; if ( pos == os.size() - 2 && os.size() >= 3 ) return true; return false; } int RationalBezierCurveTypeConstructor::wantArgs( const std::vector& os, const KigDocument&, const KigWidget& ) const { int count=os.size() - 1; for ( int i = 0; i <= count; i++ ) { if ( ! ( os[i]->imp()->inherits( i % 2 == 0 ? PointImp::stype() : &weightimptypeinstance ) ) ) return ArgsParser::Invalid; } if ( count < 6 ) return ArgsParser::Valid; if ( count % 2 == 0 && ( os[count] == os[count - 2] ) ) return ArgsParser::Complete; return ArgsParser::Valid; } std::vector RationalBezierCurveTypeConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const { uint count = parents.size() - 1; assert ( count >= 3 ); std::vector args; for ( uint i = 0; i < count; ++i ) args.push_back( parents[i] ); ObjectTypeCalcer* calcer = new ObjectTypeCalcer( RationalBezierCurveType::instance(), args ); ObjectHolder* h = new ObjectHolder( calcer ); std::vector ret; ret.push_back( h ); return ret; } void RationalBezierCurveTypeConstructor::handleArgs( const std::vector& os, KigPart& d, KigWidget& v ) const { std::vector bos = build( os, d.document(), v ); for ( std::vector::iterator i = bos.begin(); i != bos.end(); ++i ) { (*i)->calc( d.document() ); } d.addObjects( bos ); } QString RationalBezierCurveTypeConstructor::useText( const ObjectCalcer&, const std::vector& os, const KigDocument&, const KigWidget& ) const { if ( os.size() % 2 == 0 ) return i18n("... assign this weight to last selected control point"); if ( os.size() > 6 ) return i18n("... with this control point (click again on the last control point or weight to terminate construction)"); else return i18n("Construct a rational Bézier curve with this control point"); } QString RationalBezierCurveTypeConstructor::selectStatement( const std::vector& os, const KigDocument&, const KigWidget& ) const { if ( os.size() % 2 == 0 ) return i18n("Select a point to be a control point of the new rational Bézier curve..."); else return i18n("Select a numeric label to be a weight of last selected point..."); } void RationalBezierCurveTypeConstructor::drawprelim( const ObjectDrawer& , KigPainter& p, const std::vector& parents, const KigDocument& ) const { if ( parents.size() < 5 ) return; std::vector points; std::vector weights; uint count = parents.size(); for ( uint i = 0; i < count; i += 2 ) { bool valid; assert ( parents[i]->imp()->inherits( PointImp::stype() ) ); const Coordinate vertex = static_cast( parents[i]->imp() )->coordinate(); points.push_back( vertex ); if ( i+1 >= count ) break; assert ( parents[i+1]->imp()->inherits( &weightimptypeinstance ) ); const double weight = getDoubleFromImp( parents[i+1]->imp(), valid ); assert ( valid ); weights.push_back( weight ); } if ( count % 2 == 1 ) { // point was selected, we weights.push_back( 1 ); // don't have its weight so far } assert ( points.size() == weights.size() ); RationalBezierImp rB = RationalBezierImp( points, weights ); rB.draw( p ); } void RationalBezierCurveTypeConstructor::handlePrelim( KigPainter& p, const std::vector& os, const KigDocument& d, const KigWidget& ) const { uint count = os.size(); if ( count < 5 ) return; for ( uint i = 0; i < count; i += 2 ) { assert ( os[i]->imp()->inherits( PointImp::stype() ) ); if ( i+1 >= count ) break; assert ( os[i+1]->imp()->inherits( &weightimptypeinstance ) ); } std::vector args = os; p.setBrushStyle( Qt::NoBrush ); p.setBrushColor( Qt::red ); p.setPen( QPen ( Qt::red, 1) ); p.setWidth( -1 ); // -1 means the default width for the object being // drawn.. ObjectDrawer drawer( Qt::red ); drawprelim( drawer, p, args, d ); } void RationalBezierCurveTypeConstructor::plug( KigPart*, KigGUIAction* ) { } bool RationalBezierCurveTypeConstructor::isTransform() const { return false; } /* * ConicConic intersection... */ static const ArgsParser::spec argsspectc[] = { { ConicImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", true }, { ConicImp::stype(), "SHOULD NOT BE SEEN", "SHOULD NOT BE SEEN", true } }; ConicConicIntersectionConstructor::ConicConicIntersectionConstructor() : StandardConstructorBase( "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "curvelineintersection", mparser ), mparser( argsspectc, 2 ) { } ConicConicIntersectionConstructor::~ConicConicIntersectionConstructor() { } void ConicConicIntersectionConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const { if ( parents.size() != 2 ) return; assert ( parents[0]->imp()->inherits( ConicImp::stype() ) && parents[1]->imp()->inherits( ConicImp::stype() ) ); const ConicCartesianData conica = static_cast( parents[0]->imp() )->cartesianData(); const ConicCartesianData conicb = static_cast( parents[1]->imp() )->cartesianData(); bool ok = true; for ( int wr = -1; wr < 2; wr += 2 ) { LineData radical = calcConicRadical( conica, conicb, wr, 1, ok ); if ( ok ) { for ( int wi = -1; wi < 2; wi += 2 ) { Coordinate c = calcConicLineIntersect( conica, radical, 0.0, wi ); if ( c.valid() ) { PointImp pi( c ); drawer.draw( pi, p, true ); } }; }; }; } std::vector ConicConicIntersectionConstructor::build( const std::vector& os, KigDocument& doc, KigWidget& ) const { assert( os.size() == 2 ); std::vector ret; ObjectCalcer* conica = os[0]; ObjectConstCalcer* zeroindexdo = new ObjectConstCalcer( new IntImp( 1 ) ); for ( int wr = -1; wr < 2; wr += 2 ) { std::vector args = os; args.push_back( new ObjectConstCalcer( new IntImp( wr ) ) ); args.push_back( zeroindexdo ); ObjectTypeCalcer* radical = new ObjectTypeCalcer( ConicRadicalType::instance(), args ); radical->calc( doc ); for ( int wi = -1; wi < 2; wi += 2 ) { args.clear(); args.push_back( conica ); args.push_back( radical ); args.push_back( new ObjectConstCalcer( new IntImp( wi ) ) ); ret.push_back( new ObjectHolder( new ObjectTypeCalcer( ConicLineIntersectionType::instance(), args ) ) ); }; }; return ret; } void ConicConicIntersectionConstructor::plug( KigPart*, KigGUIAction* ) { } bool ConicConicIntersectionConstructor::isTransform() const { return false; } ConicLineIntersectionConstructor::ConicLineIntersectionConstructor() : MultiObjectTypeConstructor( ConicLineIntersectionType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "curvelineintersection", -1, 1 ) { } ConicLineIntersectionConstructor::~ConicLineIntersectionConstructor() { } ArcLineIntersectionConstructor::ArcLineIntersectionConstructor() : MultiObjectTypeConstructor( ArcLineIntersectionType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "curvelineintersection", -1, 1 ) { } ArcLineIntersectionConstructor::~ArcLineIntersectionConstructor() { } QString ConicRadicalConstructor::useText( const ObjectCalcer& o, const std::vector&, const KigDocument&, const KigWidget& ) const { if ( o.imp()->inherits( CircleImp::stype() ) ) return i18n( "Construct the Radical Lines of This Circle" ); else return i18n( "Construct the Radical Lines of This Conic" ); } /* * generic affinity and generic projectivity. A unique affinity can be * obtained by specifying the image of three points (four for projectivity) * in the end we need, besides the object to be transformed, a total of * six point or (alternatively) two triangles; our affinity will map the * first triangle onto the second with corresponding ordering of their * vertices. Since we allow for two different ways of specifying the six * points we shall use a Generic constructor, like that for intersections. */ GenericAffinityConstructor::GenericAffinityConstructor() : MergeObjectConstructor( I18N_NOOP( "Generic Affinity" ), I18N_NOOP( "The unique affinity that maps three points (or a triangle) onto three other points (or a triangle)" ), "genericaffinity" ) { SimpleObjectTypeConstructor* b2tr = new SimpleObjectTypeConstructor( AffinityB2TrType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "genericaffinity" ); SimpleObjectTypeConstructor* gi3p = new SimpleObjectTypeConstructor( AffinityGI3PType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "genericaffinity" ); merge( b2tr ); merge( gi3p ); } GenericAffinityConstructor::~GenericAffinityConstructor() {} bool GenericAffinityConstructor::isAlreadySelectedOK(const std::vector< ObjectCalcer* >& , const uint& ) const { return true; } GenericProjectivityConstructor::GenericProjectivityConstructor() : MergeObjectConstructor( I18N_NOOP( "Generic Projective Transformation" ), I18N_NOOP( "The unique projective transformation that maps four points (or a quadrilateral) onto four other points (or a quadrilateral)" ), "genericprojectivity" ) { SimpleObjectTypeConstructor* b2qu = new SimpleObjectTypeConstructor( ProjectivityB2QuType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "genericprojectivity" ); SimpleObjectTypeConstructor* gi4p = new SimpleObjectTypeConstructor( ProjectivityGI4PType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "genericprojectivity" ); merge( b2qu ); merge( gi4p ); } GenericProjectivityConstructor::~GenericProjectivityConstructor() {} bool GenericProjectivityConstructor::isAlreadySelectedOK(const std::vector< ObjectCalcer* >& , const uint& ) const { return true; } /* * inversion of points, lines with respect to a circle */ InversionConstructor::InversionConstructor() : MergeObjectConstructor( I18N_NOOP( "Inversion of Point, Line or Circle" ), I18N_NOOP( "The inversion of a point, line or circle with respect to a circle" ), "inversion" ) { SimpleObjectTypeConstructor* pointobj = new SimpleObjectTypeConstructor( InvertPointType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "inversion" ); SimpleObjectTypeConstructor* curveobj = new SimpleObjectTypeConstructor( CircularInversionType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "inversion" ); // SimpleObjectTypeConstructor* lineobj = // new SimpleObjectTypeConstructor( // InvertLineType::instance(), // "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", // "inversion" ); // // SimpleObjectTypeConstructor* segmentobj = // new SimpleObjectTypeConstructor( // InvertSegmentType::instance(), // "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", // "inversion" ); // // SimpleObjectTypeConstructor* circleobj = // new SimpleObjectTypeConstructor( // InvertCircleType::instance(), // "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", // "inversion" ); // // SimpleObjectTypeConstructor* arcobj = // new SimpleObjectTypeConstructor( // InvertArcType::instance(), // "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", // "inversion" ); // merge( arcobj ); // merge( circleobj ); merge( curveobj ); merge( pointobj ); // merge( segmentobj ); // merge( lineobj ); } InversionConstructor::~InversionConstructor() {} /* * Transport of Measure */ MeasureTransportConstructor::MeasureTransportConstructor() : mtype( MeasureTransportType::instance() ) { } MeasureTransportConstructor::~MeasureTransportConstructor() { } const QString MeasureTransportConstructor::descriptiveName() const { return i18n("Measure Transport"); } const QString MeasureTransportConstructor::description() const { return i18n("Transport the measure of a segment or arc over a line or circle."); } const QByteArray MeasureTransportConstructor::iconFileName( const bool ) const { return "measuretransport"; } bool MeasureTransportConstructor::isAlreadySelectedOK( const std::vector&, const uint& ) const { return false; } /* * we want the arguments in the exact order, this makes * the code simpler, but I guess it is also less confusing * to the user */ int MeasureTransportConstructor::wantArgs( const std::vector& os, const KigDocument& doc, const KigWidget& ) const { if ( os.size() == 0 ) return ArgsParser::Valid; if ( ! os[0]->imp()->inherits( &lengthimptypeinstance ) ) return ArgsParser::Invalid; if ( os.size() == 1 ) return ArgsParser::Valid; if ( ! os[1]->imp()->inherits( LineImp::stype() ) && ! os[1]->imp()->inherits( CircleImp::stype() ) ) return ArgsParser::Invalid; const CurveImp* c = static_cast( os[1]->imp() ); if ( os.size() == 2 ) return ArgsParser::Valid; if ( ! os[2]->imp()->inherits( PointImp::stype() ) ) return ArgsParser::Invalid; const PointImp* p = static_cast( os[2]->imp() ); // we have two choices: // - using "isPointOnCurve" produces a "by construction" incidence // test. This would be fine, but doesn't always work; e.g. if we // have two points A, B, the segment s = AB and we construct the // support line of the segment (property of segments), then kig // is not able to understand that A is "by construction" on the // constructed line. // Moreover there are problems when hovering the cursor over points // that are on both a segment and its support line. // if ( ! isPointOnCurve( os[2], os[1] ) ) // - using "containsPoint", which is actually the test performed // when calc-ing the TransportOfMeasure; the risk here is to // be able to select points that are only coincidentally on the line. if ( ! c->containsPoint( p->coordinate(), doc ) ) return ArgsParser::Invalid; if ( os.size() == 3 ) return ArgsParser::Complete; return ArgsParser::Invalid; } void MeasureTransportConstructor::handleArgs( const std::vector& os, KigPart& d, KigWidget& v ) const { std::vector bos = build( os, d.document(), v ); for ( std::vector::iterator i = bos.begin(); i != bos.end(); ++i ) { (*i)->calc( d.document() ); } d.addObjects( bos ); } void MeasureTransportConstructor::handlePrelim( KigPainter& p, const std::vector& os, const KigDocument& d, const KigWidget& ) const { p.setBrushStyle( Qt::NoBrush ); p.setBrushColor( Qt::red ); p.setPen( QPen ( Qt::red, 1) ); p.setWidth( -1 ); // -1 means the default width for the object being // drawn.. ObjectDrawer drawer( Qt::red ); drawprelim( drawer, p, os, d ); } void MeasureTransportConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& doc ) const { Args args; using namespace std; transform( parents.begin(), parents.end(), back_inserter( args ), mem_fun( &ObjectCalcer::imp ) ); ObjectImp* data = mtype->calc( args, doc ); drawer.draw( *data, p, true ); delete data; } QString MeasureTransportConstructor::useText( const ObjectCalcer& o, const std::vector& os, const KigDocument&, const KigWidget& ) const { if ( o.imp()->inherits( SegmentImp::stype() ) ) return i18n("Segment to transport"); if ( o.imp()->inherits( ArcImp::stype() ) ) return i18n("Arc to transport"); if ( o.imp()->inherits( NumericTextImp::stype() ) ) return i18n("Value to transport"); if ( o.imp()->inherits( LineImp::stype() ) ) return i18n("Transport a measure on this line"); if ( o.imp()->inherits( CircleImp::stype() ) ) return i18n("Transport a measure on this circle"); if ( o.imp()->inherits( PointImp::stype() ) ) { if ( os[1]->imp()->inherits( CircleImp::stype() ) ) return i18n("Start transport from this point of the circle"); if ( os[1]->imp()->inherits( LineImp::stype() ) ) return i18n("Start transport from this point of the line"); else return i18n("Start transport from this point of the curve"); // well, this isn't impemented yet, should never get here } return ""; } QString MeasureTransportConstructor::selectStatement( const std::vector& os, const KigDocument&, const KigWidget& ) const { switch ( os.size() ) { case 0: return i18n( "Select a segment, arc or numeric label to be transported..." ); break; case 1: return i18n( "Select a destination line or circle..." ); break; case 2: return i18n( "Choose a starting point on the line/circle..." ); break; } return ""; } std::vector MeasureTransportConstructor::build( const std::vector& parents, KigDocument&, KigWidget& ) const { assert ( parents.size() == 3 ); // std::vector args; // for ( uint i = 0; i < count; ++i ) args.push_back( parents[i] ); ObjectTypeCalcer* calcer = new ObjectTypeCalcer( mtype, parents ); ObjectHolder* h = new ObjectHolder( calcer ); std::vector ret; ret.push_back( h ); return ret; } void MeasureTransportConstructor::plug( KigPart*, KigGUIAction* ) { } bool MeasureTransportConstructor::isTransform() const { return false; } /* * Generic intersection */ /* * these two argsparser spec vectors are used for the special * construction of conic-line and circle-circle constructions */ static const struct ArgsParser::spec argsspeccli[] = { { ConicImp::stype(), I18N_NOOP( "Intersect with this conic" ), "SHOULD NOT BE SEEN", true }, { AbstractLineImp::stype(), I18N_NOOP( "Intersect with this line" ), "SHOULD NOT BE SEEN", true } }; static const struct ArgsParser::spec argsspeccbli[] = { { CubicImp::stype(), I18N_NOOP( "Intersect with this cubic" ), "SHOULD NOT BE SEEN", true }, { AbstractLineImp::stype(), I18N_NOOP( "Intersect with this line" ), "SHOULD NOT BE SEEN", true } }; static const struct ArgsParser::spec argsspeccci[] = { { CircleImp::stype(), I18N_NOOP( "Intersect with this circle" ), "SHOULD NOT BE SEEN", true }, { CircleImp::stype(), I18N_NOOP( "Intersect with this circle" ), "SHOULD NOT BE SEEN", true } }; GenericIntersectionConstructor::GenericIntersectionConstructor() : MergeObjectConstructor( I18N_NOOP( "Intersect" ), I18N_NOOP( "The intersection of two objects" ), "curvelineintersection" ) { // intersection type.. // There is one "toplevel" object_constructor, that is composed // of multiple subconstructors.. First we build the // subconstructors: SimpleObjectTypeConstructor* lineline = new SimpleObjectTypeConstructor( LineLineIntersectionType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "curvelineintersection" ); ObjectConstructor* lineconic = // new ConicLineIntersectionConstructor(); new TwoOrOneIntersectionConstructor( ConicLineIntersectionType::instance(), ConicLineOtherIntersectionType::instance(), "curvelineintersection", argsspeccli); ObjectConstructor* arcline = new ArcLineIntersectionConstructor(); ObjectConstructor* linecubic = new ThreeTwoOneIntersectionConstructor( CubicLineIntersectionType::instance(), CubicLineOtherIntersectionType::instance(), "curvelineintersection", argsspeccbli); ObjectConstructor* conicconic = new ConicConicIntersectionConstructor(); // MultiObjectTypeConstructor* circlecircle = // new MultiObjectTypeConstructor( // CircleCircleIntersectionType::instance(), // "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", // "circlecircleintersection", -1, 1 ); ObjectConstructor* circlecircle = new TwoOrOneIntersectionConstructor( CircleCircleIntersectionType::instance(), CircleCircleOtherIntersectionType::instance(), "circlecircleintersection", argsspeccci); SimpleObjectTypeConstructor* polygonline = new SimpleObjectTypeConstructor( PolygonLineIntersectionType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "curvelineintersection" ); SimpleObjectTypeConstructor* polygonpolygon = new SimpleObjectTypeConstructor( PolygonPolygonIntersectionType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "curvelineintersection" ); MultiObjectTypeConstructor* opolygonalline = new MultiObjectTypeConstructor( OPolygonalLineIntersectionType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "curvelineintersection", -1, 1 ); MultiObjectTypeConstructor* cpolygonalline = new MultiObjectTypeConstructor( CPolygonalLineIntersectionType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "curvelineintersection", -1, 1 ); merge( lineline ); merge( circlecircle ); merge( lineconic ); merge( linecubic ); merge( conicconic ); merge( arcline ); merge( polygonline ); merge( opolygonalline ); merge( cpolygonalline ); merge( polygonpolygon ); } GenericIntersectionConstructor::~GenericIntersectionConstructor() { } bool GenericIntersectionConstructor::isIntersection() const { return true; } QString GenericIntersectionConstructor::useText( const ObjectCalcer& o, const std::vector& os, const KigDocument&, const KigWidget& ) const { QString preamble; switch (os.size()) { case 1: if ( o.imp()->inherits( CircleImp::stype() ) ) return i18n( "Intersect this Circle" ); else if ( o.imp()->inherits( ConicImp::stype() ) ) return i18n( "Intersect this Conic" ); else if ( o.imp()->inherits( SegmentImp::stype() ) ) return i18n( "Intersect this Segment" ); else if ( o.imp()->inherits( RayImp::stype() ) ) return i18n( "Intersect this Half-line" ); else if ( o.imp()->inherits( LineImp::stype() ) ) return i18n( "Intersect this Line" ); else if ( o.imp()->inherits( CubicImp::stype() ) ) return i18n( "Intersect this Cubic Curve" ); else if ( o.imp()->inherits( ArcImp::stype() ) ) return i18n( "Intersect this Arc" ); else if ( o.imp()->inherits( FilledPolygonImp::stype() ) ) return i18n( "Intersect this Polygon" ); else if ( o.imp()->inherits( AbstractPolygonImp::stype() ) ) return i18n( "Intersect this Polygonal" ); else assert( false ); break; case 2: if ( o.imp()->inherits( CircleImp::stype() ) ) return i18n( "with this Circle" ); else if ( o.imp()->inherits( ConicImp::stype() ) ) return i18n( "with this Conic" ); else if ( o.imp()->inherits( SegmentImp::stype() ) ) return i18n( "with this Segment" ); else if ( o.imp()->inherits( RayImp::stype() ) ) return i18n( "with this Half-line" ); else if ( o.imp()->inherits( LineImp::stype() ) ) return i18n( "with this Line" ); else if ( o.imp()->inherits( CubicImp::stype() ) ) return i18n( "with this Cubic Curve" ); else if ( o.imp()->inherits( ArcImp::stype() ) ) return i18n( "with this Arc" ); else if ( o.imp()->inherits( FilledPolygonImp::stype() ) ) return i18n( "with this Polygon" ); else if ( o.imp()->inherits( AbstractPolygonImp::stype() ) ) return i18n( "with this Polygonal" ); else assert( false ); break; } return QString(); } static const ArgsParser::spec argsspecMidPointOfTwoPoints[] = { - { PointImp::stype(), I18N_NOOP( "Construct Midpoint of This Point and Another One" ), + { PointImp::stype(), I18N_NOOP( "Construct midpoint of this point and another one" ), I18N_NOOP( "Select the first of the points of which you want to construct the midpoint..." ), false }, { PointImp::stype(), I18N_NOOP( "Construct the midpoint of this point and another one" ), I18N_NOOP( "Select the other of the points of which to construct the midpoint..." ), false } }; MidPointOfTwoPointsConstructor::MidPointOfTwoPointsConstructor() : StandardConstructorBase( "Mid Point", "Construct the midpoint of two points", "bisection", mparser ), mparser( argsspecMidPointOfTwoPoints, 2 ) { } MidPointOfTwoPointsConstructor::~MidPointOfTwoPointsConstructor() { } void MidPointOfTwoPointsConstructor::drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const { if ( parents.size() != 2 ) return; assert( parents[0]->imp()->inherits( PointImp::stype() ) ); assert( parents[1]->imp()->inherits( PointImp::stype() ) ); const Coordinate m = ( static_cast( parents[0]->imp() )->coordinate() + static_cast( parents[1]->imp() )->coordinate() ) / 2; drawer.draw( PointImp( m ), p, true ); } std::vector MidPointOfTwoPointsConstructor::build( const std::vector& os, KigDocument& d, KigWidget& ) const { ObjectTypeCalcer* seg = new ObjectTypeCalcer( SegmentABType::instance(), os ); seg->calc( d ); // int index = seg->imp()->propertiesInternalNames().indexOf( "mid-point" ); // assert( index != -1 ); ObjectPropertyCalcer* prop = new ObjectPropertyCalcer( seg, "mid-point" ); prop->calc( d ); std::vector ret; ret.push_back( new ObjectHolder( prop ) ); return ret; } void MidPointOfTwoPointsConstructor::plug( KigPart*, KigGUIAction* ) { } bool MidPointOfTwoPointsConstructor::isTransform() const { return false; } +static const ArgsParser::spec argsspecGoldenPointOfTwoPoints[] = +{ + { PointImp::stype(), I18N_NOOP( "Construct golden ratio point of this point and another one" ), + I18N_NOOP( "Select the first of the points of which you want to construct the golden ratio point..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct the golden ratio point of this point and another one" ), + I18N_NOOP( "Select the other of the points of which to construct the golden ratio point..." ), false } +}; + +GoldenPointOfTwoPointsConstructor::GoldenPointOfTwoPointsConstructor() + : StandardConstructorBase( "Golden Ratio Point", + "Construct the golden ratio point of two points", + "bisection", mparser ), + mparser( argsspecGoldenPointOfTwoPoints, 2 ) +{ +} + +GoldenPointOfTwoPointsConstructor::~GoldenPointOfTwoPointsConstructor() +{ +} + +void GoldenPointOfTwoPointsConstructor::drawprelim( + const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& ) const +{ + if ( parents.size() != 2 ) return; + assert( parents[0]->imp()->inherits( PointImp::stype() ) ); + assert( parents[1]->imp()->inherits( PointImp::stype() ) ); + const Coordinate m = + ( static_cast( parents[0]->imp() )->coordinate() + + (sqrt(5) - 1) / 2 * + ( static_cast( parents[1]->imp() )->coordinate() - + static_cast( parents[0]->imp() )->coordinate() + ) + ); + drawer.draw( PointImp( m ), p, true ); +} + +std::vector GoldenPointOfTwoPointsConstructor::build( + const std::vector& os, KigDocument& d, KigWidget& ) const +{ + ObjectTypeCalcer* seg = new ObjectTypeCalcer( SegmentABType::instance(), os ); + seg->calc( d ); +// int index = seg->imp()->propertiesInternalNames().indexOf( "golden-point" ); +// assert( index != -1 ); + ObjectPropertyCalcer* prop = new ObjectPropertyCalcer( seg, "golden-point" ); + prop->calc( d ); + std::vector ret; + ret.push_back( new ObjectHolder( prop ) ); + return ret; +} + +void GoldenPointOfTwoPointsConstructor::plug( KigPart*, KigGUIAction* ) +{ +} + +bool GoldenPointOfTwoPointsConstructor::isTransform() const +{ + return false; +} + TestConstructor::TestConstructor( const ArgsParserObjectType* type, const char* descname, const char* desc, const char* iconfile ) : StandardConstructorBase( descname, desc, iconfile, type->argsParser() ), mtype( type ) { } TestConstructor::~TestConstructor() { } void TestConstructor::drawprelim( const ObjectDrawer&, KigPainter&, const std::vector&, const KigDocument& ) const { // not used, only here because of the wrong // ObjectConstructor-GUIAction design. See the TODO } std::vector TestConstructor::build( const std::vector&, KigDocument&, KigWidget& ) const { // not used, only here because of the wrong // ObjectConstructor-GUIAction design. See the TODO std::vector ret; return ret; } void TestConstructor::plug( KigPart*, KigGUIAction* ) { } bool TestConstructor::isTransform() const { return false; } bool TestConstructor::isTest() const { return true; } BaseConstructMode* TestConstructor::constructMode( KigPart& doc ) { return new TestConstructMode( doc, mtype ); } int TestConstructor::wantArgs( const std::vector& os, const KigDocument& d, const KigWidget& v ) const { int ret = StandardConstructorBase::wantArgs( os, d, v ); if ( ret == ArgsParser::Complete ) ret = ArgsParser::Valid; return ret; } QString GenericIntersectionConstructor::selectStatement( const std::vector& sel, const KigDocument&, const KigWidget& ) const { if ( sel.size() == 0 ) return i18n( "Select the first object to intersect..." ); else return i18n( "Select the second object to intersect..." ); } TangentConstructor::TangentConstructor() : MergeObjectConstructor( I18N_NOOP( "Tangent" ), I18N_NOOP( "The line tangent to a curve" ), "tangent" ) { SimpleObjectTypeConstructor* conic = new SimpleObjectTypeConstructor( TangentConicType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "tangentconic" ); SimpleObjectTypeConstructor* arc = new SimpleObjectTypeConstructor( TangentArcType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "tangentarc" ); SimpleObjectTypeConstructor* cubic = new SimpleObjectTypeConstructor( TangentCubicType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "tangentcubic" ); SimpleObjectTypeConstructor* curve = new SimpleObjectTypeConstructor( TangentCurveType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "tangentcurve" ); merge( conic ); merge( arc ); merge( cubic ); merge( curve ); } TangentConstructor::~TangentConstructor() { } QString TangentConstructor::useText( const ObjectCalcer& o, const std::vector&, const KigDocument&, const KigWidget& ) const { if ( o.imp()->inherits( CircleImp::stype() ) ) return i18n( "Tangent to This Circle" ); else if ( o.imp()->inherits( ConicImp::stype() ) ) return i18n( "Tangent to This Conic" ); else if ( o.imp()->inherits( ArcImp::stype() ) ) return i18n( "Tangent to This Arc" ); else if ( o.imp()->inherits( CubicImp::stype() ) ) return i18n( "Tangent to This Cubic Curve" ); else if ( o.imp()->inherits( CurveImp::stype() ) ) return i18n( "Tangent to This Curve" ); else if ( o.imp()->inherits( PointImp::stype() ) ) return i18n( "Tangent at This Point" ); // else assert( false ); return QString(); } //QString TangentConstructor::selectStatement( // const std::vector& sel, const KigDocument&, // const KigWidget& ) const //{ // if ( sel.size() == 0 ) // return i18n( "Select the object..." ); // else // return i18n( "Select the point for the tangent to go through..." ); //} /* * center of curvature of a curve */ CocConstructor::CocConstructor() : MergeObjectConstructor( I18N_NOOP( "Center Of Curvature" ), I18N_NOOP( "The center of the osculating circle to a curve" ), "centerofcurvature" ) { SimpleObjectTypeConstructor* conic = new SimpleObjectTypeConstructor( CocConicType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "cocconic" ); SimpleObjectTypeConstructor* cubic = new SimpleObjectTypeConstructor( CocCubicType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "coccubic" ); SimpleObjectTypeConstructor* curve = new SimpleObjectTypeConstructor( CocCurveType::instance(), "SHOULDNOTBESEEN", "SHOULDNOTBESEEN", "coccurve" ); merge( conic ); merge( cubic ); merge( curve ); } CocConstructor::~CocConstructor() { } QString CocConstructor::useText( const ObjectCalcer& o, const std::vector&, const KigDocument&, const KigWidget& ) const { if ( o.imp()->inherits( ConicImp::stype() ) ) return i18n( "Center of Curvature of This Conic" ); else if ( o.imp()->inherits( CubicImp::stype() ) ) return i18n( "Center of Curvature of This Cubic Curve" ); else if ( o.imp()->inherits( CurveImp::stype() ) ) return i18n( "Center of Curvature of This Curve" ); else if ( o.imp()->inherits( PointImp::stype() ) ) return i18n( "Center of Curvature at This Point" ); return QString(); } bool relativePrimes( int n, int p ) { if ( p > n ) return relativePrimes( p, n ); assert ( p >= 0 ); if ( p == 0 ) return false; if ( p == 1 ) return true; int d = int( n/p ); return relativePrimes( p, n-d*p ); } //QString CocConstructor::selectStatement( // const std::vector& sel, const KigDocument&, // const KigWidget& ) const //{ // if ( sel.size() == 0 ) // return i18n( "Select the object..." ); // else // return i18n( "Select the point where to compute the center of curvature..." ); //} diff --git a/misc/special_constructors.h b/misc/special_constructors.h index f333a1f9..a61d2298 100644 --- a/misc/special_constructors.h +++ b/misc/special_constructors.h @@ -1,467 +1,482 @@ // Copyright (C) 2003 Dominique Devriese // This program 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 2 // of the License, or (at your option) any later version. // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301, USA. #ifndef KIG_MISC_SPECIAL_CONSTRUCTORS_H #define KIG_MISC_SPECIAL_CONSTRUCTORS_H #include "object_constructor.h" class TwoOrOneIntersectionConstructor : public StandardConstructorBase { const ArgsParserObjectType* mtype_std; const ArgsParserObjectType* mtype_special; ArgsParser margsparser; public: TwoOrOneIntersectionConstructor( const ArgsParserObjectType* t_std, const ArgsParserObjectType* t_special, const char* iconfile, const struct ArgsParser::spec argsspecv[] ); ~TwoOrOneIntersectionConstructor(); void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const Q_DECL_OVERRIDE; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const Q_DECL_OVERRIDE; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; }; class ThreeTwoOneIntersectionConstructor : public StandardConstructorBase { const ArgsParserObjectType* mtype_std; const ArgsParserObjectType* mtype_special; ArgsParser margsparser; public: ThreeTwoOneIntersectionConstructor( const ArgsParserObjectType* t_std, const ArgsParserObjectType* t_special, const char* iconfile, const struct ArgsParser::spec argsspecv[] ); ~ThreeTwoOneIntersectionConstructor(); void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const Q_DECL_OVERRIDE; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const Q_DECL_OVERRIDE; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; }; class PolygonVertexTypeConstructor : public StandardConstructorBase { const ArgsParserObjectType* mtype; ArgsParser margsparser; public: PolygonVertexTypeConstructor(); ~PolygonVertexTypeConstructor(); void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const Q_DECL_OVERRIDE; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const Q_DECL_OVERRIDE; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; }; class PolygonSideTypeConstructor : public StandardConstructorBase { const ArgsParserObjectType* mtype; ArgsParser margsparser; public: PolygonSideTypeConstructor(); ~PolygonSideTypeConstructor(); void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const Q_DECL_OVERRIDE; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const Q_DECL_OVERRIDE; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; }; /* */ class PointSequenceConstructor : public ObjectConstructor { const char* mdescname; const char* mdesc; const char* miconfile; const ObjectType* mtype; public: PointSequenceConstructor( const char* descname, const char* desc, const char* iconfile, const ObjectType* type ); const QString descriptiveName() const Q_DECL_OVERRIDE; const QString description() const Q_DECL_OVERRIDE; const QByteArray iconFileName( const bool canBeNull = false ) const Q_DECL_OVERRIDE; void handleArgs( const std::vector& os, KigPart& d, KigWidget& v ) const Q_DECL_OVERRIDE; void handlePrelim( KigPainter& p, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; // TODO: move here actual drawprelm when AbstractPolygon is in place! virtual void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const = 0; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; }; /* * classes PolygonBNPTypeConstructor, OpenPolygonTypeConstructor and * BezierCurveTypeConstructor * all inherit from the PointSequenceConstructor */ class PolygonBNPTypeConstructor : public PointSequenceConstructor { public: PolygonBNPTypeConstructor(); ~PolygonBNPTypeConstructor(); bool isAlreadySelectedOK( const std::vector& os, const uint& ) const Q_DECL_OVERRIDE; int wantArgs( const std::vector& os, const KigDocument& d, const KigWidget& v) const Q_DECL_OVERRIDE; QString useText( const ObjectCalcer& o, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; QString selectStatement( const std::vector& sel, const KigDocument& d, const KigWidget& w ) const Q_DECL_OVERRIDE; void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const Q_DECL_OVERRIDE; }; class OpenPolygonTypeConstructor : public PointSequenceConstructor { public: OpenPolygonTypeConstructor(); ~OpenPolygonTypeConstructor(); bool isAlreadySelectedOK( const std::vector& os, const uint& ) const Q_DECL_OVERRIDE; int wantArgs( const std::vector& os, const KigDocument& d, const KigWidget& v) const Q_DECL_OVERRIDE; QString useText( const ObjectCalcer& o, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; QString selectStatement( const std::vector& sel, const KigDocument& d, const KigWidget& w ) const Q_DECL_OVERRIDE; void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const Q_DECL_OVERRIDE; }; class PolygonBCVConstructor : public ObjectConstructor { const ObjectType* mtype; public: PolygonBCVConstructor(); ~PolygonBCVConstructor(); const QString descriptiveName() const Q_DECL_OVERRIDE; const QString description() const Q_DECL_OVERRIDE; const QByteArray iconFileName( const bool canBeNull = false ) const Q_DECL_OVERRIDE; bool isAlreadySelectedOK( const std::vector& os, const uint& ) const Q_DECL_OVERRIDE; int wantArgs( const std::vector& os, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; void handleArgs( const std::vector& os, KigPart& d, KigWidget& v ) const Q_DECL_OVERRIDE; QString useText( const ObjectCalcer& o, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; QString selectStatement( const std::vector& sel, const KigDocument& d, const KigWidget& w ) const Q_DECL_OVERRIDE; void handlePrelim( KigPainter& p, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; int computeNsides( const Coordinate& c, const Coordinate& v, const Coordinate& cntrl, int& winding ) const; Coordinate getRotatedCoord( const Coordinate& c1, const Coordinate& c2, double alpha ) const; }; class BezierCurveTypeConstructor : public PointSequenceConstructor { public: BezierCurveTypeConstructor(); ~BezierCurveTypeConstructor(); bool isAlreadySelectedOK( const std::vector& os, const uint& ) const Q_DECL_OVERRIDE; int wantArgs( const std::vector& os, const KigDocument& d, const KigWidget& v) const Q_DECL_OVERRIDE; QString useText( const ObjectCalcer& o, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; QString selectStatement( const std::vector& sel, const KigDocument& d, const KigWidget& w ) const Q_DECL_OVERRIDE; void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const Q_DECL_OVERRIDE; }; class RationalBezierCurveTypeConstructor : public ObjectConstructor { public: RationalBezierCurveTypeConstructor(); ~RationalBezierCurveTypeConstructor(); const QString descriptiveName() const Q_DECL_OVERRIDE; const QString description() const Q_DECL_OVERRIDE; const QByteArray iconFileName( const bool canBeNull = false ) const Q_DECL_OVERRIDE; bool isAlreadySelectedOK( const std::vector& os, const uint& ) const Q_DECL_OVERRIDE; int wantArgs( const std::vector& os, const KigDocument& d, const KigWidget& v) const Q_DECL_OVERRIDE; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const; void handleArgs( const std::vector& os, KigPart& d, KigWidget& v ) const Q_DECL_OVERRIDE; QString useText( const ObjectCalcer& o, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; QString selectStatement( const std::vector& sel, const KigDocument& d, const KigWidget& w ) const Q_DECL_OVERRIDE; void handlePrelim( KigPainter& p, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& d ) const; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; }; class MeasureTransportConstructor : public ObjectConstructor { const ObjectType* mtype; public: MeasureTransportConstructor(); ~MeasureTransportConstructor(); const QString descriptiveName() const Q_DECL_OVERRIDE; const QString description() const Q_DECL_OVERRIDE; const QByteArray iconFileName( const bool canBeNull = false ) const Q_DECL_OVERRIDE; bool isAlreadySelectedOK( const std::vector& os, const uint& ) const Q_DECL_OVERRIDE; int wantArgs( const std::vector& os, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; void handleArgs( const std::vector& os, KigPart& d, KigWidget& v ) const Q_DECL_OVERRIDE; QString useText( const ObjectCalcer& o, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; QString selectStatement( const std::vector& sel, const KigDocument& d, const KigWidget& w ) const Q_DECL_OVERRIDE; void handlePrelim( KigPainter& p, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; }; class ConicRadicalConstructor : public StandardConstructorBase { const ArgsParserObjectType* mtype; const ArgsParser mparser; public: ConicRadicalConstructor(); ~ConicRadicalConstructor(); QString useText( const ObjectCalcer& o, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const Q_DECL_OVERRIDE; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const Q_DECL_OVERRIDE; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; }; class LocusConstructor : public StandardConstructorBase { ArgsParser margsparser; public: LocusConstructor(); ~LocusConstructor(); /** * we override the wantArgs() function, since we need to see * something about the objects that an ArgsParser can't know about, * namely, whether the first point is a constrained point... */ int wantArgs( const std::vector& os, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; QString useText( const ObjectCalcer& o, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const Q_DECL_OVERRIDE; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const Q_DECL_OVERRIDE; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; }; class GenericAffinityConstructor : public MergeObjectConstructor { public: GenericAffinityConstructor(); ~GenericAffinityConstructor(); bool isAlreadySelectedOK(const std::vector< ObjectCalcer* >& os, const uint& ) const Q_DECL_OVERRIDE; }; class GenericProjectivityConstructor : public MergeObjectConstructor { public: GenericProjectivityConstructor(); ~GenericProjectivityConstructor(); bool isAlreadySelectedOK(const std::vector< ObjectCalcer* >& os, const uint& ) const Q_DECL_OVERRIDE; }; class InversionConstructor : public MergeObjectConstructor { public: InversionConstructor(); ~InversionConstructor(); }; class GenericIntersectionConstructor : public MergeObjectConstructor { public: GenericIntersectionConstructor(); ~GenericIntersectionConstructor(); bool isIntersection() const Q_DECL_OVERRIDE; QString useText( const ObjectCalcer& o, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; QString selectStatement( const std::vector& sel, const KigDocument& d, const KigWidget& w ) const Q_DECL_OVERRIDE; }; class MidPointOfTwoPointsConstructor : public StandardConstructorBase { ArgsParser mparser; public: MidPointOfTwoPointsConstructor(); ~MidPointOfTwoPointsConstructor(); void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const Q_DECL_OVERRIDE; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const Q_DECL_OVERRIDE; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; }; +class GoldenPointOfTwoPointsConstructor + : public StandardConstructorBase +{ + ArgsParser mparser; +public: + GoldenPointOfTwoPointsConstructor(); + ~GoldenPointOfTwoPointsConstructor(); + void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, + const KigDocument& ) const Q_DECL_OVERRIDE; + std::vector build( const std::vector& os, KigDocument& d, + KigWidget& w ) const Q_DECL_OVERRIDE; + void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; + bool isTransform() const Q_DECL_OVERRIDE; +}; + class TestConstructor : public StandardConstructorBase { const ArgsParserObjectType* mtype; public: TestConstructor( const ArgsParserObjectType* type, const char* descname, const char* desc, const char* iconfile ); ~TestConstructor(); void drawprelim( const ObjectDrawer& drawer, KigPainter& p, const std::vector& parents, const KigDocument& ) const Q_DECL_OVERRIDE; std::vector build( const std::vector& os, KigDocument& d, KigWidget& w ) const Q_DECL_OVERRIDE; int wantArgs( const std::vector& os, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; void plug( KigPart* doc, KigGUIAction* kact ) Q_DECL_OVERRIDE; bool isTransform() const Q_DECL_OVERRIDE; bool isTest() const Q_DECL_OVERRIDE; BaseConstructMode* constructMode( KigPart& doc ) Q_DECL_OVERRIDE; }; class TangentConstructor : public MergeObjectConstructor { public: TangentConstructor(); ~TangentConstructor(); QString useText( const ObjectCalcer& o, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; // QString selectStatement( // const std::vector& sel, const KigDocument& d, // const KigWidget& w ) const; }; class CocConstructor : public MergeObjectConstructor { public: CocConstructor(); ~CocConstructor(); QString useText( const ObjectCalcer& o, const std::vector& sel, const KigDocument& d, const KigWidget& v ) const Q_DECL_OVERRIDE; // QString selectStatement( // const std::vector& sel, const KigDocument& d, // const KigWidget& w ) const; }; bool relativePrimes( int n, int p ); std::vector removeDuplicatedPoints( std::vector points ); bool coincidentPoints( const ObjectImp* p1, const ObjectImp* p2 ); #endif diff --git a/objects/line_imp.cc b/objects/line_imp.cc index 154237a6..9e36935b 100644 --- a/objects/line_imp.cc +++ b/objects/line_imp.cc @@ -1,653 +1,659 @@ // Copyright (C) 2002 Dominique Devriese // This program 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 2 // of the License, or (at your option) any later version. // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301, USA. #include "line_imp.h" #include "bogus_imp.h" #include "point_imp.h" #include "../misc/rect.h" #include "../misc/common.h" #include "../misc/kigtransform.h" #include "../misc/kigpainter.h" #include "../misc/equationstring.h" #include "../kig/kig_view.h" #include using namespace std; AbstractLineImp::AbstractLineImp( const Coordinate& a, const Coordinate& b ) : mdata( a, b ) { } AbstractLineImp::~AbstractLineImp() { } bool AbstractLineImp::inRect( const Rect& r, int width, const KigWidget& w ) const { return lineInRect( r, mdata.a, mdata.b, width, this, w ); } int AbstractLineImp::numberOfProperties() const { return Parent::numberOfProperties() + 2; } const ObjectImpType* AbstractLineImp::impRequirementForProperty( int which ) const { if ( which < Parent::numberOfProperties() ) return Parent::impRequirementForProperty( which ); else return AbstractLineImp::stype(); } const char* AbstractLineImp::iconForProperty( int which ) const { if ( which < Parent::numberOfProperties() ) return Parent::iconForProperty( which ); if ( which == Parent::numberOfProperties() ) return "slope"; // slope if ( which == Parent::numberOfProperties() + 1 ) return "kig_text"; // equation else assert( false ); return ""; } ObjectImp* AbstractLineImp::property( int which, const KigDocument& w ) const { if ( which < Parent::numberOfProperties() ) return Parent::property( which, w ); if ( which == Parent::numberOfProperties() ) return new DoubleImp( slope() ); if ( which == Parent::numberOfProperties() + 1 ) return new StringImp( equationString() ); else assert( false ); return new InvalidImp; } const QByteArrayList AbstractLineImp::propertiesInternalNames() const { QByteArrayList l = Parent::propertiesInternalNames(); l << "slope"; l << "equation"; assert( l.size() == AbstractLineImp::numberOfProperties() ); return l; } const QByteArrayList AbstractLineImp::properties() const { QByteArrayList l = Parent::properties(); l << I18N_NOOP( "Slope" ); l << I18N_NOOP( "Equation" ); assert( l.size() == AbstractLineImp::numberOfProperties() ); return l; } int SegmentImp::numberOfProperties() const { - return Parent::numberOfProperties() + 5; + return Parent::numberOfProperties() + 6; } const QByteArrayList SegmentImp::propertiesInternalNames() const { QByteArrayList s = Parent::propertiesInternalNames(); s << "length"; s << "mid-point"; + s << "golden-point"; s << "support"; s << "end-point-A"; s << "end-point-B"; assert( s.size() == SegmentImp::numberOfProperties() ); return s; } const QByteArrayList SegmentImp::properties() const { QByteArrayList s = Parent::properties(); s << I18N_NOOP( "Length" ); s << I18N_NOOP( "Mid Point" ); + s << I18N_NOOP( "Golden Ratio Point" ); s << I18N_NOOP( "Support Line" ); s << I18N_NOOP( "First End Point" ); s << I18N_NOOP( "Second End Point" ); assert( s.size() == SegmentImp::numberOfProperties() ); return s; } const ObjectImpType* SegmentImp::impRequirementForProperty( int which ) const { if ( which < Parent::numberOfProperties() ) return Parent::impRequirementForProperty( which ); else return SegmentImp::stype(); } const char* SegmentImp::iconForProperty( int which ) const { int pnum = 0; if ( which < Parent::numberOfProperties() ) return Parent::iconForProperty( which ); else if ( which == Parent::numberOfProperties() + pnum++ ) return "distance"; // length else if ( which == Parent::numberOfProperties() + pnum++ ) return "segment_midpoint"; // mid point + else if ( which == Parent::numberOfProperties() + pnum++ ) + return "segment_golden_point"; // golden ratio point else if ( which == Parent::numberOfProperties() + pnum++ ) return ""; // support line else if ( which == Parent::numberOfProperties() + pnum++ ) return "endpoint1"; // mid point else if ( which == Parent::numberOfProperties() + pnum++ ) return "endpoint2"; // mid point else assert( false ); return ""; } ObjectImp* SegmentImp::property( int which, const KigDocument& w ) const { int pnum = 0; if ( which < Parent::numberOfProperties() ) return Parent::property( which, w ); else if ( which == Parent::numberOfProperties() + pnum++ ) return new DoubleImp( mdata.dir().length() ); else if ( which == Parent::numberOfProperties() + pnum++ ) return new PointImp( ( mdata.a + mdata.b ) / 2 ); + else if ( which == Parent::numberOfProperties() + pnum++ ) + return new PointImp( mdata.a + (sqrt(5) - 1) / 2 * (mdata.b - mdata.a) ); else if ( which == Parent::numberOfProperties() + pnum++ ) return new LineImp( mdata.a, mdata.b ); else if ( which == Parent::numberOfProperties() + pnum++ ) return new PointImp( mdata.a ); else if ( which == Parent::numberOfProperties() + pnum++ ) return new PointImp( mdata.b ); else assert( false ); return new InvalidImp; } int RayImp::numberOfProperties() const { return Parent::numberOfProperties() + 2; } const QByteArrayList RayImp::propertiesInternalNames() const { QByteArrayList s = Parent::propertiesInternalNames(); s << "support"; s << "end-point-A"; assert( s.size() == RayImp::numberOfProperties() ); return s; } const QByteArrayList RayImp::properties() const { QByteArrayList s = Parent::properties(); s << I18N_NOOP( "Support Line" ); s << I18N_NOOP( "End Point" ); assert( s.size() == RayImp::numberOfProperties() ); return s; } const ObjectImpType* RayImp::impRequirementForProperty( int which ) const { if ( which < Parent::numberOfProperties() ) return Parent::impRequirementForProperty( which ); else return RayImp::stype(); } const char* RayImp::iconForProperty( int which ) const { int pnum = 0; if ( which < Parent::numberOfProperties() ) return Parent::iconForProperty( which ); else if ( which == Parent::numberOfProperties() + pnum++ ) return ""; // support line else if ( which == Parent::numberOfProperties() + pnum++ ) return "endpoint1"; // end point else assert( false ); return ""; } ObjectImp* RayImp::property( int which, const KigDocument& w ) const { int pnum = 0; if ( which < Parent::numberOfProperties() ) return Parent::property( which, w ); else if ( which == Parent::numberOfProperties() + pnum++ ) return new LineImp( mdata.a, mdata.b ); else if ( which == Parent::numberOfProperties() + pnum++ ) return new PointImp( mdata.a ); else assert( false ); return new InvalidImp; } double AbstractLineImp::slope() const { Coordinate diff = mdata.dir(); return diff.y / diff.x; } const QString AbstractLineImp::equationString() const { Coordinate p = mdata.a; Coordinate q = mdata.b; EquationString ret = EquationString( "" ); double a = q.y - p.y; double b = p.x - q.x; double c = q.x*p.y - q.y*p.x; bool needsign = false; if ( fabs( b ) < 1e-6*fabs( a ) ) { ret.addTerm( 1.0, ret.x(), needsign ); ret.addTerm( b/a, ret.y(), needsign ); ret.addTerm( c/a, "", needsign ); ret.append( " = 0" ); return ret; } ret.append( "y = " ); ret.addTerm( -a/b, ret.x(), needsign ); ret.addTerm( -c/b, "", needsign ); if ( ! needsign ) ret.append( "0" ); // double m = ( q.y - p.y ) / ( q.x - p.x ); // double r = - ( q.y - p.y ) * p.x / ( q.x - p.x ) + p.y; // // QString ret = QString::fromUtf8( "y = %1x " ) + // QString::fromUtf8( r > 0 ? "+" : "-" ) + // QString::fromUtf8( " %2" ); // // ret = ret.arg( m, 0, 'g', 3 ); // ret = ret.arg( abs( r ), 0, 'g', 3 ); return ret; } void SegmentImp::draw( KigPainter& p ) const { p.drawSegment( mdata ); } bool SegmentImp::contains( const Coordinate& p, int width, const KigWidget& w ) const { return internalContainsPoint( p, w.screenInfo().normalMiss( width ) ); } void RayImp::draw( KigPainter& p ) const { p.drawRay( mdata ); } bool RayImp::contains( const Coordinate& p, int width, const KigWidget& w ) const { return internalContainsPoint( p, w.screenInfo().normalMiss( width ) ); } void LineImp::draw( KigPainter& p ) const { p.drawLine( mdata ); } bool LineImp::contains( const Coordinate& p, int width, const KigWidget& w ) const { return internalContainsPoint( p, w.screenInfo().normalMiss( width ) ); } SegmentImp::SegmentImp( const Coordinate& a, const Coordinate& b ) : AbstractLineImp( a, b ) { } RayImp::RayImp( const Coordinate& a, const Coordinate& b ) : AbstractLineImp( a, b ) { } LineImp::LineImp( const Coordinate& a, const Coordinate& b ) : AbstractLineImp( a, b ) { } SegmentImp* SegmentImp::copy() const { return new SegmentImp( mdata ); } RayImp* RayImp::copy() const { return new RayImp( mdata ); } LineImp* LineImp::copy() const { return new LineImp( mdata ); } const Coordinate SegmentImp::getPoint( double param, const KigDocument& ) const { return mdata.a + mdata.dir()*param; } double SegmentImp::getParam( const Coordinate& p, const KigDocument& ) const { Coordinate pt = calcPointOnPerpend( data(), p ); pt = calcIntersectionPoint( data(), LineData( p, pt ) ); // if pt is over the end of the segment ( i.e. it's on the line // which the segment is a part of, but not of the segment itself..; // ) we set it to one of the end points of the segment... if ((pt - mdata.a).length() > mdata.dir().length() ) pt = mdata.b; else if ( (pt- mdata.b).length() > mdata.dir().length() ) pt = mdata.a; if (mdata.b == mdata.a) return 0; return ((pt - mdata.a).length())/(mdata.dir().length()); } LineData AbstractLineImp::data() const { return mdata; } const Coordinate RayImp::getPoint( double param, const KigDocument& ) const { param = 1.0/param - 1.0; return mdata.a + mdata.dir()*param; } double RayImp::getParam( const Coordinate& p, const KigDocument& ) const { const LineData ld = data(); Coordinate pt = calcPointOnPerpend( ld, p ); pt = calcIntersectionPoint( ld, LineData( p, pt )); // if pt is over the end of the ray ( i.e. it's on the line // which the ray is a part of, but not of the ray itself..; // ) we set it to the start point of the ray... Coordinate dir = ld.dir(); pt -= ld.a; double param; if ( dir.x != 0 ) param = pt.x / dir.x; else if ( dir.y != 0 ) param = pt.y / dir.y; else param = 0.; if ( param < 0. ) param = 0.; // mp: let's try with 1/(x+1), this reverses the mapping, but // should allow to take advantage of the tightness of floating point // numbers near zero, in order to get more possible positions near // infinity param = 1./( param + 1. ); assert( param >= 0. && param <= 1. ); return param; } const Coordinate LineImp::getPoint( double p, const KigDocument& ) const { // inspired upon KSeg // we need to spread the points over the line, it should also come near // the (infinite) end of the line, but most points should be near // the two points we contain... if ( p <= 0. ) p = 1e-6; if ( p >= 1. ) p = 1 - 1e-6; p = 2*p - 1; if (p > 0) p = p/(1 - p); else p = p/(1 + p); // p *= 1024; // such multiplying factor could be useful in order to // have more points near infinity, at the expense of // points near ma and mb return mdata.a + p*mdata.dir(); } double LineImp::getParam( const Coordinate& point, const KigDocument& ) const { // somewhat the reverse of getPoint, although it also supports // points not on the line... Coordinate pa = point - mdata.a; Coordinate ba = mdata.dir(); double balsq = ba.x*ba.x + ba.y*ba.y; assert (balsq > 0); double p = (pa.x*ba.x + pa.y*ba.y)/balsq; // p /= 1024; if (p > 0) p = p/(1+p); else p = p/(1-p); return 0.5*(p + 1); } ObjectImp* SegmentImp::transform( const Transformation& t ) const { if ( ! t.isAffine() ) /* we need to check the position of the two points */ { if ( t.getProjectiveIndicator( mdata.a ) * t.getProjectiveIndicator( mdata.b ) < 0 ) return new InvalidImp(); } Coordinate na = t.apply( mdata.a ); Coordinate nb = t.apply( mdata.b ); if( na.valid() && nb.valid() ) return new SegmentImp( na, nb ); else return new InvalidImp(); } ObjectImp* LineImp::transform( const Transformation& t ) const { Coordinate na = t.apply( mdata.a ); Coordinate nb = t.apply( mdata.b ); if ( na.valid() && nb.valid() ) return new LineImp( na, nb ); else return new InvalidImp(); } ObjectImp* RayImp::transform( const Transformation& t ) const { if ( ! t.isAffine() ) /* we need to check the position of the two points */ { double pa = t.getProjectiveIndicator( mdata.a ); double pb = t.getProjectiveIndicator( mdata.b ); if ( pa < 0 ) pb = -pb; if ( pb < fabs (pa) ) return new InvalidImp(); Coordinate na = t.apply( mdata.a ); Coordinate nb = t.apply0( mdata.b - mdata.a ); if ( na.valid() && nb.valid() ) return new SegmentImp( na, nb ); else return new InvalidImp(); } Coordinate na = t.apply( mdata.a ); Coordinate nb = t.apply( mdata.b ); if ( na.valid() && nb.valid() ) return new RayImp( na, nb ); else return new InvalidImp(); } AbstractLineImp::AbstractLineImp( const LineData& d ) : mdata( d ) { } SegmentImp::SegmentImp( const LineData& d ) : AbstractLineImp( d ) { } RayImp::RayImp( const LineData& d ) : AbstractLineImp( d ) { } LineImp::LineImp( const LineData& d ) : AbstractLineImp( d ) { } double SegmentImp::length() const { return mdata.length(); } void SegmentImp::visit( ObjectImpVisitor* vtor ) const { vtor->visit( this ); } void RayImp::visit( ObjectImpVisitor* vtor ) const { vtor->visit( this ); } void LineImp::visit( ObjectImpVisitor* vtor ) const { vtor->visit( this ); } bool AbstractLineImp::equals( const ObjectImp& rhs ) const { return rhs.type() == type() && static_cast( rhs ).data() == data(); } const ObjectImpType* AbstractLineImp::stype() { static const ObjectImpType t( Parent::stype(), "line", I18N_NOOP( "line" ), I18N_NOOP( "Select a Line" ), 0, 0, 0, 0, 0, 0, 0 ); return &t; } const ObjectImpType* LineImp::stype() { static const ObjectImpType t( Parent::stype(), "line", I18N_NOOP( "line" ), I18N_NOOP( "Select this line" ), I18N_NOOP( "Select line %1" ), I18N_NOOP( "Remove a Line" ), I18N_NOOP( "Add a Line" ), I18N_NOOP( "Move a Line" ), I18N_NOOP( "Attach to this line" ), I18N_NOOP( "Show a Line" ), I18N_NOOP( "Hide a Line" ) ); return &t; } const ObjectImpType* SegmentImp::stype() { static const ObjectImpType t( Parent::stype(), "segment", I18N_NOOP( "segment" ), I18N_NOOP( "Select this segment" ), I18N_NOOP( "Select segment %1" ), I18N_NOOP( "Remove a Segment" ), I18N_NOOP( "Add a Segment" ), I18N_NOOP( "Move a Segment" ), I18N_NOOP( "Attach to this segment" ), I18N_NOOP( "Show a Segment" ), I18N_NOOP( "Hide a Segment" ) ); return &t; } const ObjectImpType* RayImp::stype() { static const ObjectImpType t( Parent::stype(), "ray", I18N_NOOP( "half-line" ), I18N_NOOP( "Select this half-line" ), I18N_NOOP( "Select half-line %1" ), I18N_NOOP( "Remove a Half-Line" ), I18N_NOOP( "Add a Half-Line" ), I18N_NOOP( "Move a Half-Line" ), I18N_NOOP( "Attach to this half-line" ), I18N_NOOP( "Show a Half-Line" ), I18N_NOOP( "Hide a Half-Line" ) ); return &t; } const ObjectImpType* SegmentImp::type() const { return SegmentImp::stype(); } const ObjectImpType* RayImp::type() const { return RayImp::stype(); } const ObjectImpType* LineImp::type() const { return LineImp::stype(); } bool SegmentImp::containsPoint( const Coordinate& p, const KigDocument& ) const { return internalContainsPoint( p, test_threshold ); } bool SegmentImp::internalContainsPoint( const Coordinate& p, double threshold ) const { return isOnSegment( p, mdata.a, mdata.b, threshold ); } bool RayImp::containsPoint( const Coordinate& p, const KigDocument& ) const { return internalContainsPoint( p, test_threshold ); } bool RayImp::internalContainsPoint( const Coordinate& p, double threshold ) const { return isOnRay( p, mdata.a, mdata.b, threshold ); } bool LineImp::containsPoint( const Coordinate& p, const KigDocument& ) const { return internalContainsPoint( p, test_threshold ); } bool LineImp::internalContainsPoint( const Coordinate& p, double threshold ) const { return isOnLine( p, mdata.a, mdata.b, threshold ); } bool AbstractLineImp::isPropertyDefinedOnOrThroughThisImp( int which ) const { int pnum = 0; if ( which < Parent::numberOfProperties() ) return Parent::isPropertyDefinedOnOrThroughThisImp( which ); else if ( which == Parent::numberOfProperties() + pnum++ ) return false; else if ( which == Parent::numberOfProperties() + pnum++ ) return true; else if ( which == Parent::numberOfProperties() + pnum++ ) return true; else if ( which == Parent::numberOfProperties() + pnum++ ) return true; else assert( false ); return false; } Rect SegmentImp::surroundingRect() const { return Rect( mdata.a, mdata.b ); } Rect RayImp::surroundingRect() const { return Rect::invalidRect(); } Rect LineImp::surroundingRect() const { return Rect::invalidRect(); } diff --git a/objects/point_type.cc b/objects/point_type.cc index 6ed1a222..734d660e 100644 --- a/objects/point_type.cc +++ b/objects/point_type.cc @@ -1,849 +1,884 @@ // Copyright (C) 2002 Dominique Devriese // This program 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 2 // of the License, or (at your option) any later version. // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301, USA. #include "point_type.h" #include #include "special_imptypes.h" #include "point_imp.h" #include "curve_imp.h" #include "line_imp.h" #include "other_imp.h" #include "bogus_imp.h" #include "../modes/moving.h" #include "../misc/coordinate_system.h" #include "../misc/common.h" #include "../misc/calcpaths.h" #include "../misc/kiginputdialog.h" #include "../kig/kig_part.h" #include "../kig/kig_document.h" #include "../kig/kig_view.h" #include "../kig/kig_commands.h" static const ArgsParser::spec argsspecFixedPoint[] = { { DoubleImp::stype(), "x", "SHOULD NOT BE SEEN", false }, { DoubleImp::stype(), "y", "SHOULD NOT BE SEEN", false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( FixedPointType ) FixedPointType::FixedPointType() : ArgsParserObjectType( "FixedPoint", argsspecFixedPoint, 2 ) { } FixedPointType::~FixedPointType() { } ObjectImp* FixedPointType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; double a = static_cast( parents[0] )->data(); double b = static_cast( parents[1] )->data(); return new PointImp( Coordinate( a, b ) ); } static const ArgsParser::spec argsspecRelativePoint[] = { { DoubleImp::stype(), "relative-x", "SHOULD NOT BE SEEN", false }, { DoubleImp::stype(), "relative-y", "SHOULD NOT BE SEEN", false }, { ObjectImp::stype(), "object", "SHOULD NOT BE SEEN", false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( RelativePointType ) RelativePointType::RelativePointType() : ArgsParserObjectType( "RelativePoint", argsspecRelativePoint, 3 ) { } RelativePointType::~RelativePointType() { } ObjectImp* RelativePointType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; if ( ! parents[2]->attachPoint().valid() ) return new InvalidImp; Coordinate reference = static_cast( parents[2] )->attachPoint(); double a = static_cast( parents[0] )->data(); double b = static_cast( parents[1] )->data(); return new PointImp( reference + Coordinate( a, b ) ); } KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( CursorPointType ) CursorPointType::CursorPointType() : ObjectType( "CursorPoint" ) { } CursorPointType::~CursorPointType() { } const CursorPointType* CursorPointType::instance() { static const CursorPointType t; return &t; } ObjectImp* CursorPointType::calc( const Args& parents, const KigDocument& ) const { assert ( parents[0]->inherits( DoubleImp::stype() ) ); assert ( parents[1]->inherits( DoubleImp::stype() ) ); double a = static_cast( parents[0] )->data(); double b = static_cast( parents[1] )->data(); return new BogusPointImp( Coordinate( a, b ) ); } const ObjectImpType* CursorPointType::resultId() const { return BogusPointImp::stype(); } ObjectImp* ConstrainedPointType::calc( const Args& parents, const KigDocument& doc ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; double param = static_cast( parents[0] )->data(); const Coordinate nc = static_cast( parents[1] )->getPoint( param, doc ); doc.mcachedparam = param; if ( nc.valid() ) return new PointImp( nc ); else return new InvalidImp; } const ArgsParser::spec argsspecConstrainedPoint[] = { { DoubleImp::stype(), "parameter", "SHOULD NOT BE SEEN", false }, { CurveImp::stype(), "Constrain the point to this curve", "SHOULD NOT BE SEEN", true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConstrainedPointType ) ConstrainedPointType::ConstrainedPointType() : ArgsParserObjectType( "ConstrainedPoint", argsspecConstrainedPoint, 2 ) { } ConstrainedPointType::~ConstrainedPointType() { } void FixedPointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, const KigDocument& ) const { // fetch the old coord..; std::vector pa = ourobj.parents(); assert( margsparser.checkArgs( pa ) ); assert( dynamic_cast( pa.front() ) ); assert( dynamic_cast( pa.back() ) ); ObjectConstCalcer* ox = static_cast( pa.front() ); ObjectConstCalcer* oy = static_cast( pa.back() ); ox->setImp( new DoubleImp( to.x ) ); oy->setImp( new DoubleImp( to.y ) ); } void RelativePointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, const KigDocument& ) const { // fetch the attach point..; // this routine is tightly paired with what moveReferencePoint returns! // right now moveReferencePoint always returns the origin std::vector pa = ourobj.parents(); assert( margsparser.checkArgs( pa ) ); assert( dynamic_cast( pa[0] ) ); assert( dynamic_cast( pa[1] ) ); ObjectConstCalcer* ox = static_cast( pa[0] ); ObjectConstCalcer* oy = static_cast( pa[1] ); ObjectCalcer* ob = static_cast( pa[2] ); Coordinate attach = ob->imp()->attachPoint(); ox->setImp( new DoubleImp( to.x - attach.x ) ); oy->setImp( new DoubleImp( to.y - attach.y ) ); } void CursorPointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, const KigDocument& ) const { // fetch the old coord..; std::vector pa = ourobj.parents(); assert( pa.size() == 2 ); assert( dynamic_cast( pa.front() ) ); assert( dynamic_cast( pa.back() ) ); ObjectConstCalcer* ox = static_cast( pa.front() ); ObjectConstCalcer* oy = static_cast( pa.back() ); ox->setImp( new DoubleImp( to.x ) ); oy->setImp( new DoubleImp( to.y ) ); } void ConstrainedPointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, const KigDocument& d ) const { // fetch the CurveImp.. std::vector parents = ourobj.parents(); assert( margsparser.checkArgs( parents ) ); assert( dynamic_cast( parents[0] ) ); ObjectConstCalcer* paramo = static_cast( parents[0] ); const CurveImp* ci = static_cast( parents[1]->imp() ); // fetch the new param.. const double np = ci->getParam( to, d ); paramo->setImp( new DoubleImp( np ) ); } bool ConstrainedPointType::canMove( const ObjectTypeCalcer& ) const { return true; } bool ConstrainedPointType::isFreelyTranslatable( const ObjectTypeCalcer& ) const { return false; } bool FixedPointType::canMove( const ObjectTypeCalcer& ) const { return true; } bool FixedPointType::isFreelyTranslatable( const ObjectTypeCalcer& ) const { return true; } bool RelativePointType::canMove( const ObjectTypeCalcer& ) const { return true; } bool RelativePointType::isFreelyTranslatable( const ObjectTypeCalcer& ) const { return true; } bool CursorPointType::canMove( const ObjectTypeCalcer& ) const { return true; } static const ArgsParser::spec argsspecMidPoint[] = { { PointImp::stype(), I18N_NOOP( "Construct the midpoint of this point and another point" ), I18N_NOOP( "Select the first of the two points of which you want to construct the midpoint..." ), false }, { PointImp::stype(), I18N_NOOP( "Construct the midpoint of this point and another point" ), I18N_NOOP( "Select the other of the two points of which you want to construct the midpoint..." ), false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( MidPointType ) MidPointType::MidPointType() : ObjectABType( "MidPoint", argsspecMidPoint, 2 ) { } MidPointType::~MidPointType() { } const MidPointType* MidPointType::instance() { static const MidPointType t; return &t; } ObjectImp* MidPointType::calcx( const Coordinate& a, const Coordinate& b ) const { return new PointImp( ( a + b ) / 2 ); } +static const ArgsParser::spec argsspecGoldenPoint[] = +{ + { PointImp::stype(), I18N_NOOP( "Construct the golden ratio point of this point and another point" ), + I18N_NOOP( "Select the first of the two points of which you want to construct the golden ratio point..." ), false }, + { PointImp::stype(), I18N_NOOP( "Construct the golden ratio point of this point and another point" ), + I18N_NOOP( "Select the other of the two points of which you want to construct the golden ratio point..." ), false } +}; + +KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( GoldenPointType ) + +GoldenPointType::GoldenPointType() + : ObjectABType( "GoldenPoint", argsspecGoldenPoint, 2 ) +{ +} + +GoldenPointType::~GoldenPointType() +{ +} + +const GoldenPointType* GoldenPointType::instance() +{ + static const GoldenPointType t; + return &t; +} + +ObjectImp* GoldenPointType::calcx( const Coordinate& a, const Coordinate& b ) const +{ + return new PointImp( a + (sqrt(5) - 1) * (b - a) / 2 ); +} + bool ConstrainedPointType::inherits( int type ) const { return type == ID_ConstrainedPointType; } const ConstrainedPointType* ConstrainedPointType::instance() { static const ConstrainedPointType t; return &t; } bool FixedPointType::inherits( int type ) const { return type == ID_FixedPointType; } const FixedPointType* FixedPointType::instance() { static const FixedPointType t; return &t; } const ObjectImpType* FixedPointType::resultId() const { return PointImp::stype(); } const RelativePointType* RelativePointType::instance() { static const RelativePointType t; return &t; } const ObjectImpType* RelativePointType::resultId() const { return PointImp::stype(); } const ObjectImpType* ConstrainedPointType::resultId() const { return PointImp::stype(); } const ObjectImpType* CursorPointType::impRequirement( const ObjectImp* o, const Args& ) const { if ( o->inherits( DoubleImp::stype() ) ) return DoubleImp::stype(); if ( o->inherits( PointImp::stype() ) ) return PointImp::stype(); return 0; } bool CursorPointType::isDefinedOnOrThrough( const ObjectImp*, const Args& ) const { return false; } std::vector CursorPointType::sortArgs( const std::vector& args ) const { return args; } Args CursorPointType::sortArgs( const Args& args ) const { return args; } const ObjectImpType* MidPointType::resultId() const { return PointImp::stype(); } +const ObjectImpType* GoldenPointType::resultId() const +{ + return PointImp::stype(); +} + QStringList FixedPointType::specialActions() const { QStringList ret; ret << i18n( "Set &Coordinate..." ); ret << i18n( "Redefine" ); return ret; } QStringList ConstrainedPointType::specialActions() const { QStringList ret; ret << i18n( "Set &Parameter..." ); ret << i18n( "Redefine" ); return ret; } static void redefinePoint( ObjectHolder* o, KigPart& d, KigWidget& w ) { PointRedefineMode pm( o, d, w ); d.runMode( &pm ); } void FixedPointType::executeAction( int i, ObjectHolder& oh, ObjectTypeCalcer& o, KigPart& d, KigWidget& w, NormalMode& ) const { switch( i ) { case 0: { bool ok = true; assert ( o.imp()->inherits( PointImp::stype() ) ); Coordinate oldc = static_cast( o.imp() )->coordinate(); KigInputDialog::getCoordinate( i18n( "Set Coordinate" ), i18n( "Enter the new coordinate." ) + QString::fromLatin1( "
" ) + d.document().coordinateSystem().coordinateFormatNoticeMarkup(), &w, &ok, d.document(), &oldc ); if ( ! ok ) break; MonitorDataObjects mon( getAllParents( &o ) ); o.move( oldc, d.document() ); KigCommand* kc = new KigCommand( d, PointImp::stype()->moveAStatement() ); mon.finish( kc ); d.history()->push( kc ); break; }; case 1: redefinePoint( &oh, d, w ); break; default: assert( false ); }; } void ConstrainedPointType::executeAction( int i, ObjectHolder& oh, ObjectTypeCalcer& o, KigPart& d, KigWidget& w, NormalMode& ) const { switch( i ) { case 1: redefinePoint( &oh, d, w ); break; case 0: { std::vector parents = o.parents(); assert( dynamic_cast( parents[0] ) && parents[0]->imp()->inherits( DoubleImp::stype() ) ); ObjectConstCalcer* po = static_cast( parents[0] ); double oldp = static_cast( po->imp() )->data(); bool ok = true; double newp = getDoubleFromUser( i18n( "Set Point Parameter" ), i18n( "Choose the new parameter: " ), oldp, &w, &ok, 0, 1, 4 ); if ( ! ok ) return; MonitorDataObjects mon( parents ); po->setImp( new DoubleImp( newp ) ); KigCommand* kc = new KigCommand( d, i18n( "Change Parameter of Constrained Point" ) ); mon.finish( kc ); d.history()->push( kc ); break; }; default: assert( false ); }; } const Coordinate FixedPointType::moveReferencePoint( const ObjectTypeCalcer& ourobj ) const { assert( ourobj.imp()->inherits( PointImp::stype() ) ); return static_cast( ourobj.imp() )->coordinate(); } const Coordinate RelativePointType::moveReferencePoint( const ObjectTypeCalcer& ourobj ) const { assert( ourobj.imp()->inherits( PointImp::stype() ) ); // return static_cast( ourobj.imp() )->coordinate(); return Coordinate( 0., 0. ); } const Coordinate ConstrainedPointType::moveReferencePoint( const ObjectTypeCalcer& ourobj ) const { assert( ourobj.imp()->inherits( PointImp::stype() ) ); return static_cast( ourobj.imp() )->coordinate(); } std::vector FixedPointType::movableParents( const ObjectTypeCalcer& ourobj ) const { return ourobj.parents(); } std::vector RelativePointType::movableParents( const ObjectTypeCalcer& ourobj ) const { std::vector ret; ret.push_back( ourobj.parents()[0] ); ret.push_back( ourobj.parents()[1] ); return ret; } std::vector ConstrainedPointType::movableParents( const ObjectTypeCalcer& ourobj ) const { std::vector ret; ret.push_back( ourobj.parents()[0] ); return ret; } static const ArgsParser::spec argsspecConstrainedRelativePoint[] = { { DoubleImp::stype(), "relative-x", "SHOULD NOT BE SEEN", false }, { DoubleImp::stype(), "relative-y", "SHOULD NOT BE SEEN", false }, { DoubleImp::stype(), "parameter", "SHOULD NOT BE SEEN", false }, { CurveImp::stype(), "curve", "SHOULD NOT BE SEEN", false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ConstrainedRelativePointType ) ConstrainedRelativePointType::ConstrainedRelativePointType() : ArgsParserObjectType( "ConstrainedRelativePoint", argsspecConstrainedRelativePoint, 4 ) { } ConstrainedRelativePointType::~ConstrainedRelativePointType() { } ObjectImp* ConstrainedRelativePointType::calc( const Args& parents, const KigDocument& doc ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; double a = static_cast( parents[0] )->data(); double b = static_cast( parents[1] )->data(); double p = static_cast( parents[2] )->data(); Coordinate reference = static_cast( parents[3] )->getPoint( p, doc ); return new PointImp( reference + Coordinate( a, b ) ); } void ConstrainedRelativePointType::move( ObjectTypeCalcer& ourobj, const Coordinate& to, const KigDocument& doc ) const { // this routine is tightly paired with what moveReferencePoint returns! // right now moveReferencePoint always returns the origin std::vector pa = ourobj.parents(); assert( margsparser.checkArgs( pa ) ); assert( dynamic_cast( pa[0] ) ); assert( dynamic_cast( pa[1] ) ); assert( dynamic_cast( pa[2] ) ); ObjectConstCalcer* ox = static_cast( pa[0] ); ObjectConstCalcer* oy = static_cast( pa[1] ); ObjectConstCalcer* op = static_cast( pa[2] ); ObjectCalcer* ob = static_cast( pa[3] ); const CurveImp* curve = static_cast( ob->imp() ); double newp = curve->getParam( to, doc ); Coordinate attach = curve->getPoint( newp, doc ); ox->setImp( new DoubleImp( to.x - attach.x ) ); oy->setImp( new DoubleImp( to.y - attach.y ) ); op->setImp( new DoubleImp( newp ) ); } bool ConstrainedRelativePointType::canMove( const ObjectTypeCalcer& ) const { return true; } bool ConstrainedRelativePointType::isFreelyTranslatable( const ObjectTypeCalcer& ) const { return true; } const ConstrainedRelativePointType* ConstrainedRelativePointType::instance() { static const ConstrainedRelativePointType t; return &t; } const ObjectImpType* ConstrainedRelativePointType::resultId() const { return PointImp::stype(); } const Coordinate ConstrainedRelativePointType::moveReferencePoint( const ObjectTypeCalcer& ourobj ) const { assert( ourobj.imp()->inherits( PointImp::stype() ) ); return Coordinate( 0., 0. ); } std::vector ConstrainedRelativePointType::movableParents( const ObjectTypeCalcer& ourobj ) const { std::vector ret; ret.push_back( ourobj.parents()[0] ); ret.push_back( ourobj.parents()[1] ); ret.push_back( ourobj.parents()[2] ); return ret; } /* ----------------- Transport of measure ------------------------------ */ ObjectImp* MeasureTransportType::calc( const Args& parents, const KigDocument& doc ) const { double measure; if ( parents.size() != 3 ) return new InvalidImp; bool valid; measure = getDoubleFromImp( parents[0], valid ); if ( ! valid ) return new InvalidImp; const Coordinate& p = static_cast( parents[2] )->coordinate(); if ( parents[1]->inherits (LineImp::stype()) ) { const LineImp* c = static_cast( parents[1] ); if ( !c->containsPoint( p, doc ) ) return new InvalidImp; const LineData line = c->data(); const Coordinate dir = line.dir()/line.length(); const Coordinate nc = p + measure*dir; if ( nc.valid() ) return new PointImp( nc ); else return new InvalidImp; } else if ( parents[1]->inherits (CircleImp::stype()) ) { const CircleImp* c = static_cast( parents[1] ); if ( !c->containsPoint( p, doc ) ) return new InvalidImp; double param = c->getParam( p, doc ); measure /= 2*c->radius()*M_PI; param += measure; while (param > 1) param -= 1; const Coordinate nc = c->getPoint( param, doc ); if ( nc.valid() ) return new PointImp( nc ); else return new InvalidImp; } return new InvalidImp; } // I18N_NOOP( "Select the segment/arc to transport on the circle/line..." ), false }, // I18N_NOOP( "Select the circle/line on which to transport a measure..." ), true }, // I18N_NOOP( "Select a point on the circle/line..." ), false } KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( MeasureTransportType ) MeasureTransportType::MeasureTransportType() : ObjectType( "TransportOfMeasure" ) { } MeasureTransportType::~MeasureTransportType() { } const MeasureTransportType* MeasureTransportType::instance() { static const MeasureTransportType t; return &t; } const ObjectImpType* MeasureTransportType::resultId() const { return PointImp::stype(); } const ObjectImpType* MeasureTransportType::impRequirement( const ObjectImp* obj, const Args& ) const { if ( obj->inherits( PointImp::stype () ) ) return PointImp::stype (); if ( obj->inherits( LineImp::stype () ) ) return LineImp::stype (); if ( obj->inherits( CircleImp::stype () ) ) return CircleImp::stype (); if ( obj->inherits( SegmentImp::stype () ) ) return SegmentImp::stype (); if ( obj->inherits( ArcImp::stype () ) ) return ArcImp::stype (); return 0; } bool MeasureTransportType::isDefinedOnOrThrough( const ObjectImp* o, const Args& ) const { if ( o->inherits( LineImp::stype() ) ) return true; if ( o->inherits( CircleImp::stype() ) ) return true; return false; } std::vector MeasureTransportType::sortArgs( const std::vector& args ) const { return args; /* should already be in correct order */ } Args MeasureTransportType::sortArgs( const Args& args ) const { return args; } /* - transport of measure (old, for compatibility with prev. kig files) - */ /* it should be safe now to remove this completely, since the loading of "MeasureTransport" * is treated in "load07" building a node that uses the new version */ ObjectImp* MeasureTransportTypeOld::calc( const Args& parents, const KigDocument& doc ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; const CircleImp* c = static_cast( parents[0] ); const Coordinate& p = static_cast( parents[1] )->coordinate(); if ( !c->containsPoint( p, doc ) ) return new InvalidImp; const SegmentImp* s = static_cast( parents[2] ); double param = c->getParam( p, doc ); double measure = s->length(); measure /= 2*c->radius()*M_PI; param += measure; while (param > 1) param -= 1; const Coordinate nc = c->getPoint( param, doc ); if ( nc.valid() ) return new PointImp( nc ); else return new InvalidImp; } static const ArgsParser::spec argsspecMeasureTransportOld[] = { { CircleImp::stype(), "Transport a measure on this circle", I18N_NOOP( "Select the circle on which to transport a measure..." ), true }, { PointImp::stype(), "Start transport from this point of the circle", I18N_NOOP( "Select a point on the circle..." ), false }, { SegmentImp::stype(), "Segment to transport", I18N_NOOP( "Select the segment to transport on the circle..." ), false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( MeasureTransportTypeOld ) MeasureTransportTypeOld::MeasureTransportTypeOld() : ArgsParserObjectType( "MeasureTransportObsoleted", argsspecMeasureTransportOld, 3 ) { } MeasureTransportTypeOld::~MeasureTransportTypeOld() { } const MeasureTransportTypeOld* MeasureTransportTypeOld::instance() { static const MeasureTransportTypeOld t; return &t; } const ObjectImpType* MeasureTransportTypeOld::resultId() const { return PointImp::stype(); } /* ----------------- end transport of measure ------------------------- */ /* Construct a point whose coordinates are indicated by numeric labels */ ObjectImp* PointByCoordsType::calc( const Args& parents, const KigDocument& ) const { if ( ! margsparser.checkArgs( parents ) ) return new InvalidImp; bool valid; double x = getDoubleFromImp( parents[0], valid); if ( ! valid ) return new InvalidImp; double y = getDoubleFromImp( parents[1], valid); if ( ! valid ) return new InvalidImp; const Coordinate nc = Coordinate( x, y ); if ( nc.valid() ) return new PointImp( nc ); else return new InvalidImp; } static const ArgsParser::spec argsspecPointByCoords[] = { { &lengthimptypeinstance, "X coordinate given by this number/length", I18N_NOOP( "Select a number/length as x coordinate of the point..." ), false }, { &lengthimptypeinstance, "Y coordinate given by this number/length", I18N_NOOP( "Select a number/length as y coordinate of the point..." ), false } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( PointByCoordsType ) PointByCoordsType::PointByCoordsType() : ArgsParserObjectType( "PointByCoordinates", argsspecPointByCoords, 2 ) { } PointByCoordsType::~PointByCoordsType() { } const PointByCoordsType* PointByCoordsType::instance() { static const PointByCoordsType t; return &t; } const ObjectImpType* PointByCoordsType::resultId() const { return PointImp::stype(); } static const ArgsParser::spec argsspecProjectedPoint[] = { { PointImp::stype(), "Point to project", I18N_NOOP( "Select a point to project onto a line..." ), false }, { AbstractLineImp::stype(), "Line where to project", I18N_NOOP( "Line where the projected point will lie..." ), true } }; KIG_INSTANTIATE_OBJECT_TYPE_INSTANCE( ProjectedPointType ) ProjectedPointType::ProjectedPointType() : ArgsParserObjectType( "ProjectedPoint", argsspecProjectedPoint, 2 ) { } ProjectedPointType::~ProjectedPointType() { } const ProjectedPointType* ProjectedPointType::instance() { static const ProjectedPointType t; return &t; } ObjectImp* ProjectedPointType::calc(const Args& parents, const KigDocument& ) const { if( parents.size() == 2 ) { const PointImp* point = static_cast( parents[0] ); const LineImp* line = static_cast( parents[1] ); return new PointImp( calcPointProjection( point->coordinate(), line->data() ) ); } return new InvalidImp(); } const ObjectImpType* ProjectedPointType::resultId() const { return PointImp::stype(); } diff --git a/objects/point_type.h b/objects/point_type.h index c7c4e0de..304dd08e 100644 --- a/objects/point_type.h +++ b/objects/point_type.h @@ -1,204 +1,216 @@ // Copyright (C) 2002 Dominique Devriese // This program 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 2 // of the License, or (at your option) any later version. // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301, USA. #ifndef KIG_OBJECTS_POINT_TYPE_H #define KIG_OBJECTS_POINT_TYPE_H #include "base_type.h" #include "common.h" #include "circle_imp.h" class FixedPointType : public ArgsParserObjectType { FixedPointType(); ~FixedPointType(); static const ArgsParser::spec argsspec[1]; public: static const FixedPointType* instance(); bool inherits( int type ) const Q_DECL_OVERRIDE; ObjectImp* calc( const Args& parents, const KigDocument& ) const Q_DECL_OVERRIDE; bool canMove( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; bool isFreelyTranslatable( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; std::vector movableParents( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; const Coordinate moveReferencePoint( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; void move( ObjectTypeCalcer& ourobj, const Coordinate& to, const KigDocument& ) const Q_DECL_OVERRIDE; const ObjectImpType* resultId() const Q_DECL_OVERRIDE; QStringList specialActions() const Q_DECL_OVERRIDE; void executeAction( int i, ObjectHolder& o, ObjectTypeCalcer& t, KigPart& d, KigWidget& w, NormalMode& m ) const Q_DECL_OVERRIDE; }; class RelativePointType : public ArgsParserObjectType { RelativePointType(); ~RelativePointType(); static const ArgsParser::spec argsspec[1]; public: static const RelativePointType* instance(); ObjectImp* calc( const Args& parents, const KigDocument& ) const Q_DECL_OVERRIDE; bool canMove( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; bool isFreelyTranslatable( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; std::vector movableParents( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; const Coordinate moveReferencePoint( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; void move( ObjectTypeCalcer& ourobj, const Coordinate& to, const KigDocument& ) const Q_DECL_OVERRIDE; const ObjectImpType* resultId() const Q_DECL_OVERRIDE; // QStringList specialActions() const; // void executeAction( int i, ObjectHolder& o, ObjectTypeCalcer& t, // KigPart& d, KigWidget& w, NormalMode& m ) const; }; class ConstrainedRelativePointType : public ArgsParserObjectType { ConstrainedRelativePointType(); ~ConstrainedRelativePointType(); static const ArgsParser::spec argsspec[1]; public: static const ConstrainedRelativePointType* instance(); ObjectImp* calc( const Args& parents, const KigDocument& ) const Q_DECL_OVERRIDE; bool canMove( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; bool isFreelyTranslatable( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; std::vector movableParents( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; const Coordinate moveReferencePoint( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; void move( ObjectTypeCalcer& ourobj, const Coordinate& to, const KigDocument& ) const Q_DECL_OVERRIDE; const ObjectImpType* resultId() const Q_DECL_OVERRIDE; }; class CursorPointType : public ObjectType { CursorPointType(); ~CursorPointType(); public: static const CursorPointType* instance(); ObjectImp* calc( const Args& parents, const KigDocument& ) const Q_DECL_OVERRIDE; const ObjectImpType* impRequirement( const ObjectImp* o, const Args& parents ) const Q_DECL_OVERRIDE; bool isDefinedOnOrThrough( const ObjectImp* o, const Args& parents ) const Q_DECL_OVERRIDE; std::vector sortArgs( const std::vector& args ) const Q_DECL_OVERRIDE; Args sortArgs( const Args& args ) const Q_DECL_OVERRIDE; bool canMove( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; void move( ObjectTypeCalcer& ourobj, const Coordinate& to, const KigDocument& ) const Q_DECL_OVERRIDE; const ObjectImpType* resultId() const Q_DECL_OVERRIDE; }; class ConstrainedPointType : public ArgsParserObjectType { ConstrainedPointType(); ~ConstrainedPointType(); public: static const ConstrainedPointType* instance(); bool inherits( int type ) const Q_DECL_OVERRIDE; ObjectImp* calc( const Args& parents, const KigDocument& ) const Q_DECL_OVERRIDE; bool canMove( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; bool isFreelyTranslatable( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; std::vector movableParents( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; const Coordinate moveReferencePoint( const ObjectTypeCalcer& ourobj ) const Q_DECL_OVERRIDE; void move( ObjectTypeCalcer& ourobj, const Coordinate& to, const KigDocument& ) const Q_DECL_OVERRIDE; const ObjectImpType* resultId() const Q_DECL_OVERRIDE; QStringList specialActions() const Q_DECL_OVERRIDE; void executeAction( int i, ObjectHolder&, ObjectTypeCalcer& o, KigPart& d, KigWidget& w, NormalMode& m ) const Q_DECL_OVERRIDE; }; class MidPointType : public ObjectABType { MidPointType(); ~MidPointType(); public: static const MidPointType* instance(); // calcx was an overloaded calc, which produced a compilation warning ObjectImp* calcx( const Coordinate& a, const Coordinate& b ) const Q_DECL_OVERRIDE; const ObjectImpType* resultId() const Q_DECL_OVERRIDE; }; +class GoldenPointType + : public ObjectABType +{ + GoldenPointType(); + ~GoldenPointType(); +public: + static const GoldenPointType* instance(); + // calcx was an overloaded calc, which produced a compilation warning + ObjectImp* calcx( const Coordinate& a, const Coordinate& b ) const Q_DECL_OVERRIDE; + const ObjectImpType* resultId() const Q_DECL_OVERRIDE; +}; + class MeasureTransportType : public ObjectType { MeasureTransportType(); ~MeasureTransportType(); public: static const MeasureTransportType* instance(); ObjectImp* calc( const Args& parents, const KigDocument& ) const Q_DECL_OVERRIDE; const ObjectImpType* resultId() const Q_DECL_OVERRIDE; const ObjectImpType* impRequirement( const ObjectImp* o, const Args& parents ) const Q_DECL_OVERRIDE; bool isDefinedOnOrThrough( const ObjectImp* o, const Args& parents ) const Q_DECL_OVERRIDE; std::vector sortArgs( const std::vector& args )const Q_DECL_OVERRIDE; Args sortArgs( const Args& args ) const Q_DECL_OVERRIDE; }; class MeasureTransportTypeOld : public ArgsParserObjectType { MeasureTransportTypeOld(); ~MeasureTransportTypeOld(); public: static const MeasureTransportTypeOld* instance(); ObjectImp* calc( const Args& parents, const KigDocument& ) const Q_DECL_OVERRIDE; const ObjectImpType* resultId() const Q_DECL_OVERRIDE; }; class PointByCoordsType : public ArgsParserObjectType { PointByCoordsType(); ~PointByCoordsType(); public: static const PointByCoordsType* instance(); ObjectImp* calc( const Args& parents, const KigDocument& ) const Q_DECL_OVERRIDE; const ObjectImpType* resultId() const Q_DECL_OVERRIDE; }; class ProjectedPointType : public ArgsParserObjectType { ProjectedPointType(); ~ProjectedPointType(); public: static const ProjectedPointType* instance(); ObjectImp* calc( const Args& parents, const KigDocument& ) const Q_DECL_OVERRIDE; const ObjectImpType * resultId() const Q_DECL_OVERRIDE; }; #endif