mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-13 14:07:01 -04:00
Implemented rotation and reflection
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@536 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -78,14 +78,17 @@ menu:
|
|||||||
store symbol: S&tore Ctrl+Enter
|
store symbol: S&tore Ctrl+Enter
|
||||||
close symbol editor:Close Alt+F4
|
close symbol editor:Close Alt+F4
|
||||||
|
|
||||||
duplicate: Duplicate Ctrl+D
|
duplicate: &Duplicate Ctrl+D
|
||||||
|
group: &Group Ctrl+G
|
||||||
|
ungroup: &Ungroup Ctrl+U
|
||||||
|
|
||||||
tool: &Tool
|
tool: &Tool
|
||||||
select: &Select F5
|
select: &Select F5
|
||||||
rotate: &Rotate F6
|
rotate: &Rotate F6
|
||||||
points: &Points F7
|
points: &Points F7
|
||||||
basic shapes: &Basic Shapes F8
|
basic shapes: &Basic Shapes F8
|
||||||
paint: P&aint F9
|
symmetry: S&ymmetry F9
|
||||||
|
paint: P&aint F10
|
||||||
|
|
||||||
############################################################## Menu help texts
|
############################################################## Menu help texts
|
||||||
help:
|
help:
|
||||||
@@ -179,6 +182,8 @@ help:
|
|||||||
close symbol editor:Closes the symbol editor
|
close symbol editor:Closes the symbol editor
|
||||||
|
|
||||||
duplicate: Duplicates the selected shapes
|
duplicate: Duplicates the selected shapes
|
||||||
|
group: Group the selected shapes together
|
||||||
|
ungroup: Break up the selected group
|
||||||
|
|
||||||
grid: Show gridlines
|
grid: Show gridlines
|
||||||
snap: Snap shapes and points to gridlines
|
snap: Snap shapes and points to gridlines
|
||||||
@@ -188,6 +193,7 @@ help:
|
|||||||
rotate: Rotate and shear shapes
|
rotate: Rotate and shear shapes
|
||||||
points: Edit control points for a shape in the symbol
|
points: Edit control points for a shape in the symbol
|
||||||
basic shapes: Draw basic shapes, such as rectangles and circles
|
basic shapes: Draw basic shapes, such as rectangles and circles
|
||||||
|
symmetry: Add symmetries to the symbol
|
||||||
paint: Paint on the shape using a paintbrush
|
paint: Paint on the shape using a paintbrush
|
||||||
|
|
||||||
select editor:
|
select editor:
|
||||||
@@ -247,6 +253,7 @@ tool:
|
|||||||
rotate: Rotate
|
rotate: Rotate
|
||||||
points: Points
|
points: Points
|
||||||
basic shapes: Basic Shapes
|
basic shapes: Basic Shapes
|
||||||
|
symmetry: Symmetry
|
||||||
paint: Paint
|
paint: Paint
|
||||||
|
|
||||||
merge: Merge
|
merge: Merge
|
||||||
@@ -261,6 +268,9 @@ tool:
|
|||||||
polygon: Polygon
|
polygon: Polygon
|
||||||
star: Star
|
star: Star
|
||||||
|
|
||||||
|
rotation: Rotation
|
||||||
|
reflection: Reflection
|
||||||
|
|
||||||
line segment: Line
|
line segment: Line
|
||||||
curve segment: Curve
|
curve segment: Curve
|
||||||
free point: Free
|
free point: Free
|
||||||
@@ -314,7 +324,8 @@ tooltip:
|
|||||||
rotate: Rotate (F6)
|
rotate: Rotate (F6)
|
||||||
points: Points (F7)
|
points: Points (F7)
|
||||||
basic shapes: Basic Shapes (F8)
|
basic shapes: Basic Shapes (F8)
|
||||||
paint: Paint on Shape (F9)
|
symmetry: Symmetry (F9)
|
||||||
|
paint: Paint on Shape (F10)
|
||||||
|
|
||||||
merge: Merge with shapes below
|
merge: Merge with shapes below
|
||||||
subtract: Subtract from shapes below
|
subtract: Subtract from shapes below
|
||||||
@@ -328,6 +339,9 @@ tooltip:
|
|||||||
polygon: Polygon
|
polygon: Polygon
|
||||||
star: Star
|
star: Star
|
||||||
|
|
||||||
|
rotation: Rotational symmetry (wheel)
|
||||||
|
reflection: Reflectional symmetry (mirror)
|
||||||
|
|
||||||
line segment: To straigt line
|
line segment: To straigt line
|
||||||
curve segment: To curve
|
curve segment: To curve
|
||||||
free point: Unlock point
|
free point: Unlock point
|
||||||
@@ -513,6 +527,8 @@ action:
|
|||||||
reorder parts: Reorder
|
reorder parts: Reorder
|
||||||
change combine mode:Change combine mode
|
change combine mode:Change combine mode
|
||||||
change shape name: Change shape name
|
change shape name: Change shape name
|
||||||
|
group parts: Group
|
||||||
|
ungroup parts: Ungroup
|
||||||
|
|
||||||
# Symbol Part Actions
|
# Symbol Part Actions
|
||||||
convert to line: Convert to line
|
convert to line: Convert to line
|
||||||
@@ -608,6 +624,10 @@ type:
|
|||||||
polygon: polygon
|
polygon: polygon
|
||||||
star: star
|
star: star
|
||||||
|
|
||||||
|
rotation: rotation
|
||||||
|
reflection: reflection
|
||||||
|
group: group
|
||||||
|
|
||||||
point: point
|
point: point
|
||||||
points: points
|
points: points
|
||||||
handle: handle
|
handle: handle
|
||||||
|
|||||||
@@ -62,13 +62,12 @@ void SymbolPartMoveAction::movePart(SymbolPart& part) {
|
|||||||
}
|
}
|
||||||
} else if (SymbolSymmetry* s = part.isSymbolSymmetry()) {
|
} else if (SymbolSymmetry* s = part.isSymbolSymmetry()) {
|
||||||
s->center -= moved;
|
s->center -= moved;
|
||||||
} else if (SymbolGroup* g = part.isSymbolGroup()) {
|
}
|
||||||
|
if (SymbolGroup* g = part.isSymbolGroup()) {
|
||||||
FOR_EACH(p, g->parts) {
|
FOR_EACH(p, g->parts) {
|
||||||
movePart(*p);
|
movePart(*p);
|
||||||
}
|
}
|
||||||
g->calculateBoundsNonRec();
|
g->calculateBoundsNonRec();
|
||||||
} else {
|
|
||||||
throw InternalError(_("Invalid symbol part type"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,13 +107,12 @@ void SymbolPartMatrixAction::transform(SymbolPart& part, const Matrix2D& m) {
|
|||||||
} else if (SymbolSymmetry* s = part.isSymbolSymmetry()) {
|
} else if (SymbolSymmetry* s = part.isSymbolSymmetry()) {
|
||||||
s->center = (s->center - center) * m + center;
|
s->center = (s->center - center) * m + center;
|
||||||
s->handle = s->handle * m;
|
s->handle = s->handle * m;
|
||||||
} else if (SymbolGroup* g = part.isSymbolGroup()) {
|
}
|
||||||
|
if (SymbolGroup* g = part.isSymbolGroup()) {
|
||||||
FOR_EACH(p, g->parts) {
|
FOR_EACH(p, g->parts) {
|
||||||
transform(*p, m);
|
transform(*p, m);
|
||||||
}
|
}
|
||||||
g->calculateBoundsNonRec();
|
g->calculateBoundsNonRec();
|
||||||
} else {
|
|
||||||
throw InternalError(_("Invalid symbol part type"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,13 +282,12 @@ void SymbolPartScaleAction::transformPart(SymbolPart& part) {
|
|||||||
} else if (SymbolSymmetry* s = part.isSymbolSymmetry()) {
|
} else if (SymbolSymmetry* s = part.isSymbolSymmetry()) {
|
||||||
transform(s->center);
|
transform(s->center);
|
||||||
s->handle.mul(new_size.div(old_size));
|
s->handle.mul(new_size.div(old_size));
|
||||||
} else if (SymbolGroup* g = part.isSymbolGroup()) {
|
}
|
||||||
|
if (SymbolGroup* g = part.isSymbolGroup()) {
|
||||||
FOR_EACH(p, g->parts) {
|
FOR_EACH(p, g->parts) {
|
||||||
transformPart(*p);
|
transformPart(*p);
|
||||||
}
|
}
|
||||||
g->calculateBoundsNonRec();
|
g->calculateBoundsNonRec();
|
||||||
} else {
|
|
||||||
throw InternalError(_("Invalid symbol part type"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -59,7 +59,7 @@ void deCasteljau(const Vector2D& a1, Vector2D& a21, Vector2D& a34, const Vector2
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Drawing
|
// ----------------------------------------------------------------------------- : Drawing
|
||||||
|
|
||||||
void curve_subdivide(const BezierCurve& c, const Vector2D& p0, const Vector2D& p1, double t0, double t1, const Rotation& rot, vector<wxPoint>& out, UInt level) {
|
void curve_subdivide(const BezierCurve& c, const Vector2D& p0, const Vector2D& p1, double t0, double t1, const Vector2D& origin, const Matrix2D& m, vector<wxPoint>& out, UInt level) {
|
||||||
if (level <= 0) return;
|
if (level <= 0) return;
|
||||||
double midtime = (t0+t1) * 0.5f;
|
double midtime = (t0+t1) * 0.5f;
|
||||||
Vector2D midpoint = c.pointAt(midtime);
|
Vector2D midpoint = c.pointAt(midtime);
|
||||||
@@ -70,23 +70,23 @@ void curve_subdivide(const BezierCurve& c, const Vector2D& p0, const Vector2D& p
|
|||||||
double treshold = fabs( atan2(d0.x,d0.y) - atan2(d1.x,d1.y)) * (p0-p1).lengthSqr();
|
double treshold = fabs( atan2(d0.x,d0.y) - atan2(d1.x,d1.y)) * (p0-p1).lengthSqr();
|
||||||
bool subdivide = treshold >= .0001;
|
bool subdivide = treshold >= .0001;
|
||||||
// subdivide left
|
// subdivide left
|
||||||
curve_subdivide(c, p0, midpoint, t0, midtime, rot, out, level - 1);
|
curve_subdivide(c, p0, midpoint, t0, midtime, origin, m, out, level - 1);
|
||||||
// add midpoint
|
// add midpoint
|
||||||
if (subdivide) {
|
if (subdivide) {
|
||||||
out.push_back(rot.tr(midpoint));
|
out.push_back(origin + midpoint * m);
|
||||||
}
|
}
|
||||||
// subdivide right
|
// subdivide right
|
||||||
curve_subdivide(c, midpoint, p1, midtime, t1, rot, out, level - 1);
|
curve_subdivide(c, midpoint, p1, midtime, t1, origin, m, out, level - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void segment_subdivide(const ControlPoint& p0, const ControlPoint& p1, const Rotation& rot, vector<wxPoint>& out) {
|
void segment_subdivide(const ControlPoint& p0, const ControlPoint& p1, const Vector2D& origin, const Matrix2D& m, vector<wxPoint>& out) {
|
||||||
assert(p0.segment_after == p1.segment_before);
|
assert(p0.segment_after == p1.segment_before);
|
||||||
// always the start
|
// always the start
|
||||||
out.push_back(rot.tr(p0.pos));
|
out.push_back(origin + p0.pos * m);
|
||||||
if (p0.segment_after == SEGMENT_CURVE) {
|
if (p0.segment_after == SEGMENT_CURVE) {
|
||||||
// need more points?
|
// need more points?
|
||||||
BezierCurve curve(p0,p1);
|
BezierCurve curve(p0,p1);
|
||||||
curve_subdivide(curve, p0.pos, p1.pos, 0, 1, rot, out, 5);
|
curve_subdivide(curve, p0.pos, p1.pos, 0, 1, origin, m, out, 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -15,7 +15,7 @@
|
|||||||
// ----------------------------------------------------------------------------- : Includes
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <util/rotation.hpp>
|
#include <util/vector2d.hpp>
|
||||||
#include <data/symbol.hpp>
|
#include <data/symbol.hpp>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Evaluation
|
// ----------------------------------------------------------------------------- : Evaluation
|
||||||
@@ -65,9 +65,9 @@ void deCasteljau(const Vector2D& a1, Vector2D& a21, Vector2D& a34, const Vector2
|
|||||||
|
|
||||||
/// Devide a segment into a number of straight lines for display purposes
|
/// Devide a segment into a number of straight lines for display purposes
|
||||||
/** Adds the resulting corner points of those lines to out, the last point is not added.
|
/** Adds the resulting corner points of those lines to out, the last point is not added.
|
||||||
* All points are converted to display coordinates using rot.tr
|
* All points are converted to display coordinates by multiplying with m and adding origin
|
||||||
*/
|
*/
|
||||||
void segment_subdivide(const ControlPoint& p0, const ControlPoint& p1, const Rotation& rot, vector<wxPoint>& out);
|
void segment_subdivide(const ControlPoint& p0, const ControlPoint& p1, const Vector2D& origin, const Matrix2D& m, vector<wxPoint>& out);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Bounds
|
// ----------------------------------------------------------------------------- : Bounds
|
||||||
|
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ void SymbolControl::onChar(wxKeyEvent& ev) {
|
|||||||
|
|
||||||
void SymbolControl::onSize(wxSizeEvent& ev) {
|
void SymbolControl::onSize(wxSizeEvent& ev) {
|
||||||
wxSize s = GetClientSize();
|
wxSize s = GetClientSize();
|
||||||
rotation.setZoom(min(s.GetWidth(), s.GetHeight()));
|
setZoom(min(s.GetWidth(), s.GetHeight()));
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
}
|
}
|
||||||
void SymbolControl::onUpdateUI(wxUpdateUIEvent& ev) {
|
void SymbolControl::onUpdateUI(wxUpdateUIEvent& ev) {
|
||||||
@@ -248,6 +248,9 @@ void SymbolControl::onUpdateUI(wxUpdateUIEvent& ev) {
|
|||||||
// can only edit points when a shape is available
|
// can only edit points when a shape is available
|
||||||
ev.Enable(selected_parts.getAShape());
|
ev.Enable(selected_parts.getAShape());
|
||||||
}
|
}
|
||||||
|
if (ev.GetId() == ID_MODE_SYMMETRY) {
|
||||||
|
ev.Enable(!selected_parts.empty());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ID_MODE_PAINT:
|
case ID_MODE_PAINT:
|
||||||
ev.Enable(false); // TODO
|
ev.Enable(false); // TODO
|
||||||
|
|||||||
@@ -24,10 +24,11 @@ void SymbolPartsSelection::clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SymbolPartsSelection::select(const SymbolPartP& part, SelectMode mode) {
|
bool SymbolPartsSelection::select(const SymbolPartP& part, SelectMode mode) {
|
||||||
|
assert(part);
|
||||||
// make sure part is not the decendent of a part that is already selected
|
// make sure part is not the decendent of a part that is already selected
|
||||||
if (mode != SELECT_OVERRIDE) {
|
if (mode != SELECT_OVERRIDE) {
|
||||||
FOR_EACH(s, selection) {
|
FOR_EACH(s, selection) {
|
||||||
if (isAncestor(s.get(), part.get())) return false;
|
if (s != part && s->isAncestor(*part)) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// select
|
// select
|
||||||
@@ -70,15 +71,6 @@ void SymbolPartsSelection::clearChildren(SymbolPart* part) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SymbolPartsSelection::isAncestor(SymbolPart* ancestor, SymbolPart* part) {
|
|
||||||
if (SymbolGroup* g = ancestor->isSymbolGroup()) {
|
|
||||||
FOR_EACH(p, g->parts) {
|
|
||||||
if (part == p.get()) return true;
|
|
||||||
if (isAncestor(p.get(), part)) return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Position based
|
// ----------------------------------------------------------------------------- : Position based
|
||||||
|
|
||||||
@@ -116,7 +108,7 @@ bool SymbolPartsSelection::selectRect(const Vector2D& a, const Vector2D& b, cons
|
|||||||
}
|
}
|
||||||
bool SymbolPartsSelection::selectRect(const SymbolGroup& parent, const Vector2D& a, const Vector2D& b, const Vector2D& c) {
|
bool SymbolPartsSelection::selectRect(const SymbolGroup& parent, const Vector2D& a, const Vector2D& b, const Vector2D& c) {
|
||||||
bool changes = false;
|
bool changes = false;
|
||||||
FOR_EACH_CONST(p, root->parts) {
|
FOR_EACH_CONST(p, parent.parts) {
|
||||||
bool in_ab = (p->min_pos.x >= min(a.x, b.x) && p->min_pos.y >= min(a.y, b.y) && p->max_pos.x <= max(a.x, b.x) && p->max_pos.y <= max(a.y, b.y));
|
bool in_ab = (p->min_pos.x >= min(a.x, b.x) && p->min_pos.y >= min(a.y, b.y) && p->max_pos.x <= max(a.x, b.x) && p->max_pos.y <= max(a.y, b.y));
|
||||||
bool in_bc = (p->min_pos.x >= min(a.x, c.x) && p->min_pos.y >= min(a.y, c.y) && p->max_pos.x <= max(a.x, c.x) && p->max_pos.y <= max(a.y, c.y));
|
bool in_bc = (p->min_pos.x >= min(a.x, c.x) && p->min_pos.y >= min(a.y, c.y) && p->max_pos.x <= max(a.x, c.x) && p->max_pos.y <= max(a.y, c.y));
|
||||||
if (in_ab != in_bc) {
|
if (in_ab != in_bc) {
|
||||||
|
|||||||
@@ -73,8 +73,6 @@ class SymbolPartsSelection {
|
|||||||
|
|
||||||
/// Make sure not both a parent and its child/decendant are selected
|
/// Make sure not both a parent and its child/decendant are selected
|
||||||
void clearChildren (SymbolPart* part);
|
void clearChildren (SymbolPart* part);
|
||||||
/// Is a part another's ancestor?
|
|
||||||
static bool isAncestor(SymbolPart* ancestor, SymbolPart* part);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : EOF
|
// ----------------------------------------------------------------------------- : EOF
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
/// Editor for adding symmetries
|
/// Editor for adding symmetries
|
||||||
class SymbolSymmetryEditor : public SymbolEditorBase {
|
class SymbolSymmetryEditor : public SymbolEditorBase {
|
||||||
public:
|
public:
|
||||||
|
/** The symmetry parameter is optional, if it is not set, then only new ones can be created */
|
||||||
|
//%SymbolSymmetryEditor(SymbolControl* control, SymbolSymmetryP symmetry);
|
||||||
SymbolSymmetryEditor(SymbolControl* control);
|
SymbolSymmetryEditor(SymbolControl* control);
|
||||||
|
|
||||||
// --------------------------------------------------- : Drawing
|
// --------------------------------------------------- : Drawing
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ SymbolWindow::SymbolWindow(Window* parent) {
|
|||||||
|
|
||||||
SymbolWindow::SymbolWindow(Window* parent, const String& filename) {
|
SymbolWindow::SymbolWindow(Window* parent, const String& filename) {
|
||||||
// open file
|
// open file
|
||||||
Reader reader(filename);
|
Reader reader(new_shared1<wxFileInputStream>(filename), filename);
|
||||||
SymbolP symbol;
|
SymbolP symbol;
|
||||||
reader.handle_greedy(symbol);
|
reader.handle_greedy(symbol);
|
||||||
init(parent, symbol);
|
init(parent, symbol);
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ DECLARE_TYPEOF_COLLECTION(SymbolPartP);
|
|||||||
// ----------------------------------------------------------------------------- : Simple rendering
|
// ----------------------------------------------------------------------------- : Simple rendering
|
||||||
|
|
||||||
Image render_symbol(const SymbolP& symbol, double border_radius, int size) {
|
Image render_symbol(const SymbolP& symbol, double border_radius, int size) {
|
||||||
SymbolViewer viewer(symbol, border_radius);
|
SymbolViewer viewer(symbol, size, border_radius);
|
||||||
Bitmap bmp(size, size);
|
Bitmap bmp(size, size);
|
||||||
wxMemoryDC dc;
|
wxMemoryDC dc;
|
||||||
dc.SelectObject(bmp);
|
dc.SelectObject(bmp);
|
||||||
clearDC(dc, Color(0,128,0));
|
clearDC(dc, Color(0,128,0));
|
||||||
viewer.rotation.setZoom(size);
|
viewer.setZoom(size);
|
||||||
viewer.draw(dc);
|
viewer.draw(dc);
|
||||||
dc.SelectObject(wxNullBitmap);
|
dc.SelectObject(wxNullBitmap);
|
||||||
return bmp.ConvertToImage();
|
return bmp.ConvertToImage();
|
||||||
@@ -28,13 +28,20 @@ Image render_symbol(const SymbolP& symbol, double border_radius, int size) {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Constructor
|
// ----------------------------------------------------------------------------- : Constructor
|
||||||
|
|
||||||
SymbolViewer::SymbolViewer(const SymbolP& symbol, double border_radius)
|
SymbolViewer::SymbolViewer(const SymbolP& symbol, double size, double border_radius)
|
||||||
: border_radius(border_radius)
|
: border_radius(border_radius)
|
||||||
, rotation(0, RealRect(0,0,500,500), 500)
|
, rotation(0, RealRect(0,0,size,size), size)
|
||||||
|
, multiply(size,0,0,size)
|
||||||
|
, origin(0,0)
|
||||||
{
|
{
|
||||||
setSymbol(symbol);
|
setSymbol(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SymbolViewer::setZoom(double zoom) {
|
||||||
|
rotation.setZoom(zoom);
|
||||||
|
multiply = Matrix2D(zoom,0, 0,zoom);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Drawing
|
// ----------------------------------------------------------------------------- : Drawing
|
||||||
|
|
||||||
typedef shared_ptr<wxMemoryDC> MemoryDCP;
|
typedef shared_ptr<wxMemoryDC> MemoryDCP;
|
||||||
@@ -73,16 +80,16 @@ void SymbolViewer::draw(DC& dc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Draw all parts
|
// Draw all parts
|
||||||
combineSymbolPart(dc, *symbol, paintedSomething, buffersFilled, borderDC, interiorDC);
|
combineSymbolPart(dc, *symbol, paintedSomething, buffersFilled, true, borderDC, interiorDC);
|
||||||
|
|
||||||
// Output the final parts from the buffer
|
// Output the final parts from the buffer
|
||||||
if (buffersFilled) {
|
if (buffersFilled) {
|
||||||
combineBuffers(dc, borderDC.get(), interiorDC.get());
|
combineBuffers(dc, borderDC.get(), interiorDC.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void SymbolViewer::combineSymbolPart(DC& dc, const SymbolPart& part, bool& paintedSomething, bool& buffersFilled, MemoryDCP& borderDC, MemoryDCP& interiorDC) {
|
void SymbolViewer::combineSymbolPart(DC& dc, const SymbolPart& part, bool& paintedSomething, bool& buffersFilled, bool allow_overlap, MemoryDCP& borderDC, MemoryDCP& interiorDC) {
|
||||||
if (const SymbolShape* s = part.isSymbolShape()) {
|
if (const SymbolShape* s = part.isSymbolShape()) {
|
||||||
if (s->combine == SYMBOL_COMBINE_OVERLAP && buffersFilled) {
|
if (s->combine == SYMBOL_COMBINE_OVERLAP && buffersFilled && allow_overlap) {
|
||||||
// We will be overlapping some previous parts, write them to the screen
|
// We will be overlapping some previous parts, write them to the screen
|
||||||
combineBuffers(dc, borderDC.get(), interiorDC.get());
|
combineBuffers(dc, borderDC.get(), interiorDC.get());
|
||||||
// Clear the buffers
|
// Clear the buffers
|
||||||
@@ -111,14 +118,61 @@ void SymbolViewer::combineSymbolPart(DC& dc, const SymbolPart& part, bool& paint
|
|||||||
combineSymbolShape(*s, *borderDC, *interiorDC, false, false);
|
combineSymbolShape(*s, *borderDC, *interiorDC, false, false);
|
||||||
buffersFilled = true;
|
buffersFilled = true;
|
||||||
}
|
}
|
||||||
// Paint symmetric versions of this part
|
|
||||||
// TODO
|
|
||||||
} else if (const SymbolSymmetry* s = part.isSymbolSymmetry()) {
|
} else if (const SymbolSymmetry* s = part.isSymbolSymmetry()) {
|
||||||
// symmetry, already handled above
|
// Draw all parts, in reverse order (bottom to top), also draw rotated copies
|
||||||
|
double b = 2 * atan2(s->handle.y, s->handle.x);
|
||||||
|
Matrix2D old_m = multiply;
|
||||||
|
Vector2D old_o = origin;
|
||||||
|
int copies = s->kind == SYMMETRY_REFLECTION ? s->copies / 2 * 2 : s->copies;
|
||||||
|
FOR_EACH_CONST_REVERSE(p, s->parts) {
|
||||||
|
for (int i = 0 ; i < copies ; ++i) {
|
||||||
|
if (s->clip) {
|
||||||
|
// todo: clip
|
||||||
|
}
|
||||||
|
double a = i * 2 * M_PI / copies;
|
||||||
|
if (s->kind == SYMMETRY_ROTATION || i % 2 == 0) {
|
||||||
|
// set matrix
|
||||||
|
// Calling:
|
||||||
|
// - p the input point
|
||||||
|
// - p' the output point
|
||||||
|
// - rot our rotation matrix
|
||||||
|
// - d out origin
|
||||||
|
// - o the current origin (old_o)
|
||||||
|
// - m the current matrix (old_m)
|
||||||
|
// We want:
|
||||||
|
// p' = ((p - d) * rot + d) * m + o
|
||||||
|
// = (p * rot - d * rot + d) * m + o
|
||||||
|
// = p * rot * m + (d - d * rot) * m + o
|
||||||
|
Matrix2D rot(cos(a),-sin(a), sin(a),cos(a));
|
||||||
|
multiply.mx = rot.mx * old_m;
|
||||||
|
multiply.my = rot.my * old_m;
|
||||||
|
origin = old_o + (s->center - s->center * rot) * old_m;
|
||||||
|
} else {
|
||||||
|
// reflection
|
||||||
|
// Calling angle = b
|
||||||
|
// Matrix2D ref(cos(b),sin(b), sin(b),-cos(b));
|
||||||
|
// Matrix2D rot(cos(a),-sin(a), sin(a),cos(a));
|
||||||
|
//
|
||||||
|
// ref * rot
|
||||||
|
// /cos b sin b\ /cos a -sin a\
|
||||||
|
// = \sin b -cos b/ \sin a cos a/
|
||||||
|
// = /cos(a+b) sin(a+b)\
|
||||||
|
// \sin(a+b) -cos(a+b)/
|
||||||
|
Matrix2D rot(cos(a+b),sin(a+b), sin(a+b),-cos(a+b));
|
||||||
|
multiply.mx = rot.mx * old_m;
|
||||||
|
multiply.my = rot.my * old_m;
|
||||||
|
origin = old_o + (s->center - s->center * rot) * old_m;
|
||||||
|
}
|
||||||
|
// draw rotated copy
|
||||||
|
combineSymbolPart(dc, *p, paintedSomething, buffersFilled, allow_overlap && i == 0, borderDC, interiorDC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
multiply = old_m;
|
||||||
|
origin = old_o;
|
||||||
} else if (const SymbolGroup* g = part.isSymbolGroup()) {
|
} else if (const SymbolGroup* g = part.isSymbolGroup()) {
|
||||||
// Draw all parts, in reverse order (bottom to top)
|
// Draw all parts, in reverse order (bottom to top)
|
||||||
FOR_EACH_CONST_REVERSE(p, g->parts) {
|
FOR_EACH_CONST_REVERSE(p, g->parts) {
|
||||||
combineSymbolPart(dc, *p, paintedSomething, buffersFilled, borderDC, interiorDC);
|
combineSymbolPart(dc, *p, paintedSomething, buffersFilled, allow_overlap, borderDC, interiorDC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,7 +193,7 @@ void SymbolViewer::highlightPart(DC& dc, const SymbolShape& shape, HighlightStyl
|
|||||||
vector<wxPoint> points;
|
vector<wxPoint> points;
|
||||||
size_t size = shape.points.size();
|
size_t size = shape.points.size();
|
||||||
for(size_t i = 0 ; i < size ; ++i) {
|
for(size_t i = 0 ; i < size ; ++i) {
|
||||||
segment_subdivide(*shape.getPoint((int)i), *shape.getPoint((int)i+1), rotation, points);
|
segment_subdivide(*shape.getPoint((int)i), *shape.getPoint((int)i+1), origin, multiply, points);
|
||||||
}
|
}
|
||||||
// draw
|
// draw
|
||||||
if (style == HIGHLIGHT_BORDER) {
|
if (style == HIGHLIGHT_BORDER) {
|
||||||
@@ -238,7 +292,7 @@ void SymbolViewer::drawSymbolShape(const SymbolShape& shape, DC* border, DC* int
|
|||||||
vector<wxPoint> points;
|
vector<wxPoint> points;
|
||||||
size_t size = shape.points.size();
|
size_t size = shape.points.size();
|
||||||
for(size_t i = 0 ; i < size ; ++i) {
|
for(size_t i = 0 ; i < size ; ++i) {
|
||||||
segment_subdivide(*shape.getPoint((int)i), *shape.getPoint((int)i+1), rotation, points);
|
segment_subdivide(*shape.getPoint((int)i), *shape.getPoint((int)i+1), origin, multiply, points);
|
||||||
}
|
}
|
||||||
// draw border
|
// draw border
|
||||||
if (border && border_radius > 0) {
|
if (border && border_radius > 0) {
|
||||||
|
|||||||
@@ -32,14 +32,18 @@ enum HighlightStyle
|
|||||||
class SymbolViewer : public SymbolView {
|
class SymbolViewer : public SymbolView {
|
||||||
public:
|
public:
|
||||||
// --------------------------------------------------- : Data
|
// --------------------------------------------------- : Data
|
||||||
SymbolViewer(const SymbolP& symbol, double border_radius = 0.05);
|
SymbolViewer(const SymbolP& symbol, double size = 500, double border_radius = 0.05);
|
||||||
|
|
||||||
// drawing
|
// drawing
|
||||||
double border_radius;
|
double border_radius;
|
||||||
|
|
||||||
// --------------------------------------------------- : Point translation
|
// --------------------------------------------------- : Point translation
|
||||||
|
|
||||||
|
void setZoom(double zoom);
|
||||||
|
|
||||||
Rotation rotation; ///< Object that handles rotation, scaling and translation
|
Rotation rotation; ///< Object that handles rotation, scaling and translation
|
||||||
|
Matrix2D multiply; ///< Scaling/rotation of actual parts
|
||||||
|
Vector2D origin; ///< Origin of parts
|
||||||
|
|
||||||
// --------------------------------------------------- : Drawing
|
// --------------------------------------------------- : Drawing
|
||||||
|
|
||||||
@@ -57,7 +61,7 @@ class SymbolViewer : public SymbolView {
|
|||||||
typedef shared_ptr<wxMemoryDC> MemoryDCP;
|
typedef shared_ptr<wxMemoryDC> MemoryDCP;
|
||||||
|
|
||||||
/// Combine a symbol part with the dc
|
/// Combine a symbol part with the dc
|
||||||
void SymbolViewer::combineSymbolPart(DC& dc, const SymbolPart& part, bool& paintedSomething, bool& buffersFilled, MemoryDCP& borderDC, MemoryDCP& interiorDC);
|
void SymbolViewer::combineSymbolPart(DC& dc, const SymbolPart& part, bool& paintedSomething, bool& buffersFilled, bool allow_overlap, MemoryDCP& borderDC, MemoryDCP& interiorDC);
|
||||||
|
|
||||||
/// Combines a symbol part with what is currently drawn, the border and interior are drawn separatly
|
/// Combines a symbol part with what is currently drawn, the border and interior are drawn separatly
|
||||||
/** directB/directI are true if the border/interior is the screen dc, false if it
|
/** directB/directI are true if the border/interior is the screen dc, false if it
|
||||||
|
|||||||
Reference in New Issue
Block a user