D3.JS删除点并同时重新索引点和线段数组

问题描述 投票:0回答:1

假设我有一个任意的点数组,即

var points = [

    //e: terminals
    //a: arm
    //s: support

    {x: 32, y: 256, t: "e"},
    {x: 250, y: 256, t: "a"},
    {x: 260, y: 256, t: "s"},
    {x: 320, y: 256, t: "a"},
    {x: 330, y: 256, t: "s"},
    {x: 128, y: 256, t: "a"},
    {x: 138, y: 256, t: "s"},
    {x: 480, y: 256, t: "e"}

];

还有另一个称为线段,它定义了这些点如何设置为一条路径:

var segments = [

    {start: 0, support: null, end: 5},
    {start: 5, support: 6, end: 1},
    {start: 1, support: 2, end: 3},
    {start: 3, support: 4, end: 7}

];

手臂点(t:“ a”)始终具有以下t:“ s”支持一个。

通过双击臂点(洋红色),代码必须删除它以及其支撑点(青色)以及重新索引点和线段数组。

例如,如果您要删除{x:128,y:256,t:“ a”}及其对{x:138,y:256,t:“ s”},则重新索引的数组必须为像这样:

var points = [

{x: 32, y: 256, t: "e"},
{x: 250, y: 256, t: "a"},
{x: 260, y: 256, t: "s"},
{x: 320, y: 256, t: "a"},
{x: 330, y: 256, t: "s"},
{x: 480, y: 256, t: "e"}

];

可变段= [

{start: 0, support: null, end: 1},
{start: 1, support: 2, end: 3},
{start: 3, support: 5, end: 5}

];

而且我可以找到一种有效的方法来进行重新索引。附带代码。

var points = [
    
    //e: terminals
    //a: arm
    //s: support
    
    {x: 32, y: 256, t: "e"},
    {x: 250, y: 256, t: "a"},
    {x: 260, y: 256, t: "s"},
    {x: 320, y: 256, t: "a"},
    {x: 330, y: 256, t: "s"},
    {x: 128, y: 256, t: "a"},
    {x: 138, y: 256, t: "s"},
    {x: 480, y: 256, t: "e"}
    
    //the fist and last points are always end ones
    
];
    
var segments = [
    
    {start: 0, support: null, end: 5},
    {start: 5, support: 6, end: 1},
    {start: 1, support: 2, end: 3},
    {start: 3, support: 4, end: 7}

];

var svg = d3.select("#container");

var path = svg.append("path")
           .attr("d", generatePath())
           .attr("stroke", "#000000")
           .attr("stroke-width", 2);
    
var node = svg.selectAll(".node")
           .data(getAllPoints())
           .enter()
           .append("circle")
           .attr("class", "node")
           .attr("cx", function(d_) { return d_.x; })
           .attr("cy", function(d_) { return d_.y; })
           .attr("r", 4)
           .attr("fill", function(d_){ 
               
               if(d_.t == "e") { return "#FF0000"; }
               else if(d_.t == "s") { return "#00FFFF"; }
               return "#FF00FF";
                                     
           })
           .on("dblclick", function(d_){
               
               if(d_.t == "a"){
                   
                   console.log("have to delete this point and its support")
                   console.log("and reindex points and segments array")
                    
                   //if there is only one pair of a/s points
                   //the solution is straight forward
                   //while first and last points are always end ones
                   
                   if(segments.length == 2){
       
                       points.splice(d_.id, 2);
                       points.forEach(function(p_, i_){ p_.id = i_; });
                       newSegments = [{start: 0, support: null, end: 1}];
                       
                   }else{
                       
                        //could find effective solution here
                        //has to work but it doesn't
                       
                        //segments.forEach(function(segment_){
                        //
                        //  if(segment_.end != d_.id){
                        //
                        //      var start = segment_.start,
                        //          support = segment_.support,
                        //          end = segment_.end;
                        //
                        //      if(start > d_.id - 2) { start -= 2; }
                        //      if(support > d_.id - 2 && support != null) { support -= 2; }
                        //      if(end > d_.id - 2) { end -= 2; }
                        //
                        //      newSegments.push({start: start, support: support, end: end})
                        //
                        //  }
                        //
                        //  points.splice(d_.id, 2);
                        //  points.forEach(function(p_, i_){ p_.id = i_; });
                        //  segments = newSegments;
    
                   }
               }
               
           })

function generatePath(){
    
    var out = "";

    segments.forEach(function(segment_, i_){
        
        if(i_ == 0) { 
            
            //skip support point
            out += "M" + points[segment_.start].x + " " + points[segment_.start].y;
            out += " L" + points[segment_.end].x + " " + points[segment_.end].y;
        
        }else{
            
            out += " L" + points[segment_.start].x + " " + points[segment_.start].y;
            out += " L" + points[segment_.support].x + " " + points[segment_.support].y;
            out += " L" + points[segment_.end].x + " " + points[segment_.end].y;
            
        }

    })

    return out;
    
}
    
function getAllPoints(){
    
    var out = [];

    points.forEach(function(point_, i_){ out.push(point_); out[out.length - 1].id = i_; });

    return out;
    
}
   
 body { margin: 0; }
        #container { 
            
            position: absolute; 
            left: 0; top: 0; 
            width: 512px; 
            height: 512px; 
            background-color: darkgray;
        
        }
<!DOCTYPE html>
<html>
<head>
    
    <meta charset="utf-8" />
    <title>D3.JS: Points chain</title>
  
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />

    <script src="https://d3js.org/d3.v4.min.js"></script>
    
    
</head>
<body>

<svg id="container" width="512" height="512"></svg>


</body>
</html>
arrays d3.js point splice reindex
1个回答
0
投票

似乎我自己找到了解决方案。

var points = [
    
    //e: terminals
    //a: arm
    //s: support
    
    {x: 32, y: 256, t: "e"},
    {x: 250, y: 256, t: "a"},
    {x: 260, y: 256, t: "s"},
    {x: 320, y: 256, t: "a"},
    {x: 330, y: 256, t: "s"},
    {x: 128, y: 256, t: "a"},
    {x: 138, y: 256, t: "s"},
    {x: 480, y: 256, t: "e"}
    
    //the fist and last points are always end ones
    
];
    
var segments = [
    
    {start: 0, support: null, end: 5},
    {start: 5, support: 6, end: 1},
    {start: 1, support: 2, end: 3},
    {start: 3, support: 4, end: 7}

];


var svg = d3.select("#container");    
    
draw();


function draw(){
    
    svg.selectAll("path").remove();
    svg.selectAll("circle").remove();
    
    var path = svg.append("path")
           .attr("d", generatePath())
           .attr("stroke", "#000000")
           .attr("stroke-width", 2);
    
var node = svg.selectAll(".node")
           .data(getAllPoints())
           .enter()
           .append("circle")
           .attr("class", "node")
           .attr("cx", function(d_) { return d_.x; })
           .attr("cy", function(d_) { return d_.y; })
           .attr("r", 4)
           .attr("fill", function(d_){ 
               
               if(d_.t == "e") { return "#FF0000"; }
               else if(d_.t == "s") { return "#00FFFF"; }
               return "#FF00FF";
                                     
           })
           .on("dblclick", function(d_){
               
               if(d_.t == "a"){
                   
                   if(segments.length == 2){
       
                       points.splice(d_.id, 2);
                       points.forEach(function(p_, i_){ p_.id = i_; });
                       segments = [{start: 0, support: null, end: 1}];
                       
                   }else{
                        
                        var newsegs = [];
                       
                        for(var i = 0; i < segments.length; i++){
                          
                          if(segments[i].end == d_.id){
                              
                              if(i < segments.length - 2){
                                  
                                  newsegs.push({

                                      start: segments[i].start,
                                      support: segments[i].support,
                                      end: segments[i + 1].end


                                  });

                                  newsegs.push({

                                      start: segments[i + 2].start,
                                      support: segments[i + 2].support,
                                      end: segments[i + 2].end


                                  });

                                  i += 2; continue;
                                  
                              }else{
                                                                    
                                  newsegs.push({

                                      start: segments[i].start,
                                      support: segments[i].support,
                                      end: segments[i + 1].end

                                  });
                                  
                                  i++; continue;
        
                              }
                              
                          }else{
                              
                              newsegs.push(segments[i]);
                              
                          }
                          
                      }
                       
                      newsegs.forEach(function(segment_){
                          
                          if(segment_.start >= d_.id) { segment_.start -= 2; }
                          if(segment_.support >= d_.id) { segment_.support -= 2; }
                          if(segment_.end >= d_.id) { segment_.end -= 2; }
                          
                      })
                       
                        segments = newsegs;
                        points.splice(d_.id, 2);
                        points.forEach(function(p_, i_){ p_.id = i_; });

                   }
                   
                   console.log(points);
                   console.log(segments);
                   draw();
               }
               
           })

    
}
function generatePath(){
    
    var out = "";

    segments.forEach(function(segment_, i_){
        
        if(i_ == 0) { 
            
            //skip support point
            out += "M" + points[segment_.start].x + " " + points[segment_.start].y;
            out += " L" + points[segment_.end].x + " " + points[segment_.end].y;
        
        }else{
            
            out += " L" + points[segment_.start].x + " " + points[segment_.start].y;
            //out += " L" + points[segment_.support].x + " " + points[segment_.support].y;
            out += " L" + points[segment_.end].x + " " + points[segment_.end].y;
            
        }

    })

    return out;
    
}
    
function getAllPoints(){
    
    var out = [];

    points.forEach(function(point_, i_){ out.push(point_); out[out.length - 1].id = i_; });

    return out;
    
}
    
    body { margin: 0; }
        #container { 
            
            position: absolute; 
            left: 0; top: 0; 
            width: 512px; 
            height: 512px; 
            background-color: darkgray;
        
        }
<!DOCTYPE html>
<html>
<head>
    
    <meta charset="utf-8" />
    <title>D3.JS: Points chain</title>
  
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />

    
    <script src="https://d3js.org/d3.v4.min.js"></script>
    
    
</head>
<body>

<svg id="container" width="512" height="512"></svg>

</body>
</html>
© www.soinside.com 2019 - 2024. All rights reserved.