In the previous article "Automatic layout of telecommunication network topology Diagram", we introduced the knowledge of the automatic layout of HT for Web Telecommunication network topology diagram, but did not describe the usage of various automatic layouts in depth, and we will focus on the concrete implementation of the bus here today.
In the HT for WEB Connection manual, it is explained that the type of connection can be customized via HT. Default.setedgetype (Type, func, mutual) function definition, the bus we are describing today is also implemented by this method.
Let's briefly describe this method, although the document (http://www.hightopo.com/guide/guide/plugin/edgetype/ ht-edgetype-guide.html) has been described in detail, for the following work can be better carried out, I would still stress on this side.
This function name is Setedgetype, as the name implies, it is used to customize a edgetype, then the first parameter type is used to define the name of the Edgetype, on the Edge of the style set Edge.type property is a type value, you can let this link Line usage is our custom edgetype.
Then the second parameter, which is used to calculate the line information of the function, the callback function will be passed four parameters, namely: Edge, Gap, Graphview, Samesourcewithfirstedge, where the edge is the style set Edge.type The property is a line object of type value, this parameter is the most important, usually with this parameter can complete the format of all kinds of lines. Other parameters are clearly described in the manual and can be transferred to the manual for reading, http://www.hightopo.com/guide/guide/plugin/edgetype/ht-edgetype-guide.html.
The third parameter, is to determine whether the connection affects the start or end of the node on all the lines, this parameter is more complex to explain, the subsequent opportunity, we will explain in detail.
Let's take a look at a simple example, http://www.hightopo.com/guide/guide/plugin/edgetype/examples/example_custom.html.
, you can see that the connection between the nodes is not a normal line, or a simple polyline, but a beautiful curve, then how is this curve generated? Since this example is put here as a case, then it must use the function of the custom edgetype, see the picture can be found that the curve can actually be expressed in two square curve, so, we in the callback of the Setedgetype function returned to the message, It can be described as a two-time square curve. That's a bit of a detour, let's take a look at the code implementation.
Ht. Default.setedgetype (' Custom ',function(Edge, Gap, Graphview, Samesourcewithfirstedge) {varSourcepoint =edge.getsourceagent (). GetPosition (), TargetPoint=edge.gettargetagent (). GetPosition (), Points=Newht. List (); Points.Add (Sourcepoint); Points.Add ({x: (Sourcepoint.x+ targetpoint.x)/2, Y: (Sourcepoint.y + targetpoint.y)/2 + 300 }); Points.Add (TargetPoint); return{points:points, Segments:NewHt. List ([1, 3]) }; });
As can be seen from the code, the return to the vertex is the beginning and end of the line, as well as the middle of the two-square curve of the control point, as well as the way to set the vertex, that is, the segments,1 in return is the beginning of the path, 3 represents the two-square curve, the relevant knowledge points in the HT for Web The shape of the manual is described clearly, do not understand can go to the manual detailed understanding, http://www.hightopo.com/guide/guide/core/shape/ht-shape-guide.html.
The front of the nonsense too much, the following is our main content today, to see how the custom Edgetype to achieve the effect of the bus, http://www.hightopo.com/demo/EdgeType/BusEdgeType.html.
is a simple example of a bus, all the nodes through the line link Black bus, the direction of the connection is the shortest distance from the node to the bus.
Speaking of the overall design ideas, in fact, in general, is the point of the vertical point of the calculation of the problem. So the question is, what happens to the curve? In fact, the curve can also be differentiated into lines to deal with, as to the division of this segment of the fineness of the user needs to be defined.
Edgetype with Shapelayout for uniform automatic layout: http://www.hightopo.com/demo/EdgeType/ShapeLayout-Oval.html.
But what about the Oval bus as shown? For this kind of shape with fixed expressions, we do not need to use the method of curve segmentation to do the bus layout, we can completely get to the circle or ellipse point, so in the processing circle and ellipse, we get edge connecting edge node line, and then calculate the angle, A point on the bus is calculated by means of a triangular function representation of a circle or ellipse, which forms the connection.
In, we used the shapelayout from the dynamic layout and bus connections to the node, so that it is relatively evenly distributed around the bus, for the shapelayout of the relevant design ideas in the following chapters in detail.
So our content today is here, for the bus design is not very simple, the following is attached to all the bus code, if necessary, can be directly copied out, in the page introduced the HT for Web core package Ht.js After the introduction of the following code can directly use the bus function. Code is not much, also nearly 200 lines, interested friends can read through, what the problem, but also please enlighten.
;(function(window, HT) {varGetPoint =function(node, outpoint) {varRect =node.getrect (), POS=node.getposition (), p=ht. Default.intersectionlinerect (POS, outpoint, rect); if(p)return{x:p[0], y:p[1] }; returnPOS; }; varPointtoinsideline =function(P1, p2, p) {varX1 =p1.x, y1=P1.y, x2=p2.x, y2=p2.y, x=p.x, y=p.y, result={}, DX= X2-x1, dy= y2-Y1, D= math.sqrt (DX * dx + dy *dy), CA= dx/d,//cosineSA = dy/d,//SineMX = (-x1 + x) * CA + (-y1 + y) *sa; Result.x= x1 + MX *CA; Result.y= y1 + MX *sa; if(!ispointinline (Result, p1, p2)) {Result.x= Math.Abs (result.x-p1.x) < Math.Abs (result.x-p2.x)?p1.x:p2.x; Result.y= Math.Abs (RESULT.Y-P1.Y) < Math.Abs (RESULT.Y-P2.Y)?p1.y:p2.y; } DX= X-Result.x; Dy= y-Result.y; Result.z= math.sqrt (DX * dx + dy *dy); returnresult; }; varIspointinline =function(P, p1, p2) {returnp.x >= math.min (p1.x, p2.x) &&p.x<= Math.max (p1.x, p2.x) &&p.y>= math.min (p1.y, P2.Y) &&p.y<=Math.max (P1.Y, P2.Y); }; varBezier2 =function(t, P0, p1, p2) {varT1 = 1-T; returnT1*t1*p0 + 2*T*T1*P1 + t*t*P2; }; varBezier3 =function(t, P0, p1, p2, p3) {varT1 = 1-T; returnT1*t1*t1*p0 + 3*t1*t1*t*p1 + 3*t1*t*t*p2 + t*t*t*P3; }; varDistance =function(P1, p2) {varDX = p2.x-p1.x, Dy= P2.y-p1.y; returnMATH.SQRT (Math.pow (DX, 2) + Math.pow (DY, 2)); }; varGetpointwithlength =function(length, p1, p2) {vardis =distance (p1, p2), temp= Length/Dis, DX= p2.x-p1.x, Dy= P2.y-p1.y; return{x:p1.x + dx * temp, y:p1.y + dy *temp}; }; varGetpointinoval =function(L, R, p1, p2) {varA = Math.atan2 (P2.y-p1.y, p2.x-p1.x); return{X:l * Math.Cos (a) + p1.x, Y:r * Math.sin (a) +P1.Y}; }; Ht. Default.setedgetype (' Bus ',function(Edge, Gap, Graphview, Samesourcewithfirstedge) {varSource =edge.getsourceagent (), Target=edge.gettargetagent (), Shapelist= [' Circle ', ' oval '], shape, Beginnode, Endnode; if(Shapelist.indexof (SOURCE.S (' shape ')) >= 0) {Shape= SOURCE.S (' Shape '); Beginnode=source; Endnode=Target; } Else if(Shapelist.indexof (Target.s (' shape ')) >= 0) {Shape= Target.s (' Shape '); Beginnode=Target; Endnode=source; } if(Shapelist.indexof (Shape) >= 0) { varW =beginnode.getwidth (), H=beginnode.getheight (), L= Math.max (W, h)/2, R= Math.min (W, h)/2; if(Shape = = = ' Circle ') L = R =math.min (L, R); varp =Getpointinoval (L, R, Beginnode.getposition (), endnode.getposition ()); return{points:Newht. List ([P, GetPoint (Endnode, p)]), Segments:NewHt. List ([1, 2 ]) }; } varsegments, points, endPoint; if(Sourceinstanceofht. Shape) {Segments=source.getsegments (); Points=source.getpoints (); Beginnode=source; EndPoint=target.getposition (); Endnode=Target; } Else if(Targetinstanceofht. Shape) {Segments=target.getsegments (); Points=target.getpoints (); Beginnode=Target; EndPoint=source.getposition (); Endnode=source; } if(!points) { return{points:Newht. List ([GetPoint (Source, Target.getposition ()), GetPoint (Target, source.getposition () )]), Segments:NewHt. List ([1, 2 ]) }; } if(!segments &&points) {Segments=Newht. List (); Points.each (function() {Segments.add (2); }); Segments.set (0, 1); } varSeglen =segments.size (), SegV, Segnextv, Beginpoint, J, p1, P2, p3, P4, p, TP1, tP2, TRes, C Urveresolution= Beginnode.a (' edge.curve.resolution ') | | 50, Pointsindex= 0; for(vari = 0; i < segLen-1; i++) {SEGNEXTV= Segments.get (i + 1); if(Segnextv = = 1) {Pointsindex++; Continue; } p1= Points.get (pointsindex++); if(SEGNEXTV = = = 2 | | segnextv = = 5) {P2= Points.get ((segnextv = = = 5)? 0: Pointsindex); P=Pointtoinsideline (P1, p2, endPoint); if(!beginpoint | | beginpoint.z >p.z) Beginpoint=p; } Else if(SEGNEXTV = = 3) {P2= Points.get (pointsindex++); P3=Points.get (Pointsindex); TP2={x:p1.x, y:p1.y}; for(j = 1; J <= Curveresolution; j + +) {tP1=tP2; TRes= J/curveresolution; TP2={x:bezier2 (tRes, p1.x, p2.x, p3.x), Y:bezier2 (TRes, P1.y, P2.y, p3.y ), }; P=pointtoinsideline (tP1, tP2, EndPoint); if(!beginpoint | | beginpoint.z >p.z) Beginpoint=p; } } Else if(SEGNEXTV = = 4) {P2= Points.get (pointsindex++); P3= Points.get (pointsindex++); P4=Points.get (Pointsindex); TP2={x:p1.x, y:p1.y}; for(j = 1; J <= Curveresolution; j + +) {tP1=tP2; TRes= J/curveresolution; TP2={X:bezier3 (tRes, p1.x, p2.x, p3.x, p4.x), Y:bezier3 (TRes, P1.Y, p2.y , P3.y, P4.y),}; P=pointtoinsideline (tP1, tP2, EndPoint); if(!beginpoint | | beginpoint.z >p.z) Beginpoint=p; } }} endPoint=GetPoint (Endnode, beginpoint); return{points:Newht. List ([{x:beginpoint.x, Y:beginpoint.y}, EndPoint]), Segments:
NewHt. List ([1, 2 ]) }; });} (window, HT));
Bus for automatic layout of topology diagram of telecommunication network