I am developing a Visio add-in in C#. The purpose of the add-in is to allow an SVG file to be edited in Visio, but not using Visio's SVG import/export. The SVG file contains private namespace data and some other specialized stuff that must be preserved, so the normal SVG open/save process cannot be used. The add-in reads the SVG as XML and creates the Visio shapes programmatically, then reverses the process when the file is saved.
The problem I am encountering with this is that I can't figure out how to convert elliptical arcs. The SVG format uses a starting and ending point with two radii to specify the arc, while Visio uses a different basis for defining the arc. I know the equations to convert back and forth exist because the SVG is rendered correctly if I just open the file using Visio, but I have searched extensively and can't find anything that addresses my question, "how can I convert an SVG path arc to Visio and back again?"
Anyone out there familiar with Visio internals (or very good with geometry) that can provide the necessary equations?
Thanks
Bob
This is really about translating center points to major/minor axis.
Perhaps these might help to understand how to:
Top is regular arc (right click)
bottom is elliptical arc (right click)
Then you can look at the shape sheet for conversion approach.
Thanks, I think I understand the concept, but I am still struggling with the execution.
Here is the SVG path I'm dealing with: <path d="M12 19 A6 6 236.1413 0 0 5 30" />
This decodes as "move to x=12, y=19", "arc with radii 6,6 to x=5, y=30" The parameters between "6 6" and "5 30" are not relevant to this exercise.
Here is the geometry that Visio generates for this shape when it opens the SVG file:
Name | X | Y | A | B | C | D |
RelMoveTo | 1.0000 | 1.0000 | | | | |
RelEllipticalArcTo | 0.2222 | 0.0000 | 0.0000 | 0.8182 | 0.0000 | 1.0000 |
What I would really like is an explanation (preferably with examples) of how to get from point A to point B. Sorry, but my math skills are not up to the task.
Thanks,
Bob
I have a shape of elliptical arc.
I hope this may help you.
Hello, and thank you. I appreciate your efforts.
I can see the relationships at work here, but what I am lacking are the specific calculations required to implement the transformation that I need, which is to represent an SVG path arc in Visio, and then reverse the process.
If anyone has actual code that can accomplish this I would be grateful if you could share it.
Bob
I am sorry I cannot understand what do you mean.
@Bob, with June you've certainly met the best possible specialist to solve your issue.
The problem is, we're all very Visio focused here at the visguy forum, so if YOU could provide the formulas to describe a SVG arc, then June will certainly find a way to translate it back and forth betwenn Visio and SVG.
My 2 cents, Y.
I think Visio can open SVG file.
The following is a simple test.
1. Insert a simple SVG file that contain an elliptical arc only that is made with Visio and saved as SVG file.
2. Ungroup the inserted elliptical arc 3 times, and get the Visio alliptical arc.
3. you can edit directly on the drawing page, or on shapesheet.
You can make a macro of this proccess using macro recorder.
Bob is looking for formulas to convert by code Visio arcs into SVG and back. Description of SVG arc: https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands (https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands)
Yes! Thank you Yacine. I guess I wasn't being clear enough.
I need some help with the actual coding of the transformations using .Net 4.5 and C#.
Bob
There are already the converters in the web.
Please search in the web with the keywords like svg2vsd and vsd2svg.
It seems here you can download the source code.
http://dia-installer.de/vsd2svg/index.html.en
I think Visio includes sub program like these.
Thank you everyone for your patience. I have located the code to convert a Visio elliptical arc to SVG (VSD2SVG).
Unfortunately, there is no reciprocal function that I can find. I have searched SVG2VSD and all similar and related ideas, but with no luck.
I would appreciate any help anyone can provide on the conversion of an SVG path arc to a Visio EllipticalArcTo. Is the Visio source open? If it is I couldn't find it.
I'm sure the equations are there since Visio can open an SVG file and render the arcs correctly. As I mentioned at the beginning, I can't use the native Visio capability because there is private namespace material in the SVG file.
Bob
Quote
I am developing a Visio add-in in C#.
Why don't you use many powerful tools in Visio such as Visio mehods, properties, etc. in your add-in in your c#?
It might be much easier than you develop your own unique codes.
Hi Junichi,
A good suggestion. Presented with an SVG arc path (M from-x, from-y A rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, to-x, to-y) what Visio tool(s) should I apply to create a corresponding shape?
Thanks again,
Bob
Quote
I think Visio can open SVG file.
The following is a simple test.
1. Insert a simple SVG file that contain an elliptical arc only that is made with Visio and saved as SVG file.
2. Ungroup the inserted elliptical arc 3 times, and get the Visio alliptical arc.
3. you can edit directly on the drawing page, or on shapesheet.
You can make a macro of this proccess using macro recorder.
I think Visio is one of the best converter.
I've not seen the conversion algorithm ever. Doubt that it's available outside of the normal Visio svg file editing routine. You may have to develop a different strategy.
Wapperdude
SVG uses radiuses + angle approach to describe the elliptical arc (check "Arcs" section, it's like children's book with pictures - should explain properly how arc is described in svg):
https://developer.mozilla.org/en/docs/Web/SVG/Tutorial/Paths
Visio uses "point on the arc" approach to describe the arc (unfortunately I have not found reference with pictures)
https://msdn.microsoft.com/en-us/library/office/ff767078.aspx
Therefore to convert from SVG to Visio you'll need a point on the arc. Here is an example how to get one (check "marked as answer"):
http://math.stackexchange.com/questions/22064/calculating-a-point-that-lies-on-an-ellipse-given-an-angle
To convert back, you'll need to do the reverse..
Sorry I'm a bit too lazy for such exercises, but hope it may point you to the right direction and clarify what kind of formula you actually might need.
If you manage to find these formulas, feel free to post them here :)
Add to Nikolay's comment:
To uniquely specify the arc from one version to the other, I suspect you need 4 points: both ends, and 2 points in between to make a unique solution. Might need 1 more, but I think 4 is sufficient.
Too much math to grind thru, though.
Wapperdude
I roughly imaged a conversion formulas from SVG to Visio shape sheet formulas.
But I am never sure they are right.
Even if they have any possiblity, many times of try and error will be necessary.
If you read carefully the source code of vsd2SVG, you might find lines corresponds to such conversion formulas. The lines will be for contrarily direction. but might give you any hint.
Visio vs SVG
x1=Xc (current point of SvG curve drawn last time or moveto.)
y1=Yc
x2=X1 (end point on SVG elliptical arc)
y2=Y1
A=X2 (point on SVG elliptical arc)
B=Y2
C=Calculated Relative Angle to base line
D=Xr/Yr or Yr/Xr
Here is a document that may help to calculate this issue.
http://stackoverflow.com/questions/197649/how-to-calculate-center-of-an-ellipse-by-two-points-and-radius-sizes
Tha way explained here is able to simplify the calculation.
But it does not applied to an angular ellipse.
So, I tried to expand the method.
Here is a hand written formulas on my notebook.
Cool. In some years, this will be part of Junichi's legacy.
I wonder if I should buy it right now.
;D
hmmm....looks remarkably similar to Einstein field equations.....hmmm
June...nice piece of work
Or it is more easy to convert with hand operation geometrically.
Here is an example drawing of the result of my experiment.
It has 2 pages steps, you may feel long, but not so long if you really operaye on drawaing.
I tried to convert these hand operations into pure mathematical VBA program, but for me it is too hard.
Revision:
Step 4 was blank, and added "Multiply by 0.3528 (mm) to Point Data."
Above drawing was replaced.
It seems that the topic-starter hoped to get just the formula to transform SVG "elliptical path" to VSD "elliptical path" and not PHD in math transforms :)
Looks like we have lost him? :D
Here is an trial VBA macro.
Option Explicit
Sub ConvertSVGArcToVisioArc()
Dim LAF As Long, SWF As Long 'Long arc flag and sweep flag as definrd in SVG path format.
Dim cf As Double 'Number to convert length of SVG into Visio
Dim x1 As Double, y1 As Double, x2 As Double, y2 As Double ' Start point and end point of arc.
Dim xm As Double, ym As Double 'Mid point of start and end point of ard.
Dim athita As Double, thita As Double 'Angle of ellipse
Dim x0 As Double, y0 As Double, xd As Double, yd As Double 'Dummy origin not center of ellipse
Dim rx As Double, ry As Double 'Major and minor radius of ellipse
Dim ratio As Double, shratio As Double 'Ratio to expand and shrink
Dim x3 As Double, y3 As Double, x4 As Double, y4 As Double 'Starting & End points of arc after Expanding
Dim x5 As Double, y5 As Double, x6 As Double, y6 As Double 'Centers of circle passing through start & end points of arc
Dim x7 As Double, y7 As Double, x8 As Double, y8 As Double 'Mid points on arc
Dim x9 As Double, y9 As Double, x10 As Double, y10 As Double 'Mid points on arc
Dim len1 As Double, len2 As Double, len3 As Double, len4 As Double
Dim xms As Double, yms As Double 'Selected mid point on arc at step 10
Dim shp As Visio.Shape
Dim xmss As Double, ymss As Double 'Mid points of selected mid point after shrink.
LAF = 0
SWF = 0
cf = 0.3528
xd = 0#
yd = 20#
x1 = 68.45
y1 = 27.43
x2 = 0#
y2 = 9.09
rx = 41.2537
ry = 27.5024
athita = -5#
' Step 4 Convert SVG coordinete into Visio coordinate.
x1 = xd + x1 * cf 'Starting Point of arc
y1 = yd - y1 * cf
x2 = xd + x2 * cf 'Ebd point of arc
y2 = yd - y2 * cf
rx = rx * cf
ry = ry * cf
x0 = x1
y0 = y1
thita = -athita * pi() / 180#
' Step 7 & 9 Expand points along minor radius of ellipse.
ratio = rx / ry ' Greater than 1.0
ExpandSp x1, y1, ratio, thita, x0, y0, x3, y3 ' Expand along minor radious by ratio
ExpandSp x2, y2, ratio, thita, x0, y0, x4, y4 ' Expand along minor radious by ratio
' Get Mid point of Start and end points of arc.
xm = (x3 + x4) / 2#
ym = (y3 + y4) / 2#
' Step 10 : Get center of ciecles.
CenterOfCircle x3, y3, x4, y4, rx, x5, y5, x6, y6
' Step Extra 1 : Get Mid point2 on arcs.
MidPointsOnCircle x3, y3, x4, y4, rx, x5, y5, x7, y7, x8, y8
MidPointsOnCircle x3, y3, x4, y4, rx, x6, y6, x9, y9, x10, y10
' Step 10 : Select a Mid point on arc reffering to 2 factors in SVG, Large Arc Flag and Sweep Flag.
SellectMidPointOnArc LAF, SWF, rx, xm, ym, x3, y3, x4, y4, x5, y5, x7, y7, x8, y8, x9, y9, x10, y10, xms, yms
' Step 12 & 13 Shrink selected mid point along minor radius of ellipse.
shratio = ry / rx ' Les than 1.0
ExpandSp xms, yms, shratio, thita, x0, y0, xmss, ymss ' Expand along minor radious by ratio
' Step 14 : Draw Elliptical arc
DrawArcMm x1, y1, x2, y2, xmss, ymss, athita, ratio
End Sub
Other sub routines are in sample drawing.
Hereis a short vide to show the speed of macro.
https://youtu.be/RJ-2sHYIZbk
Here is another macro using trigonometric method.
Please enjoy.
All necessary sub routines are in the attached drawing.
Option Explicit
Sub ConvertSVGArcToVisioArc()
Dim LAF As Long, SWF As Long 'Long arc flag and sweep flag as definrd in SVG path format.
Dim cf As Double 'Number to convert length of SVG into Visio
Dim x1 As Double, y1 As Double, x2 As Double, y2 As Double ' Start point and end point of arc.
Dim xm As Double, ym As Double 'Mid point of start and end point of ard.
Dim athita As Double, thita As Double 'Angle of ellipse
Dim x0 As Double, y0 As Double, xd As Double, yd As Double 'Dummy origin not center of ellipse
Dim rx As Double, ry As Double 'Major and minor radius of ellipse
Dim x3 As Double, y3 As Double, x4 As Double, y4 As Double 'Starting & End points of arc after Expanding
Dim x5 As Double, y5 As Double, x6 As Double, y6 As Double 'Centers of circle passing through start & end points of arc
Dim x7 As Double, y7 As Double, x8 As Double, y8 As Double 'Mid points on arc
Dim x9 As Double, y9 As Double, x10 As Double, y10 As Double 'Mid points on arc
Dim shp As Visio.Shape
Dim xmss As Double, ymss As Double 'Mid points of selected mid point after shrink.
Dim th1 As Double
Dim thH1 As Double, thI1 As Double
Dim eps As Double
eps = 0.001
cf = 0.3528
xd = 0#
yd = 20#
x1 = 99.21
y1 = 57.5
rx = 86.0239
ry = 43.012
athita = -175.26
LAF = 0
SWF = 0
x2 = 0
y2 = 0.81
' Convert SVG coordinete into Visio coordinate.
x1 = xd + x1 * cf 'Starting Point of arc
y1 = yd - y1 * cf
x2 = xd + x2 * cf 'Ebd point of arc
y2 = yd - y2 * cf
rx = rx * cf
ry = ry * cf
x0 = x1
y0 = y1
' Get mid point on the line start and end point of arc.
xm = (x1 + x2) / 2#
ym = (y1 + y2) / 2#
thita = -athita * pi / 180#
' Get large thita from my formula.
thH1 = Atn((ry / rx) * ((x1 - x2) * Cos(thita) + (y1 - y2) * Sin(thita)) / _
((x1 - x2) * Sin(thita) - (y1 - y2) * Cos(thita)))
' thH2 = thH1 + pi
thI1 = ASin(-(x1 - x2) / (2# * (rx * Cos(thita) * Sin(thH1) + ry * Sin(thita) * Cos(thH1))))
' Get small thita from definitions.
th1 = thH1 + thI1
' Get center points of ellipse
x5 = x1 - rx * Cos(th1) * Cos(thita) + ry * Sin(th1) * Sin(thita)
y5 = y1 - rx * Cos(th1) * Sin(thita) - ry * Sin(th1) * Cos(thita)
x6 = 2# * xm - x5
y6 = 2# * ym - y5
' Get middle points on arcs from my formula.
x7 = x5 + rx * Cos(thH1) * Cos(thita) - ry * Sin(thH1) * Sin(thita)
y7 = y5 + rx * Cos(thH1) * Sin(thita) + ry * Sin(thH1) * Cos(thita)
x8 = 2# * xm - x7
y8 = 2# * ym - y7
x9 = x6 + rx * Cos(thH1) * Cos(thita) - ry * Sin(thH1) * Sin(thita)
y9 = y6 + rx * Cos(thH1) * Sin(thita) + ry * Sin(thH1) * Cos(thita)
x10 = 2# * xm - x9
y10 = 2# * ym - y9
SellectMidPointOnArc LAF, SWF, rx, xm, ym, x1, y1, x2, y2, x5, y5, x7, y7, x8, y8, x9, y9, x10, y10, xmss, ymss
DrawArcMm x1, y1, x2, y2, xmss, ymss, athita, rx / ry
End Sub