Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
magicseteditor
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
magicseteditor
Commits
2961a3be
Commit
2961a3be
authored
Aug 27, 2008
by
twanvl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cleaned up the calculation of bounds of symbols, this fixes bounds calculation with symmetries.
parent
2562da1e
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
192 additions
and
135 deletions
+192
-135
src/data/action/symbol.cpp
src/data/action/symbol.cpp
+17
-24
src/data/action/symbol.hpp
src/data/action/symbol.hpp
+5
-5
src/data/symbol.cpp
src/data/symbol.cpp
+86
-34
src/data/symbol.hpp
src/data/symbol.hpp
+36
-8
src/gfx/bezier.cpp
src/gfx/bezier.cpp
+19
-25
src/gfx/bezier.hpp
src/gfx/bezier.hpp
+3
-9
src/gui/symbol/select_editor.cpp
src/gui/symbol/select_editor.cpp
+8
-17
src/gui/symbol/select_editor.hpp
src/gui/symbol/select_editor.hpp
+1
-4
src/gui/symbol/selection.cpp
src/gui/symbol/selection.cpp
+4
-2
src/render/symbol/viewer.cpp
src/render/symbol/viewer.cpp
+4
-6
src/util/vector2d.hpp
src/util/vector2d.hpp
+9
-1
No files found.
src/data/action/symbol.cpp
View file @
2961a3be
...
@@ -32,14 +32,12 @@ SymbolPartsAction::SymbolPartsAction(const set<SymbolPartP>& parts)
...
@@ -32,14 +32,12 @@ SymbolPartsAction::SymbolPartsAction(const set<SymbolPartP>& parts)
SymbolPartMoveAction
::
SymbolPartMoveAction
(
const
set
<
SymbolPartP
>&
parts
,
const
Vector2D
&
delta
)
SymbolPartMoveAction
::
SymbolPartMoveAction
(
const
set
<
SymbolPartP
>&
parts
,
const
Vector2D
&
delta
)
:
SymbolPartsAction
(
parts
)
:
SymbolPartsAction
(
parts
)
,
delta
(
delta
),
moved
(
-
delta
)
,
delta
(
delta
),
moved
(
-
delta
)
,
min_pos
(
Vector2D
::
infinity
()),
max_pos
(
-
Vector2D
::
infinity
())
,
constrain
(
false
)
,
constrain
(
false
)
,
snap
(
0
)
,
snap
(
0
)
{
{
// Determine min/max_pos
// Determine min/max_pos
FOR_EACH
(
p
,
parts
)
{
FOR_EACH
(
p
,
parts
)
{
min_pos
=
piecewise_min
(
min_pos
,
p
->
min_pos
);
bounds
.
update
(
p
->
bounds
);
max_pos
=
piecewise_max
(
max_pos
,
p
->
max_pos
);
}
}
}
}
...
@@ -55,9 +53,9 @@ void SymbolPartMoveAction::perform(bool to_undo) {
...
@@ -55,9 +53,9 @@ void SymbolPartMoveAction::perform(bool to_undo) {
moved
=
-
moved
;
moved
=
-
moved
;
}
}
void
SymbolPartMoveAction
::
movePart
(
SymbolPart
&
part
)
{
void
SymbolPartMoveAction
::
movePart
(
SymbolPart
&
part
)
{
part
.
bounds
.
min
-=
moved
;
part
.
bounds
.
max
-=
moved
;
if
(
SymbolShape
*
s
=
part
.
isSymbolShape
())
{
if
(
SymbolShape
*
s
=
part
.
isSymbolShape
())
{
s
->
min_pos
-=
moved
;
s
->
max_pos
-=
moved
;
FOR_EACH
(
pnt
,
s
->
points
)
{
FOR_EACH
(
pnt
,
s
->
points
)
{
pnt
->
pos
-=
moved
;
pnt
->
pos
-=
moved
;
}
}
...
@@ -68,14 +66,13 @@ void SymbolPartMoveAction::movePart(SymbolPart& part) {
...
@@ -68,14 +66,13 @@ void SymbolPartMoveAction::movePart(SymbolPart& part) {
FOR_EACH
(
p
,
g
->
parts
)
{
FOR_EACH
(
p
,
g
->
parts
)
{
movePart
(
*
p
);
movePart
(
*
p
);
}
}
g
->
calculateBoundsNonRec
();
}
}
}
}
void
SymbolPartMoveAction
::
move
(
const
Vector2D
&
deltaDelta
)
{
void
SymbolPartMoveAction
::
move
(
const
Vector2D
&
deltaDelta
)
{
delta
+=
deltaDelta
;
delta
+=
deltaDelta
;
// Determine actual delta, possibly constrained and snapped
// Determine actual delta, possibly constrained and snapped
Vector2D
d
=
constrain_snap_vector_offset
(
min_pos
,
max_pos
,
delta
,
constrain
,
snap
);
Vector2D
d
=
constrain_snap_vector_offset
(
bounds
.
min
,
bounds
.
max
,
delta
,
constrain
,
snap
);
Vector2D
dd
=
d
-
moved
;
// move this much more
Vector2D
dd
=
d
-
moved
;
// move this much more
// Move each point by d
// Move each point by d
moved
=
-
dd
;
moved
=
-
dd
;
...
@@ -94,6 +91,7 @@ void SymbolPartMatrixAction::transform(const Matrix2D& m) {
...
@@ -94,6 +91,7 @@ void SymbolPartMatrixAction::transform(const Matrix2D& m) {
// Transform each part
// Transform each part
FOR_EACH
(
p
,
parts
)
{
FOR_EACH
(
p
,
parts
)
{
transform
(
*
p
,
m
);
transform
(
*
p
,
m
);
p
->
updateBounds
();
}
}
}
}
void
SymbolPartMatrixAction
::
transform
(
SymbolPart
&
part
,
const
Matrix2D
&
m
)
{
void
SymbolPartMatrixAction
::
transform
(
SymbolPart
&
part
,
const
Matrix2D
&
m
)
{
...
@@ -103,8 +101,6 @@ void SymbolPartMatrixAction::transform(SymbolPart& part, const Matrix2D& m) {
...
@@ -103,8 +101,6 @@ void SymbolPartMatrixAction::transform(SymbolPart& part, const Matrix2D& m) {
pnt
->
delta_before
=
pnt
->
delta_before
*
m
;
pnt
->
delta_before
=
pnt
->
delta_before
*
m
;
pnt
->
delta_after
=
pnt
->
delta_after
*
m
;
pnt
->
delta_after
=
pnt
->
delta_after
*
m
;
}
}
// bounds change after transforming
s
->
calculateBounds
();
}
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
;
...
@@ -113,7 +109,6 @@ void SymbolPartMatrixAction::transform(SymbolPart& part, const Matrix2D& m) {
...
@@ -113,7 +109,6 @@ void SymbolPartMatrixAction::transform(SymbolPart& part, const Matrix2D& m) {
FOR_EACH
(
p
,
g
->
parts
)
{
FOR_EACH
(
p
,
g
->
parts
)
{
transform
(
*
p
,
m
);
transform
(
*
p
,
m
);
}
}
g
->
calculateBoundsNonRec
();
}
}
}
}
...
@@ -205,15 +200,13 @@ SymbolPartScaleAction::SymbolPartScaleAction(const set<SymbolPartP>& parts, int
...
@@ -205,15 +200,13 @@ SymbolPartScaleAction::SymbolPartScaleAction(const set<SymbolPartP>& parts, int
,
snap
(
0
)
,
snap
(
0
)
{
{
// Find min and max coordinates
// Find min and max coordinates
old_min
=
Vector2D
(
1e6
,
1e6
);
Bounds
bounds
;
Vector2D
old_max
(
-
1e6
,
-
1e6
);
FOR_EACH
(
p
,
parts
)
{
FOR_EACH
(
p
,
parts
)
{
old_min
=
piecewise_min
(
old_min
,
p
->
min_pos
);
bounds
.
update
(
p
->
bounds
);
old_max
=
piecewise_max
(
old_max
,
p
->
max_pos
);
}
}
// new == old
// new == old
new_min
=
new_real_min
=
old_min
;
new_min
=
new_real_min
=
old_min
=
bounds
.
min
;
new_size
=
new_real_size
=
old_size
=
old_max
-
old_
min
;
new_size
=
new_real_size
=
old_size
=
bounds
.
max
-
bounds
.
min
;
}
}
String
SymbolPartScaleAction
::
getName
(
bool
to_undo
)
const
{
String
SymbolPartScaleAction
::
getName
(
bool
to_undo
)
const
{
...
@@ -266,14 +259,15 @@ void SymbolPartScaleAction::transformAll() {
...
@@ -266,14 +259,15 @@ void SymbolPartScaleAction::transformAll() {
}
}
}
}
void
SymbolPartScaleAction
::
transformPart
(
SymbolPart
&
part
)
{
void
SymbolPartScaleAction
::
transformPart
(
SymbolPart
&
part
)
{
// update bounds
part
.
bounds
.
min
=
transform
(
part
.
bounds
.
min
);
part
.
bounds
.
max
=
transform
(
part
.
bounds
.
max
);
// make sure that max >= min
if
(
part
.
bounds
.
min
.
x
>
part
.
bounds
.
max
.
x
)
swap
(
part
.
bounds
.
min
.
x
,
part
.
bounds
.
max
.
x
);
if
(
part
.
bounds
.
min
.
y
>
part
.
bounds
.
max
.
y
)
swap
(
part
.
bounds
.
min
.
y
,
part
.
bounds
.
max
.
y
);
if
(
SymbolShape
*
s
=
part
.
isSymbolShape
())
{
if
(
SymbolShape
*
s
=
part
.
isSymbolShape
())
{
Vector2D
scale
=
new_size
.
div
(
old_size
);
s
->
min_pos
=
transform
(
s
->
min_pos
);
s
->
max_pos
=
transform
(
s
->
max_pos
);
// make sure that max >= min
if
(
s
->
min_pos
.
x
>
s
->
max_pos
.
x
)
swap
(
s
->
min_pos
.
x
,
s
->
max_pos
.
x
);
if
(
s
->
min_pos
.
y
>
s
->
max_pos
.
y
)
swap
(
s
->
min_pos
.
y
,
s
->
max_pos
.
y
);
// scale all points
// scale all points
Vector2D
scale
=
new_size
.
div
(
old_size
);
FOR_EACH
(
pnt
,
s
->
points
)
{
FOR_EACH
(
pnt
,
s
->
points
)
{
pnt
->
pos
=
transform
(
pnt
->
pos
);
pnt
->
pos
=
transform
(
pnt
->
pos
);
// also scale handles
// also scale handles
...
@@ -288,7 +282,6 @@ void SymbolPartScaleAction::transformPart(SymbolPart& part) {
...
@@ -288,7 +282,6 @@ void SymbolPartScaleAction::transformPart(SymbolPart& part) {
FOR_EACH
(
p
,
g
->
parts
)
{
FOR_EACH
(
p
,
g
->
parts
)
{
transformPart
(
*
p
);
transformPart
(
*
p
);
}
}
g
->
calculateBoundsNonRec
();
}
}
}
}
...
@@ -538,7 +531,7 @@ GroupSymbolPartsAction::GroupSymbolPartsAction(SymbolGroup& root, const set<Symb
...
@@ -538,7 +531,7 @@ GroupSymbolPartsAction::GroupSymbolPartsAction(SymbolGroup& root, const set<Symb
old_part_list
.
push_back
(
p
);
old_part_list
.
push_back
(
p
);
}
}
}
}
group
->
calcul
ateBounds
();
group
->
upd
ateBounds
();
}
}
String
GroupSymbolPartsAction
::
getName
(
bool
to_undo
)
const
{
String
GroupSymbolPartsAction
::
getName
(
bool
to_undo
)
const
{
return
group
->
isSymbolSymmetry
()
?
_ACTION_
(
"add symmetry"
)
:
_ACTION_
(
"group parts"
);
return
group
->
isSymbolSymmetry
()
?
_ACTION_
(
"add symmetry"
)
:
_ACTION_
(
"group parts"
);
...
...
src/data/action/symbol.hpp
View file @
2961a3be
...
@@ -48,14 +48,14 @@ class SymbolPartMoveAction : public SymbolPartsAction {
...
@@ -48,14 +48,14 @@ class SymbolPartMoveAction : public SymbolPartsAction {
void
move
(
const
Vector2D
&
delta
);
void
move
(
const
Vector2D
&
delta
);
private:
private:
Vector2D
delta
;
///< How much to move
Vector2D
delta
;
///< How much to move
Vector2D
moved
;
///< How much has been moved
Vector2D
moved
;
///< How much has been moved
Vector2D
min_pos
,
max_po
s
;
///< Bounding box of the thing we are moving
Bounds
bound
s
;
///< Bounding box of the thing we are moving
void
movePart
(
SymbolPart
&
part
);
///< Move a single part
void
movePart
(
SymbolPart
&
part
);
///< Move a single part
public:
public:
bool
constrain
;
///< Constrain movement?
bool
constrain
;
///< Constrain movement?
int
snap
;
///< Snap to grid?
int
snap
;
///< Snap to grid?
};
};
// ----------------------------------------------------------------------------- : Rotating symbol parts
// ----------------------------------------------------------------------------- : Rotating symbol parts
...
...
src/data/symbol.cpp
View file @
2961a3be
...
@@ -94,11 +94,36 @@ Vector2D& ControlPoint::getOther(WhichHandle wh) {
...
@@ -94,11 +94,36 @@ Vector2D& ControlPoint::getOther(WhichHandle wh) {
}
}
}
}
// ----------------------------------------------------------------------------- : Bounds
void
Bounds
::
update
(
const
Vector2D
&
p
)
{
min
=
piecewise_min
(
min
,
p
);
max
=
piecewise_max
(
max
,
p
);
}
void
Bounds
::
update
(
const
Bounds
&
b
)
{
min
=
piecewise_min
(
min
,
b
.
min
);
max
=
piecewise_max
(
max
,
b
.
max
);
}
bool
Bounds
::
contains
(
const
Vector2D
&
p
)
const
{
return
p
.
x
>=
min
.
x
&&
p
.
y
>=
min
.
y
&&
p
.
x
<=
max
.
x
&&
p
.
y
<=
max
.
y
;
}
bool
Bounds
::
contains
(
const
Bounds
&
b
)
const
{
return
b
.
min
.
x
>=
min
.
x
&&
b
.
min
.
y
>=
min
.
y
&&
b
.
max
.
x
<=
max
.
x
&&
b
.
max
.
y
<=
max
.
y
;
}
Vector2D
Bounds
::
corner
(
int
dx
,
int
dy
)
const
{
return
Vector2D
(
0.5
*
(
min
.
x
+
max
.
x
+
dx
*
(
max
.
x
-
min
.
x
)),
0.5
*
(
min
.
y
+
max
.
y
+
dy
*
(
max
.
y
-
min
.
y
)));
}
// ----------------------------------------------------------------------------- : SymbolPart
// ----------------------------------------------------------------------------- : SymbolPart
void
SymbolPart
::
calculateBounds
()
{
void
SymbolPart
::
updateBounds
()
{
min_pos
=
Vector2D
::
infinity
();
calculateBounds
(
Vector2D
(),
Matrix2D
(),
true
);
max_pos
=
-
Vector2D
::
infinity
();
}
}
IMPLEMENT_REFLECTION
(
SymbolPart
)
{
IMPLEMENT_REFLECTION
(
SymbolPart
)
{
...
@@ -133,6 +158,23 @@ IMPLEMENT_REFLECTION_ENUM(SymbolShapeCombine) {
...
@@ -133,6 +158,23 @@ IMPLEMENT_REFLECTION_ENUM(SymbolShapeCombine) {
VALUE_N
(
"border"
,
SYMBOL_COMBINE_BORDER
);
VALUE_N
(
"border"
,
SYMBOL_COMBINE_BORDER
);
}
}
template
<
typename
T
>
void
fix
(
const
T
&
,
SymbolShape
&
)
{}
void
fix
(
const
Reader
&
reader
,
SymbolShape
&
shape
)
{
if
(
reader
.
file_app_version
!=
Version
())
return
;
shape
.
updateBounds
();
if
(
shape
.
bounds
.
max
.
x
<
100
||
shape
.
bounds
.
max
.
y
<
100
)
return
;
// this is a <= 0.1.2 symbol, points range [0...500] instead of [0...1]
// adjust it
FOR_EACH
(
p
,
shape
.
points
)
{
p
->
pos
/=
500.0
;
p
->
delta_before
/=
500.0
;
p
->
delta_after
/=
500.0
;
}
if
(
shape
.
name
.
empty
())
shape
.
name
=
_
(
"Shape"
);
shape
.
updateBounds
();
}
IMPLEMENT_REFLECTION
(
SymbolShape
)
{
IMPLEMENT_REFLECTION
(
SymbolShape
)
{
REFLECT_BASE
(
SymbolPart
);
REFLECT_BASE
(
SymbolPart
);
REFLECT
(
combine
);
REFLECT
(
combine
);
...
@@ -141,21 +183,11 @@ IMPLEMENT_REFLECTION(SymbolShape) {
...
@@ -141,21 +183,11 @@ IMPLEMENT_REFLECTION(SymbolShape) {
REFLECT_IF_READING
{
REFLECT_IF_READING
{
// enforce constraints
// enforce constraints
enforceConstraints
();
enforceConstraints
();
calculateBounds
();
fix
(
tag
,
*
this
);
if
(
max_pos
.
x
>
100
&&
max_pos
.
y
>
100
)
{
// this is a <= 0.1.2 symbol, points range [0...500] instead of [0...1]
// adjust it
FOR_EACH
(
p
,
points
)
{
p
->
pos
/=
500.0
;
p
->
delta_before
/=
500.0
;
p
->
delta_after
/=
500.0
;
}
if
(
name
.
empty
())
name
=
_
(
"Shape"
);
calculateBounds
();
}
}
}
}
}
SymbolShape
::
SymbolShape
()
SymbolShape
::
SymbolShape
()
:
combine
(
SYMBOL_COMBINE_OVERLAP
),
rotation_center
(
.5
,
.5
)
:
combine
(
SYMBOL_COMBINE_OVERLAP
),
rotation_center
(
.5
,
.5
)
{}
{}
...
@@ -182,13 +214,13 @@ void SymbolShape::enforceConstraints() {
...
@@ -182,13 +214,13 @@ void SymbolShape::enforceConstraints() {
}
}
}
}
void
SymbolShape
::
calculateBounds
()
{
Bounds
SymbolShape
::
calculateBounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
bool
is_identity
)
{
min_pos
=
Vector2D
::
infinity
();
Bounds
bounds
;
max_pos
=
-
Vector2D
::
infinity
();
Rotation
rot
(
0
);
for
(
int
i
=
0
;
i
<
(
int
)
points
.
size
()
;
++
i
)
{
for
(
int
i
=
0
;
i
<
(
int
)
points
.
size
()
;
++
i
)
{
segment_bounds
(
rot
,
*
getPoint
(
i
),
*
getPoint
(
i
+
1
),
min_pos
,
max_pos
);
bounds
.
update
(
segment_bounds
(
origin
,
m
,
*
getPoint
(
i
),
*
getPoint
(
i
+
1
))
);
}
}
if
(
is_identity
)
this
->
bounds
=
bounds
;
return
bounds
;
}
}
// ----------------------------------------------------------------------------- : SymbolSymmetry
// ----------------------------------------------------------------------------- : SymbolSymmetry
...
@@ -220,6 +252,32 @@ String SymbolSymmetry::expectedName() const {
...
@@ -220,6 +252,32 @@ String SymbolSymmetry::expectedName() const {
+
String
::
Format
(
_
(
" (%d)"
),
copies
);
+
String
::
Format
(
_
(
" (%d)"
),
copies
);
}
}
Bounds
SymbolSymmetry
::
calculateBounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
bool
is_identity
)
{
Bounds
bounds
;
// See SymbolViewer::draw
double
b
=
2
*
handle
.
angle
();
int
copies
=
kind
==
SYMMETRY_REFLECTION
?
this
->
copies
&
~
1
:
this
->
copies
;
FOR_EACH_CONST
(
p
,
parts
)
{
for
(
int
i
=
0
;
i
<
copies
;
++
i
)
{
double
a
=
i
*
2
*
M_PI
/
copies
;
if
(
kind
==
SYMMETRY_ROTATION
||
i
%
2
==
0
)
{
Matrix2D
rot
(
cos
(
a
),
-
sin
(
a
),
sin
(
a
),
cos
(
a
));
bounds
.
update
(
p
->
calculateBounds
(
origin
+
(
center
-
center
*
rot
)
*
m
,
rot
*
m
,
is_identity
&&
i
==
0
)
);
}
else
{
Matrix2D
rot
(
cos
(
a
+
b
),
sin
(
a
+
b
),
sin
(
a
+
b
),
-
cos
(
a
+
b
));
bounds
.
update
(
p
->
calculateBounds
(
origin
+
(
center
-
center
*
rot
)
*
m
,
rot
*
m
,
is_identity
&&
i
==
0
)
);
}
}
}
// done
if
(
is_identity
)
this
->
bounds
=
bounds
;
return
bounds
;
}
IMPLEMENT_REFLECTION
(
SymbolSymmetry
)
{
IMPLEMENT_REFLECTION
(
SymbolSymmetry
)
{
REFLECT_BASE
(
SymbolPart
);
REFLECT_BASE
(
SymbolPart
);
REFLECT
(
kind
);
REFLECT
(
kind
);
...
@@ -227,7 +285,6 @@ IMPLEMENT_REFLECTION(SymbolSymmetry) {
...
@@ -227,7 +285,6 @@ IMPLEMENT_REFLECTION(SymbolSymmetry) {
REFLECT
(
center
);
REFLECT
(
center
);
REFLECT
(
handle
);
REFLECT
(
handle
);
REFLECT
(
parts
);
REFLECT
(
parts
);
REFLECT_IF_READING
calculateBoundsNonRec
();
}
}
// ----------------------------------------------------------------------------- : SymbolGroup
// ----------------------------------------------------------------------------- : SymbolGroup
...
@@ -257,30 +314,25 @@ bool SymbolGroup::isAncestor(const SymbolPart& that) const {
...
@@ -257,30 +314,25 @@ bool SymbolGroup::isAncestor(const SymbolPart& that) const {
return
false
;
return
false
;
}
}
void
SymbolGroup
::
calculateBounds
()
{
Bounds
SymbolGroup
::
calculateBounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
bool
is_identity
)
{
FOR_EACH
(
p
,
parts
)
p
->
calculateBounds
();
Bounds
bounds
;
calculateBoundsNonRec
();
}
void
SymbolGroup
::
calculateBoundsNonRec
()
{
min_pos
=
Vector2D
::
infinity
();
max_pos
=
-
Vector2D
::
infinity
();
FOR_EACH
(
p
,
parts
)
{
FOR_EACH
(
p
,
parts
)
{
min_pos
=
piecewise_min
(
min_pos
,
p
->
min_pos
);
bounds
.
update
(
p
->
calculateBounds
(
origin
,
m
,
is_identity
));
max_pos
=
piecewise_max
(
max_pos
,
p
->
max_pos
);
}
}
if
(
is_identity
)
this
->
bounds
=
bounds
;
return
bounds
;
}
}
IMPLEMENT_REFLECTION
(
SymbolGroup
)
{
IMPLEMENT_REFLECTION
(
SymbolGroup
)
{
REFLECT_BASE
(
SymbolPart
);
REFLECT_BASE
(
SymbolPart
);
REFLECT
(
parts
);
REFLECT
(
parts
);
REFLECT_IF_READING
calculateBoundsNonRec
();
}
}
// ----------------------------------------------------------------------------- : Symbol
// ----------------------------------------------------------------------------- : Symbol
IMPLEMENT_REFLECTION
(
Symbol
)
{
IMPLEMENT_REFLECTION
(
Symbol
)
{
REFLECT
(
parts
);
REFLECT
(
parts
);
REFLECT_IF_READING
calculateBoundsNonRec
();
REFLECT_IF_READING
updateBounds
();
}
}
double
Symbol
::
aspectRatio
()
const
{
double
Symbol
::
aspectRatio
()
const
{
...
@@ -288,8 +340,8 @@ double Symbol::aspectRatio() const {
...
@@ -288,8 +340,8 @@ double Symbol::aspectRatio() const {
// In each direction take the lowest one
// In each direction take the lowest one
// This is at most 0.5 (if the symbol is just a line in the middle)
// This is at most 0.5 (if the symbol is just a line in the middle)
// Multiply by 2 (below) to give something in the range [0...1] i.e. [touches the edge...only in the middle]
// Multiply by 2 (below) to give something in the range [0...1] i.e. [touches the edge...only in the middle]
double
margin_x
=
min
(
0.4999
,
max
(
0.
,
min
(
min_pos
.
x
,
1
-
max_pos
.
x
)));
double
margin_x
=
min
(
0.4999
,
max
(
0.
,
min
(
bounds
.
min
.
x
,
1
-
bounds
.
max
.
x
)));
double
margin_y
=
min
(
0.4999
,
max
(
0.
,
min
(
min_pos
.
y
,
1
-
max_pos
.
y
)));
double
margin_y
=
min
(
0.4999
,
max
(
0.
,
min
(
bounds
.
min
.
y
,
1
-
bounds
.
max
.
y
)));
// The difference between these two,
// The difference between these two,
// e.g. if the vertical margin is more then the horizontal one, the symbol is 'flat'
// e.g. if the vertical margin is more then the horizontal one, the symbol is 'flat'
double
delta
=
2
*
(
margin_y
-
margin_x
);
double
delta
=
2
*
(
margin_y
-
margin_x
);
...
...
src/data/symbol.hpp
View file @
2961a3be
...
@@ -13,6 +13,7 @@
...
@@ -13,6 +13,7 @@
#include <util/reflect.hpp>
#include <util/reflect.hpp>
#include <util/action_stack.hpp>
#include <util/action_stack.hpp>
#include <util/vector2d.hpp>
#include <util/vector2d.hpp>
#include <util/real_point.hpp>
DECLARE_POINTER_TYPE
(
ControlPoint
);
DECLARE_POINTER_TYPE
(
ControlPoint
);
DECLARE_POINTER_TYPE
(
SymbolPart
);
DECLARE_POINTER_TYPE
(
SymbolPart
);
...
@@ -105,6 +106,32 @@ class SelectedHandle {
...
@@ -105,6 +106,32 @@ class SelectedHandle {
};
};
// ----------------------------------------------------------------------------- : Bounds
/// Bounding box of a symbol part
class
Bounds
{
public:
inline
Bounds
()
:
min
(
Vector2D
::
infinity
()),
max
(
-
Vector2D
::
infinity
())
{}
inline
explicit
Bounds
(
const
Vector2D
&
p
)
:
min
(
p
),
max
(
p
)
{}
inline
Bounds
(
const
Vector2D
&
min
,
const
Vector2D
&
max
)
:
min
(
min
),
max
(
max
)
{}
/// Combine with another bounding box
void
update
(
const
Bounds
&
b
);
void
update
(
const
Vector2D
&
p
);
/// Does this box contain the given point?
bool
contains
(
const
Vector2D
&
p
)
const
;
/// Does this box contain the given rectangle?
bool
contains
(
const
Bounds
&
b
)
const
;
/// Corner or center of this bounding box, dx,dy in <-1, 0, 1>
Vector2D
corner
(
int
dx
,
int
dy
)
const
;
Vector2D
min
,
max
;
inline
operator
RealRect
()
const
{
return
RealRect
(
min
,
RealSize
(
max
-
min
));
}
};
// ----------------------------------------------------------------------------- : SymbolPart
// ----------------------------------------------------------------------------- : SymbolPart
/// A part of a symbol, not necesserly a shape
/// A part of a symbol, not necesserly a shape
...
@@ -114,7 +141,7 @@ class SymbolPart : public IntrusivePtrVirtualBase {
...
@@ -114,7 +141,7 @@ class SymbolPart : public IntrusivePtrVirtualBase {
String
name
;
String
name
;
/// Position and size of the part.
/// Position and size of the part.
/** this is the smallest axis aligned bounding box that fits around the part */
/** this is the smallest axis aligned bounding box that fits around the part */
Vector2D
min_pos
,
max_po
s
;
Bounds
bound
s
;
/// Type of this part
/// Type of this part
virtual
String
typeName
()
const
=
0
;
virtual
String
typeName
()
const
=
0
;
...
@@ -137,8 +164,10 @@ class SymbolPart : public IntrusivePtrVirtualBase {
...
@@ -137,8 +164,10 @@ class SymbolPart : public IntrusivePtrVirtualBase {
/** also true if this==that*/
/** also true if this==that*/
virtual
bool
isAncestor
(
const
SymbolPart
&
that
)
const
{
return
this
==
&
that
;
}
virtual
bool
isAncestor
(
const
SymbolPart
&
that
)
const
{
return
this
==
&
that
;
}
/// Calculate the position and size of the part (min_pos and max_pos)
/// Calculate the position and size of the part (bounds)
virtual
void
calculateBounds
();
virtual
void
updateBounds
();
/// Calculate the position and size of the part using the given rotation matrix
virtual
Bounds
calculateBounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
bool
is_identity
)
=
0
;
DECLARE_REFLECTION_VIRTUAL
();
DECLARE_REFLECTION_VIRTUAL
();
};
};
...
@@ -189,8 +218,8 @@ class SymbolShape : public SymbolPart {
...
@@ -189,8 +218,8 @@ class SymbolShape : public SymbolPart {
/// Enforce lock constraints
/// Enforce lock constraints
void
enforceConstraints
();
void
enforceConstraints
();
/// Calculate the position and size of the part
/// Calculate the position and size of the part
using the given rotation matrix
virtual
void
calculateBounds
(
);
virtual
Bounds
calculateBounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
bool
is_identity
);
DECLARE_REFLECTION
();
DECLARE_REFLECTION
();
};
};
...
@@ -212,9 +241,7 @@ class SymbolGroup : public SymbolPart {
...
@@ -212,9 +241,7 @@ class SymbolGroup : public SymbolPart {
virtual
bool
isAncestor
(
const
SymbolPart
&
that
)
const
;
virtual
bool
isAncestor
(
const
SymbolPart
&
that
)
const
;
virtual
void
calculateBounds
();
virtual
Bounds
calculateBounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
bool
is_identity
);
/// re-calculate the bounds, but not of the contained parts
void
calculateBoundsNonRec
();
DECLARE_REFLECTION
();
DECLARE_REFLECTION
();
};
};
...
@@ -245,6 +272,7 @@ class SymbolSymmetry : public SymbolGroup {
...
@@ -245,6 +272,7 @@ class SymbolSymmetry : public SymbolGroup {
virtual
const
SymbolSymmetry
*
isSymbolSymmetry
()
const
{
return
this
;
}
virtual
const
SymbolSymmetry
*
isSymbolSymmetry
()
const
{
return
this
;
}
String
expectedName
()
const
;
String
expectedName
()
const
;
virtual
Bounds
calculateBounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
bool
is_identity
);
DECLARE_REFLECTION
();
DECLARE_REFLECTION
();
};
};
...
...
src/gfx/bezier.cpp
View file @
2961a3be
...
@@ -94,23 +94,28 @@ void segment_subdivide(const ControlPoint& p0, const ControlPoint& p1, const Vec
...
@@ -94,23 +94,28 @@ void segment_subdivide(const ControlPoint& p0, const ControlPoint& p1, const Vec
// ----------------------------------------------------------------------------- : Bounds
// ----------------------------------------------------------------------------- : Bounds
void
segment_bounds
(
const
Rotation
&
rot
,
const
ControlPoint
&
p1
,
const
ControlPoint
&
p2
,
Vector2D
&
min
,
Vector2D
&
max
)
{
Bounds
segment_bounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
const
ControlPoint
&
p1
,
const
ControlPoint
&
p2
)
{
assert
(
p1
.
segment_after
==
p2
.
segment_before
);
assert
(
p1
.
segment_after
==
p2
.
segment_before
);
if
(
p1
.
segment_after
==
SEGMENT_LINE
)
{
if
(
p1
.
segment_after
==
SEGMENT_LINE
)
{
line_bounds
(
rot
,
p1
.
pos
,
p2
.
pos
,
min
,
max
);
return
line_bounds
(
origin
,
m
,
p1
.
pos
,
p2
.
pos
);
}
else
{
}
else
{
bezier_bounds
(
rot
,
p1
,
p2
,
min
,
max
);
return
bezier_bounds
(
origin
,
m
,
p1
,
p2
);
}
}
}
}
void
bezier_bounds
(
const
Rotation
&
rot
,
const
ControlPoint
&
p1
,
const
ControlPoint
&
p2
,
Vector2D
&
min
,
Vector2D
&
max
)
{
Bounds
bezier_bounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
const
ControlPoint
&
p1
,
const
ControlPoint
&
p2
)
{
assert
(
p1
.
segment_after
==
SEGMENT_CURVE
);
assert
(
p1
.
segment_after
==
SEGMENT_CURVE
);
// Transform the control points
Vector2D
r1
=
origin
+
p1
.
pos
*
m
;
Vector2D
r2
=
origin
+
(
p1
.
pos
+
p1
.
delta_after
)
*
m
;
Vector2D
r3
=
origin
+
(
p2
.
pos
+
p2
.
delta_before
)
*
m
;
Vector2D
r4
=
origin
+
p2
.
pos
*
m
;
// First of all, the corners should be in the bounding box
// First of all, the corners should be in the bounding box
point_bounds
(
rot
,
p1
.
pos
,
min
,
max
);
Bounds
bounds
(
r1
);
point_bounds
(
rot
,
p2
.
pos
,
min
,
max
);
bounds
.
update
(
r4
);
// Solve the derivative of the bezier curve to find its extremes
// Solve the derivative of the bezier curve to find its extremes
// It's only a quadtratic equation :)
// It's only a quadtratic equation :)
BezierCurve
curve
(
p1
,
p2
);
BezierCurve
curve
(
r1
,
r2
,
r3
,
r4
);
double
roots
[
4
];
double
roots
[
4
];
UInt
count
;
UInt
count
;
count
=
solve_quadratic
(
3
*
curve
.
a
.
x
,
2
*
curve
.
b
.
x
,
curve
.
c
.
x
,
roots
);
count
=
solve_quadratic
(
3
*
curve
.
a
.
x
,
2
*
curve
.
b
.
x
,
curve
.
c
.
x
,
roots
);
...
@@ -119,35 +124,24 @@ void bezier_bounds(const Rotation& rot, const ControlPoint& p1, const ControlPoi
...
@@ -119,35 +124,24 @@ void bezier_bounds(const Rotation& rot, const ControlPoint& p1, const ControlPoi
for
(
UInt
i
=
0
;
i
<
count
;
++
i
)
{
for
(
UInt
i
=
0
;
i
<
count
;
++
i
)
{
double
t
=
roots
[
i
];
double
t
=
roots
[
i
];
if
(
t
>=
0
&&
t
<=
1
)
{
if
(
t
>=
0
&&
t
<=
1
)
{
point_bounds
(
rot
,
curve
.
pointAt
(
t
),
min
,
max
);
bounds
.
update
(
curve
.
pointAt
(
t
)
);
}
}
}
}
return
bounds
;
}
}
void
line_bounds
(
const
Rotation
&
rot
,
const
Vector2D
&
p1
,
const
Vector2D
&
p2
,
Vector2D
&
min
,
Vector2D
&
max
)
{
Bounds
line_bounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
const
Vector2D
&
p1
,
const
Vector2D
&
p2
)
{
point_bounds
(
rot
,
p1
,
min
,
max
);
Bounds
bounds
(
origin
+
p1
*
m
);
point_bounds
(
rot
,
p2
,
min
,
max
);
bounds
.
update
(
origin
+
p2
*
m
);
}
return
bounds
;
void
point_bounds
(
const
Rotation
&
rot
,
const
Vector2D
&
p
,
Vector2D
&
min
,
Vector2D
&
max
)
{
Vector2D
pr
=
rot
.
tr
(
p
);
min
=
piecewise_min
(
min
,
pr
);
max
=
piecewise_max
(
max
,
pr
);
}
}
// Is a point inside the bounds <min...max>?
bool
point_in_bounds
(
const
Vector2D
&
p
,
const
Vector2D
&
min
,
const
Vector2D
&
max
)
{
return
p
.
x
>=
min
.
x
&&
p
.
y
>=
min
.
y
&&
p
.
x
<=
max
.
x
&&
p
.
y
<=
max
.
y
;
}
// ----------------------------------------------------------------------------- : Point tests
// ----------------------------------------------------------------------------- : Point tests
// Is a point inside a symbol shape?
// Is a point inside a symbol shape?
bool
point_in_shape
(
const
Vector2D
&
pos
,
const
SymbolShape
&
shape
)
{
bool
point_in_shape
(
const
Vector2D
&
pos
,
const
SymbolShape
&
shape
)
{
// Step 1. compare bounding box of the part
// Step 1. compare bounding box of the part
if
(
!
point_in_bounds
(
pos
,
shape
.
min_pos
,
shape
.
max_
pos
))
return
false
;
if
(
!
shape
.
bounds
.
contains
(
pos
))
return
false
;
// Step 2. trace ray outward, count intersections
// Step 2. trace ray outward, count intersections
int
count
=
0
;
int
count
=
0
;
...
...
src/gfx/bezier.hpp
View file @
2961a3be
...
@@ -78,25 +78,19 @@ void segment_subdivide(const ControlPoint& p0, const ControlPoint& p1, const Vec
...
@@ -78,25 +78,19 @@ void segment_subdivide(const ControlPoint& p0, const ControlPoint& p1, const Vec
* min is only changed if the minimum is smaller then the current value in min,
* min is only changed if the minimum is smaller then the current value in min,
* max only if the maximum is larger.
* max only if the maximum is larger.
*/
*/
void
segment_bounds
(
const
Rotation
&
rot
,
const
ControlPoint
&
p1
,
const
ControlPoint
&
p2
,
Vector2D
&
min
,
Vector2D
&
max
);
Bounds
segment_bounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
const
ControlPoint
&
p1
,
const
ControlPoint
&
p2
);
/// Find a bounding box that fits a curve between p1 and p2, stores the results in min and max.
/// Find a bounding box that fits a curve between p1 and p2, stores the results in min and max.
/** min is only changed if the minimum is smaller then the current value in min,
/** min is only changed if the minimum is smaller then the current value in min,
* max only if the maximum is larger
* max only if the maximum is larger
*/
*/
void
bezier_bounds
(
const
Rotation
&
rot
,
const
ControlPoint
&
p1
,
const
ControlPoint
&
p2
,
Vector2D
&
min
,
Vector2D
&
max
);
Bounds
bezier_bounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
const
ControlPoint
&
p1
,
const
ControlPoint
&
p2
);
/// Find a bounding box that fits around p1 and p2, stores the result in min and max
/// Find a bounding box that fits around p1 and p2, stores the result in min and max
/** min is only changed if the minimum is smaller then the current value in min,
/** min is only changed if the minimum is smaller then the current value in min,
* max only if the maximum is larger
* max only if the maximum is larger
*/
*/
void
line_bounds
(
const
Rotation
&
rot
,
const
Vector2D
&
p1
,
const
Vector2D
&
p2
,
Vector2D
&
min
,
Vector2D
&
max
);
Bounds
line_bounds
(
const
Vector2D
&
origin
,
const
Matrix2D
&
m
,
const
Vector2D
&
p1
,
const
Vector2D
&
p2
);
/// Find a bounding 'box' that fits around a single point
/** min is only changed if the minimum is smaller then the current value in min,
* max only if the maximum is larger
*/
void
point_bounds
(
const
Rotation
&
rot
,
const
Vector2D
&
p
,
Vector2D
&
min
,
Vector2D
&
max
);
// ----------------------------------------------------------------------------- : Point tests
// ----------------------------------------------------------------------------- : Point tests
...
...
src/gui/symbol/select_editor.cpp
View file @
2961a3be
...
@@ -39,7 +39,7 @@ SymbolSelectEditor::SymbolSelectEditor(SymbolControl* control, bool rotate)
...
@@ -39,7 +39,7 @@ SymbolSelectEditor::SymbolSelectEditor(SymbolControl* control, bool rotate)
handleShearY
=
wxBitmap
(
rotate_image
(
shear
,
90
));
handleShearY
=
wxBitmap
(
rotate_image
(
shear
,
90
));
handleCenter
=
wxBitmap
(
load_resource_image
(
_
(
"handle_center"
)));
handleCenter
=
wxBitmap
(
load_resource_image
(
_
(
"handle_center"
)));
// Make sure all parts have updated bounds
// Make sure all parts have updated bounds
getSymbol
()
->
calcul
ateBounds
();
getSymbol
()
->
upd
ateBounds
();
resetActions
();
resetActions
();
}
}
...
@@ -87,7 +87,7 @@ void SymbolSelectEditor::drawHandles(DC& dc) {
...
@@ -87,7 +87,7 @@ void SymbolSelectEditor::drawHandles(DC& dc) {
}
}
void
SymbolSelectEditor
::
drawHandle
(
DC
&
dc
,
int
dx
,
int
dy
)
{
void
SymbolSelectEditor
::
drawHandle
(
DC
&
dc
,
int
dx
,
int
dy
)
{
wxPoint
p
=
control
.
rotation
.
tr
(
handlePos
(
dx
,
dy
));
wxPoint
p
=
control
.
rotation
.
tr
(
bounds
.
corner
(
dx
,
dy
));
p
.
x
+=
4
*
dx
;
p
.
x
+=
4
*
dx
;
p
.
y
+=
4
*
dy
;
p
.
y
+=
4
*
dy
;
if
(
rotate
)
{
if
(
rotate
)
{
...
@@ -312,7 +312,7 @@ void SymbolSelectEditor::onMouseDrag (const Vector2D& from, const Vector2D& to,
...
@@ -312,7 +312,7 @@ void SymbolSelectEditor::onMouseDrag (const Vector2D& from, const Vector2D& to,
if
(
rotate
)
{
if
(
rotate
)
{
if
(
scaleX
==
0
||
scaleY
==
0
)
{
if
(
scaleX
==
0
||
scaleY
==
0
)
{
// shear, center/fixed point on the opposite side
// shear, center/fixed point on the opposite side
shearAction
=
new
SymbolPartShearAction
(
control
.
selected_parts
.
get
(),
handlePos
(
-
scaleX
,
-
scaleY
));
shearAction
=
new
SymbolPartShearAction
(
control
.
selected_parts
.
get
(),
bounds
.
corner
(
-
scaleX
,
-
scaleY
));
addAction
(
shearAction
);
addAction
(
shearAction
);
}
else
{
}
else
{
// rotate
// rotate
...
@@ -360,7 +360,7 @@ void SymbolSelectEditor::onMouseDrag (const Vector2D& from, const Vector2D& to,
...
@@ -360,7 +360,7 @@ void SymbolSelectEditor::onMouseDrag (const Vector2D& from, const Vector2D& to,
// shear the selected parts
// shear the selected parts
Vector2D
delta
=
to
-
from
;
Vector2D
delta
=
to
-
from
;
delta
=
delta
.
mul
(
Vector2D
(
scaleY
,
scaleX
));
delta
=
delta
.
mul
(
Vector2D
(
scaleY
,
scaleX
));
delta
=
delta
.
div
(
maxV
-
minV
);
delta
=
delta
.
div
(
bounds
.
max
-
bounds
.
min
);
// shearAction->constrain = ev.ControlDown();
// shearAction->constrain = ev.ControlDown();
shearAction
->
snap
=
snap
(
ev
);
shearAction
->
snap
=
snap
(
ev
);
shearAction
->
move
(
delta
);
shearAction
->
move
(
delta
);
...
@@ -426,15 +426,8 @@ bool SymbolSelectEditor::isEditing() {
...
@@ -426,15 +426,8 @@ bool SymbolSelectEditor::isEditing() {
// ----------------------------------------------------------------------------- : Other
// ----------------------------------------------------------------------------- : Other
Vector2D
SymbolSelectEditor
::
handlePos
(
int
dx
,
int
dy
)
{
return
Vector2D
(
0.5
*
(
maxV
.
x
+
minV
.
x
+
dx
*
(
maxV
.
x
-
minV
.
x
)),
0.5
*
(
maxV
.
y
+
minV
.
y
+
dy
*
(
maxV
.
y
-
minV
.
y
))
);
}
bool
SymbolSelectEditor
::
onHandle
(
const
Vector2D
&
mpos
,
int
dx
,
int
dy
)
{
bool
SymbolSelectEditor
::
onHandle
(
const
Vector2D
&
mpos
,
int
dx
,
int
dy
)
{
wxPoint
p
=
control
.
rotation
.
tr
(
handlePos
(
dx
,
dy
));
wxPoint
p
=
control
.
rotation
.
tr
(
bounds
.
corner
(
dx
,
dy
));
wxPoint
mp
=
control
.
rotation
.
tr
(
mpos
);
wxPoint
mp
=
control
.
rotation
.
tr
(
mpos
);
p
.
x
=
p
.
x
+
4
*
dx
;
p
.
x
=
p
.
x
+
4
*
dx
;
p
.
y
=
p
.
y
+
4
*
dy
;
p
.
y
=
p
.
y
+
4
*
dy
;
...
@@ -460,11 +453,9 @@ double SymbolSelectEditor::angleTo(const Vector2D& pos) {
...
@@ -460,11 +453,9 @@ double SymbolSelectEditor::angleTo(const Vector2D& pos) {
void
SymbolSelectEditor
::
updateBoundingBox
()
{
void
SymbolSelectEditor
::
updateBoundingBox
()
{
// Find min and max coordinates
// Find min and max coordinates
minV
=
Vector2D
::
infinity
();
bounds
=
Bounds
();
maxV
=
-
Vector2D
::
infinity
();
FOR_EACH
(
p
,
control
.
selected_parts
.
get
())
{
FOR_EACH
(
p
,
control
.
selected_parts
.
get
())
{
minV
=
piecewise_min
(
minV
,
p
->
min_pos
);
bounds
.
update
(
p
->
bounds
);
maxV
=
piecewise_max
(
maxV
,
p
->
max_pos
);
}
}
/* // Find rotation center
/* // Find rotation center
center = Vector2D(0,0);
center = Vector2D(0,0);
...
@@ -475,7 +466,7 @@ void SymbolSelectEditor::updateBoundingBox() {
...
@@ -475,7 +466,7 @@ void SymbolSelectEditor::updateBoundingBox() {
}
}
center /= control.selected_parts.size();
center /= control.selected_parts.size();
*/
*/
center
=
(
minV
+
maxV
)
/
2
;
center
=
bounds
.
corner
(
0
,
0
)
;
}
}
void
SymbolSelectEditor
::
resetActions
()
{
void
SymbolSelectEditor
::
resetActions
()
{
...
...
src/gui/symbol/select_editor.hpp
View file @
2961a3be
...
@@ -71,7 +71,7 @@ class SymbolSelectEditor : public SymbolEditorBase {
...
@@ -71,7 +71,7 @@ class SymbolSelectEditor : public SymbolEditorBase {
SymbolPartRotateAction
*
rotateAction
;
SymbolPartRotateAction
*
rotateAction
;
SymbolPartShearAction
*
shearAction
;
SymbolPartShearAction
*
shearAction
;
// Bounding box of selection
// Bounding box of selection
Vector2D
minV
,
maxV
;
Bounds
bounds
;
// Where is the rotation center?
// Where is the rotation center?
Vector2D
center
;
Vector2D
center
;
// What kind of clicking/dragging are we doing
// What kind of clicking/dragging are we doing
...
@@ -112,9 +112,6 @@ class SymbolSelectEditor : public SymbolEditorBase {
...
@@ -112,9 +112,6 @@ class SymbolSelectEditor : public SymbolEditorBase {
/// Angle between center and pos
/// Angle between center and pos
double
angleTo
(
const
Vector2D
&
pos
);
double
angleTo
(
const
Vector2D
&
pos
);
/// Return the position of a handle, dx,dy in <-1, 0, 1>
Vector2D
handlePos
(
int
dx
,
int
dy
);
/// Update minV and maxV to be the bounding box of the selected_parts
/// Update minV and maxV to be the bounding box of the selected_parts
/// Updates center to be the rotation center of the parts
/// Updates center to be the rotation center of the parts
void
updateBoundingBox
();
void
updateBoundingBox
();
...
...
src/gui/symbol/selection.cpp
View file @
2961a3be
...
@@ -116,9 +116,11 @@ bool SymbolPartsSelection::selectRect(const Vector2D& a, const Vector2D& b, cons
...
@@ -116,9 +116,11 @@ 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
;
Bounds
ab
(
a
);
ab
.
update
(
b
);
Bounds
bc
(
b
);
bc
.
update
(
c
);
FOR_EACH_CONST
(
p
,
parent
.
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
=
ab
.
contains
(
p
->
bounds
);
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
=
bc
.
contains
(
p
->
bounds
);
if
(
in_ab
!=
in_bc
)
{
if
(
in_ab
!=
in_bc
)
{
select
(
p
,
SELECT_TOGGLE
);
select
(
p
,
SELECT_TOGGLE
);
changes
=
true
;
changes
=
true
;
...
...
src/render/symbol/viewer.cpp
View file @
2961a3be
...
@@ -151,7 +151,7 @@ void SymbolViewer::combineSymbolPart(DC& dc, const SymbolPart& part, bool& paint
...
@@ -151,7 +151,7 @@ void SymbolViewer::combineSymbolPart(DC& dc, const SymbolPart& part, bool& paint
}
}
}
else
if
(
const
SymbolSymmetry
*
s
=
part
.
isSymbolSymmetry
())
{
}
else
if
(
const
SymbolSymmetry
*
s
=
part
.
isSymbolSymmetry
())
{
// Draw all parts, in reverse order (bottom to top), also draw rotated copies
// Draw all parts, in reverse order (bottom to top), also draw rotated copies
double
b
=
2
*
atan2
(
s
->
handle
.
y
,
s
->
handle
.
x
);
double
b
=
2
*
s
->
handle
.
angle
(
);
Matrix2D
old_m
=
multiply
;
Matrix2D
old_m
=
multiply
;
Vector2D
old_o
=
origin
;
Vector2D
old_o
=
origin
;
int
copies
=
s
->
kind
==
SYMMETRY_REFLECTION
?
s
->
copies
/
2
*
2
:
s
->
copies
;
int
copies
=
s
->
kind
==
SYMMETRY_REFLECTION
?
s
->
copies
/
2
*
2
:
s
->
copies
;
...
@@ -177,8 +177,7 @@ void SymbolViewer::combineSymbolPart(DC& dc, const SymbolPart& part, bool& paint
...
@@ -177,8 +177,7 @@ void SymbolViewer::combineSymbolPart(DC& dc, const SymbolPart& part, bool& paint
// = (p * rot - d * rot + d) * m + o
// = (p * rot - d * rot + d) * m + o
// = p * rot * m + (d - d * rot) * m + o
// = p * rot * m + (d - d * rot) * m + o
Matrix2D
rot
(
cos
(
a
),
-
sin
(
a
),
sin
(
a
),
cos
(
a
));
Matrix2D
rot
(
cos
(
a
),
-
sin
(
a
),
sin
(
a
),
cos
(
a
));
multiply
.
mx
=
rot
.
mx
*
old_m
;
multiply
=
rot
*
old_m
;
multiply
.
my
=
rot
.
my
*
old_m
;
origin
=
old_o
+
(
s
->
center
-
s
->
center
*
rot
)
*
old_m
;
origin
=
old_o
+
(
s
->
center
-
s
->
center
*
rot
)
*
old_m
;
}
else
{
}
else
{
// reflection
// reflection
...
@@ -192,8 +191,7 @@ void SymbolViewer::combineSymbolPart(DC& dc, const SymbolPart& part, bool& paint
...
@@ -192,8 +191,7 @@ void SymbolViewer::combineSymbolPart(DC& dc, const SymbolPart& part, bool& paint
// = [ cos(a+b) sin(a+b) !
// = [ cos(a+b) sin(a+b) !
// ! sin(a+b) -cos(a+b) ]
// ! sin(a+b) -cos(a+b) ]
Matrix2D
rot
(
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
=
rot
*
old_m
;
multiply
.
my
=
rot
.
my
*
old_m
;
origin
=
old_o
+
(
s
->
center
-
s
->
center
*
rot
)
*
old_m
;
origin
=
old_o
+
(
s
->
center
-
s
->
center
*
rot
)
*
old_m
;
}
}
// draw rotated copy
// draw rotated copy
...
@@ -366,7 +364,7 @@ void SymbolViewer::highlightPart(DC& dc, const SymbolGroup& group, HighlightStyl
...
@@ -366,7 +364,7 @@ void SymbolViewer::highlightPart(DC& dc, const SymbolGroup& group, HighlightStyl
if
(
style
==
HIGHLIGHT_BORDER
)
{
if
(
style
==
HIGHLIGHT_BORDER
)
{
dc
.
SetBrush
(
*
wxTRANSPARENT_BRUSH
);
dc
.
SetBrush
(
*
wxTRANSPARENT_BRUSH
);
dc
.
SetPen
(
wxPen
(
Color
(
255
,
0
,
0
),
2
));
dc
.
SetPen
(
wxPen
(
Color
(
255
,
0
,
0
),
2
));
dc
.
DrawRectangle
(
rotation
.
trRectToBB
(
RealRect
(
group
.
min_pos
,
RealSize
(
group
.
max_pos
-
group
.
min_pos
)
)));
dc
.
DrawRectangle
(
rotation
.
trRectToBB
(
RealRect
(
group
.
bounds
)));
}
}
FOR_EACH_CONST
(
part
,
group
.
parts
)
{
FOR_EACH_CONST
(
part
,
group
.
parts
)
{
highlightPart
(
dc
,
*
part
,
(
HighlightStyle
)(
style
|
HIGHLIGHT_LESS
));
highlightPart
(
dc
,
*
part
,
(
HighlightStyle
)(
style
|
HIGHLIGHT_LESS
));
...
...
src/util/vector2d.hpp
View file @
2961a3be
...
@@ -96,6 +96,10 @@ class Vector2D {
...
@@ -96,6 +96,10 @@ class Vector2D {
inline
Vector2D
normalized
()
const
{
inline
Vector2D
normalized
()
const
{
return
*
this
/
length
();
return
*
this
/
length
();
}
}
/// Angle between this vector and the x axis
inline
double
angle
()
const
{
return
atan2
(
y
,
x
);
}
inline
operator
wxPoint
()
const
{
inline
operator
wxPoint
()
const
{
return
wxPoint
(
to_int
(
x
),
to_int
(
y
));
return
wxPoint
(
to_int
(
x
),
to_int
(
y
));
...
@@ -142,7 +146,7 @@ class Matrix2D {
...
@@ -142,7 +146,7 @@ class Matrix2D {
public:
public:
Vector2D
mx
,
my
;
Vector2D
mx
,
my
;
inline
Matrix2D
()
{}
inline
Matrix2D
()
:
mx
(
1
,
0
),
my
(
0
,
1
)
{}
inline
Matrix2D
(
const
Vector2D
&
mx
,
const
Vector2D
&
my
)
:
mx
(
mx
),
my
(
my
)
{}
inline
Matrix2D
(
const
Vector2D
&
mx
,
const
Vector2D
&
my
)
:
mx
(
mx
),
my
(
my
)
{}
inline
Matrix2D
(
double
a
,
double
b
,
double
c
,
double
d
)
:
mx
(
a
,
b
),
my
(
c
,
d
)
{}
inline
Matrix2D
(
double
a
,
double
b
,
double
c
,
double
d
)
:
mx
(
a
,
b
),
my
(
c
,
d
)
{}
};
};
...
@@ -151,6 +155,10 @@ class Matrix2D {
...
@@ -151,6 +155,10 @@ class Matrix2D {
inline
Vector2D
operator
*
(
const
Vector2D
&
a
,
const
Matrix2D
&
m
)
{
inline
Vector2D
operator
*
(
const
Vector2D
&
a
,
const
Matrix2D
&
m
)
{
return
Vector2D
(
dot
(
a
,
m
.
mx
),
dot
(
a
,
m
.
my
));
return
Vector2D
(
dot
(
a
,
m
.
mx
),
dot
(
a
,
m
.
my
));
}
}
/// vector-matrix product
inline
Matrix2D
operator
*
(
const
Matrix2D
&
a
,
const
Matrix2D
&
m
)
{
return
Matrix2D
(
a
.
mx
*
m
,
a
.
my
*
m
);
}
// ----------------------------------------------------------------------------- : EOF
// ----------------------------------------------------------------------------- : EOF
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment