Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
minerva
core
Commits
345b351b
Commit
345b351b
authored
May 28, 2019
by
Piotr Gawron
Browse files
when transforming lines create defensive copy of lines
parent
affb89d3
Changes
2
Hide whitespace changes
Inline
Side-by-side
converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/geometry/helper/CellDesignerLineTransformation.java
View file @
345b351b
...
...
@@ -4,13 +4,14 @@ import java.awt.geom.Point2D;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
lcsb.mapviewer.common.exception.InvalidArgumentException
;
import
lcsb.mapviewer.common.geometry.LineTransformation
;
import
lcsb.mapviewer.common.geometry.PointTransformation
;
import
lcsb.mapviewer.model.graphics.PolylineData
;
import
org.apache.logging.log4j.*
;
/**
* Class with basic operations on lines with special functions for CellDesigner
* format.
...
...
@@ -20,116 +21,118 @@ import org.apache.logging.log4j.*;
*/
public
class
CellDesignerLineTransformation
extends
LineTransformation
{
/**
* Default class logger.
*/
@SuppressWarnings
(
"unused"
)
private
static
Logger
logger
=
LogManager
.
getLogger
(
CellDesignerLineTransformation
.
class
.
getName
());
/**
* Class used for transformations on {@link Point2D} class.
*/
private
static
PointTransformation
pt
=
new
PointTransformation
();
/**
* Transform data in CellDesigner format into typical x,y coordinates for all
* points.
*
* CellDesigner format stores coordinates of a line in a different base. In
* this base we have two points that define a base: vector between these
* points is 1 unit in first coordinate, and orthogonal vector to the one
* mentioned before is 1 unit in the second coordinate. Moreover, these two
* points defining base belong to this line.
*
*
* @param startPoint
* first point defining CellDesigner base
* @param endPoint
* second point defining CellDesigner base
* @param midPoints
* points defining line
* @return line in standard x,y format
*/
public
List
<
Point2D
>
getLinePointsFromPoints
(
final
Point2D
startPoint
,
final
Point2D
endPoint
,
final
List
<
Point2D
>
midPoints
)
{
if
(!
pt
.
isValidPoint
(
startPoint
))
{
throw
new
InvalidArgumentException
(
"Invalid start point: "
+
startPoint
);
}
if
(!
pt
.
isValidPoint
(
endPoint
))
{
throw
new
InvalidArgumentException
(
"Invalid end point: "
+
endPoint
);
}
List
<
Point2D
>
result
=
new
ArrayList
<
Point2D
>();
double
dx1
=
endPoint
.
getX
()
-
startPoint
.
getX
();
double
dy1
=
endPoint
.
getY
()
-
startPoint
.
getY
();
double
dx2
=
-
dy1
;
double
dy2
=
dx1
;
result
.
add
(
startPoint
);
if
(
midPoints
!=
null
)
{
for
(
Point2D
p
:
midPoints
)
{
if
(!
pt
.
isValidPoint
(
p
))
{
throw
new
InvalidArgumentException
(
"Invalid point: "
+
p
);
}
double
x
=
startPoint
.
getX
()
+
dx1
*
p
.
getX
()
+
dx2
*
p
.
getY
();
double
y
=
startPoint
.
getY
()
+
dy1
*
p
.
getX
()
+
dy2
*
p
.
getY
();
result
.
add
(
new
Point2D
.
Double
(
x
,
y
));
}
}
result
.
add
(
endPoint
);
return
result
;
}
/**
* Transform line of typical xy coordinates into coordinates used by
* celldesigner.
*
* CellDesigner format stores coordinates of a line in a different base. In
* this base we have two points that define a base: vector between these
* points is 1 unit in first coordinate, and orthogonal vector to the one
* mentioned before is 1 unit in the second coordinate. These two points are
* the first and the last.
*
* @param line
* line to be transformed into CellDesigner format
* @return points of the line in CellDesigner format (without the first and
* the last)
*/
public
List
<
Point2D
>
getPointsFromLine
(
final
PolylineData
line
)
{
if
(
line
==
null
)
{
throw
new
InvalidArgumentException
(
"Line cannot be null."
);
}
if
(
line
.
getPoints
().
size
()
<
2
)
{
throw
new
InvalidArgumentException
(
"Invalid line passed as an argument."
);
}
double
ax
=
line
.
getBeginPoint
().
getX
();
double
ay
=
line
.
getBeginPoint
().
getY
();
double
bx
=
line
.
getEndPoint
().
getX
();
double
by
=
line
.
getEndPoint
().
getY
();
double
dx
=
bx
-
ax
;
double
dy
=
by
-
ay
;
List
<
Point2D
>
result
=
new
ArrayList
<
Point2D
>();
if
(
dy
*
dy
+
dx
*
dx
==
0
)
{
throw
new
InvalidArgumentException
(
"First and last point in the line must differ but found: "
+
line
.
getBeginPoint
()
+
", "
+
line
.
getEndPoint
());
}
for
(
int
i
=
1
;
i
<
line
.
getPoints
().
size
()
-
1
;
i
++)
{
double
ox
=
line
.
getPoints
().
get
(
i
).
getX
();
double
oy
=
line
.
getPoints
().
get
(
i
).
getY
();
double
py
=
(
dy
*
(
ax
-
ox
)
+
dx
*
(
oy
-
ay
))
/
(
dy
*
dy
+
dx
*
dx
);
double
px
=
(
dx
*
(
ox
-
ax
)
+
dy
*
(
oy
-
ay
))
/
(
dx
*
dx
+
dy
*
dy
);
result
.
add
(
new
Point2D
.
Double
(
px
,
py
));
}
return
result
;
}
/**
* Default class logger.
*/
@SuppressWarnings
(
"unused"
)
private
static
Logger
logger
=
LogManager
.
getLogger
(
CellDesignerLineTransformation
.
class
.
getName
());
/**
* Class used for transformations on {@link Point2D} class.
*/
private
static
PointTransformation
pt
=
new
PointTransformation
();
/**
* Transform data in CellDesigner format into typical x,y coordinates for all
* points.
*
* CellDesigner format stores coordinates of a line in a different base. In this
* base we have two points that define a base: vector between these points is 1
* unit in first coordinate, and orthogonal vector to the one mentioned before
* is 1 unit in the second coordinate. Moreover, these two points defining base
* belong to this line.
*
*
* @param startPoint
* first point defining CellDesigner base
* @param endPoint
* second point defining CellDesigner base
* @param midPoints
* points defining line
* @return line in standard x,y format
*/
public
List
<
Point2D
>
getLinePointsFromPoints
(
final
Point2D
startPoint
,
final
Point2D
endPoint
,
final
List
<
Point2D
>
midPoints
)
{
if
(!
pt
.
isValidPoint
(
startPoint
))
{
throw
new
InvalidArgumentException
(
"Invalid start point: "
+
startPoint
);
}
if
(!
pt
.
isValidPoint
(
endPoint
))
{
throw
new
InvalidArgumentException
(
"Invalid end point: "
+
endPoint
);
}
List
<
Point2D
>
result
=
new
ArrayList
<>();
double
dx1
=
endPoint
.
getX
()
-
startPoint
.
getX
();
double
dy1
=
endPoint
.
getY
()
-
startPoint
.
getY
();
double
dx2
=
-
dy1
;
double
dy2
=
dx1
;
result
.
add
(
new
Point2D
.
Double
(
startPoint
.
getX
(),
startPoint
.
getY
()));
if
(
midPoints
!=
null
)
{
for
(
Point2D
p
:
midPoints
)
{
if
(!
pt
.
isValidPoint
(
p
))
{
throw
new
InvalidArgumentException
(
"Invalid point: "
+
p
);
}
double
x
=
startPoint
.
getX
()
+
dx1
*
p
.
getX
()
+
dx2
*
p
.
getY
();
double
y
=
startPoint
.
getY
()
+
dy1
*
p
.
getX
()
+
dy2
*
p
.
getY
();
result
.
add
(
new
Point2D
.
Double
(
x
,
y
));
}
}
result
.
add
(
new
Point2D
.
Double
(
endPoint
.
getX
(),
endPoint
.
getY
()));
return
result
;
}
/**
* Transform line of typical xy coordinates into coordinates used by
* celldesigner.
*
* CellDesigner format stores coordinates of a line in a different base. In this
* base we have two points that define a base: vector between these points is 1
* unit in first coordinate, and orthogonal vector to the one mentioned before
* is 1 unit in the second coordinate. These two points are the first and the
* last.
*
* @param line
* line to be transformed into CellDesigner format
* @return points of the line in CellDesigner format (without the first and the
* last)
*/
public
List
<
Point2D
>
getPointsFromLine
(
final
PolylineData
line
)
{
if
(
line
==
null
)
{
throw
new
InvalidArgumentException
(
"Line cannot be null."
);
}
if
(
line
.
getPoints
().
size
()
<
2
)
{
throw
new
InvalidArgumentException
(
"Invalid line passed as an argument."
);
}
double
ax
=
line
.
getBeginPoint
().
getX
();
double
ay
=
line
.
getBeginPoint
().
getY
();
double
bx
=
line
.
getEndPoint
().
getX
();
double
by
=
line
.
getEndPoint
().
getY
();
double
dx
=
bx
-
ax
;
double
dy
=
by
-
ay
;
List
<
Point2D
>
result
=
new
ArrayList
<
Point2D
>();
if
(
dy
*
dy
+
dx
*
dx
==
0
)
{
throw
new
InvalidArgumentException
(
"First and last point in the line must differ but found: "
+
line
.
getBeginPoint
()
+
", "
+
line
.
getEndPoint
());
}
for
(
int
i
=
1
;
i
<
line
.
getPoints
().
size
()
-
1
;
i
++)
{
double
ox
=
line
.
getPoints
().
get
(
i
).
getX
();
double
oy
=
line
.
getPoints
().
get
(
i
).
getY
();
double
py
=
(
dy
*
(
ax
-
ox
)
+
dx
*
(
oy
-
ay
))
/
(
dy
*
dy
+
dx
*
dx
);
double
px
=
(
dx
*
(
ox
-
ax
)
+
dy
*
(
oy
-
ay
))
/
(
dx
*
dx
+
dy
*
dy
);
result
.
add
(
new
Point2D
.
Double
(
px
,
py
));
}
return
result
;
}
}
converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/geometry/helper/CellDesignerLineTransformationTest.java
View file @
345b351b
package
lcsb.mapviewer.converter.model.celldesigner.geometry.helper
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
fail
;
...
...
@@ -9,7 +10,8 @@ import java.awt.geom.Point2D;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.apache.logging.log4j.*
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Test
;
...
...
@@ -19,200 +21,256 @@ import lcsb.mapviewer.common.geometry.PointTransformation;
import
lcsb.mapviewer.model.graphics.PolylineData
;
public
class
CellDesignerLineTransformationTest
{
Logger
logger
=
LogManager
.
getLogger
(
CellDesignerLineTransformationTest
.
class
);
CellDesignerLineTransformation
lineTransformation
=
new
CellDesignerLineTransformation
();
PointTransformation
pointTransformation
=
new
PointTransformation
();
@Before
public
void
setUp
()
throws
Exception
{
}
@After
public
void
tearDown
()
throws
Exception
{
}
@Test
public
void
testGetPointsFromLine
()
{
try
{
Point2D
startPoint
=
new
Point2D
.
Double
(
1
,
7
);
Point2D
endPoint
=
new
Point2D
.
Double
(
3
,
5
);
List
<
Point2D
>
points
=
new
ArrayList
<
Point2D
>();
points
.
add
(
new
Point2D
.
Double
(
1.5
,
2.5
));
points
.
add
(
new
Point2D
.
Double
(
12
,
13
));
points
.
add
(
new
Point2D
.
Double
(
30
,
40
));
PolylineData
line
=
new
PolylineData
(
lineTransformation
.
getLinePointsFromPoints
(
startPoint
,
endPoint
,
points
));
List
<
Point2D
>
newPoints
=
lineTransformation
.
getPointsFromLine
(
line
);
assertNotNull
(
newPoints
);
assertEquals
(
points
.
size
(),
newPoints
.
size
());
for
(
int
i
=
0
;
i
<
points
.
size
();
i
++)
{
double
dist
=
points
.
get
(
i
).
distance
(
newPoints
.
get
(
i
));
assertTrue
(
"Distance to big: "
+
dist
+
" for points "
+
points
.
get
(
i
)
+
" and "
+
newPoints
.
get
(
i
),
dist
<
1
e
-
6
);
assertTrue
(
pointTransformation
.
isValidPoint
(
newPoints
.
get
(
i
)));
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
fail
(
"Exception occured: "
+
e
.
getMessage
());
}
}
@Test
public
void
testGetProblematicPointsFromLine
()
{
try
{
Point2D
startPoint
=
new
Point2D
.
Double
(
1
,
7
);
Point2D
endPoint
=
new
Point2D
.
Double
(
1
,
5
);
List
<
Point2D
>
points
=
new
ArrayList
<
Point2D
>();
points
.
add
(
new
Point2D
.
Double
(
1.5
,
2.5
));
points
.
add
(
new
Point2D
.
Double
(
12
,
13
));
points
.
add
(
new
Point2D
.
Double
(
30
,
40
));
PolylineData
line
=
new
PolylineData
(
lineTransformation
.
getLinePointsFromPoints
(
startPoint
,
endPoint
,
points
));
List
<
Point2D
>
newPoints
=
lineTransformation
.
getPointsFromLine
(
line
);
assertNotNull
(
newPoints
);
assertEquals
(
points
.
size
(),
newPoints
.
size
());
for
(
int
i
=
0
;
i
<
points
.
size
();
i
++)
{
assertTrue
(
"Invalid point after transformation: "
+
newPoints
.
get
(
i
),
pointTransformation
.
isValidPoint
(
newPoints
.
get
(
i
)));
double
dist
=
points
.
get
(
i
).
distance
(
newPoints
.
get
(
i
));
assertTrue
(
"Distance to big: "
+
dist
+
" for points "
+
points
.
get
(
i
)
+
" and "
+
newPoints
.
get
(
i
),
dist
<
1
e
-
6
);
assertTrue
(
pointTransformation
.
isValidPoint
(
newPoints
.
get
(
i
)));
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
throw
e
;
}
}
@Test
public
void
testGetProblematicPointsFromLine2
()
{
try
{
Point2D
startPoint
=
new
Point2D
.
Double
(
5
,
1
);
Point2D
endPoint
=
new
Point2D
.
Double
(
70
,
1
);
List
<
Point2D
>
points
=
new
ArrayList
<
Point2D
>();
points
.
add
(
new
Point2D
.
Double
(
1.5
,
2.5
));
points
.
add
(
new
Point2D
.
Double
(
12
,
13
));
points
.
add
(
new
Point2D
.
Double
(-
12
,
-
13
));
points
.
add
(
new
Point2D
.
Double
(
30
,
40
));
PolylineData
line
=
new
PolylineData
(
lineTransformation
.
getLinePointsFromPoints
(
startPoint
,
endPoint
,
points
));
List
<
Point2D
>
newPoints
=
lineTransformation
.
getPointsFromLine
(
line
);
assertNotNull
(
newPoints
);
assertEquals
(
points
.
size
(),
newPoints
.
size
());
for
(
int
i
=
0
;
i
<
points
.
size
();
i
++)
{
assertTrue
(
"Invalid point after transformation: "
+
newPoints
.
get
(
i
),
pointTransformation
.
isValidPoint
(
newPoints
.
get
(
i
)));
double
dist
=
points
.
get
(
i
).
distance
(
newPoints
.
get
(
i
));
assertTrue
(
"Distance to big: "
+
dist
+
" for points "
+
points
.
get
(
i
)
+
" and "
+
newPoints
.
get
(
i
),
dist
<
1
e
-
6
);
assertTrue
(
pointTransformation
.
isValidPoint
(
newPoints
.
get
(
i
)));
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
throw
e
;
}
}
@Test
public
void
testGetLinePointsFromInvalidPoints
()
{
try
{
Point2D
startPoint
=
new
Point2D
.
Double
(
Double
.
POSITIVE_INFINITY
,
1
);
Point2D
endPoint
=
new
Point2D
.
Double
(
70
,
1
);
lineTransformation
.
getLinePointsFromPoints
(
startPoint
,
endPoint
,
new
ArrayList
<>());
fail
(
"Excepiton expceted"
);
}
catch
(
InvalidArgumentException
e
)
{
assertTrue
(
e
.
getMessage
().
contains
(
"Invalid start point"
));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
throw
e
;
}
}
@Test
public
void
testGetLinePointsFromInvalidPoints2
()
{
try
{
Point2D
endPoint
=
new
Point2D
.
Double
(
Double
.
POSITIVE_INFINITY
,
1
);
Point2D
startPoint
=
new
Point2D
.
Double
(
70
,
1
);
lineTransformation
.
getLinePointsFromPoints
(
startPoint
,
endPoint
,
new
ArrayList
<>());
fail
(
"Excepiton expceted"
);
}
catch
(
InvalidArgumentException
e
)
{
assertTrue
(
e
.
getMessage
().
contains
(
"Invalid end point"
));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
throw
e
;
}
}
@Test
public
void
testGetLinePointsFromInvalidPoints3
()
{
try
{
Point2D
endPoint
=
new
Point2D
.
Double
(
70
,
2
);
Point2D
startPoint
=
new
Point2D
.
Double
(
70
,
1
);
List
<
Point2D
>
list
=
new
ArrayList
<>();
list
.
add
(
new
Point2D
.
Double
(
Double
.
POSITIVE_INFINITY
,
1
));
lineTransformation
.
getLinePointsFromPoints
(
startPoint
,
endPoint
,
list
);
fail
(
"Excepiton expceted"
);
}
catch
(
InvalidArgumentException
e
)
{
assertTrue
(
e
.
getMessage
().
contains
(
"Invalid point"
));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
throw
e
;
}
}
@Test
public
void
testGetPointsFromInvalidLine
()
{
try
{
lineTransformation
.
getPointsFromLine
(
null
);
fail
(
"Excepiton expceted"
);
}
catch
(
InvalidArgumentException
e
)
{
assertTrue
(
e
.
getMessage
().
contains
(
"Line cannot be null"
));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
throw
e
;
}
}
@Test
public
void
testGetPointsFromInvalidLine2
()
{
try
{
lineTransformation
.
getPointsFromLine
(
new
PolylineData
());
fail
(
"Excepiton expceted"
);
}
catch
(
InvalidArgumentException
e
)
{
assertTrue
(
e
.
getMessage
().
contains
(
"Invalid line passed as an argument"
));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
throw
e
;
}
}
@Test
public
void
testGetPointsFromInvalidLine3
()
{
try
{
lineTransformation
.
getPointsFromLine
(
new
PolylineData
(
new
Point2D
.
Double
(),
new
Point2D
.
Double
()));
fail
(
"Excepiton expceted"
);
}
catch
(
InvalidArgumentException
e
)
{
assertTrue
(
e
.
getMessage
().
contains
(
"First and last point in the line must differ but found"
));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
throw
e
;
}
}
Logger
logger
=
LogManager
.
getLogger
(
CellDesignerLineTransformationTest
.
class
);
CellDesignerLineTransformation
lineTransformation
=
new
CellDesignerLineTransformation
();
PointTransformation
pointTransformation
=
new
PointTransformation
();
@Before
public
void
setUp
()
throws
Exception
{
}
@After
public
void
tearDown
()
throws
Exception
{
}
@Test
public
void
testGetPointsFromLine
()
{
try
{
Point2D
startPoint
=
new
Point2D
.
Double
(
1
,
7
);
Point2D
endPoint
=
new
Point2D
.
Double
(
3
,
5
);
List
<
Point2D
>
points
=
new
ArrayList
<
Point2D
>();
points
.
add
(
new
Point2D
.
Double
(
1.5
,
2.5
));
points
.
add
(
new
Point2D
.
Double
(
12
,
13
));
points
.
add
(
new
Point2D
.
Double
(
30
,
40
));
PolylineData
line
=
new
PolylineData
(
lineTransformation
.
getLinePointsFromPoints
(
startPoint
,
endPoint
,
points
));
List
<
Point2D
>
newPoints
=
lineTransformation
.
getPointsFromLine
(
line
);
assertNotNull
(
newPoints
);
assertEquals
(
points
.
size
(),
newPoints
.
size
());
for
(
int
i
=
0
;
i
<
points
.
size
();
i
++)
{
double
dist
=
points
.
get
(
i
).
distance
(
newPoints
.
get
(
i
));
assertTrue
(
"Distance to big: "
+
dist
+
" for points "
+
points
.
get
(
i
)
+
" and "
+
newPoints
.
get
(
i
),
dist
<
1
e
-
6
);
assertTrue
(
pointTransformation
.
isValidPoint
(
newPoints
.
get
(
i
)));
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
throw
e
;
}
}
@Test
public
void
testGetPointsFromLineShouldCreateDefensiveCopy
()
{
try
{
Point2D
startPoint
=
new
Point2D
.
Double
(
1
,
7
);
Point2D
endPoint
=
new
Point2D
.
Double
(
3
,
5
);
List
<
Point2D
>
points
=
new
ArrayList
<>();
points
.
add
(
new
Point2D
.
Double
(
1.5
,
2.5
));
points
.
add
(
new
Point2D
.
Double
(
12
,
13
));
points
.
add
(
new
Point2D
.
Double
(
30
,
40
));
PolylineData
line
=
new
PolylineData
(
lineTransformation
.
getLinePointsFromPoints
(
startPoint
,
endPoint
,
points
));
List
<
Point2D
>
newPoints
=
lineTransformation
.
getPointsFromLine
(
line
);
List
<
Point2D
>
newPoints2
=
lineTransformation
.
getPointsFromLine
(
line
);
for
(
Point2D
point
:
newPoints2
)
{
for
(
Point2D
point2
:
newPoints
)
{
assertFalse
(
point
==
point2
);
}
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
throw
e
;
}
}