我有以下图像SVG文件:如何以编程方式在SVG文件中进行转换?
每个箭头是由像这样的代码表示:
<g
transform="matrix(-1,0,0,-1,149.82549,457.2455)"
id="signS"
inkscape:label="#sign">
<title
id="title4249">South, 180</title>
<path
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0"
id="path4251"
d="m 30.022973,250.04026 4.965804,-2.91109 4.988905,2.91109"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.6855976px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<rect
y="250.11305"
x="29.768578"
height="2.6057031"
width="10.105703"
id="rect4253"
style="fill:#008000;fill-opacity:1;stroke:#000000;stroke-width:0.53715414;stroke-opacity:1" />
</g>
我要计算的矩形的绝对位置 (rect
节点)。为了做到这一点,我需要评估g
标记的transform
标记内的表达式(上例中的matrix(-1,0,0,-1,149.82549,457.2455)
)。
我该怎么办?
我认为第一步是使用Apache Batik读取该文件作为SVGDocument
:
import java.io.IOException;
import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
import org.apache.batik.util.XMLResourceDescriptor;
import org.w3c.dom.Document;
try {
String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
String uri = "http://www.example.org/diagram.svg";
Document doc = f.createDocument(uri);
} catch (IOException ex) {
// ...
}
据我所知,doc
可以转换为SVGDocument。
如何从SVG文档获取矩形或组的绝对位置?注意:我需要一些现有的代码,它可以完成上面的转换(不要告诉我自己实现这些转换 - 它们必须已经实现,我希望重新使用该代码)。
更新1(2015年11月8日12:56 MSK):
落实罗伯特Longson的建议,第一次尝试:
public final class BatikTest {
@Test
public void test() throws XPathExpressionException {
try {
final File initialFile =
new File("src/main/resources/trailer/scene05_signs.svg");
InputStream sceneFileStream = Files.asByteSource(initialFile).openStream();
String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
String uri = "http://www.example.org/diagram.svg";
final SVGOMDocument doc = (SVGOMDocument) f.createDocument(
uri, sceneFileStream);
final NodeList nodes =
doc.getDocumentElement().getElementsByTagName("g");
SVGOMGElement signSouth = null;
for (int i=0; (i < nodes.getLength()) && (signSouth == null); i++) {
final Node curNode = nodes.item(i);
final Node id = curNode.getAttributes().getNamedItem("id");
if ("signS".equals(id.getTextContent())) {
signSouth = (SVGOMGElement) curNode;
}
System.out.println("curNode: " + nodes);
}
System.out.println("signSouth: " + signSouth);
final NodeList rectNodes = signSouth.getElementsByTagName("rect");
System.out.println("rectNodes: " + rectNodes);
SVGOMRectElement rectNode = (SVGOMRectElement) rectNodes.item(0);
System.out.println("rectNode: " + rectNode);
final SVGMatrix m2 =
signSouth.getTransformToElement(rectNode);
System.out.println("m2: " + m2);
} catch (IOException ex) {
Assert.fail(ex.getMessage());
}
}
}
呼叫至m2.getA()
- m2.getF()
结果NullPointerException
秒。
更新2(2015年8月11日13时38分MSK):
添加以下代码来创建SVGPoint
并应用矩阵变换到它:
final SVGSVGElement docElem = (SVGSVGElement)
doc.getDocumentElement();
final SVGPoint svgPoint = docElem.createSVGPoint();
svgPoint.setX((float) x);
svgPoint.setY((float) y);
final SVGPoint svgPoint1 =
svgPoint.matrixTransform(signSouth.getScreenCTM()); // Line 77
System.out.println("x: " + svgPoint1.getX());
System.out.println("y: " + svgPoint1.getY());
结果:
java.lang.NullPointerException
at org.apache.batik.dom.svg.SVGLocatableSupport$3.getAffineTransform(Unknown Source)
at org.apache.batik.dom.svg.AbstractSVGMatrix.getA(Unknown Source)
at org.apache.batik.dom.svg.SVGOMPoint.matrixTransform(Unknown Source)
at org.apache.batik.dom.svg.SVGOMPoint.matrixTransform(Unknown Source)
at [...].BatikTest.test(BatikTest.java:77)
更新3,条款的赏金(10.11.2015 MSK):
条件,这必须被满足,以获得赏金:
我将颁发奖金的英雄或女主角,谁管理,以实现在JUnit测试方法magicallyCalculateXCoordinate
和magicallyCalculateYCoordinate
BatikTest,这样我可以在我的Java代码中获取InkScape中显示的形状的坐标(请参阅下面的示例截图)。
计算形状在SVG文件中的位置的呈现的方法必须工作,要么
- 为组节点(像在图像和在sample file)或
- 为三角形。
您提供的代码必须适用于样本文件中的所有四个形状,即使用它我必须能够在Java代码中计算它们的坐标,它们与Inkscape中显示的坐标相同。
您可以将参数添加到方法magicallyCalculateXCoordinate
和magicallyCalculateYCoordinate
,您也可以创建自己的方法来计算坐标。
您可以使用任何图书馆,这些图书馆可以合法用于商业目的。
与此请求相关的所有文件请从GitHub获取。我设法使用IntelliJ Idea Community Edition 14.1.5编译测试。
任何getScreenCTM,getCTM或getTransformToElement都会为您提供从绝对单位到本地单位的整体转换。将其应用于元素的本地协调者,并以绝对单位给出坐标。 –
@RobertLongson谢谢。我试图实现你的方法,参见更新1.我可以在其中找到组节点和rect节点。如何应用矩阵来获取该代码中的实际坐标? –
创建SVGPoint将其值设置为本地坐标,请调用matrixTransform http://www.w3.org/TR/SVG/coords.html#InterfaceSVGPoint和http://www.w3.org/TR/SVG/ struct.html #__ svg__SVGSVGElement__createSVGPoint –