我有以下圖像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 –