D3 的3d图

LCF

http://mathworld.wolfram.com/LCFNotation.html



http://selection.datavisualization.ch/

地图
http://kartograph.org/
http://kartograph.org/showcase/italia/


3d
http://bl.ocks.org/1703449

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <title>Cubic Hamiltonian Graphs from LCF Notation</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.min.js"></script>
    <script type="text/javascript" src="http://mbostock.github.com/d3/d3.v2.min.js"></script>
    <script type="text/javascript" src="http://jcaret.googlecode.com/files/jquery.caret.1.02.min.js"></script>
    <link rel="stylesheet" href="http://current.bootstrapcdn.com/bootstrap-v204/css/bootstrap.min.css">
    <style type="text/css">
body {
  margin-left: 10px;
}
circle {
  stroke: #999;
  stroke-opacity: .5;
}
.link {
  stroke: #999;
}
    </style>
  </head>
  <body>
  <div class="row">
    <div class="span3">
      <div class="form" style="background-color:white">
        <label for="lcfCodes">Preset LCF Codes</label>
        <select id="lcfCodes">
          <option></option>
          <option value="[2]4">Tetrahedral graph</option>
          <option value="[3]6">Utility graph</option>
          <option value="[3,-3]4">Cubical graph</option>
          <option value="[4]8">Wagner graph</option>
          <option value="[6,4,-4]4">Bidiakis cube</option>
          <option value="[5,-5]6">Franklin graph</option>
          <option value="[-5,-2,-4,2,5,-2,2,5,-2,-5,4,2]">Frucht graph</option>
          <option value="[2,6,-2]4">Truncated tetrahedral graph</option>
          <option value="[5,-5]7">Heawood graph</option>
          <option value="[5,-5]8">Mobius-Kantor graph</option>
          <option value="[5,7,-7,7,-7,-5]3">Pappus graph</option>
          <option value="[5,-5,9,-9]5">Desargues graph</option>
          <option value="[10,7,4,-4,-7,10,-4,7,-7,4]2">Dodecahedral graph</option>
          <option value="[12,7,-7]8">McGee graph</option>
          <option value="[2,9,-2,2,-9,-2]4">Truncated cubical graph</option>
          <option value="[3,-7,7,-3]6">Truncated octahedral graph</option>
          <option value="[5,-9,7,-7,9,-5]4">Nauru graph</option>
          <option value="[-7, 7]13">F26A graph</option>
          <option value="[-13,-9,7,-7,9,13]5">Tutte–Coxeter graph</option>
          <option value="[5,-5,13,-13]8">Dyck graph</option>
          <option value="[-25,7,-7,13,-13,25]9">Gray graph</option>
          <option value="[30, -2, 2, 21, -2, 2, 12, -2, 2, -12, -2, 2, -21, -2, 2, 30, -2, 2, -12, -2, 2, 21, -2, 2, -21, -2, 2, 12, -2, 2]2">Truncated dodecahedral graph</option>
          <option value="[-29,-19,-13,13,21,-27,27,33,-13,13,19,-21,-33,29]5">Harries graph</option>
          <option value="[9, 25, 31, -17, 17, 33, 9, -29, -15, -9, 9, 25, -25, 29, 17, -9, 9, -27, 35, -9, 9, -17, 21, 27, -29, -9, -25, 13, 19, -9, -33, -17, 19, -31, 27, 11, -25, 29, -33, 13, -13, 21, -29, -21, 25, 9, -11, -19, 29, 9, -27, -19, -13, -35, -9, 9, 17, 25, -9, 9, 27, -27, -21, 15, -9, 29, -29, 33, -9, -25]">Harries–Wong graph</option>
          <option value="[-9, -25, -19, 29, 13, 35, -13, -29, 19, 25, 9, -29, 29, 17, 33, 21, 9,-13, -31, -9, 25, 17, 9, -31, 27, -9, 17, -19, -29, 27, -17, -9, -29, 33, -25,25, -21, 17, -17, 29, 35, -29, 17, -17, 21, -25, 25, -33, 29, 9, 17, -27, 29, 19, -17, 9, -27, 31, -9, -17, -25, 9, 31, 13, -9, -21, -33, -17, -29, 29]">Balaban 10-cage</option>
          <option value="[17,-9,37,-37,9,-17]15">Foster graph</option>
          <option value="[16, 24, -38, 17, 34, 48, -19, 41, -35, 47, -20, 34, -36, 21, 14, 48, -16, -36, -43, 28, -17, 21, 29, -43, 46, -24, 28, -38, -14, -50, -45, 21, 8, 27, -21, 20, -37, 39, -34, -44, -8, 38, -21, 25, 15, -34, 18, -28, -41, 36, 8, -29, -21, -48, -28, -20, -47, 14, -8, -15, -27, 38, 24, -48, -18, 25, 38, 31, -25, 24, -46, -14, 28, 11, 21, 35, -39, 43, 36, -38, 14, 50, 43, 36, -11, -36, -24, 45, 8, 19, -25, 38, 20, -24, -14, -21, -8, 44, -31, -38, -28, 37]">Biggs-Smith graph</option>
          <option value="[44, 26, -47, -15, 35, -39, 11, -27, 38, -37, 43, 14, 28, 51, -29, -16, 41, -11, -26, 15, 22, -51, -35, 36, 52, -14, -33, -26, -46, 52, 26, 16, 43, 33, -15, 17, -53, 23, -42, -35, -28, 30, -22, 45, -44, 16, -38, -16, 50, -55, 20, 28, -17, -43, 47, 34, -26, -41, 11, -36, -23, -16, 41, 17, -51, 26, -33, 47, 17, -11, -20, -30, 21, 29, 36, -43, -52, 10, 39, -28, -17, -52, 51, 26, 37, -17, 10, -10, -45, -34, 17, -26, 27, -21, 46, 53, -10, 29, -50, 35, 15, -47, -29, -41, 26, 33, 55, -17, 42, -26, -36, 16]">Balaban 11-cage</option>
          <option value="[47, -23, -31, 39, 25, -21, -31, -41, 25, 15, 29, -41, -19, 15, -49, 33, 39, -35, -21, 17, -33, 49, 41, 31, -15, -29, 41, 31, -15, -25, 21, 31, -51, -25, 23, 9, -17, 51, 35, -29, 21, -51, -39, 33, -9, -51, 51, -47, -33, 19, 51, -21, 29, 21, -31, -39]2">Ljubljana graph</option>
          <option value="[17, 27, -13, -59, -35, 35, -11, 13, -53, 53, -27, 21, 57, 11, -21, -57, 59, -17]7">Tutte 12-cage</option>
        </select>

        <label for="lcfCode">LCF Code <sup><small>[<a href="http://mathworld.wolfram.com/LCFNotation.html" target="_blank">Wolfram MathWorld</a>]</small></sup></label>
        <textarea id="lcfCode" value="" rows="3"></textarea>

        <label for="animationSpeed">Animation Speed</label>
        <select id="animationSpeed">
          <option value="0">No Animation</option>
          <option value="1">Fast</option>
          <option value="100">Slow</option>
          <option value="1000">Slowest</option>
        </select>

        <label for="lockVertices">
          <input type="checkbox" id="lockVertices" /> Lock Vertices to Circumference
        </label>
       
        <button id="redraw" class="btn btn-primary">
          <i class="icon-repeat icon-white"></i>
          Redraw
        </button>
      </div>

      <div style="position:absolute;bottom:0;z-index:-1">
        <label for="permalink">Permalink</label>
        <div class="input">
          <textarea id="permalink" disabled="disabled" rows="10" style="color:black"></textarea>
        </div>
       </div>
    </div>
    <div class="row-fluid">
      <div class="span9" id="chart"></div>
    </div>
  </div>
    <script type="text/javascript">
        //http://stackoverflow.com/a/901144/678708
        function getParameterByName(name) {
          name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
          var regexS = "[\\?&]" + name + "=([^&#]*)";
          var regex = new RegExp(regexS);
          var results = regex.exec(parent.window.location.href);
          if(results == null)
            return "";
          else
            return decodeURIComponent(results[1].replace(/\+/g, " "));
        }

        function lcfCodeToVerticesAndStepsArrayAndNumRepeats(lcfCode) {
            lcfCode = lcfCode.replace(/ /g,"").replace(/−/g,"-")
            var steps = lcfCode.match(/\[(.*?)\]/)[1]
            if(steps=="") {
                steps = []
            }else{
                steps = steps.split(',').filter(Number)
            }
            var numRepeats = parseInt(lcfCode.split(']')[1]) || 0
            return [steps.length * (numRepeats || 1), steps, numRepeats]
        }

        function getLcfChords(numVertices, stepsArray, numRepeats){
            var numSteps = stepsArray.length;
            if(numRepeats < 0) throw "Repeats must be positive"
            if(numSteps < 1) throw "Must have at least one step"

            var numChords = numSteps*numRepeats,
                chords = [];

            for(var chord=1; chord<=numChords; chord++){
                chords.push({source: chord % numVertices, target: (numVertices+chord+stepsArray[chord % numSteps]) % numVertices});
            }

            return chords;
        }

var w = $(window).width() - 230,
    h = $(window).height() - 5,
    rcx = w/2,
    rcy = h/2,
    radius = 245,
    numVertices = 0,
    colors = d3.scale.category10().range(),
    //the node with index 0 is fixed to the center and has a high charge
    nodes = [],
    links = [],
    lcfStepsAndRepeats = [],
    stepsArray = [],
    lcfChords,
    animationSpeed = 0,
    interval = null,
    lockVertices = true;

function draw(numVertices, stepsArray, numRepeats){
    clearInterval(interval)
    lcfChords = getLcfChords(numVertices, stepsArray, numRepeats)
    if(lcfChords.length > 500){
        if(!confirm('More than 500 chords will be drawn. Continue?')) return
    }
    links = []
    nodes = [{fixed: true, x: w/2, y:h/2}].concat(d3.range(numVertices).map(function(d, i) { return {x:rcx+radius*Math.cos((i*2*Math.PI/numVertices) - Math.PI/2), y:rcy+radius*Math.sin((i*2*Math.PI/numVertices) - Math.PI/2)}; }))

    nodes.slice(1).forEach(function(target, i) {
        var node = nodes[i == nodes.length - 2 ? 1 : i+2],
            x = target.x - node.x,
            y = target.y - node.y;
        links.push({source: node, target: target, linkDistance:0});
    });

    var currentVertex = 0
    var currentVertexOffset = 0
    function animateLcf() {
        var stepInstruction = stepsArray[currentVertex % stepsArray.length]
        var currentStep = (currentVertex + currentVertexOffset) - numVertices * Math.floor((currentVertex + currentVertexOffset) / numVertices)
        if(currentVertexOffset == 0){
            svg.selectAll("circle").filter(function(d,i){return currentVertex == currentStep}).style("fill", colors[1])
            svg.selectAll("circle").filter(function(d,i){return currentVertex > i}).style("fill",colors[0])
            svg.selectAll("circle").filter(function(d,i){return currentVertex < i}).style("fill","white")
            currentVertexOffset += (stepInstruction > 0 ? 1 : -1);
        }else if(currentVertexOffset != stepInstruction){
            svg.selectAll("circle").filter(function(d,i){return currentStep == i}).style("fill",colors[1])
            currentVertexOffset += (stepInstruction > 0 ? 1 : -1)
        }else{
            svg.selectAll("circle").filter(function(d,i){return currentStep == i}).style("fill",colors[1])
            links.push({source: nodes.slice(1)[currentVertex], target: nodes.slice(1)[currentStep]});
            drawLines()
            currentVertex++
            currentVertexOffset = 0;
        }
        if(currentVertex != numVertices){
            if($("#animationSpeed").val() == 0){
                animateLcf()
            }else{
                interval = setTimeout(animateLcf, $("#animationSpeed").val())
            }
        } else {
            interval = null
            svg.selectAll("circle").style("fill",colors[0])
        }

        if(!lockVertices) {
            force.links(links)
            force.start()
        }
    }

    force.nodes(nodes)
    force.start()
    drawLines()
    drawCircles()
    if($("#animationSpeed").val() == 0){
        animateLcf()
    }else{
        interval = setTimeout(animateLcf, $("#animationSpeed").val())
    }
}

function getValuesAndDraw(){
    savePermalink();
    lcfStepsAndRepeats = lcfCodeToVerticesAndStepsArrayAndNumRepeats($("#lcfCode").val())
    draw(lcfStepsAndRepeats[0], lcfStepsAndRepeats[1], lcfStepsAndRepeats[2])
}

var force = d3.layout.force()
    .charge(function(d, i) { return lockVertices ? (i ? -1 : -6000) : (i ? -100 : 0) })
    .size([w, h]);

var svg = d3.select("#chart").append("svg:svg")
    .attr("width", w)
    .attr("height", h);

$("#lcfCodes").bind('change keyup', function(){
    $("#lcfCode").val($(this).val());
    getValuesAndDraw();
})

$("#lcfCode").bind('keydown mousewheel', function(e){
    if (event.which == 38 || event.which == 40 || event.type == 'mousewheel') {
        e.preventDefault();
        val = $(this).val();
        cursorIndex = $(this).caret().start;
        cursorString = [val.slice(0, cursorIndex), 'CURSOR', val.slice(cursorIndex)].join('');
        re = /(-?\d*)CURSOR\s*(-?\d*)/g
        matches = re.exec(cursorString);
        result = parseInt(matches[1] + matches[2]) + (event.which == 40 || event.wheelDelta < 0 ? -1 : 1);
        if(!isNaN(result)){
            $(this).val(cursorString.replace(re, result));
        }
        $(this).caret(matches.index, matches.index);
    }
    if($.inArray(e.keyCode, [9, 17, 18, 32, 37, 39, 188]) == -1) {
        getValuesAndDraw();
    }
});

$("#animationSpeed").change(function(){
    getValuesAndDraw();
})

$("#lockVertices").change(function(){
    lockVertices = $(this).is(":checked")
    getValuesAndDraw()
})

$("#redraw").click(getValuesAndDraw)

function setDefaultValues(){
    $("#lockVertices").attr('checked', parseInt(getParameterByName('lockVertices')) != 1 ?  null : 'checked')
    lockVertices = $("#lockVertices").is(":checked")
    $("#animationSpeed").val(getParameterByName('animationSpeed') == '' ? 1 : getParameterByName('animationSpeed'))
    var urlLcfCode = getParameterByName('lcfCode')
    if(urlLcfCode){
        $("#lcfCode").val(urlLcfCode)
        getValuesAndDraw();
    }else{
        $("#lcfCodes").val("[30, -2, 2, 21, -2, 2, 12, -2, 2, -12, -2, 2, -21, -2, 2, 30, -2, 2, -12, -2, 2, 21, -2, 2, -21, -2, 2, 12, -2, 2]2").trigger("change")
    }
}

function savePermalink(){
    $("#permalink").val(window.parent.location.origin + window.parent.location.pathname + "?lcfCode="+$("#lcfCode").val()+"&animationSpeed="+$("#animationSpeed").val()+"&lockVertices="+($("#lockVertices").is(":checked")?'1':'0'))
}

setDefaultValues();

function drawCircles() {
    circles = svg.selectAll("circle")
        .data(nodes.slice(1))
    circles.enter()
        .append("svg:circle")
        .attr("r", 5)
        .style("fill", "white")
        .text(function(d, i){return i})
        .call(force.drag);
    circles.exit().remove();
}
function drawLines(){
    lines = svg.selectAll("line.link")
        .data(links)
    lines.enter().insert("svg:line", "circle.node")
        .attr("class", "link")
        .attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; })
        .attr("drawn", 1);
    lines.exit().remove()
}

force.on("tick", function(e) {
    svg.selectAll("circle")
       .attr("cx", function(d) { return d.x; })
       .attr("cy", function(d) { return d.y; });

    svg.selectAll("line.link")
       .attr("x1", function(d) { return d.source.x; })
       .attr("y1", function(d) { return d.source.y; })
       .attr("x2", function(d) { return d.target.x; })
       .attr("y2", function(d) { return d.target.y; });
});
    </script>
  </body>
</html>

猜你喜欢

转载自haoningabc.iteye.com/blog/1679424
D3