{"id":49616,"date":"2026-11-06T11:10:44","date_gmt":"2026-11-06T03:10:44","guid":{"rendered":"https:\/\/www.qiusir.com\/?p=49616"},"modified":"2026-11-06T11:12:18","modified_gmt":"2026-11-06T03:12:18","slug":"qiutopia3d%e6%9d%8e%e8%90%a8%e8%8c%b9%e5%9b%be","status":"publish","type":"post","link":"https:\/\/www.qiusir.com\/?p=49616","title":{"rendered":"qiutopIA:3D\u674e\u8428\u8339\u56fe"},"content":{"rendered":"\r\n<div class=\"qiutopia-lissajous-3d\" style=\"max-width: 680px; margin: 30px auto; font-family: 'Times New Roman', Times, Georgia, serif; background: #ffffff; color: #111; border: 1.5px solid #222; box-sizing: border-box; user-select: none;\">\r\n\r\n  <!-- \u9876\u90e8\u72b6\u6001\u680f -->\r\n  <div style=\"padding: 8px 16px; border-bottom: 1.2px solid #222; display: flex; justify-content: space-between; align-items: baseline; background: #fafafa; font-size: 13px;\">\r\n    <span style=\"font-weight: bold; font-style: italic;\">3D Lissajous Knot<\/span>\r\n    <div><span style=\"font-style: italic; color: #555;\">\u03c9\u2081 : \u03c9\u2082 : \u03c9\u2083<\/span> = <strong class=\"q-ratio\" style=\"font-variant-numeric: tabular-nums;\">3 : 2 : 5<\/strong><\/div>\r\n  <\/div>\r\n\r\n  <!-- 3D \u6e32\u67d3\u4e3b\u89c6\u7a97 -->\r\n  <div style=\"position: relative; width: 100%; height: 440px; background: #ffffff; line-height: 0;\">\r\n    <div class=\"q-wrap\" style=\"width: 100%; height: 100%;\"><\/div>\r\n    <div style=\"position: absolute; top: 8px; left: 12px; font-size: 11px; font-style: italic; color: #888; pointer-events: none;\">Drag to rotate \/ Scroll to zoom<\/div>\r\n  <\/div>\r\n\r\n  <!-- \u5e95\u90e8\u6ed1\u5757\u63a7\u5236\u680f -->\r\n  <div style=\"padding: 10px 16px; border-top: 1.2px solid #222; background: #fafafa; display: grid; grid-template-columns: repeat(3, 1fr) 1.2fr; gap: 12px; font-size: 12px;\">\r\n    <div>\r\n      <div style=\"display: flex; justify-content: space-between; margin-bottom: 2px;\">\r\n        <span style=\"font-style: italic; color: #555;\">\u03c9\u2081 (X)<\/span>\r\n        <strong class=\"q-w1-lbl\">3<\/strong>\r\n      <\/div>\r\n      <input type=\"range\" class=\"q-w1\" min=\"1\" max=\"6\" step=\"1\" value=\"3\" style=\"width: 100%; cursor: pointer; accent-color: #222;\">\r\n    <\/div>\r\n    <div>\r\n      <div style=\"display: flex; justify-content: space-between; margin-bottom: 2px;\">\r\n        <span style=\"font-style: italic; color: #555;\">\u03c9\u2082 (Y)<\/span>\r\n        <strong class=\"q-w2-lbl\">2<\/strong>\r\n      <\/div>\r\n      <input type=\"range\" class=\"q-w2\" min=\"1\" max=\"6\" step=\"1\" value=\"2\" style=\"width: 100%; cursor: pointer; accent-color: #222;\">\r\n    <\/div>\r\n    <div>\r\n      <div style=\"display: flex; justify-content: space-between; margin-bottom: 2px;\">\r\n        <span style=\"font-style: italic; color: #555;\">\u03c9\u2083 (Z)<\/span>\r\n        <strong class=\"q-w3-lbl\">5<\/strong>\r\n      <\/div>\r\n      <input type=\"range\" class=\"q-w3\" min=\"1\" max=\"6\" step=\"1\" value=\"5\" style=\"width: 100%; cursor: pointer; accent-color: #222;\">\r\n    <\/div>\r\n    <div>\r\n      <div style=\"display: flex; justify-content: space-between; margin-bottom: 2px;\">\r\n        <span style=\"font-style: italic; color: #555;\">Phase \u03b4\u2081 (X)<\/span>\r\n        <strong class=\"q-d1-lbl\">0.30 \u03c0<\/strong>\r\n      <\/div>\r\n      <input type=\"range\" class=\"q-d1\" min=\"0\" max=\"2\" step=\"0.05\" value=\"0.3\" style=\"width: 100%; cursor: pointer; accent-color: #222;\">\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<script>\r\n(function() {\r\n  function loadThree(cb) {\r\n    if (window.THREE && window.THREE.Scene) return cb();\r\n    var s = document.createElement('script');\r\n    s.src = 'https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/three.js\/r128\/three.min.js';\r\n    s.onload = cb;\r\n    document.head.appendChild(s);\r\n  }\r\n\r\n  function run() {\r\n    var boxes = document.querySelectorAll('.qiutopia-lissajous-3d');\r\n    var root = boxes[boxes.length - 1];\r\n    if (!root) return;\r\n\r\n    var wrap = root.querySelector('.q-wrap');\r\n    if (!wrap || wrap.clientWidth === 0) {\r\n      setTimeout(run, 60);\r\n      return;\r\n    }\r\n\r\n    var w1In = root.querySelector('.q-w1'), w2In = root.querySelector('.q-w2'), w3In = root.querySelector('.q-w3'), d1In = root.querySelector('.q-d1');\r\n    var w1Lbl = root.querySelector('.q-w1-lbl'), w2Lbl = root.querySelector('.q-w2-lbl'), w3Lbl = root.querySelector('.q-w3-lbl'), d1Lbl = root.querySelector('.q-d1-lbl');\r\n    var ratioLbl = root.querySelector('.q-ratio');\r\n\r\n    var L = 2.4, t = 0;\r\n    var scene = new THREE.Scene();\r\n    scene.background = new THREE.Color(0xffffff);\r\n\r\n    var cam = new THREE.PerspectiveCamera(35, wrap.clientWidth \/ wrap.clientHeight, 0.1, 100);\r\n    var theta = Math.PI \/ 4, phi = Math.PI \/ 6.5, rad = 9.4;\r\n\r\n    function updateCam() {\r\n      cam.position.set(rad * Math.cos(phi) * Math.sin(theta), rad * Math.sin(phi), rad * Math.cos(phi) * Math.cos(theta));\r\n      cam.lookAt(0, 0, 0);\r\n    }\r\n    updateCam();\r\n\r\n    var ren = new THREE.WebGLRenderer({ antialias: true });\r\n    ren.setSize(wrap.clientWidth, wrap.clientHeight);\r\n    ren.setPixelRatio(window.devicePixelRatio || 1);\r\n    wrap.innerHTML = '';\r\n    wrap.appendChild(ren.domElement);\r\n\r\n    \/\/ \u7ecf\u5178\u767d\u63cf\u7ebf\u6846\u76d2\r\n    scene.add(new THREE.LineSegments(\r\n      new THREE.EdgesGeometry(new THREE.BoxBufferGeometry(2 * L, 2 * L, 2 * L)),\r\n      new THREE.LineBasicMaterial({ color: 0xe0e0e0 })\r\n    ));\r\n\r\n    \/\/ \u4e2d\u95f4 3D \u66f2\u7ebf\u52a0\u91cd\uff08\u91c7\u7528 Tube \u5b9e\u4f53\u7ba1\u9053\u7f51\u683c\uff0c\u7c97\u5b9e\u7eaf\u9ed1\u4e14\u4e0d\u53d7\u539f\u751f WebGL \u7ebf\u5bbd 1px \u9650\u5236\uff09\r\n    var tubeMat = new THREE.MeshBasicMaterial({ color: 0x050505 });\r\n    var tubeMesh = new THREE.Mesh(new THREE.BufferGeometry(), tubeMat);\r\n    scene.add(tubeMesh);\r\n\r\n    \/\/ \u4e09\u58c1\u9762\u6295\u5f71\u7ebf\uff08\u4fdd\u6301\u6de1\u58a8\u8272\uff0c\u886c\u6258\u4e2d\u95f4\u52a0\u91cd\u5b9e\u5fc3\u8f68\u8ff9\uff09\r\n    var pMat = new THREE.LineBasicMaterial({ color: 0x888888, transparent: true, opacity: 0.7 });\r\n    var prjXY = new THREE.Line(new THREE.BufferGeometry(), pMat);\r\n    var prjXZ = new THREE.Line(new THREE.BufferGeometry(), pMat);\r\n    var prjYZ = new THREE.Line(new THREE.BufferGeometry(), pMat);\r\n    scene.add(prjXY, prjXZ, prjYZ);\r\n\r\n    \/\/ \u52a8\u70b9\u4e0e\u7a7a\u95f4\u6b63\u4ea4\u5f15\u7ebf\r\n    var dotGeo = new THREE.SphereGeometry(0.065, 12, 12);\r\n    var mXY = new THREE.Mesh(dotGeo, new THREE.MeshBasicMaterial({ color: 0x444444 }));\r\n    var mXZ = new THREE.Mesh(dotGeo, new THREE.MeshBasicMaterial({ color: 0x444444 }));\r\n    var mYZ = new THREE.Mesh(dotGeo, new THREE.MeshBasicMaterial({ color: 0x444444 }));\r\n    var m3D = new THREE.Mesh(new THREE.SphereGeometry(0.095, 16, 16), new THREE.MeshBasicMaterial({ color: 0x000000 }));\r\n    var guides = new THREE.LineSegments(new THREE.BufferGeometry(), new THREE.LineDashedMaterial({ color: 0x888888, dashSize: 0.15, gapSize: 0.1, transparent: true, opacity: 0.45 }));\r\n    scene.add(mXY, mXZ, mYZ, m3D, guides);\r\n\r\n    function updateMesh() {\r\n      var w1 = parseFloat(w1In.value), w2 = parseFloat(w2In.value), w3 = parseFloat(w3In.value), d1 = parseFloat(d1In.value) * Math.PI;\r\n      w1Lbl.textContent = w1;\r\n      w2Lbl.textContent = w2;\r\n      w3Lbl.textContent = w3;\r\n      d1Lbl.textContent = parseFloat(d1In.value).toFixed(2) + ' \u03c0';\r\n      ratioLbl.textContent = w1 + ' : ' + w2 + ' : ' + w3;\r\n\r\n      var pts = [], pXY = [], pXZ = [], pYZ = [], N = 600;\r\n      for (var i = 0; i <= N; i++) {\r\n        var u = (i \/ N) * Math.PI * 2;\r\n        var x = L * Math.sin(w1 * u + d1), y = L * Math.sin(w2 * u), z = L * Math.sin(w3 * u);\r\n        pts.push(new THREE.Vector3(x, y, z));\r\n        pXY.push(new THREE.Vector3(x, y, -L));\r\n        pXZ.push(new THREE.Vector3(x, -L, z));\r\n        pYZ.push(new THREE.Vector3(-L, y, z));\r\n      }\r\n\r\n      \/\/ \u7528\u6837\u6761\u66f2\u7ebf\u4e0e TubeGeometry \u751f\u6210\u771f\u6b63\u5177\u5907\u539a\u5ea6\u7684\u7c97\u58a8\u7ebf (\u534a\u5f84 0.024)\r\n      var path = new THREE.CatmullRomCurve3(pts, true);\r\n      if (tubeMesh.geometry) tubeMesh.geometry.dispose();\r\n      tubeMesh.geometry = new THREE.TubeBufferGeometry(path, 400, 0.024, 6, true);\r\n\r\n      prjXY.geometry.setFromPoints(pXY);\r\n      prjXZ.geometry.setFromPoints(pXZ);\r\n      prjYZ.geometry.setFromPoints(pYZ);\r\n    }\r\n\r\n    function loop() {\r\n      requestAnimationFrame(loop);\r\n      t += 0.015;\r\n      var w1 = parseFloat(w1In.value), w2 = parseFloat(w2In.value), w3 = parseFloat(w3In.value), d1 = parseFloat(d1In.value) * Math.PI;\r\n      var x = L * Math.sin(w1 * t + d1), y = L * Math.sin(w2 * t), z = L * Math.sin(w3 * t);\r\n\r\n      m3D.position.set(x, y, z);\r\n      mXY.position.set(x, y, -L);\r\n      mXZ.position.set(x, -L, z);\r\n      mYZ.position.set(-L, y, z);\r\n\r\n      guides.geometry.setFromPoints([\r\n        new THREE.Vector3(x, y, -L), new THREE.Vector3(x, y, z),\r\n        new THREE.Vector3(-L, y, z), new THREE.Vector3(x, y, z),\r\n        new THREE.Vector3(x, -L, z), new THREE.Vector3(x, y, z)\r\n      ]);\r\n      guides.computeLineDistances();\r\n\r\n      ren.render(scene, cam);\r\n    }\r\n\r\n    \/\/ \u9f20\u6807\u4ea4\u4e92\u63a7\u5236\r\n    var drag = false, px = 0, py = 0;\r\n    wrap.addEventListener('mousedown', function(e) { drag = true; px = e.clientX; py = e.clientY; });\r\n    window.addEventListener('mousemove', function(e) {\r\n      if (!drag) return;\r\n      theta -= (e.clientX - px) * 0.008;\r\n      phi = Math.max(-1.45, Math.min(1.45, phi + (e.clientY - py) * 0.008));\r\n      px = e.clientX; py = e.clientY;\r\n      updateCam();\r\n    });\r\n    window.addEventListener('mouseup', function() { drag = false; });\r\n    wrap.addEventListener('wheel', function(e) {\r\n      e.preventDefault();\r\n      rad = Math.max(4.5, Math.min(16.0, rad + e.deltaY * 0.005));\r\n      updateCam();\r\n    }, { passive: false });\r\n\r\n    window.addEventListener('resize', function() {\r\n      if (!wrap.clientWidth) return;\r\n      cam.aspect = wrap.clientWidth \/ wrap.clientHeight;\r\n      cam.updateProjectionMatrix();\r\n      ren.setSize(wrap.clientWidth, wrap.clientHeight);\r\n    });\r\n\r\n    w1In.oninput = updateMesh;\r\n    w2In.oninput = updateMesh;\r\n    w3In.oninput = updateMesh;\r\n    d1In.oninput = updateMesh;\r\n\r\n    updateMesh();\r\n    loop();\r\n  }\r\n\r\n  loadThree(run);\r\n})();\r\n<\/script>\r\n\r\n\u4ee5\u524d\u6784\u9020\u674e\u8428\u8339\u56fe\u53ef\u662f\u5e9f\u4e86\u4e0d\u5c11\u529f\u592b\uff0c\u73b0\u5728\u7684\u6f14\u793a\u597d\u8f7b\u677e~~~\r\n<blockquote class=\"wp-embedded-content\" data-secret=\"RLdwq9kE5J\"><a href=\"https:\/\/www.qiusir.com\/?p=16531\">\u674e\u8428\u8339\u56fe\u7684\u4e5d\u4e5d\u8868<\/a><\/blockquote><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; visibility: hidden;\" title=\"\u300a \u674e\u8428\u8339\u56fe\u7684\u4e5d\u4e5d\u8868 \u300b\u2014\u6c42\u5e08\u5f97\u6559\u80b2\u5b9e\u9a8c\u5ba4\" src=\"https:\/\/www.qiusir.com\/?p=16531&amp;embed=true#?secret=1YAHFmd595#?secret=RLdwq9kE5J\" data-secret=\"RLdwq9kE5J\" width=\"600\" height=\"338\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>","protected":false},"excerpt":{"rendered":"<p>3D Lissajous Knot \u03c9\u2081 : \u03c9\u2082 : \u03c9\u2083 = 3 : 2 : 5 Drag to rota &#8230; <a title=\"qiutopIA:3D\u674e\u8428\u8339\u56fe\" class=\"read-more\" href=\"https:\/\/www.qiusir.com\/?p=49616\" aria-label=\"\u9605\u8bfb qiutopIA:3D\u674e\u8428\u8339\u56fe\">\u9605\u8bfb\u66f4\u591a<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"image","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[8],"tags":[443,247],"class_list":["post-49616","post","type-post","status-publish","format-image","hentry","category-idea","tag-ai","tag-physics","post_format-post-format-image"],"_links":{"self":[{"href":"https:\/\/www.qiusir.com\/index.php?rest_route=\/wp\/v2\/posts\/49616","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.qiusir.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.qiusir.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.qiusir.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.qiusir.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=49616"}],"version-history":[{"count":9,"href":"https:\/\/www.qiusir.com\/index.php?rest_route=\/wp\/v2\/posts\/49616\/revisions"}],"predecessor-version":[{"id":49633,"href":"https:\/\/www.qiusir.com\/index.php?rest_route=\/wp\/v2\/posts\/49616\/revisions\/49633"}],"wp:attachment":[{"href":"https:\/\/www.qiusir.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=49616"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.qiusir.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=49616"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.qiusir.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=49616"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}