修复pin 连接点不随着转动而变动的问题

main
zcy 2024-03-24 23:41:03 +08:00
parent 0a9ca68dbd
commit a3aa0f292d
2 changed files with 436 additions and 65 deletions

View File

@ -20,6 +20,11 @@ style="overflow:auto;position:relative;width:1500px;height:600px;border:1px soli
<div>
<pre id="results"></pre>
</div>
<button onclick="window.renderer.delete_select_cop()"> 删除</button>
<script type="text/javascript">
</script>
<script type="text/javascript">
// renderSchematic(getTestFile());
@ -95,13 +100,9 @@ function doSave(value, type, name) {
var anchor = document.createElement("a");
if ('download' in anchor) {
anchor.style.visibility = "hidden";
anchor.href = bloburl;
anchor.download = name;
document.body.appendChild(anchor);
var evt = document.createEvent("MouseEvents");
@ -149,8 +150,11 @@ function renderSchematic(data)
let altiumDocument = new AltiumDocument(data);
window.altiumDocument = altiumDocument;
let renderer = new AltiumSchematicRenderer(canvas, altiumDocument);
window.renderer = renderer
renderer.render();
}
</script>
</body>
</html

View File

@ -24,12 +24,8 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
mxConnectionHandler.prototype.movePreviewAway = false;
mxConnectionHandler.prototype.waypointsEnabled = true;
mxGraph.prototype.resetEdgesOnConnect = false;
mxConstants.SHADOWCOLOR = '#C0C0C0';
var joinNodeSize = 7;
var strokeWidth = 2;
class AltiumSchematicRenderer
{
@ -59,9 +55,351 @@ class AltiumSchematicRenderer
return parent.current_part_id == object.owner_part_id;
}
delete_select_cop(){ // 删除选中器件
this.graph.removeCells();
}
render() {
this.graph = new mxGraph(document.getElementById('graphContainer'));
mxConnectionHandler.prototype.movePreviewAway = false;
mxConnectionHandler.prototype.waypointsEnabled = true;
mxGraph.prototype.resetEdgesOnConnect = true;
mxConstants.SHADOWCOLOR = '#C0C0C0';
var joinNodeSize = 4;
var strokeWidth = 2;
// Enables guides
mxGraphHandler.prototype.guidesEnabled = false;
// Alt disables guides
mxGuide.prototype.isEnabledForEvent = function(evt)
{
return !mxEvent.isAltDown(evt);
};
// Enables snapping waypoints to terminals
mxEdgeHandler.prototype.snapToTerminals = true;
mxEdgeStyle.WireConnector = function(state, source, target, hints, result)
{
mxLog.debug('add waypoint');
mxLog.debug("WireConnector",state,source,target,hint)
// Creates array of all way- and terminalpoints
var pts = state.absolutePoints;
var horizontal = true;
var hint = null;
// Gets the initial connection from the source terminal or edge
if (source != null && state.view.graph.model.isEdge(source.cell))
{
horizontal = state.style['sourceConstraint'] == 'horizontal';
}
else if (source != null)
{
horizontal = source.style['portConstraint'] != 'vertical';
// Checks the direction of the shape and rotates
var direction = source.style[mxConstants.STYLE_DIRECTION];
if (direction == 'north' || direction == 'south')
{
horizontal = !horizontal;
}
}
// Adds the first point
// TODO: Should move along connected segment
var pt = pts[0];
if (pt == null && source != null)
{
pt = new mxPoint(state.view.getRoutingCenterX(source), state.view.getRoutingCenterY(source));
}
else if (pt != null)
{
pt = pt.clone();
}
var first = pt;
// Adds the waypoints
if (hints != null && hints.length > 0)
{
// FIXME: First segment not movable
hint = state.view.transformControlPoint(state, hints[0]);
mxLog.show();
mxLog.debug(hints.length,'hints0.y='+hint.y, pt.y)
if (horizontal && Math.floor(hint.y) != Math.floor(pt.y))
{
mxLog.show();
mxLog.debug('add waypoint');
pt = new mxPoint(pt.x, hint.y);
result.push(pt);
pt = pt.clone();
//horizontal = !horizontal;
}
for (var i = 0; i < hints.length; i++)
{
horizontal = !horizontal;
hint = state.view.transformControlPoint(state, hints[i]);
if (horizontal)
{
if (pt.y != hint.y)
{
pt.y = hint.y;
result.push(pt.clone());
}
}
else if (pt.x != hint.x)
{
pt.x = hint.x;
result.push(pt.clone());
}
}
}
else
{
hint = pt;
}
// Adds the last point
pt = pts[pts.length - 1];
// TODO: Should move along connected segment
if (pt == null && target != null)
{
pt = new mxPoint(state.view.getRoutingCenterX(target), state.view.getRoutingCenterY(target));
}
if (horizontal)
{
if (pt.y != hint.y && first.x != pt.x)
{
// result.push(new mxPoint(pt.x, hint.y));
}
}
else if (pt.x != hint.x && first.y != pt.y)
{
// result.push(new mxPoint(hint.x, pt.y));
}
};
mxStyleRegistry.putValue('wireEdgeStyle', mxEdgeStyle.WireConnector);
let mxGraphGetCellStyle = mxGraph.prototype.getCellStyle;
mxGraph.prototype.getCellStyle = function(cell)
{
var style = mxGraphGetCellStyle.apply(this, arguments);
if (style != null && this.model.isEdge(cell))
{
style = mxUtils.clone(style);
if (this.model.isEdge(this.model.getTerminal(cell, true)))
{
style['startArrow'] = 'oval';
}
if (this.model.isEdge(this.model.getTerminal(cell, false)))
{
style['endArrow'] = 'oval';
}
}
return style;
};
let mxConnectionHandlerCreateMarker = mxConnectionHandler.prototype.createMarker;
mxConnectionHandler.prototype.createMarker = function() {
var marker = mxConnectionHandlerCreateMarker.apply(this, arguments);
// Uses complete area of cell for new connections (no hotspot)
marker.intersects = function(state, evt)
{
return true;
};
// Adds in-place highlighting
mxCellHighlightHighlight = mxCellHighlight.prototype.highlight;
marker.highlight.highlight = function(state)
{
if (this.state != state)
{
if (this.state != null)
{
this.state.style = this.lastStyle;
// Workaround for shape using current stroke width if no strokewidth defined
this.state.style['strokeWidth'] = this.state.style['strokeWidth'] || '1';
this.state.style['strokeColor'] = this.state.style['strokeColor'] || 'none';
if (this.state.shape != null)
{
this.state.view.graph.cellRenderer.configureShape(this.state);
this.state.shape.redraw();
}
}
if (state != null)
{
this.lastStyle = state.style;
state.style = mxUtils.clone(state.style);
state.style['strokeColor'] = '#00ff00';
state.style['strokeWidth'] = '3';
if (state.shape != null)
{
state.view.graph.cellRenderer.configureShape(state);
state.shape.redraw();
}
}
this.state = state;
}
};
return marker;
};
let mxEdgeHandlerCreateMarker = mxEdgeHandler.prototype.createMarker;
mxEdgeHandler.prototype.createMarker = function()
{
var marker = mxEdgeHandlerCreateMarker.apply(this, arguments);
marker.highlight.highlight = this.graph.connectionHandler.marker.highlight.highlight;
return marker;
}
// Sets source terminal point for edge-to-edge connections.
mxConnectionHandler.prototype.createEdgeState = function(me)
{
var edge = this.graph.createEdge();
if (this.sourceConstraint != null && this.previous != null)
{
edge.style = mxConstants.STYLE_EXIT_X+'='+this.sourceConstraint.point.x+';'+
mxConstants.STYLE_EXIT_Y+'='+this.sourceConstraint.point.y+';';
}
else if (this.graph.model.isEdge(me.getCell()))
{
var scale = this.graph.view.scale;
var tr = this.graph.view.translate;
var pt = new mxPoint(this.graph.snap(me.getGraphX() / scale) - tr.x,
this.graph.snap(me.getGraphY() / scale) - tr.y);
edge.geometry.setTerminalPoint(pt, true);
}
return this.graph.view.createState(edge);
};
// Uses right mouse button to create edges on background (see also: lines 67 ff)
mxConnectionHandler.prototype.isStopEvent = function(me)
{
return me.getState() != null || mxEvent.isRightMouseButton(me.getEvent());
};
// Updates target terminal point for edge-to-edge connections.
let mxConnectionHandlerUpdateCurrentState = mxConnectionHandler.prototype.updateCurrentState;
mxConnectionHandler.prototype.updateCurrentState = function(me)
{
mxConnectionHandlerUpdateCurrentState.apply(this, arguments);
if (this.edgeState != null)
{
this.edgeState.cell.geometry.setTerminalPoint(null, false);
if (this.shape != null && this.currentState != null &&
this.currentState.view.graph.model.isEdge(this.currentState.cell))
{
var scale = this.graph.view.scale;
var tr = this.graph.view.translate;
var pt = new mxPoint(this.graph.snap(me.getGraphX() / scale) - tr.x,
this.graph.snap(me.getGraphY() / scale) - tr.y);
this.edgeState.cell.geometry.setTerminalPoint(pt, false);
}
}
};
// Updates the terminal and control points in the cloned preview.
mxEdgeSegmentHandler.prototype.clonePreviewState = function(point, terminal) {
var clone = mxEdgeHandler.prototype.clonePreviewState.apply(this, arguments);
clone.cell = clone.cell.clone();
if (this.isSource || this.isTarget)
{
clone.cell.geometry = clone.cell.geometry.clone();
// Sets the terminal point of an edge if we're moving one of the endpoints
if (this.graph.getModel().isEdge(clone.cell))
{
// TODO: Only set this if the target or source terminal is an edge
clone.cell.geometry.setTerminalPoint(point, this.isSource);
}
else
{
clone.cell.geometry.setTerminalPoint(null, this.isSource);
}
}
return clone;
};
var mxEdgeHandlerConnect = mxEdgeHandler.prototype.connect;
mxEdgeHandler.prototype.connect = function(edge, terminal, isSource, isClone, me)
{
var result = null;
var model = this.graph.getModel();
var parent = model.getParent(edge);
model.beginUpdate();
try
{
result = mxEdgeHandlerConnect.apply(this, arguments);
var geo = model.getGeometry(result);
if (geo != null)
{
geo = geo.clone();
var pt = null;
if (model.isEdge(terminal))
{
pt = this.abspoints[(this.isSource) ? 0 : this.abspoints.length - 1];
pt.x = pt.x / this.graph.view.scale - this.graph.view.translate.x;
pt.y = pt.y / this.graph.view.scale - this.graph.view.translate.y;
var pstate = this.graph.getView().getState(
this.graph.getModel().getParent(edge));
if (pstate != null)
{
pt.x -= pstate.origin.x;
pt.y -= pstate.origin.y;
}
pt.x -= this.graph.panDx / this.graph.view.scale;
pt.y -= this.graph.panDy / this.graph.view.scale;
}
geo.setTerminalPoint(pt, isSource);
model.setGeometry(edge, geo);
}
}
finally
{
model.endUpdate();
}
return result;
};
// https://github.com/jgraph/mxgraph/blob/master/javascript/src/js/handler/mxGraphHandler.js#L1036
mxGraphHandler.prototype.updatePreview = function(remote) {
if (this.livePreviewUsed && !remote) {
@ -76,17 +414,14 @@ class AltiumSchematicRenderer
this.updatePreviewShape();
}
};
this.graph = new mxGraph(document.getElementById('graphContainer'));
let oldMove = mxGraphHandler.prototype.mouseMove
mxGraphHandler.prototype.mouseMove = function(sender, me){
console.log("mouse move",sender,me)
// mxLog.debug("mouse move",sender,me)
// https://github.com/jgraph/mxgraph/blob/master/javascript/src/js/handler/mxGraphHandler.js#L901
if (!this.livePreviewUsed && this.shape == null) {
this.shape = this.createPreviewShape(this.bounds);
}else if(this.shape != null){
console.log("mouseMove",this)
// mxLog.debug("mouseMove",this)
}
oldMove.call(this, sender, me);
}
@ -94,13 +429,15 @@ class AltiumSchematicRenderer
let oldClick = mxGraphHandler.prototype.mouseDown
mxGraphHandler.prototype.mouseDown = function(sender, me){
console.log("mouse down",sender,me)
mxLog.debug("mouse down",sender,me,this.graph.getSelectionCells())
if(this.graph.getSelectionCells().length > 0)
this.graph.clearSelection()
// https://github.com/jgraph/mxgraph/blob/master/javascript/src/js/handler/mxGraphHandler.js#L901
if(me.state != undefined){
if(me.state.cell.children != undefined){
oldClick.call(this, sender, me);
}else{
console.log(me.state.cell)
mxLog.debug(me.state.cell)
if(me.state.cell.parent != undefined){
this.graph.addSelectionCell(me.state.cell.parent)
oldClick.call(this, sender, me);
@ -108,12 +445,11 @@ class AltiumSchematicRenderer
// oldClick.call(this, sender, me);
}
}
}
let oldMouseUp = mxGraphHandler.prototype.mouseUp
mxGraphHandler.prototype.mouseUp = function(sender, me){
console.log("mouse up",sender,me)
mxGraphHandler.prototype.mouseUp = function(sender, me) {
mxLog.debug("mouse up",sender,me)
// https://github.com/jgraph/mxgraph/blob/master/javascript/src/js/handler/mxGraphHandler.js#L901
if(me.state != undefined){
if(me.state.cell.children != undefined){
@ -121,15 +457,15 @@ class AltiumSchematicRenderer
}else{
if(me.state.cell.parent != undefined){
this.graph.addSelectionCell(me.state.cell.parent)
oldMouseUp.call(this, sender, me);
// oldMouseUp.call(this, sender, me);
}
// oldClick.call(this, sender, me);
}
}
oldMouseUp.call(this, sender, me);
}
this.graph.setPanning(true);
this.graph.setConnectable(true);
this.graph.setConnectableEdges(true);
@ -152,8 +488,7 @@ class AltiumSchematicRenderer
// Adds rubberband selection
new mxRubberband(this.graph);
this.graph.addListener(mxEvent.CLICK, function(sender, evt)
{
this.graph.addListener(mxEvent.CLICK, function(sender, evt) {
var e = evt.getProperty('event'); // mouse event
var cell = evt.getProperty('cell'); // cell may be null
@ -165,8 +500,7 @@ class AltiumSchematicRenderer
});
var connectionHandlerMouseUp = this.graph.connectionHandler.mouseUp;
this.graph.connectionHandler.mouseUp = function(sender, me)
{
this.graph.connectionHandler.mouseUp = function(sender, me) {
if (this.first != null && this.previous != null)
{
var point = mxUtils.convertPoint(this.graph.container, me.getX(), me.getY());
@ -177,7 +511,7 @@ class AltiumSchematicRenderer
{
// Selects edges in non-wire mode for single clicks, but starts
// connecting for non-edges regardless of wire-mode
console.log("sss")
mxLog.debug("sss")
return;
}
@ -192,13 +526,26 @@ class AltiumSchematicRenderer
// incoming/outgoing direction.
this.graph.getAllConnectionConstraints = function(terminal) {
var geo = (terminal != null) ? this.getCellGeometry(terminal.cell) : null;
console.log("getAllConnectionConstraints ",terminal)
if ((geo != null ? !geo.relative : false) &&
this.getModel().isVertex(terminal.cell) &&
this.getModel().getChildCount(terminal.cell) == 0)
{
return [
new mxConnectionConstraint(new mxPoint(1, 0.5), false)];
if(terminal.cell.Pin == true){ // a pin
mxLog.debug("getAllConnectionConstraints ",terminal.cell.angle)
if(terminal.cell.angle == 90){
return [new mxConnectionConstraint(new mxPoint(0,0), false)];
}else if(terminal.cell.angle == 180){
return [new mxConnectionConstraint(new mxPoint(0,0), false)];
}else if(terminal.cell.angle == 270){
return [new mxConnectionConstraint(new mxPoint(1, 0), false)];
}else{
return [new mxConnectionConstraint(new mxPoint(1, 0), false)];
}
}
}
if((geo != null) && (this.getModel.isEdge(terminal.cell))){
console.log(terminal.cell)
}
return null;
};
@ -216,6 +563,8 @@ class AltiumSchematicRenderer
}
};
var parent = this.graph.getDefaultParent();
mxVertexHandler.prototype.livePreview = true;
@ -358,7 +707,7 @@ class AltiumSchematicRenderer
// var obj2 = this.graph.getCellAt(obj.points[obj.points.length - 1].x,
// obj.points[obj.points.length - 1].y,parent)
// console.log(obj1,obj2)
// mxLog.debug(obj1,obj2)
// // if (!this.#shouldShow(obj)) continue;
// // ctx.strokeStyle = this.#altiumColourToHex(obj.colour);
@ -425,7 +774,7 @@ class AltiumSchematicRenderer
obj.top = 840 - obj.top
obj.bottom = 840 - obj.bottom
if(!obj.transparent){
console.log('verticalLabelPosition=top;verticalAlign=bottom;fillColor='
mxLog.debug('verticalLabelPosition=top;verticalAlign=bottom;fillColor='
+ this.#altiumColourToHex(obj.attributes.areacolor))
let v1 = this.graph.insertVertex(parent, null, '',
obj.left, obj.top,
@ -516,7 +865,7 @@ class AltiumSchematicRenderer
}
obj.y = 840 - obj.y
// console.log(style)
// mxLog.debug(style)
var v11 = this.graph.insertVertex(parent, null, name, obj.x, obj.y,
obj.length, 1,
style);
@ -525,7 +874,10 @@ class AltiumSchematicRenderer
if(chips[obj.owner_record_index] == undefined){
chips[obj.owner_record_index] = []
}
console.log(v11.geometry.getTerminalPoint (true))
v11.Pin = true
v11.angle = obj.angle
v11.length = obj.length
mxLog.debug(v11.geometry.getTerminalPoint (true))
chips[obj.owner_record_index].push(v11)
// v11.geometry.offset = new mxPoint(-v11.geometry.width, 2); // ctx.strokeStyle = "#000000";
@ -569,7 +921,7 @@ class AltiumSchematicRenderer
obj.x2 = 840 - obj.x2
obj.y2 = 840 - obj.y2
style = 'shape=polyline;strokeColor=#0000ff;'
// console.log(style)
// mxLog.debug(style)
var v11 = this.graph.insertVertex(parent, null, '', obj.x1, obj.x2,
1,1,style);
v11.points = [new mxPoint(obj.y1 - obj.x1,obj.y2 - obj.x2)]
@ -629,7 +981,7 @@ class AltiumSchematicRenderer
obj.x2 = 840 - obj.x2
obj.y2 = 840 - obj.y2
style = 'shape=polygon;strokeColor=#0000ff;'
// console.log(style)
// mxLog.debug(style)
var v11 = this.graph.insertVertex(parent, null, '', obj.points[0], obj.points[0],
1,1,style);
@ -661,17 +1013,6 @@ class AltiumSchematicRenderer
// ctx.lineWidth = 1;
}
for (let obj of doc.objects.filter((o) => o instanceof AltiumJunction))
{
obj = obj
// if (!this.#shouldShow(obj)) continue;
// ctx.fillStyle = this.#altiumColourToHex(obj.colour);
// ctx.beginPath();
// ctx.ellipse(obj.x, obj.y, 5, 4, 0, 0, 2*Math.PI);
// ctx.fill();
}
for (let obj of doc.objects.filter((o) => o instanceof AltiumPowerPort))
{
@ -771,10 +1112,10 @@ class AltiumSchematicRenderer
{
obj.y = 840 - obj.y
if(obj.text != undefined){
console.log(obj.text.length)
mxLog.debug(obj.text.length)
var v11 = this.graph.insertVertex(parent, null, obj.text, obj.x, obj.y - 4,
obj.text.length*9/2, 0,
"shape=label;fontSize=9;");
"shape=label;fontSize=6;");
v11.geometry.relative = false;
v11.setConnectable(false);
if(obj.owner_record_index != 1)
@ -803,8 +1144,8 @@ class AltiumSchematicRenderer
obj = obj
obj.y = 840 - obj.y
if(obj.text != undefined){
console.log(obj.text.length)
var v11 = this.graph.insertVertex(parent, null, obj.text, obj.x, obj.y - 4,
mxLog.debug(obj.text.length)
var v11 = this.graph.insertVertex(parent, null, obj.text, obj.x, obj.y - 5,
obj.text.length*9/2, 0,
"shape=label;fontSize=9;");
v11.geometry.relative = false;
@ -812,14 +1153,7 @@ class AltiumSchematicRenderer
if(obj.owner_record_index != 1)
chips[obj.owner_record_index].push(v11)
}
// if (!this.#shouldShow(obj)) continue;
// if (obj.hidden)
// continue;
// ctx.textAlign = ["left", "left", "right", "right"][obj.orientation];
// ctx.textBaseline = ["bottom", "bottom", "top", "top"][obj.orientation];
// ctx.fillStyle = this.#altiumColourToHex(obj.colour);
// ctx.fillText(obj.full_designator, obj.x, canvas.height - obj.y);
}
// ctx.textAlign = "left";
// ctx.textBaseline = "bottom";
@ -1000,14 +1334,22 @@ class AltiumSchematicRenderer
}
}
var e6 = this.graph.insertEdge(parent, null, '')
var e6 = this.graph.insertEdge(parent, null, '',null,null,'fillColor=fff2ff,startArrow=oval')
e6.geometry.points = poi
e6.geometry.setTerminalPoint(new mxPoint(obj.points[0].x, obj.points[0].y), true)
e6.geometry.setTerminalPoint(new mxPoint(obj.points[obj.points.length - 1].x,
obj.points[obj.points.length - 1].y), false)
if(this.wires == undefined){
this.wires = []
this.wires.push(e6)
}else{
this.wires.push(e6)
}
// if (!this.#shouldShow(obj)) continue;
// ctx.strokeStyle = this.#altiumColourToHex(obj.colour);
@ -1020,9 +1362,34 @@ class AltiumSchematicRenderer
// }
// ctx.stroke();
}
for (let i in chips){
let chip = this.graph.groupCells(null,0,chips[i])
chip.setStyle("border=0;strokeColor=none")
// find the junction on the wire
for (let obj of doc.objects.filter((o) => o instanceof AltiumJunction))
{
obj.y = 840 - obj.y
let found = false
for(let i = 0;i < this.wires.length;i++){
for(let j = 0;j < this.wires[i].geometry.points.length;j++){
if((this.wires[i].geometry.points[j].x == obj.x)
&&(this.wires[i].geometry.points[j].y == obj.y)){
found = true
// this.wires[i].geometry.points.push(new mxPoint(obj.x,obj.y))
// this.wires[i].geometry.points.push(obj.x,obj.y)
}
}
}
// obj = obj
// obj.y = 840 - obj.y
// let edge = this.graph.getCellsBeyond(obj.x,obj.y)
// mxLog.debug(edge)
var v11 = this.graph.insertVertex(parent, null, '', obj.x - 1, obj.y - 1,
1,1,'');
for (let i in chips){
let chip = this.graph.groupCells(null,0,chips[i])
chip.setStyle("border=0;strokeColor=none")
}
}
}
finally{