Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Devrim Gunyel
core
Commits
d866a7a6
Commit
d866a7a6
authored
Oct 31, 2019
by
Piotr Gawron
Browse files
extraction of layout from gpml improved
parent
d4dfed17
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ModelContructor.java
View file @
d866a7a6
package
lcsb.mapviewer.wikipathway.XML
;
import
java.awt.Color
;
import
java.awt.geom.*
;
import
java.awt.geom.Point2D
;
import
java.awt.geom.Rectangle2D
;
import
java.util.*
;
import
org.apache.commons.text.StringEscapeUtils
;
...
...
@@ -9,13 +10,10 @@ import org.apache.logging.log4j.LogManager;
import
org.apache.logging.log4j.Logger
;
import
lcsb.mapviewer.common.Configuration
;
import
lcsb.mapviewer.common.Pair
;
import
lcsb.mapviewer.common.exception.InvalidArgumentException
;
import
lcsb.mapviewer.common.exception.InvalidStateException
;
import
lcsb.mapviewer.common.geometry.PointTransformation
;
import
lcsb.mapviewer.common.exception.*
;
import
lcsb.mapviewer.converter.ConverterException
;
import
lcsb.mapviewer.converter.model.celldesigner.geometry.CellDesignerAliasConverter
;
import
lcsb.mapviewer.converter.model.celldesigner.geometry.
ReactionCellDesignerConverter
;
import
lcsb.mapviewer.converter.model.celldesigner.geometry.
helper.PolylineDataFactory
;
import
lcsb.mapviewer.converter.model.celldesigner.reaction.ReactionLineData
;
import
lcsb.mapviewer.converter.model.celldesigner.types.ModifierType
;
import
lcsb.mapviewer.converter.model.celldesigner.types.ModifierTypeUtils
;
...
...
@@ -33,7 +31,6 @@ import lcsb.mapviewer.model.map.species.field.*;
import
lcsb.mapviewer.modelutils.map.ElementUtils
;
import
lcsb.mapviewer.wikipathway.model.*
;
import
lcsb.mapviewer.wikipathway.model.biopax.BiopaxFactory
;
import
lcsb.mapviewer.wikipathway.utils.Geo
;
/**
* Class contains methods for GraphToModel conversion.
...
...
@@ -47,14 +44,7 @@ public class ModelContructor {
* Default color used by complexes.
*/
private
static
final
Color
DEFAULT_COMPLEX_ALIAS_COLOR
=
new
Color
(
102
,
255
,
255
);
/**
* How much of central line is used by and operator that joins reactants.
*/
private
static
final
int
AND_OPERATOR_CENTRAL_LINE_RATIO
=
10
;
/**
* How much of central line is used by split operator that split products.
*/
private
static
final
int
SPLIT_OPERATOR_CENTRAL_LINE_RATIO
=
10
;
/**
* Epsilon used for double comparison.
*/
...
...
@@ -92,58 +82,6 @@ public class ModelContructor {
* Parser used for extracting {@link MiriamData references} from GPML model.
*/
private
BiopaxFactory
biopaxFactory
=
new
BiopaxFactory
();
private
PointTransformation
pt
=
new
PointTransformation
();
/**
* This function splits {@link PolylineData} into two parts. It also assumes
* that last segment on the left part is equal to the length of the first
* segment on the right side.
*
* @param pd
* line to split
* @return pair of lines into which parameter was split to
*/
protected
Pair
<
PolylineData
,
PolylineData
>
splitPolyline
(
PolylineData
pd
)
{
PolylineData
p1
=
new
PolylineData
();
PolylineData
p2
=
new
PolylineData
();
p1
.
setColor
(
pd
.
getColor
());
p2
.
setColor
(
pd
.
getColor
());
List
<
Line2D
>
lines
=
pd
.
getLines
();
double
lenght
=
0.0
;
for
(
Line2D
line
:
lines
)
{
lenght
+=
Geo
.
lineLen
(
line
);
}
if
(
lenght
>
Configuration
.
EPSILON
)
{
double
tmp
=
0.0
;
boolean
first
=
true
;
for
(
Line2D
line
:
lines
)
{
if
(
tmp
+
Geo
.
lineLen
(
line
)
>
lenght
/
2
)
{
if
(
first
)
{
double
a
=
(
lenght
/
2
-
tmp
)
/
Geo
.
lineLen
(
line
);
double
x
=
line
.
getX1
()
+
a
*
(
line
.
getX2
()
-
line
.
getX1
());
double
y
=
line
.
getY1
()
+
a
*
(
line
.
getY2
()
-
line
.
getY1
());
p1
.
addPoint
((
Point2D
)
line
.
getP1
().
clone
());
p1
.
addPoint
(
new
Point2D
.
Double
(
x
,
y
));
p2
.
addPoint
(
new
Point2D
.
Double
(
x
,
y
));
first
=
false
;
}
p2
.
addPoint
((
Point2D
)
line
.
getP2
().
clone
());
tmp
+=
Geo
.
lineLen
(
line
);
}
else
{
p1
.
addPoint
((
Point2D
)
line
.
getP1
().
clone
());
tmp
+=
Geo
.
lineLen
(
line
);
}
}
}
else
{
// we have line with empty length
p1
.
addPoint
((
Point2D
)
pd
.
getBeginPoint
().
clone
());
p1
.
addPoint
((
Point2D
)
pd
.
getBeginPoint
().
clone
());
p2
.
addPoint
((
Point2D
)
pd
.
getBeginPoint
().
clone
());
p2
.
addPoint
((
Point2D
)
pd
.
getBeginPoint
().
clone
());
}
return
new
Pair
<
PolylineData
,
PolylineData
>(
p1
,
p2
);
}
/**
* This function creates Species from DataNode.
...
...
@@ -650,20 +588,19 @@ public class ModelContructor {
reaction
.
setZ
(
interaction
.
getzOrder
());
reaction
.
addMiriamData
(
biopaxFactory
.
getMiriamData
(
graph
.
getBiopaxData
(),
interaction
.
getBiopaxReferences
()));
PolylineData
pd
=
interaction
.
getLine
();
Pair
<
PolylineData
,
PolylineData
>
pair
=
splitPolyline
(
pd
);
PolylineData
pdfirstpart
=
pair
.
getLeft
();
PolylineData
pdsecondpart
=
pair
.
getRight
();
ReactionLayoutFinder
layoutFinder
=
new
ReactionLayoutFinder
();
Map
<
Class
<?>,
PolylineData
>
lines
=
layoutFinder
.
getNodeLines
(
interaction
);
PolylineData
reactantLine
=
lines
.
get
(
Reactant
.
class
);
PolylineData
productLine
=
lines
.
get
(
Product
.
class
);
Reactant
reactant
=
new
Reactant
();
reactant
.
setElement
(
data
.
id2alias
.
get
(
interaction
.
getStart
()));
reactant
.
setLine
(
pdfirstpart
);
reactant
.
setLine
(
reactantLine
);
reaction
.
addReactant
(
reactant
);
Product
product
=
new
Product
();
product
.
setElement
(
data
.
id2alias
.
get
(
interaction
.
getEnd
()));
product
.
setLine
(
p
dsecondpart
);
product
.
setLine
(
p
roductLine
);
reaction
.
addProduct
(
product
);
for
(
Edge
e
:
interaction
.
getReactants
())
{
...
...
@@ -676,16 +613,8 @@ public class ModelContructor {
reaction
.
addProduct
(
pro
);
}
double
centralLength
=
pdfirstpart
.
getPoints
().
get
(
pdfirstpart
.
getPoints
().
size
()
-
2
)
.
distance
(
pdfirstpart
.
getEndPoint
())
*
2
;
if
(
reaction
.
getReactants
().
size
()
>
1
)
{
PolylineData
operatorLine
=
new
PolylineData
();
operatorLine
.
setColor
(
pdfirstpart
.
getColor
());
operatorLine
.
addPoint
((
Point2D
)
pdfirstpart
.
getEndPoint
().
clone
());
operatorLine
.
addPoint
((
Point2D
)
pdfirstpart
.
getEndPoint
().
clone
());
pdfirstpart
.
trimEnd
(
centralLength
/
AND_OPERATOR_CENTRAL_LINE_RATIO
);
operatorLine
.
setStartPoint
((
Point2D
)
pdfirstpart
.
getEndPoint
().
clone
());
PolylineData
operatorLine
=
lines
.
get
(
AndOperator
.
class
);
NodeOperator
andOperator
;
// heterodimer association use association operator
if
(
reaction
instanceof
HeterodimerAssociationReaction
)
{
...
...
@@ -698,28 +627,36 @@ public class ModelContructor {
andOperator
.
setLine
(
operatorLine
);
for
(
int
i
=
1
;
i
<
reaction
.
getReactants
().
size
();
i
++)
{
Reactant
r
=
reaction
.
getReactants
().
get
(
i
);
r
.
getLine
().
ad
dPoint
(
(
Point2D
)
pdfirstpart
.
getEndPoint
().
clone
());
r
.
getLine
().
getEn
dPoint
(
).
setLocation
(
operatorLine
.
getBeginPoint
());
andOperator
.
addInput
(
r
);
}
reaction
.
addNode
(
andOperator
);
}
else
{
PolylineData
operatorLine
=
lines
.
get
(
AndOperator
.
class
);
for
(
int
i
=
1
;
i
<
operatorLine
.
getPoints
().
size
();
i
++)
{
reactantLine
.
addPoint
(
operatorLine
.
getPoints
().
get
(
i
));
}
reactant
.
setLine
(
PolylineDataFactory
.
removeCollinearPoints
(
reactantLine
));
}
if
(
reaction
.
getProducts
().
size
()
>
1
)
{
PolylineData
operatorLine
=
new
PolylineData
();
operatorLine
.
setColor
(
pdsecondpart
.
getColor
());
PolylineData
operatorLine
=
lines
.
get
(
SplitOperator
.
class
);
operatorLine
.
addPoint
((
Point2D
)
pdsecondpart
.
getBeginPoint
().
clone
());
pdsecondpart
.
trimBegin
(
centralLength
/
SPLIT_OPERATOR_CENTRAL_LINE_RATIO
);
operatorLine
.
addPoint
((
Point2D
)
pdsecondpart
.
getBeginPoint
().
clone
());
SplitOperator
splitOperator
=
new
SplitOperator
();
splitOperator
.
addOutput
(
product
);
splitOperator
.
setLine
(
operatorLine
);
splitOperator
.
setLine
(
operatorLine
.
reverse
()
);
for
(
int
i
=
1
;
i
<
reaction
.
getProducts
().
size
();
i
++)
{
Product
r
=
reaction
.
getProducts
().
get
(
i
);
r
.
getLine
().
addPoint
(
0
,
(
Point2D
)
pdsecondpart
.
getBeginPoint
().
clone
());
r
.
getLine
().
getBeginPoint
().
setLocation
(
operatorLine
.
getEndPoint
());
splitOperator
.
addOutput
(
r
);
}
reaction
.
addNode
(
splitOperator
);
}
else
{
PolylineData
operatorLine
=
lines
.
get
(
SplitOperator
.
class
);
for
(
int
i
=
0
;
i
<
operatorLine
.
getPoints
().
size
()-
1
;
i
++)
{
productLine
.
addPoint
(
i
,
operatorLine
.
getPoints
().
get
(
i
));
}
product
.
setLine
(
PolylineDataFactory
.
removeCollinearPoints
(
productLine
));
}
for
(
Edge
e
:
interaction
.
getModifiers
())
{
...
...
@@ -760,7 +697,9 @@ public class ModelContructor {
}
}
createReactionCenterLine
(
reaction
);
PolylineData
modifierLine
=
lines
.
get
(
Modifier
.
class
);
modifierLine
.
setType
(
rld
.
getLineType
());
reaction
.
setLine
(
modifierLine
);
ModifierTypeUtils
mtu
=
new
ModifierTypeUtils
();
for
(
Modifier
m
:
reaction
.
getModifiers
())
{
...
...
@@ -771,36 +710,6 @@ public class ModelContructor {
return
reaction
;
}
private
void
createReactionCenterLine
(
Reaction
reaction
)
{
AbstractNode
input
=
reaction
.
getReactants
().
get
(
0
);
AbstractNode
output
=
reaction
.
getProducts
().
get
(
0
);
for
(
NodeOperator
operator
:
reaction
.
getOperators
())
{
if
(
operator
.
isReactantOperator
())
{
input
=
operator
;
}
else
if
(
operator
.
isProductOperator
())
{
output
=
operator
;
}
}
PolylineData
line
=
new
PolylineData
();
double
distanceToTrimm
=
ReactionCellDesignerConverter
.
RECT_SIZE
;
distanceToTrimm
-=
input
.
getLine
().
trimEnd
(
distanceToTrimm
/
2
);
line
.
addPoint
(
pt
.
copyPoint
(
input
.
getLine
().
getEndPoint
()));
if
(
output
instanceof
NodeOperator
)
{
distanceToTrimm
-=
output
.
getLine
().
trimEnd
(
distanceToTrimm
);
line
.
addPoint
(
pt
.
copyPoint
(
output
.
getLine
().
getEndPoint
()));
}
else
{
distanceToTrimm
-=
output
.
getLine
().
trimBegin
(
distanceToTrimm
);
line
.
addPoint
(
pt
.
copyPoint
(
output
.
getLine
().
getBeginPoint
()));
}
line
.
setType
(
input
.
getLine
().
getType
());
line
.
setColor
(
input
.
getLine
().
getColor
());
reaction
.
setLine
(
line
);
}
/**
* Creates {@link Reactant} from GPML edge.
*
...
...
pathvisio/src/main/java/lcsb/mapviewer/wikipathway/XML/ReactionLayoutFinder.java
0 → 100644
View file @
d866a7a6
package
lcsb.mapviewer.wikipathway.XML
;
import
java.awt.geom.Line2D
;
import
java.awt.geom.Point2D
;
import
java.util.*
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
lcsb.mapviewer.common.Configuration
;
import
lcsb.mapviewer.common.Pair
;
import
lcsb.mapviewer.common.comparator.DoubleComparator
;
import
lcsb.mapviewer.common.exception.InvalidArgumentException
;
import
lcsb.mapviewer.common.geometry.LineTransformation
;
import
lcsb.mapviewer.common.geometry.PointTransformation
;
import
lcsb.mapviewer.converter.model.celldesigner.geometry.ReactionCellDesignerConverter
;
import
lcsb.mapviewer.converter.model.celldesigner.geometry.helper.PolylineDataFactory
;
import
lcsb.mapviewer.model.graphics.PolylineData
;
import
lcsb.mapviewer.model.map.reaction.*
;
import
lcsb.mapviewer.wikipathway.model.Edge
;
import
lcsb.mapviewer.wikipathway.model.Interaction
;
import
lcsb.mapviewer.wikipathway.utils.Geo
;
class
ReactionLayoutFinder
{
@SuppressWarnings
(
"unused"
)
private
Logger
logger
=
LogManager
.
getLogger
();
private
LineTransformation
lt
=
new
LineTransformation
();
private
PointTransformation
pt
=
new
PointTransformation
();
private
Interaction
interaction
;
/**
* Return coordinates where all {@link Reactant} should end, all
* {@link Modifier} should end, and all {@link Product} should start.
*
* @param interaction
* GPML {@link Interaction}
* @return map consisted of three entries for classes: {@link Product},
* {@link Reactant}, {@link Modifier}
*/
public
Map
<
Class
<?>,
Point2D
>
getNodeStartPoints
(
Interaction
interaction
)
{
this
.
interaction
=
interaction
;
List
<
Pair
<
Class
<?>,
Point2D
>>
possiblePoints
=
getPointsInOrder
(
interaction
);
Point2D
modifierPoint
=
getModifierPoint
(
possiblePoints
);
Point2D
reactantPoint
=
getReactantPoint
(
possiblePoints
,
modifierPoint
);
Point2D
productPoint
=
getProductPoint
(
possiblePoints
,
modifierPoint
);
Map
<
Class
<?>,
Point2D
>
result
=
new
HashMap
<>();
result
.
put
(
Reactant
.
class
,
reactantPoint
);
result
.
put
(
Product
.
class
,
productPoint
);
result
.
put
(
Modifier
.
class
,
modifierPoint
);
return
result
;
}
public
Map
<
Class
<?>,
PolylineData
>
getNodeLines
(
Interaction
interaction
)
{
Map
<
Class
<?>,
Point2D
>
points
=
getNodeStartPoints
(
interaction
);
Map
<
Class
<?>,
PolylineData
>
result
=
new
HashMap
<>();
PolylineData
reactantLine
=
getSubline
(
interaction
.
getLine
(),
interaction
.
getLine
().
getBeginPoint
(),
points
.
get
(
Reactant
.
class
));
PolylineData
inputReactionLine
=
getSubline
(
interaction
.
getLine
(),
points
.
get
(
Reactant
.
class
),
points
.
get
(
Modifier
.
class
));
inputReactionLine
.
trimEnd
(
ReactionCellDesignerConverter
.
RECT_SIZE
/
2
);
PolylineData
outputReactionLine
=
getSubline
(
interaction
.
getLine
(),
points
.
get
(
Modifier
.
class
),
points
.
get
(
Product
.
class
));
outputReactionLine
.
trimBegin
(
ReactionCellDesignerConverter
.
RECT_SIZE
/
2
);
PolylineData
productLine
=
getSubline
(
interaction
.
getLine
(),
points
.
get
(
Product
.
class
),
interaction
.
getLine
().
getEndPoint
());
PolylineData
modifierLine
=
new
PolylineData
(
pt
.
copyPoint
(
inputReactionLine
.
getEndPoint
()),
pt
.
copyPoint
(
outputReactionLine
.
getBeginPoint
()));
modifierLine
.
setColor
(
interaction
.
getColor
());
modifierLine
.
setWidth
(
productLine
.
getWidth
());
result
.
put
(
Reactant
.
class
,
reactantLine
);
result
.
put
(
Product
.
class
,
productLine
);
result
.
put
(
Modifier
.
class
,
modifierLine
);
result
.
put
(
AndOperator
.
class
,
inputReactionLine
);
result
.
put
(
SplitOperator
.
class
,
outputReactionLine
);
return
result
;
}
private
List
<
Pair
<
Class
<?>,
Point2D
>>
getPointsInOrder
(
Interaction
interaction
)
{
PolylineData
pd
=
interaction
.
getLine
();
List
<
Pair
<
Class
<?>,
Point2D
>>
possiblePoints
=
new
ArrayList
<>();
for
(
Edge
e
:
interaction
.
getReactants
())
{
if
(
pointOnPolyline
(
pd
,
e
.
getLine
().
getEndPoint
()))
{
possiblePoints
.
add
(
new
Pair
<>(
Reactant
.
class
,
e
.
getLine
().
getEndPoint
()));
}
else
if
(
pointOnPolyline
(
pd
,
e
.
getLine
().
getBeginPoint
()))
{
possiblePoints
.
add
(
new
Pair
<>(
Reactant
.
class
,
e
.
getLine
().
getBeginPoint
()));
}
}
for
(
Edge
e
:
interaction
.
getProducts
())
{
if
(
pointOnPolyline
(
pd
,
e
.
getLine
().
getEndPoint
()))
{
possiblePoints
.
add
(
new
Pair
<>(
Product
.
class
,
e
.
getLine
().
getEndPoint
()));
}
else
if
(
pointOnPolyline
(
pd
,
e
.
getLine
().
getBeginPoint
()))
{
possiblePoints
.
add
(
new
Pair
<>(
Product
.
class
,
e
.
getLine
().
getBeginPoint
()));
}
}
for
(
Edge
e
:
interaction
.
getModifiers
())
{
if
(
pointOnPolyline
(
pd
,
e
.
getLine
().
getEndPoint
()))
{
possiblePoints
.
add
(
new
Pair
<>(
Modifier
.
class
,
e
.
getLine
().
getEndPoint
()));
}
else
if
(
pointOnPolyline
(
pd
,
e
.
getLine
().
getBeginPoint
()))
{
possiblePoints
.
add
(
new
Pair
<>(
Modifier
.
class
,
e
.
getLine
().
getBeginPoint
()));
}
}
Comparator
<
Pair
<
Class
<?>,
Point2D
>>
comparator
=
new
Comparator
<
Pair
<
Class
<?>,
Point2D
>>()
{
@Override
public
int
compare
(
Pair
<
Class
<?>,
Point2D
>
o1
,
Pair
<
Class
<?>,
Point2D
>
o2
)
{
double
dist1
=
distanceFromPolylineStart
(
pd
,
o1
.
getRight
());
double
dist2
=
distanceFromPolylineStart
(
pd
,
o2
.
getRight
());
return
new
DoubleComparator
(
Configuration
.
EPSILON
).
compare
(
dist1
,
dist2
);
}
};
Collections
.
sort
(
possiblePoints
,
comparator
);
return
possiblePoints
;
}
private
Point2D
getProductPoint
(
List
<
Pair
<
Class
<?>,
Point2D
>>
possiblePoints
,
Point2D
modifierPoint
)
{
Point2D
result
=
null
;
for
(
Pair
<
Class
<?>,
Point2D
>
pair
:
possiblePoints
)
{
if
(
pair
.
getLeft
().
equals
(
Product
.
class
))
{
if
(
distanceFromPolylineStart
(
interaction
.
getLine
(),
modifierPoint
)
<
distanceFromPolylineStart
(
interaction
.
getLine
(),
pair
.
getRight
()))
{
result
=
pair
.
getRight
();
break
;
}
}
}
if
(
result
==
null
)
{
for
(
Point2D
point
:
interaction
.
getLine
().
getPoints
())
{
if
(
distanceFromPolylineStart
(
interaction
.
getLine
(),
modifierPoint
)
<
distanceFromPolylineStart
(
interaction
.
getLine
(),
point
))
{
double
x
=
modifierPoint
.
getX
()
+
(
point
.
getX
()
-
modifierPoint
.
getX
())
/
2
;
double
y
=
modifierPoint
.
getY
()
+
(
point
.
getY
()
-
modifierPoint
.
getY
())
/
2
;
result
=
new
Point2D
.
Double
(
x
,
y
);
break
;
}
}
}
return
result
;
}
private
Point2D
getReactantPoint
(
List
<
Pair
<
Class
<?>,
Point2D
>>
possiblePoints
,
Point2D
modifierPoint
)
{
Point2D
result
=
null
;
for
(
Pair
<
Class
<?>,
Point2D
>
pair
:
possiblePoints
)
{
if
(
pair
.
getLeft
().
equals
(
Reactant
.
class
))
{
if
(
distanceFromPolylineStart
(
interaction
.
getLine
(),
modifierPoint
)
>
distanceFromPolylineStart
(
interaction
.
getLine
(),
pair
.
getRight
()))
{
result
=
pair
.
getRight
();
}
}
}
if
(
result
==
null
)
{
for
(
Point2D
point
:
interaction
.
getLine
().
getPoints
())
{
if
(
distanceFromPolylineStart
(
interaction
.
getLine
(),
modifierPoint
)
>
distanceFromPolylineStart
(
interaction
.
getLine
(),
point
))
{
double
x
=
modifierPoint
.
getX
()
+
(
point
.
getX
()
-
modifierPoint
.
getX
())
/
2
;
double
y
=
modifierPoint
.
getY
()
+
(
point
.
getY
()
-
modifierPoint
.
getY
())
/
2
;
result
=
new
Point2D
.
Double
(
x
,
y
);
}
}
}
return
result
;
}
private
Point2D
getModifierPoint
(
List
<
Pair
<
Class
<?>,
Point2D
>>
points
)
{
List
<
Pair
<
Class
<?>,
Point2D
>>
possiblePoints
=
new
ArrayList
<>(
points
);
int
productPoints
=
0
;
int
reactantPoints
=
0
;
for
(
Pair
<
Class
<?>,
Point2D
>
pair
:
possiblePoints
)
{
if
(
pair
.
getLeft
().
equals
(
Product
.
class
))
{
productPoints
++;
}
else
if
(
pair
.
getLeft
().
equals
(
Reactant
.
class
))
{
reactantPoints
++;
}
}
int
countedReactants
=
0
;
int
countedProducts
=
0
;
int
score
=
Integer
.
MIN_VALUE
;
Point2D
point
=
null
;
for
(
Pair
<
Class
<?>,
Point2D
>
pair
:
possiblePoints
)
{
if
(
pair
.
getLeft
().
equals
(
Product
.
class
))
{
countedProducts
++;
}
else
if
(
pair
.
getLeft
().
equals
(
Reactant
.
class
))
{
countedReactants
++;
}
else
if
(
pair
.
getLeft
().
equals
(
Modifier
.
class
))
{
int
currentScore
=
countedReactants
+
(
productPoints
-
countedProducts
);
if
(
point
==
null
||
score
<
currentScore
)
{
score
=
currentScore
;
point
=
pair
.
getRight
();
}
}
}
if
(
point
==
null
)
{
possiblePoints
.
add
(
0
,
new
Pair
<
Class
<?>,
Point2D
>(
null
,
interaction
.
getLine
().
getBeginPoint
()));
possiblePoints
.
add
(
new
Pair
<
Class
<?>,
Point2D
>(
null
,
interaction
.
getLine
().
getEndPoint
()));
countedReactants
=
0
;
countedProducts
=
0
;
Point2D
previousPoint
=
null
;
for
(
Pair
<
Class
<?>,
Point2D
>
pair
:
possiblePoints
)
{
if
(
previousPoint
!=
null
)
{
int
currentScore
=
countedReactants
+
(
productPoints
-
countedProducts
);
if
(
point
==
null
||
score
<
currentScore
)
{
score
=
currentScore
;
if
(
reactantPoints
==
0
)
{
// shift to most right possible line when there are no other reactants
point
=
getRightCenterPoint
(
interaction
.
getLine
(),
previousPoint
,
pair
.
getRight
());
}
else
if
(
productPoints
==
0
)
{
point
=
getLeftCenterPoint
(
interaction
.
getLine
(),
previousPoint
,
pair
.
getRight
());
}
else
{
point
=
getCenterPoint
(
interaction
.
getLine
(),
previousPoint
,
pair
.
getRight
());
}
}
}
if
(
pair
.
getLeft
()
==
Product
.
class
)
{
countedProducts
++;
}
else
if
(
pair
.
getLeft
()
==
Reactant
.
class
)
{
countedReactants
++;
}
previousPoint
=
pair
.
getRight
();
}
}
return
point
;
}
private
Point2D
getCenterPoint
(
PolylineData
originalPolylineData
,
Point2D
startPoint
,
Point2D
endPoint
)
{
PolylineData
pd
=
getSubline
(
originalPolylineData
,
startPoint
,
endPoint
);
return
getCenterPoint
(
pd
);
}
private
Point2D
getLeftCenterPoint
(
PolylineData
originalPolylineData
,
Point2D
startPoint
,
Point2D
endPoint
)
{
PolylineData
pd
=
getSubline
(
originalPolylineData
,
startPoint
,
endPoint
);
double
x
=
pd
.
getPoints
().
get
(
0
).
getX
()
+
(
pd
.
getPoints
().
get
(
1
).
getX
()
-
pd
.
getPoints
().
get
(
0
).
getX
())
/
2
;
double
y
=
pd
.
getPoints
().
get
(
0
).
getY
()
+
(
pd
.
getPoints
().
get
(
1
).
getY
()
-
pd
.
getPoints
().
get
(
0
).
getY
())
/
2
;
return
new
Point2D
.
Double
(
x
,
y
);
}
private
Point2D
getRightCenterPoint
(
PolylineData
originalPolylineData
,
Point2D
startPoint
,
Point2D
endPoint
)
{
PolylineData
pd
=
getSubline
(
originalPolylineData
,
startPoint
,
endPoint
);
int
points
=
pd
.
getPoints
().
size
();
double
x
=
pd
.
getPoints
().
get
(
points
-
2
).
getX
()
+
(
pd
.
getPoints
().
get
(
points
-
1
).
getX
()
-
pd
.
getPoints
().
get
(
points
-
2
).
getX
())
/
2
;
double
y
=
pd
.
getPoints
().
get
(
points
-
2
).
getY
()
+
(
pd
.
getPoints
().
get
(
points
-
1
).
getY
()
-
pd
.
getPoints
().
get
(
points
-
2
).
getY
())
/
2
;
return
new
Point2D
.
Double
(
x
,
y
);
}
private
PolylineData
getSubline
(
PolylineData
originalPolylineData
,
Point2D
startPoint
,
Point2D
endPoint
)
{
int
start
=
0
;
int
end
=
originalPolylineData
.
getPoints
().
size
()
-
1
;
for
(
int
i
=
0
;
i
<
originalPolylineData
.
getPoints
().
size
();
i
++)
{
if
(
distanceFromPolylineStart
(
originalPolylineData
,
startPoint
)
>
distanceFromPolylineStart
(
originalPolylineData
,
originalPolylineData
.
getPoints
().
get
(
i
)))
{
start
=
i
;
}
if
(
distanceFromPolylineStart
(
originalPolylineData
,
endPoint
)
<
distanceFromPolylineStart
(
originalPolylineData
,
originalPolylineData
.
getPoints
().
get
(
i
)))
{
end
=
Math
.
min
(
end
,
i
);
}
}
PolylineData
result
=
originalPolylineData
.
getSubline
(
start
,
end
+
1
);
result
.
setStartPoint
(
pt
.
copyPoint
(
startPoint
));
result
.
setEndPoint
(
pt
.
copyPoint
(
endPoint
));
return
PolylineDataFactory
.
removeCollinearPoints
(
result
);
}
private
Point2D
getCenterPoint
(
PolylineData
pd
)
{
List
<
Line2D
>
lines
=
pd
.
getLines
();
double
lenght
=
0.0
;
for
(
Line2D
line
:
lines
)
{
lenght
+=
Geo
.
lineLen
(
line
);
}
double
tmp
=
0.0
;
for
(
Line2D
line
:
lines
)
{
if
(
tmp
+
Geo
.
lineLen
(
line
)
>
lenght
/
2
)
{
double
x
=
line
.
getX1
()
+
(
line
.
getX2
()
-
line
.
getX1
())
/
2
;
double
y
=
line
.
getY1
()
+
(
line
.
getY2
()
-
line
.
getY1
())
/
2
;
return
new
Point2D
.
Double
(
x
,
y
);
}
else
{
tmp
+=
Geo
.
lineLen
(
line
);
}
}
return
pt
.
copyPoint
(
pd
.
getEndPoint
());
}
double
distanceFromPolylineStart
(
PolylineData
line
,
Point2D
point
)
{
double
distance
=
0
;
for
(
Line2D
l
:
line
.
getLines
())
{
if
(
lt
.
distBetweenPointAndLineSegment
(
l
,
point
)
<=
Configuration
.
EPSILON
)
{
return
distance
+
point
.
distance
(
l
.
getP1
());
}
distance
+=
l
.
getP1
().
distance
(
l
.
getP2
());
}
throw
new
InvalidArgumentException
(
"Point doesn't lay on the line"
);
}
private
boolean
pointOnPolyline
(
PolylineData
line
,
Point2D
point
)
{
for
(
Line2D
l
:
line
.
getLines
())
{
if
(
lt
.
distBetweenPointAndLineSegment
(
l
,
point
)
<=
Configuration
.
EPSILON
)
{
return
true
;
}