<!DOCTYPE html><htmllang="zh-CN"><head><metacharset="UTF-8"/><metaname="viewport"content="width=device-width, initial-scale=1.0"/><title>0号块钢管桩支架三维布置 · 双塔双索面混凝土斜拉桥</title><style> * { margin:0; padding:0; box-sizing:border-box; } html,body { width:100%; height:100%; overflow:hidden; font-family:"Microsoft YaHei","PingFang SC",sans-serif; background:#eef1f5; } #container { width:100%; height:100%; } canvas { display:block; } #header { position:fixed; top:14px; left:16px; z-index:10; pointer-events:none; } #header h1 { font-size:18px; color:#2b3a4a; font-weight:700; text-shadow:0 1px 2px rgba(255,255,255,.85); } #header p { font-size:12px; color:#5a6b7d; margin-top:4px; text-shadow:0 1px 2px rgba(255,255,255,.85); } #panel { position:fixed; top:14px; right:16px; z-index:10; width:236px; background:rgba(255,255,255,.94); border:1px solid #d5dce4; border-radius:10px; padding:14px 14px 12px; box-shadow:0 4px 16px rgba(30,50,80,.12); max-height:calc(100% - 40px); overflow:auto; } #panel h3 { font-size:13px; color:#33475e; margin-bottom:9px; border-bottom:1px solid #e3e8ee; padding-bottom:6px; } .legend { display:flex; align-items:center; margin-bottom:5px; font-size:12px; color:#44576a; } .legend .swatch { width:16px; height:16px; border-radius:3px; margin-right:8px; flex:none; border:1px solid rgba(0,0,0,.12); } .ctrl { display:flex; align-items:center; margin:6px 0; font-size:12px; color:#44576a; cursor:pointer; user-select:none; } .ctrl input { margin-right:7px; accent-color:#2f6fb2; cursor:pointer; } .views { display:flex; flex-wrap:wrap; gap:6px; margin-top:10px; } .views button { flex:1 1 44%; padding:6px 0; font-size:12px; border:1px solid #c3ccd6; background:#fff; color:#33475e; border-radius:6px; cursor:pointer; transition:all .15s; } .views button:hover { background:#e8f0f9; border-color:#2f6fb2; } .note { margin-top:10px; font-size:11px; color:#7a8a9c; line-height:1.7; background:#f4f7fa; border-radius:6px; padding:8px 10px; } #tip { position:fixed; bottom:14px; left:50%; transform:translateX(-50%); z-index:10; background:rgba(255,255,255,.88); border:1px solid #d5dce4; border-radius:20px; padding:6px 18px; font-size:12px; color:#5a6b7d; white-space:nowrap; pointer-events:none; box-shadow:0 2px 8px rgba(30,50,80,.08); } #load-error { display:none; position:fixed; inset:0; z-index:99; background:#f7f9fb; color:#c0392b; font-size:14px; padding:80px 40px; text-align:center; line-height:2; } #load-error code { background:#f0f2f5; padding:2px 8px; border-radius:4px; font-size:12px; } #xsect { display:none; position:fixed; left:16px; bottom:56px; z-index:10; width:330px; background:rgba(255,255,255,.97); border:1px solid #d5dce4; border-radius:10px; padding:10px 12px 8px; box-shadow:0 4px 16px rgba(30,50,80,.16); } #xsect .xs-head { font-size:13px; color:#2b3a4a; font-weight:700; margin-bottom:4px; display:flex; justify-content:space-between; align-items:center; } #xsect .xs-close { cursor:pointer; color:#8a93a3; font-size:15px; line-height:1; padding:2px 5px; border-radius:4px; } #xsect .xs-close:hover { background:#eef1f5; color:#c0392b; } #xsect svg { width:100%; height:auto; display:block; } #xsect .xs-foot { font-size:11px; color:#6b7c8e; line-height:1.65; margin-top:4px; border-top:1px dashed #d5dce4; padding-top:6px; }</style></head><body><divid="container"></div><divid="header"> <h1>全桥 456m 三维布置 · 双塔双索面混凝土斜拉桥</h1> <p>布置 (121+214+121)m · 索塔 140m×2 · 0号块 20m×2 · 悬浇段 16段×6m×4组(64段)· 边跨现浇段 13m×2 · 合拢段 2m×3 · 钢管桩支架 + 贝雷梁平台 + 挂篮 · 措施设备:塔吊×2 + 施工电梯×2 + 混凝土泵管 + 液压爬模 + 塔顶缆索吊机 + 混凝土拌合站/泵站(平均运距3km)</p></div><divid="panel"> <h3>结构图例</h3> <divclass="legend"><spanclass="swatch"style="background:#4a5f7a"></span>索塔 / 下横梁 / 上横梁(永久结构)</div> <divclass="legend"><spanclass="swatch"style="background:#7d8a99"></span>过渡墩(边跨现浇段端部支点)</div> <divclass="legend"><spanclass="swatch"style="background:#e8913a"></span>0号块 / 边跨现浇段主梁(单箱双室,半透明)</div> <divclass="legend"><spanclass="swatch"style="background:#e0453a"></span>钢管桩支架 Φ60cm×40m(视觉放大)</div> <divclass="legend"><spanclass="swatch"style="background:#8ba3b8"></span>平联(横撑,每10m一道)+剪刀撑(斜撑,四周X形)</div> <divclass="legend"><spanclass="swatch"style="background:#c96a2e"></span>索塔劲性骨架(塔肢内角钢桁架:立柱+平联+剪刀撑)</div> <divclass="legend"><spanclass="swatch"style="background:#5d7186"></span>节点板+M20螺栓(6m节段分缝处)</div> <divclass="legend"><spanclass="swatch"style="background:#f0941e"></span>上塔柱锚固区(95~140m)骨架加密段</div> <divclass="legend"><spanclass="swatch"style="background:#f2c14e"></span>贝雷梁平台(2m 高)</div> <divclass="legend"><spanclass="swatch"style="background:#3fa06b"></span>挂篮(示意)</div> <divclass="legend"><spanclass="swatch"style="background:#f0c040"></span>塔吊(附壁式,每塔1台 H≈150m)</div> <divclass="legend"><spanclass="swatch"style="background:#4db8a0"></span>施工电梯(附壁于塔柱外侧)</div> <divclass="legend"><spanclass="swatch"style="background:#d43a2f"></span>混凝土泵管(塔柱附壁竖管 + 梁面水平管)</div> <divclass="legend"><spanclass="swatch"style="background:#c8a04e"></span>液压爬模(索塔施工模板 + 爬升平台)</div> <divclass="legend"><spanclass="swatch"style="background:#ff7f2a"></span>塔顶缆索吊机(主索 + 起重小车 + 背索锚碇)</div> <divclass="legend"><spanclass="swatch"style="background:#5f8fa8"></span>混凝土拌合站 / 泵站(山谷两岸场站,运距≈3km)</div> <divclass="legend"><spanclass="swatch"style="background:#9aa4b0"></span>斜拉索(双索面)</div> <divclass="legend"><spanclass="swatch"style="background:#6fa8dc"></span>悬浇段 16段×6m×4组(单箱双室三向预应力,待施工半透明)</div> <divclass="legend"><spanclass="swatch"style="background:#e74c3c"></span>纵向预应力筋(悬浇段顶/底板内,顺桥向 Z)</div> <divclass="legend"><spanclass="swatch"style="background:#3498db"></span>横向预应力筋(悬浇段顶板内,横桥向 X)</div> <divclass="legend"><spanclass="swatch"style="background:#27ae60"></span>竖向预应力筋(悬浇段三道腹板内,竖向 Y)</div> <divclass="legend"><spanclass="swatch"style="background:#8f6fc7"></span>合拢段 2m×3处(边跨×2 / 中跨×1,最后浇筑)</div> <divclass="legend"><spanclass="swatch"style="background:#e0453a;opacity:.35"></span>塔肢 / 下横梁 / 过渡墩投影 —— 禁布桩区</div> <h3style="margin-top:12px">显示控制</h3> <labelclass="ctrl"><inputtype="checkbox"id="chk-rotate"checked/>自动旋转</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-cables"checked/>斜拉索</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-cant"checked/>挂篮</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-labels"checked/>尺寸与文字标注</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-nogo"checked/>禁布桩区高亮</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-seg"checked/>悬浇段 / 合拢段</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-seg-long"checked/>纵向预应力筋(红)</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-seg-trans"checked/>横向预应力筋(蓝)</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-seg-vert"checked/>竖向预应力筋(绿)</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-tower"/>塔柱半透明(透视后方支架)</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-brace"checked/>平联 / 剪刀撑(支撑体系)</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-frame"checked/>索塔劲性骨架(塔肢内桁架,自动透视塔柱)</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-joint"checked/>节段分缝(节点板+螺栓)</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-crane"checked/>塔吊(附壁式 ×2)</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-lift"checked/>施工电梯(附壁 ×2)</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-pump"checked/>混凝土泵管</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-form"checked/>液压爬模(索塔施工)</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-cablecrane"checked/>塔顶缆索吊机(跨峡谷吊装)</label> <labelclass="ctrl"><inputtype="checkbox"id="chk-plant"checked/>混凝土拌合站 / 泵站(运距3km)</label> <divclass="views"> <buttondata-v="整体">整体</button> <buttondata-v="正面">正面</button> <buttondata-v="侧面">侧面</button> <buttondata-v="俯视">俯视</button> <buttondata-v="近景">0号块近景</button> <buttondata-v="边跨近景">边跨近景</button> <buttondata-v="边跨合拢">边跨合拢</button> <buttondata-v="中跨合拢">中跨合拢</button> <buttondata-v="塔2近景">塔2近景</button> <buttondata-v="塔吊近景">塔吊近景</button> <buttondata-v="缆索吊近景">缆索吊近景</button> <buttondata-v="拌合站近景">拌合站近景</button> <buttondata-v="横断面">横断面剖切</button> </div> <divclass="note"><b>全桥施工布置(塔柱外置型):</b>① 两塔对称布置,塔肢中心距21m、宽3.5m,塔肢外侧与桥边齐平;每塔 0号块 20m(1200m³为全桥两塔总量 → 单塔600m³≈1560t,4排×5根Φ600钢管桩,收进塔肢内侧±5.5m,中部下横梁直承、两侧悬出段由桩承,避开塔肢/下横梁投影);② 两处边跨现浇段各13m(835m³为两处总量 → 单侧417.5m³≈1086t,3排×5根桩,一端搭过渡墩分担约1/4);③ 支撑体系:40m 高支架设 5 层平联(横撑,y=1扫地杆/11/21/31/36,约每10m一道,Φ160×5)+ 四周最外立面 X 形剪刀撑(斜撑,Φ140×5),保证整体稳定与自由长度 λ<60;④ 索塔劲性骨架(赤陶色,塔肢内):140m 高塔施工"骨架先行"——每肢 8 根立柱(四角 L125×10+边中 L100×10)+平联(L75×8)+层间X形剪刀撑,供钢筋绑扎与斜拉索锚管(±5mm)定位依附;**6m节段分缝**处设节点板(360×500×10,灰蓝)+M20×8高强螺栓(银白),节段间螺栓接长随爬模逐节上升;**上塔柱锚固区(95~140m)骨架加密**(亮橙):平联由10m/道加密为5m/道、剪刀撑同步加密,保证索锚管密集区的定位刚度(双塔骨架用钢量约185t);⑤ 悬浇段 4组×16段×6m:**单箱双室三向预应力混凝土**——顶板24.5m/底板21.4m、三道腹板(边±10.5m=索面=塔肢中心+中0m)分双室;**三向预应力**=纵向(红,顶板9+底板7+附加2束/段,抗顺桥向弯矩)+横向(蓝,顶板内@1m,抗横向弯矩)+竖向(绿,腹板内@0.6m,抗剪防斜裂缝),逐段悬浇逐段张拉;挂篮对称悬浇(10天/段,半透明=待施工);⑥ 合拢段 3处各2m(两处边跨 + 一处中跨),劲性骨架锁定 + 水箱配重 + 凌晨低温浇筑,先边跨后中跨;⑦ <b>施工措施设备(V12新增)</b>:<b>附壁式塔吊</b>×2(每塔1台,H≈150m,位于桥面右侧外侧 X=+15,塔身格构标准节 + 附墙杆每20m锚固于塔柱 + 起重臂 L=30m 朝主跨 + 平衡臂配重,负责劲性骨架/钢筋/模板/索鞍吊装);<b>施工电梯</b>×2(附壁于塔柱外侧,双导轨架 + 吊笼上下,供人员/小料运输至塔顶,140m 一次到顶);<b>混凝土泵管</b>(塔柱附壁竖管 Φ125 每10m法兰 + 梁面水平管至挂篮浇筑区,分别供应索塔与主梁 C55 混凝土);<b>液压爬模</b>(紧贴塔肢外圈 4 面板 + 顶部操作平台,随节段爬升,与劲性骨架"骨架先行"配套,浇筑→爬升→再浇筑循环至塔顶);⑧ <b>塔顶缆索吊机(V13新增)</b>:本桥跨越<b>无水山区大峡谷</b>,不设栈桥/水上钻孔平台;索塔与两岸桥台间以<b>塔顶缆索吊机</b>作为主吊运手段——两塔顶间张拉<b>主索(承重索)</b>(跨中垂度 f≈L/12≈18m),上设<b>起重小车(跑车)</b>沿索横移,吊钩下放至桥面/基坑吊装劲性骨架、钢筋笼、模板、索导管等;塔顶设<b>索鞍桁架</b>,主索两端经背索锚固于两岸<b>地锚</b>;⑨ <b>混凝土拌合站与泵站(V13新增)</b>:项目全桥混凝土采用<b>泵送施工工艺</b>,平均运距 <b>3km</b>——峡谷两岸各设<b>拌合站</b>(HZS120 双机搅拌楼 + 粉料筒仓×4 + 骨料仓 + 配料皮带机)与<b>泵站</b>(HBT90 拖泵×2),混凝土自拌合楼经地面<b>泵送管线</b>沿便道输送 3km 至桥位,接塔柱附壁竖管与梁面水平管泵送至索塔与挂篮浇筑点。</div></div><divid="xsect"> <divclass="xs-head">塔中心横断面 · 边腹板 = 索面 = 塔肢 对位关系<spanclass="xs-close"id="xs-close"title="关闭剖切">✕</span></div> <svgviewBox="0 0 300 160"xmlns="http://www.w3.org/2000/svg"> <!-- 顶板 24.5m --> <rectx="27.5"y="68"width="245"height="4"fill="#e8913a"/> <!-- 底板(箱底 21m,边腹板±10.5m) --> <rectx="45"y="104"width="210"height="4"fill="#e8913a"/> <!-- 三道腹板:-10.5m / 0m / +10.5m --> <rectx="43.5"y="68"width="3"height="40"fill="#b06a1f"/> <rectx="148.5"y="68"width="3"height="40"fill="#b06a1f"/> <rectx="253.5"y="68"width="3"height="40"fill="#b06a1f"/> <!-- 塔肢(中心±10.5m 宽3.5m,外侧到桥边±12.25m,塔梁固结嵌入主梁) --> <rectx="27.5"y="8"width="35"height="100"fill="#4a5f7a"opacity="0.88"/> <rectx="237.5"y="8"width="35"height="100"fill="#4a5f7a"opacity="0.88"/> <!-- 索面竖虚线(从塔顶到梁面锚点,与边腹板/塔肢同轴) --> <linex1="45"y1="8"x2="45"y2="68"stroke="#9aa4b0"stroke-width="1.5"stroke-dasharray="4,3"/> <linex1="255"y1="8"x2="255"y2="68"stroke="#9aa4b0"stroke-width="1.5"stroke-dasharray="4,3"/> <circlecx="45"cy="68"r="3"fill="#5c3d96"/> <circlecx="255"cy="68"r="3"fill="#5c3d96"/> <!-- 钢管桩:收进塔肢内侧 ±5.5m --> <circlecx="95"cy="122"r="4"fill="#e0453a"/> <circlecx="205"cy="122"r="4"fill="#e0453a"/> <!-- 桥宽尺寸线 24.5m --> <linex1="27.5"y1="54"x2="272.5"y2="54"stroke="#44576a"stroke-width="1"/> <linex1="27.5"y1="50"x2="27.5"y2="58"stroke="#44576a"stroke-width="1"/> <linex1="272.5"y1="50"x2="272.5"y2="58"stroke="#44576a"stroke-width="1"/> <textx="150"y="48"text-anchor="middle"font-size="11"fill="#33475e">24.5m 桥宽</text> <!-- 索面间距 21m --> <linex1="45"y1="116"x2="255"y2="116"stroke="#44576a"stroke-width="1"/> <linex1="45"y1="112"x2="45"y2="120"stroke="#44576a"stroke-width="1"/> <linex1="255"y1="112"x2="255"y2="120"stroke="#44576a"stroke-width="1"/> <textx="150"y="130"text-anchor="middle"font-size="11"fill="#33475e">21m 索面间距 = 塔肢中心距 = 边腹板间距</text> <!-- 翼缘悬挑 1.75m(在塔肢上方,端部与桥边/塔肢外侧齐平) --> <textx="36"y="92"text-anchor="middle"font-size="9.5"fill="#7a5a10">悬挑1.75m</text> <textx="264"y="92"text-anchor="middle"font-size="9.5"fill="#7a5a10">悬挑1.75m</text> <!-- 塔肢标注 --> <textx="45"y="32"text-anchor="middle"font-size="9.5"fill="#dfe7f0">塔肢</text> <textx="45"y="44"text-anchor="middle"font-size="9.5"fill="#dfe7f0">3.5m</text> <textx="255"y="32"text-anchor="middle"font-size="9.5"fill="#dfe7f0">塔肢</text> <!-- 索面标注 --> <textx="55"y="24"font-size="9.5"fill="#6b7c8e">索面</text> <textx="245"y="24"text-anchor="end"font-size="9.5"fill="#6b7c8e">索面</text> <!-- 塔梁固结说明 --> <textx="150"y="84"text-anchor="middle"font-size="10"fill="#44576a">塔梁固结 · 塔肢嵌入主梁 · 翼缘在塔肢上方</text> <!-- 钢管桩说明 --> <textx="150"y="146"text-anchor="middle"font-size="10"fill="#c0392b">钢管桩:横桥向5根/排(间距2.75m),收进两塔肢内侧(±5.5m),避开塔肢投影</text> </svg> <divclass="xs-foot">双索面斜拉桥铁律:斜拉索从塔肢出发,必须锚在能传力的主梁骨架上 → 索面锚固点、边腹板、塔肢中心三者同轴(±10.5m)。塔柱外置型:塔肢中心距21m、宽3.5m,塔肢外侧与桥边齐平(±12.25m),翼缘悬挑仅1.75m且全部在塔肢上方,与照片所示一致。</div></div><divid="tip">🖱 左键拖拽旋转 · 滚轮缩放 · 右键平移</div><divid="load-error">3D 引擎加载失败,请检查网络后刷新页面(需访问 jsdelivr / unpkg CDN)。</div><script>(function(){ var CDN = [ ['https://cdn.jsdelivr.net/npm/three@0.128.0/build/three.min.js', 'https://unpkg.com/three@0.128.0/build/three.min.js', 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js'], ['https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js', 'https://unpkg.com/three@0.128.0/examples/js/controls/OrbitControls.js'] ]; function loadScript(url){ return new Promise(function(res, rej){ var s = document.createElement('script'); s.src = url; s.onload = res; s.onerror = function(){ s.remove(); rej(new Error(url)); }; document.head.appendChild(s); }); } async function loadSeq(list){ var err; for (var i = 0; i < list.length; i++){ try { await loadScript(list[i]); return; } catch(e){ err = e; } } throw err; } async function boot(){ try { await loadSeq(CDN[0]); await loadSeq(CDN[1]); init(); } catch(e){ document.getElementById('load-error').style.display = 'block'; } } var scene, camera, renderer, controls; var groups = {}; function init(){ scene = new THREE.Scene(); scene.background = new THREE.Color(0xeef1f5); scene.fog = new THREE.Fog(0xeef1f5, 700, 1700); camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 0.1, 3000); camera.position.set(280, 190, 450); renderer = new THREE.WebGLRenderer({ antialias:true }); renderer.localClippingEnabled = true; renderer.setPixelRatio(Math.min(devicePixelRatio, 2)); renderer.setSize(innerWidth, innerHeight); document.getElementById('container').appendChild(renderer.domElement); controls = new THREE.OrbitControls(camera, renderer.domElement); controls.target.set(0, 55, 107); controls.enableDamping = true; controls.dampingFactor = 0.08; controls.autoRotate = true; controls.autoRotateSpeed = 0.9; controls.minDistance = 18; controls.maxDistance = 900; controls.maxPolarAngle = Math.PI * 0.93; addLights(); buildGround(); buildNoGoZone(); buildTower(0); // 塔1(主跨左端,Z=0) buildTower(214); // 塔2(主跨右端,Z=214) buildPier(-121); // 塔1边跨过渡墩 buildPier(335); // 塔2边跨过渡墩 buildGirder(0); // 塔1 0号块 buildGirder(214); // 塔2 0号块 buildSideGirder(-114.5, -121, -108); // 塔1边跨现浇段 buildSideGirder(328.5, 322, 335); // 塔2边跨现浇段 buildSegments(); buildClosures(); buildPiles(); buildBracing(); buildBentley(); buildCantilever(); buildCrane(0, 1); // 塔1 塔吊(起重臂朝主跨 Z+) buildCrane(214, -1); // 塔2 塔吊(起重臂朝主跨 Z-) buildLift(0); // 塔1 施工电梯 buildLift(214); // 塔2 施工电梯 buildPump(0, 1); // 塔1 混凝土泵管 buildPump(214, -1); // 塔2 混凝土泵管 buildForm(-10.5, 0); // 塔1 左肢液压爬模(施工至 y=56~62) buildForm(10.5, 214); // 塔2 右肢液压爬模 buildCableCrane(); // 塔顶缆索吊机(两塔顶间主索 + 起重小车) buildPlant(); // 混凝土拌合站 + 泵站(左岸场站,运距≈3km) buildCables(); buildLabels(); bindUI(); animate(); window.addEventListener('resize', function(){ camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); renderer.setSize(innerWidth, innerHeight); }); } function addLights(){ scene.add(new THREE.HemisphereLight(0xffffff, 0xbfc9d4, 0.85)); var d1 = new THREE.DirectionalLight(0xffffff, 0.9); d1.position.set(120, 220, 90); scene.add(d1); var d2 = new THREE.DirectionalLight(0xffffff, 0.35); d2.position.set(-90, 70, -130); scene.add(d2); } function buildGround(){ var g = new THREE.GridHelper(900, 90, 0x8fa0b3, 0xc7d0da); g.position.y = 0; scene.add(g); var plane = new THREE.Mesh( new THREE.PlaneGeometry(1400, 1400), new THREE.MeshBasicMaterial({ color:0xe2e7ec, transparent:true, opacity:0.5 }) ); plane.rotation.x = -Math.PI / 2; plane.position.y = -0.05; scene.add(plane); // 峡谷山体(示意) [[-170,-70,95,60],[165,-80,85,50],[-150,130,75,42],[180,140,100,55]].forEach(function(h){ var c = new THREE.Mesh( new THREE.ConeGeometry(h[2], h[3], 8), new THREE.MeshLambertMaterial({ color:0xa8c9a0, transparent:true, opacity:0.6 }) ); c.position.set(h[0], h[3] / 2 - 0.3, h[1]); scene.add(c); }); } function buildNoGoZone(){ groups.nogo = new THREE.Group(); var mat = new THREE.MeshBasicMaterial({ color:0xe0453a, transparent:true, opacity:0.32, depthWrite:false }); function zone(x, w, z, d){ var m = new THREE.Mesh(new THREE.PlaneGeometry(w, d), mat); m.rotation.x = -Math.PI / 2; m.position.set(x, 0.16, z); groups.nogo.add(m); // 红色虚线框 var pts = [ new THREE.Vector3(x - w/2, 0.2, z - d/2), new THREE.Vector3(x + w/2, 0.2, z - d/2), new THREE.Vector3(x + w/2, 0.2, z + d/2), new THREE.Vector3(x - w/2, 0.2, z + d/2) ]; pts.push(pts[0].clone()); var ln = new THREE.Line( new THREE.BufferGeometry().setFromPoints(pts), new THREE.LineBasicMaterial({ color:0xe0453a }) ); groups.nogo.add(ln); } // 塔1 塔肢投影(中心距21m,宽3.5m,覆盖±8.75~±12.25m,桥边±12.25m) zone(-10.5, 3.5, 0, 3.5); zone( 10.5, 3.5, 0, 3.5); // 塔2 塔肢投影 zone(-10.5, 3.5, 214, 3.5); zone( 10.5, 3.5, 214, 3.5); var mat2 = new THREE.MeshBasicMaterial({ color:0xf2a53d, transparent:true, opacity:0.28, depthWrite:false }); // 塔1 下横梁投影(宽21m) var m2 = new THREE.Mesh(new THREE.PlaneGeometry(21, 3.5), mat2); m2.rotation.x = -Math.PI / 2; m2.position.set(0, 0.12, 0); groups.nogo.add(m2); // 塔2 下横梁投影 var m2b = m2.clone(); m2b.position.z = 214; groups.nogo.add(m2b); // 塔1 过渡墩投影(Z=-122.7~-119.3) var mat3 = new THREE.MeshBasicMaterial({ color:0xe0453a, transparent:true, opacity:0.3, depthWrite:false }); var m3 = new THREE.Mesh(new THREE.PlaneGeometry(6, 3.4), mat3); m3.rotation.x = -Math.PI / 2; m3.position.set(0, 0.16, -121); groups.nogo.add(m3); var pts3 = [ new THREE.Vector3(-3, 0.2, -122.7), new THREE.Vector3( 3, 0.2, -122.7), new THREE.Vector3( 3, 0.2, -119.3), new THREE.Vector3(-3, 0.2, -119.3), new THREE.Vector3(-3, 0.2, -122.7) ]; groups.nogo.add(new THREE.Line( new THREE.BufferGeometry().setFromPoints(pts3), new THREE.LineBasicMaterial({ color:0xe0453a }) )); // 塔2 过渡墩投影(Z=+333.3~+336.7) var m4 = m3.clone(); m4.position.z = 335; groups.nogo.add(m4); var pts4 = [ new THREE.Vector3(-3, 0.2, 333.3), new THREE.Vector3( 3, 0.2, 333.3), new THREE.Vector3( 3, 0.2, 336.7), new THREE.Vector3(-3, 0.2, 336.7), new THREE.Vector3(-3, 0.2, 333.3) ]; groups.nogo.add(new THREE.Line( new THREE.BufferGeometry().setFromPoints(pts4), new THREE.LineBasicMaterial({ color:0xe0453a }) )); scene.add(groups.nogo); } function buildTower(z){ groups.tower = new THREE.Group(); var mat = new THREE.MeshPhongMaterial({ color:0x4a5f7a, side:THREE.DoubleSide }); // 塔肢:宽3.5m(覆盖±8.75~±12.25m),中心距21m(±10.5m),桥边±12.25m var pier = new THREE.Mesh(new THREE.BoxGeometry(3.5, 140, 3.5), mat); pier.position.set(-10.5, 70, z); var pier2 = pier.clone(); pier2.position.x = 10.5; groups.tower.add(pier, pier2); // 下横梁(宽21m,顶面与梁底齐平,Y=35~40) var xb = new THREE.Mesh(new THREE.BoxGeometry(21, 5, 3.5), mat); xb.position.set(0, 37.5, z); groups.tower.add(xb); // 上横梁 var ub = new THREE.Mesh(new THREE.BoxGeometry(17, 4, 3.2), mat); ub.position.set(0, 94, z); groups.tower.add(ub); // 塔顶索锚固区 var an = new THREE.Mesh(new THREE.BoxGeometry(3.1, 6, 3.2), mat); an.position.set(-10.5, 137, z); var an2 = an.clone(); an2.position.x = 10.5; groups.tower.add(an, an2); // 承台 var cf = new THREE.Mesh(new THREE.BoxGeometry(11, 4, 8), new THREE.MeshPhongMaterial({ color:0x6b7684 })); cf.position.set(-10.5, 2, z); var cf2 = cf.clone(); cf2.position.x = 10.5; groups.tower.add(cf, cf2); scene.add(groups.tower); buildSteelFrame(z); // 塔柱内劲性骨架(骨架先行,供钢筋/索锚管依附) } function buildSteelFrame(z){ // 索塔劲性骨架:塔肢空心箱形(壁厚0.7m示意),内设角钢空间桁架 // 立柱 8根/肢:四角 L125×10 + 边中 L100×10(距截面中心±1.35m,位于壁厚内) // V10细化:① 6m节段分缝处节点板+M20螺栓(独立组 frameJoints,可单独开关) // ② 上塔柱锚固区(95~140m)骨架加密:平联10m/道→5m/道、剪刀撑随之加密,亮橙高亮 groups.frame = groups.frame || new THREE.Group(); // 两塔共用同一组,开关一次控制全部 groups.frameJoints = groups.frameJoints || new THREE.Group(); var matV = new THREE.MeshPhongMaterial({ color:0xc96a2e, emissive:0x40200a }); // 立柱 赤陶橙 var matH = new THREE.MeshPhongMaterial({ color:0xb85a20, emissive:0x301705 }); // 平联 var matD = new THREE.MeshPhongMaterial({ color:0xa04a18, emissive:0x2a1404 }); // 剪刀撑 var matH2 = new THREE.MeshPhongMaterial({ color:0xf0941e, emissive:0x7a3a08 }); // 锚固区平联(加密·亮橙) var matD2 = new THREE.MeshPhongMaterial({ color:0xe07b1f, emissive:0x6a3006 }); // 锚固区剪刀撑 var matPlate = new THREE.MeshPhongMaterial({ color:0x5d7186, emissive:0x232c38 }); // 节点板 灰蓝 var matBolt = new THREE.MeshPhongMaterial({ color:0xe6ecf2, emissive:0x808a94 }); // 螺栓 银白 function bar(x1,y1,z1, x2,y2,z2, r, mat){ var dx=x2-x1, dy=y2-y1, dz=z2-z1; var len = Math.sqrt(dx*dx+dy*dy+dz*dz); if(len < 0.5) return; var m = new THREE.Mesh(new THREE.CylinderGeometry(r, r, len, 6), mat); m.position.set((x1+x2)/2, (y1+y2)/2, (z1+z2)/2); m.quaternion.setFromUnitVectors(new THREE.Vector3(0,1,0), new THREE.Vector3(dx,dy,dz).normalize()); groups.frame.add(m); } // 6m 节段分缝处的节点板(360×500×10示意) + M20×8 高强螺栓(示意4颗) function joint(x, y, z){ var pl = new THREE.Mesh(new THREE.BoxGeometry(0.12, 0.5, 0.36), matPlate); pl.position.set(x, y, z); groups.frameJoints.add(pl); var bg = new THREE.CylinderGeometry(0.035, 0.035, 0.18, 6); [[-0.11, -0.16], [0.11, -0.16], [-0.11, 0.16], [0.11, 0.16]].forEach(function(b){ var bt = new THREE.Mesh(bg, matBolt); bt.position.set(x, y + b[1], z + b[0]); bt.quaternion.setFromUnitVectors(new THREE.Vector3(0,1,0), new THREE.Vector3(1,0,0)); groups.frameJoints.add(bt); }); } // 8 根立柱位置(相对塔肢中心 ±1.35m):四角 + 四边中 var cols = [[-1.35,-1.35],[1.35,-1.35],[-1.35,1.35],[1.35,1.35],[0,-1.35],[0,1.35],[-1.35,0],[1.35,0]]; // 6m 节段划分(承台顶 y=4 → 塔顶140:4/10/16/…/136/140,共23段),分缝节点 y=10,16,…,136,140 var segH = [], nodeY = []; for(var y=4; y<140; y+=6) segH.push(y); segH.push(140); for(var y=10; y<=136; y+=6) nodeY.push(y); nodeY.push(140); [-10.5, 10.5].forEach(function(ox){ cols.forEach(function(c){ for(var k=0;k<segH.length-1;k++){ bar(ox+c[0], segH[k], z+c[1], ox+c[0], segH[k+1], z+c[1], 0.13, matV); } nodeY.forEach(function(ny){ joint(ox+c[0], ny, z+c[1]); }); }); }); // 平联:普通段每10m一道(y=5~95,10层);锚固区每5m一道(y=100~140,9层·亮橙) function layer(y, mat){ [-10.5, 10.5].forEach(function(ox){ bar(ox-1.35,y,z-1.35, ox, y,z-1.35, 0.08, mat); bar(ox, y,z-1.35, ox+1.35,y,z-1.35, 0.08, mat); bar(ox+1.35,y,z-1.35, ox+1.35,y,z, 0.08, mat); bar(ox+1.35,y,z, ox+1.35,y,z+1.35, 0.08, mat); bar(ox+1.35,y,z+1.35, ox, y,z+1.35, 0.08, mat); bar(ox, y,z+1.35, ox-1.35,y,z+1.35, 0.08, mat); bar(ox-1.35,y,z+1.35, ox-1.35,y,z, 0.08, mat); bar(ox-1.35,y,z, ox-1.35,y,z-1.35, 0.08, mat); }); } for(var y=5; y<=95; y+=10) layer(y, matH); for(var y=100; y<=140; y+=5) layer(y, matH2); // 剪刀撑:层间 X 形;普通段10m层高,锚固区(95m以上)5m层高·亮橙 var lv = []; for(var y=5; y<=95; y+=10) lv.push(y); for(var y=100; y<=140; y+=5) lv.push(y); for(var k=0;k<lv.length-1;k++){ var y1=lv[k], y2=lv[k+1]; var mD = (y1 >= 95) ? matD2 : matD; [-10.5, 10.5].forEach(function(ox){ // X 向壁(横桥向立面):Z 向 X 形 bar(ox-1.35,y1,z-1.35, ox-1.35,y2,z+1.35, 0.06, mD); bar(ox-1.35,y2,z-1.35, ox-1.35,y1,z+1.35, 0.06, mD); bar(ox+1.35,y1,z-1.35, ox+1.35,y2,z+1.35, 0.06, mD); bar(ox+1.35,y2,z-1.35, ox+1.35,y1,z+1.35, 0.06, mD); // Z 向壁(顺桥向立面):X 向 X 形 bar(ox-1.35,y1,z-1.35, ox+1.35,y2,z-1.35, 0.06, mD); bar(ox-1.35,y2,z-1.35, ox+1.35,y1,z-1.35, 0.06, mD); bar(ox-1.35,y1,z+1.35, ox+1.35,y2,z+1.35, 0.06, mD); bar(ox-1.35,y2,z+1.35, ox+1.35,y1,z+1.35, 0.06, mD); }); } scene.add(groups.frame); scene.add(groups.frameJoints); } function buildPier(z){ // 过渡墩:边跨现浇段端部支点,墩帽顶面与梁底齐平 var mat = new THREE.MeshPhongMaterial({ color:0x7d8a99 }); var shaft = new THREE.Mesh(new THREE.BoxGeometry(5, 38, 3), mat); shaft.position.set(0, 19, z); groups.tower.add(shaft); var cap = new THREE.Mesh(new THREE.BoxGeometry(8, 2, 3.5), mat); cap.position.set(0, 39, z); groups.tower.add(cap); } function buildGirder(z){ groups.girder = new THREE.Group(); var panelMat = new THREE.MeshPhongMaterial({ color:0xe8913a, transparent:true, opacity:0.5, depthWrite:false, side:THREE.DoubleSide }); var top = new THREE.Mesh(new THREE.BoxGeometry(24.5, 0.5, 20), panelMat); top.position.set(0, 42.75, z); var bot = top.clone(); bot.position.y = 40.25; groups.girder.add(top, bot); // 三道腹板(单箱双室:中腹板0m,边腹板±10.5m = 索面锚固 = 塔肢中心) var webMat = new THREE.MeshPhongMaterial({ color:0xb06a1f, transparent:true, opacity:0.85, side:THREE.DoubleSide }); [-10.5, 0, 10.5].forEach(function(x){ var w = new THREE.Mesh(new THREE.BoxGeometry(0.4, 3.0, 20), webMat); w.position.set(x, 41.5, z); groups.girder.add(w); }); // 端部封板(半透明) var endMat = new THREE.MeshPhongMaterial({ color:0xe8913a, transparent:true, opacity:0.3, side:THREE.DoubleSide, depthWrite:false }); var e1 = new THREE.Mesh(new THREE.PlaneGeometry(24.5, 3), endMat); e1.position.set(0, 41.5, z - 10); var e2 = e1.clone(); e2.position.z = z + 10; groups.girder.add(e1, e2); // 轮廓线框 var edges = new THREE.EdgesGeometry(new THREE.BoxGeometry(24.5, 3, 20)); var line = new THREE.LineSegments(edges, new THREE.LineBasicMaterial({ color:0x9a6418 })); line.position.y = 41.5; line.position.z = z; groups.girder.add(line); scene.add(groups.girder); } function buildSideGirder(zc, zLo, zHi){ // 边跨现浇段:13m × 24.5m,梁底 Y=40 groups.side = new THREE.Group(); var panelMat = new THREE.MeshPhongMaterial({ color:0xe8913a, transparent:true, opacity:0.5, depthWrite:false, side:THREE.DoubleSide }); var top = new THREE.Mesh(new THREE.BoxGeometry(24.5, 0.5, 13), panelMat); top.position.set(0, 42.75, zc); var bot = top.clone(); bot.position.y = 40.25; groups.side.add(top, bot); var webMat = new THREE.MeshPhongMaterial({ color:0xb06a1f, transparent:true, opacity:0.85, side:THREE.DoubleSide }); [-10.5, 0, 10.5].forEach(function(x){ var w = new THREE.Mesh(new THREE.BoxGeometry(0.4, 3.0, 13), webMat); w.position.set(x, 41.5, zc); groups.side.add(w); }); var endMat = new THREE.MeshPhongMaterial({ color:0xe8913a, transparent:true, opacity:0.3, side:THREE.DoubleSide, depthWrite:false }); var e1 = new THREE.Mesh(new THREE.PlaneGeometry(24.5, 3), endMat); e1.position.set(0, 41.5, zLo); var e2 = e1.clone(); e2.position.z = zHi; groups.side.add(e1, e2); var edges = new THREE.EdgesGeometry(new THREE.BoxGeometry(24.5, 3, 13)); var line = new THREE.LineSegments(edges, new THREE.LineBasicMaterial({ color:0x9a6418 })); line.position.y = 41.5; line.position.z = zc; groups.side.add(line); scene.add(groups.side); } function buildSegments(){ // 悬浇段 64 段×6m:结构形式 = 单箱双室三向预应力混凝土(与项目背景一致) // 梁底 Y=40、梁顶 Y=43(梁高 3.0m);蓝色半透明 = 待施工状态 // 截面:顶板 24.5m×0.28、底板 21.4m×0.30、边腹板±10.5m+中腹板 0m(厚0.40)→ 双室 // 三向预应力:纵向(红,顶/底板内)+横向(蓝,顶板内)+竖向(绿,腹板内) groups.seg = new THREE.Group(); groups.segLong = new THREE.Group(); groups.segTrans = new THREE.Group(); groups.segVert = new THREE.Group(); var D = { segLen: 6, topY: 43, botY: 40, // 梁顶 / 梁底 topBotY: 43 - 0.28, // 顶板底 42.72 botTopY: 40 + 0.30, // 底板顶 40.30 edge: 12.25, botEdge: 10.7, // 顶板半宽 / 底板半宽 webC: 10.5, webT: 0.4 // 边腹板中心 / 腹板厚 }; var cMat = new THREE.MeshPhongMaterial({ color:0x6fa8dc, transparent:true, opacity:0.30, depthWrite:false, side:THREE.DoubleSide }); var wMat = new THREE.MeshPhongMaterial({ color:0x4a8fc4, transparent:true, opacity:0.45, depthWrite:false, side:THREE.DoubleSide }); var eMat = new THREE.LineBasicMaterial({ color:0x3f6ea5, transparent:true, opacity:0.8 }); var lMat = new THREE.MeshPhongMaterial({ color:0xe74c3c, shininess:60 }); // 纵向预应力 红 var tMat = new THREE.MeshPhongMaterial({ color:0x3498db, shininess:60 }); // 横向预应力 蓝 var vMat = new THREE.MeshPhongMaterial({ color:0x27ae60, shininess:60 }); // 竖向预应力 绿 function section(z0){ // 单箱双室截面(XY 平面轮廓,沿 Z 挤出 6m) var s = new THREE.Shape(); s.moveTo(-D.edge, D.topY); s.lineTo( D.edge, D.topY); s.lineTo( D.edge, D.topBotY); s.lineTo( D.botEdge, D.topBotY); s.lineTo( D.botEdge, D.botY); s.lineTo(-D.botEdge, D.botY); s.lineTo(-D.botEdge, D.topBotY); s.lineTo(-D.edge, D.topBotY); s.closePath(); var innerL = D.botEdge - D.webT; // 10.3(底板内缘) var midL = D.webC - D.webT/2; // 0.2(中腹板半厚) var h1 = new THREE.Path(); // 左室 h1.moveTo(-innerL, D.botTopY); h1.lineTo(-midL, D.botTopY); h1.lineTo(-midL, D.topBotY); h1.lineTo(-innerL, D.topBotY); h1.closePath(); s.holes.push(h1); var h2 = new THREE.Path(); // 右室 h2.moveTo(midL, D.botTopY); h2.lineTo(innerL, D.botTopY); h2.lineTo(innerL, D.topBotY); h2.lineTo(midL, D.topBotY); h2.closePath(); s.holes.push(h2); var g = new THREE.ExtrudeGeometry(s, { depth:D.segLen, bevelEnabled:false, steps:1 }); g.translate(0, 0, z0 - D.segLen/2); groups.seg.add(new THREE.Mesh(g, cMat)); // 三道腹板深色覆盖(视觉区分) [-D.webC, 0, D.webC].forEach(function(x){ var w = new THREE.Mesh(new THREE.BoxGeometry(D.webT, D.topBotY - D.botTopY, D.segLen), wMat); w.position.set(x, (D.topBotY + D.botTopY)/2, z0); groups.seg.add(w); }); // 两端截面轮廓线(外轮廓 + 双室内框) [z0 - D.segLen/2, z0 + D.segLen/2].forEach(function(z){ var out = [[-D.edge,D.topY],[D.edge,D.topY],[D.edge,D.topBotY],[D.botEdge,D.topBotY], [D.botEdge,D.botY],[-D.botEdge,D.botY],[-D.botEdge,D.topBotY],[-D.edge,D.topBotY], [-D.edge,D.topY]] .map(function(p){ return new THREE.Vector3(p[0], p[1], z); }); groups.seg.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(out), eMat)); var in1 = [[-innerL,D.botTopY],[-midL,D.botTopY],[-midL,D.topBotY],[-innerL,D.topBotY],[-innerL,D.botTopY]] .map(function(p){ return new THREE.Vector3(p[0], p[1], z); }); groups.seg.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(in1), eMat)); var in2 = [[midL,D.botTopY],[innerL,D.botTopY],[innerL,D.topBotY],[midL,D.topBotY],[midL,D.botTopY]] .map(function(p){ return new THREE.Vector3(p[0], p[1], z); }); groups.seg.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(in2), eMat)); }); } function tendons(z0){ // 纵向预应力(红,沿 Z):顶板 9 根 + 底板 7 根 + 顶板近边腹板 2 根 = 18 根/段 var len = D.segLen + 0.6, r = 0.05; [-10.5,-8,-5.5,-3,0,3,5.5,8,10.5].forEach(function(x){ var c = new THREE.Mesh(new THREE.CylinderGeometry(r,r,len,8), lMat); c.rotation.x = Math.PI/2; c.position.set(x, D.topY - 0.14, z0); groups.segLong.add(c); }); [-8,-5.5,-3,0,3,5.5,8].forEach(function(x){ var c = new THREE.Mesh(new THREE.CylinderGeometry(r,r,len,8), lMat); c.rotation.x = Math.PI/2; c.position.set(x, 40.15, z0); groups.segLong.add(c); }); [-10.5,10.5].forEach(function(x){ var c = new THREE.Mesh(new THREE.CylinderGeometry(r,r,len,8), lMat); c.rotation.x = Math.PI/2; c.position.set(x, D.topY - 0.20, z0); groups.segLong.add(c); }); // 横向预应力(蓝,沿 X):顶板内 6 根,间距 1.0m var tlen = D.edge*2 - 2.0; // -11.25 ~ +11.25 [-2.5,-1.5,-0.5,0.5,1.5,2.5].forEach(function(z){ var c = new THREE.Mesh(new THREE.CylinderGeometry(0.035,0.035,tlen,8), tMat); c.rotation.z = Math.PI/2; c.position.set(0, D.topY - 0.14, z0 + z); groups.segTrans.add(c); }); // 竖向预应力(绿,沿 Y):三道腹板内,间距 0.6m var vlen = D.topBotY - D.botTopY - 0.1; [-D.webC, 0, D.webC].forEach(function(x){ for (var z = -2.7; z <= 2.7; z += 0.6){ var c = new THREE.Mesh(new THREE.CylinderGeometry(0.03,0.03,vlen,6), vMat); c.position.set(x, (D.topBotY + D.botTopY)/2, z0 + z); groups.segVert.add(c); } }); } var i, z; // 塔1 边跨 16 段:Z=-10 → -106(中心 -13-6i) for (i = 0; i < 16; i++){ z = -13 - 6*i; section(z); tendons(z); } // 塔1 主跨侧 16 段:Z=+10 → +106(中心 13+6i) for (i = 0; i < 16; i++){ z = 13 + 6*i; section(z); tendons(z); } // 塔2 主跨侧 16 段:Z=+108 → +204(中心 111+6i) for (i = 0; i < 16; i++){ z = 111 + 6*i; section(z); tendons(z); } // 塔2 边跨 16 段:Z=+224 → +320(中心 227+6i) for (i = 0; i < 16; i++){ z = 227 + 6*i; section(z); tendons(z); } scene.add(groups.seg); scene.add(groups.segLong); scene.add(groups.segTrans); scene.add(groups.segVert); } function buildClosures(){ // 合拢段 3 处各 2m:塔1边跨 Z=-108~-106、中跨 Z=+106~+108、塔2边跨 Z=+320~+322,紫色高亮 groups.closure = new THREE.Group(); var mat = new THREE.MeshPhongMaterial({ color:0x8f6fc7, transparent:true, opacity:0.82, depthWrite:false, side:THREE.DoubleSide }); var edge = new THREE.LineBasicMaterial({ color:0x5c3d96 }); [-107, 107, 321].forEach(function(zc){ var b = new THREE.Mesh(new THREE.BoxGeometry(24.5, 3, 2), mat); b.position.set(0, 41.5, zc); groups.closure.add(b); var e = new THREE.LineSegments(new THREE.EdgesGeometry(b.geometry), edge); e.position.copy(b.position); groups.closure.add(e); }); scene.add(groups.closure); } function buildPiles(){ groups.piles = new THREE.Group(); var geo = new THREE.CylinderGeometry(0.55, 0.55, 38, 14); var mat = new THREE.MeshPhongMaterial({ color:0xe0453a }); // 塔1 0号块:4排×5根(单塔600m³≈1560t,验算满足),收进两塔肢内侧(±5.5m) var zs = [-8.5, -4.5, 4.5, 8.5]; var xs = [-5.5, -2.75, 0, 2.75, 5.5]; zs.forEach(function(z){ xs.forEach(function(x){ var p = new THREE.Mesh(geo, mat); p.position.set(x, 19, z); groups.piles.add(p); }); }); // 塔1 边跨现浇段:3排×5根,排距4.5m(Z=-109.5/-114/-118.5), // 无塔肢限制,横向放宽到±8.5m;最靠墩一排距墩投影边约1m var zs2 = [-109.5, -114, -118.5]; var xs2 = [-8.5, -4.25, 0, 4.25, 8.5]; zs2.forEach(function(z){ xs2.forEach(function(x){ var p = new THREE.Mesh(geo, mat); p.position.set(x, 19, z); groups.piles.add(p); }); }); // 塔2 0号块:镜像塔1(Z=+205.5/+209.5/+218.5/+222.5,中心+214,4排×5根) var zs3 = [205.5, 209.5, 218.5, 222.5]; zs3.forEach(function(z){ xs.forEach(function(x){ var p = new THREE.Mesh(geo, mat); p.position.set(x, 19, z); groups.piles.add(p); }); }); // 塔2 边跨现浇段:镜像塔1(Z=+323.5/+328/+332.5,过渡墩在+335) var zs4 = [323.5, 328, 332.5]; zs4.forEach(function(z){ xs2.forEach(function(x){ var p = new THREE.Mesh(geo, mat); p.position.set(x, 19, z); groups.piles.add(p); }); }); scene.add(groups.piles); } function buildBracing(){ // 钢管桩支架稳定支撑体系:平联(横撑)+ 剪刀撑(斜撑) // 40m 高支架按“每10m左右一道平联”设置 5 层:y = 1(扫地杆)/11/21/31/36(顶部系杆) // 剪刀撑沿支架四周最外立面设 X 形(横桥向 Z 向立面 + 顺桥向 X 向立面) groups.bracing = new THREE.Group(); var matH = new THREE.MeshPhongMaterial({ color:0x8ba3b8 }); // 平联 蓝灰 var matD = new THREE.MeshPhongMaterial({ color:0x667f9c }); // 剪刀撑 深蓝灰 function brace(x1,y1,z1, x2,y2,z2, r, mat){ var dx=x2-x1, dy=y2-y1, dz=z2-z1; var len = Math.sqrt(dx*dx+dy*dy+dz*dz); if(len < 0.5) return; var m = new THREE.Mesh(new THREE.CylinderGeometry(r, r, len, 6), mat); m.position.set((x1+x2)/2, (y1+y2)/2, (z1+z2)/2); m.quaternion.setFromUnitVectors(new THREE.Vector3(0,1,0), new THREE.Vector3(dx,dy,dz).normalize()); groups.bracing.add(m); } function addBracing(zs, xs){ var levels = [1, 11, 21, 31, 36]; var xMin = Math.min.apply(null,xs), xMax = Math.max.apply(null,xs); var zMin = Math.min.apply(null,zs), zMax = Math.max.apply(null,zs); // 平联:每层 X 向连排 + Z 向分段连列 levels.forEach(function(y){ zs.forEach(function(z){ brace(xMin, y, z, xMax, y, z, 0.10, matH); }); xs.forEach(function(x){ for(var i=0;i<zs.length-1;i++){ brace(x, y, zs[i], x, y, zs[i+1], 0.10, matH); } }); }); // 剪刀撑:四周最外立面 X 形(每相邻两层平联之间) for(var k=0;k<levels.length-1;k++){ var y1=levels[k], y2=levels[k+1]; [zMin, zMax].forEach(function(z){ for(var i=0;i<xs.length-1;i++){ brace(xs[i], y1, z, xs[i+1], y2, z, 0.09, matD); brace(xs[i], y2, z, xs[i+1], y1, z, 0.09, matD); } }); [xMin, xMax].forEach(function(x){ for(var i=0;i<zs.length-1;i++){ brace(x, y1, zs[i], x, y2, zs[i+1], 0.09, matD); brace(x, y2, zs[i], x, y1, zs[i+1], 0.09, matD); } }); } } // 塔1 0号块:4排×5根(Z=-8.5/-4.5/4.5/8.5,X=±5.5) addBracing([-8.5, -4.5, 4.5, 8.5], [-5.5, -2.75, 0, 2.75, 5.5]); // 塔1 边跨现浇段:3排×5根(Z=-109.5/-114/-118.5,X=±8.5) addBracing([-109.5, -114, -118.5], [-8.5, -4.25, 0, 4.25, 8.5]); // 塔2 0号块:镜像(中心 Z=+214) addBracing([205.5, 209.5, 218.5, 222.5], [-5.5, -2.75, 0, 2.75, 5.5]); // 塔2 边跨现浇段:镜像(中心 Z=+328.5) addBracing([323.5, 328, 332.5], [-8.5, -4.25, 0, 4.25, 8.5]); scene.add(groups.bracing); } function buildBentley(){ groups.bentley = new THREE.Group(); var mat = new THREE.MeshPhongMaterial({ color:0xf2c14e }); var mat2 = new THREE.MeshPhongMaterial({ color:0xd9a832 }); // 塔1 0号块贝雷梁平台:5列沿 Z(长17,跨4排桩),4排横向分配梁 var xs = [-5.5, -2.75, 0, 2.75, 5.5]; xs.forEach(function(x){ var b = new THREE.Mesh(new THREE.BoxGeometry(1.1, 2, 17), mat); b.position.set(x, 39, 0); groups.bentley.add(b); var e = new THREE.EdgesGeometry(b.geometry); groups.bentley.add(new THREE.LineSegments(e, new THREE.LineBasicMaterial({ color:0x8a6d1c }))); }); [-8.5, -4.5, 4.5, 8.5].forEach(function(z){ var h = new THREE.Mesh(new THREE.BoxGeometry(11, 0.5, 0.5), mat2); h.position.set(0, 39.75, z); groups.bentley.add(h); }); // 塔1 边跨现浇段贝雷梁平台:5列沿 Z(长12),3排横向分配梁 var xs2 = [-8.5, -4.25, 0, 4.25, 8.5]; xs2.forEach(function(x){ var b = new THREE.Mesh(new THREE.BoxGeometry(1.1, 2, 12), mat); b.position.set(x, 39, -114); groups.bentley.add(b); var e2 = new THREE.EdgesGeometry(b.geometry); groups.bentley.add(new THREE.LineSegments(e2, new THREE.LineBasicMaterial({ color:0x8a6d1c }))); }); [-109.5, -114, -118.5].forEach(function(z){ var h = new THREE.Mesh(new THREE.BoxGeometry(17, 0.5, 0.5), mat2); h.position.set(0, 39.75, z); groups.bentley.add(h); }); // 塔2 0号块贝雷梁平台(镜像,中心 Z=+214) xs.forEach(function(x){ var b = new THREE.Mesh(new THREE.BoxGeometry(1.1, 2, 17), mat); b.position.set(x, 39, 214); groups.bentley.add(b); var e3 = new THREE.EdgesGeometry(b.geometry); groups.bentley.add(new THREE.LineSegments(e3, new THREE.LineBasicMaterial({ color:0x8a6d1c }))); }); [205.5, 209.5, 218.5, 222.5].forEach(function(z){ var h = new THREE.Mesh(new THREE.BoxGeometry(11, 0.5, 0.5), mat2); h.position.set(0, 39.75, z); groups.bentley.add(h); }); // 塔2 边跨现浇段贝雷梁平台(镜像,中心 Z=+328.5) xs2.forEach(function(x){ var b = new THREE.Mesh(new THREE.BoxGeometry(1.1, 2, 12), mat); b.position.set(x, 39, 328.5); groups.bentley.add(b); var e4 = new THREE.EdgesGeometry(b.geometry); groups.bentley.add(new THREE.LineSegments(e4, new THREE.LineBasicMaterial({ color:0x8a6d1c }))); }); [323.5, 328, 332.5].forEach(function(z){ var h = new THREE.Mesh(new THREE.BoxGeometry(17, 0.5, 0.5), mat2); h.position.set(0, 39.75, z); groups.bentley.add(h); }); scene.add(groups.bentley); } function buildCantilever(){ groups.cant = new THREE.Group(); var mat = new THREE.MeshPhongMaterial({ color:0x3fa06b }); var matD = new THREE.MeshPhongMaterial({ color:0x2f7d52 }); // z0 = 0号块端部 Z 坐标(挂篮向 sign 方向悬伸) function addCrane(sign, z0){ var beam = new THREE.Mesh(new THREE.BoxGeometry(0.8, 0.8, 7), mat); beam.position.set(0, 46.5, z0 + 3.5 * sign); groups.cant.add(beam); [-3, 3].forEach(function(x){ var slant = new THREE.Mesh(new THREE.BoxGeometry(0.6, 6, 0.6), mat); slant.position.set(x, 43.5, z0 + 1 * sign); slant.rotation.z = 0.5 * sign; groups.cant.add(slant); }); var base = new THREE.Mesh(new THREE.BoxGeometry(7, 0.6, 6), matD); base.position.set(0, 36.8, z0 + 3 * sign); groups.cant.add(base); [-3, 3].forEach(function(x){ var rod = new THREE.Mesh(new THREE.CylinderGeometry(0.12, 0.12, 9.5, 6), matD); rod.position.set(x, 42, z0 + 1.5 * sign); groups.cant.add(rod); }); } // 塔1:0号块 Z=-10~+10,主跨侧端 +10、边跨侧端 -10 addCrane(1, 10); addCrane(-1, -10); // 塔2:0号块 Z=+204~+224,主跨侧端 +204(朝 Z- 方向)、边跨侧端 +224(朝 Z+ 方向) addCrane(-1, 204); addCrane(1, 224); scene.add(groups.cant); } // ================== V12 施工措施设备:塔吊 / 施工电梯 / 混凝土泵管 / 液压爬模 ================== // 塔吊:附壁式(附着于塔柱外侧面),每塔1台,位于桥面右侧外侧 X=+15,塔身 H=150m,起重臂朝主跨侧 function buildCrane(towerZ, dir){ groups.crane = groups.crane || new THREE.Group(); var matM = new THREE.MeshPhongMaterial({ color:0xf0c040, emissive:0x4a3208 }); // 塔身 亮黄 var matD = new THREE.MeshPhongMaterial({ color:0xd9a520, emissive:0x3a2806 }); // 深黄(横撑/配重) var matCab = new THREE.MeshPhongMaterial({ color:0x5d7186, emissive:0x232c38 }); // 驾驶室 灰蓝 var X = 15, hx = 0.5, hz = 0.8; function bar3(x1,y1,z1, x2,y2,z2, r, mat){ var dx=x2-x1, dy=y2-y1, dz=z2-z1; var len = Math.sqrt(dx*dx+dy*dy+dz*dz); if(len < 0.5) return; var m = new THREE.Mesh(new THREE.CylinderGeometry(r, r, len, 6), mat); m.position.set((x1+x2)/2, (y1+y2)/2, (z1+z2)/2); m.quaternion.setFromUnitVectors(new THREE.Vector3(0,1,0), new THREE.Vector3(dx,dy,dz).normalize()); groups.crane.add(m); } // ① 塔身格构(标准节):4 立柱 + 每10m横框 + 每20m层间对角斜撑 [[-hx,-hz],[hx,-hz],[-hx,hz],[hx,hz]].forEach(function(c){ var col = new THREE.Mesh(new THREE.CylinderGeometry(0.13, 0.13, 148, 6), matM); col.position.set(X+c[0], 74, towerZ+c[1]); groups.crane.add(col); }); for(var y=6; y<146; y+=10){ bar3(X-hx, y, towerZ-hz, X+hx, y, towerZ-hz, 0.07, matD); bar3(X+hx, y, towerZ-hz, X+hx, y, towerZ+hz, 0.07, matD); bar3(X+hx, y, towerZ+hz, X-hx, y, towerZ+hz, 0.07, matD); bar3(X-hx, y, towerZ+hz, X-hx, y, towerZ-hz, 0.07, matD); if((y-6) % 20 === 0){ bar3(X-hx, y, towerZ-hz, X+hx, y+10, towerZ+hz, 0.06, matD); bar3(X+hx, y, towerZ-hz, X-hx, y+10, towerZ+hz, 0.06, matD); bar3(X-hx, y, towerZ+hz, X+hx, y+10, towerZ-hz, 0.06, matD); bar3(X+hx, y, towerZ+hz, X-hx, y+10, towerZ-hz, 0.06, matD); } } // ② 附墙杆(附着于塔柱外侧面 X=12.25,每20m一道 + 斜撑) for(var ay=20; ay<=140; ay+=20){ bar3(X, ay, towerZ, 12.25, ay, towerZ, 0.07, matD); bar3(X, ay, towerZ, 12.25, ay+4, towerZ, 0.05, matD); } // ③ 回转台 + 驾驶室 var tt = new THREE.Mesh(new THREE.BoxGeometry(1.8, 0.7, 1.8), matD); tt.position.set(X, 148.35, towerZ); groups.crane.add(tt); var cab = new THREE.Mesh(new THREE.BoxGeometry(0.9, 0.9, 0.9), matCab); cab.position.set(X+0.62, 149.6, towerZ+0.62); groups.crane.add(cab); // ④ 塔顶(A架):4杆汇聚 + 顶部滑轮 + 顶横梁 var topY = 160.5; [[-hx,-hz],[hx,-hz],[-hx,hz],[hx,hz]].forEach(function(c){ bar3(X+c[0], 148.7, towerZ+c[1], X, topY, towerZ, 0.08, matM); }); var tip = new THREE.Mesh(new THREE.SphereGeometry(0.22, 8, 8), matM); tip.position.set(X, topY, towerZ); groups.crane.add(tip); bar3(X-hx, topY-1.2, towerZ, X+hx, topY-1.2, towerZ, 0.07, matM); // ⑤ 起重臂(朝主跨,L=30m,上弦2+下弦1+竖腹杆桁架) var boomY = 148.1, lowY = 147.2, boomLen = 30; [-0.35, 0.35].forEach(function(dx){ var bm = new THREE.Mesh(new THREE.CylinderGeometry(0.06, 0.06, boomLen, 6), matM); bm.rotation.x = Math.PI/2; bm.position.set(X+dx, boomY, towerZ + dir*(0.8 + boomLen/2)); groups.crane.add(bm); }); var low = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0.05, boomLen, 6), matM); low.rotation.x = Math.PI/2; low.position.set(X, lowY, towerZ + dir*(0.8 + boomLen/2)); groups.crane.add(low); for(var k=0; k<=6; k++){ var zb = towerZ + dir*(0.8 + k*5); bar3(X-0.35, boomY, zb, X, lowY, zb, 0.045, matD); bar3(X+0.35, boomY, zb, X, lowY, zb, 0.045, matD); } // 臂端吊钩 bar3(X, lowY, towerZ + dir*(0.8+boomLen), X, lowY-3.2, towerZ + dir*(0.8+boomLen), 0.05, matM); var hook = new THREE.Mesh(new THREE.SphereGeometry(0.28, 8, 8), matD); hook.position.set(X, lowY-3.5, towerZ + dir*(0.8+boomLen)); groups.crane.add(hook); // ⑥ 平衡臂(反向 L=11m)+ 配重块 var cwY = 147.8, cwEnd = towerZ - dir*(0.8+11); var cw = new THREE.Mesh(new THREE.CylinderGeometry(0.06, 0.06, 11, 6), matM); cw.rotation.x = Math.PI/2; cw.position.set(X, cwY, towerZ - dir*(0.8+5.5)); groups.crane.add(cw); [-0.45, 0.45].forEach(function(dx){ var w = new THREE.Mesh(new THREE.BoxGeometry(0.7, 1.3, 1.0), matD); w.position.set(X+dx, cwY-0.75, cwEnd); groups.crane.add(w); }); bar3(X, topY-2, towerZ, X, cwY, cwEnd, 0.05, matD); // ⑦ 起重臂拉索(塔顶→臂上弦 2/3 处 + 端部) bar3(X, topY-2, towerZ, X-0.35, boomY, towerZ + dir*21, 0.05, matD); bar3(X, topY-2, towerZ, X+0.35, boomY, towerZ + dir*21, 0.05, matD); bar3(X, topY-2, towerZ, X, lowY, towerZ + dir*(0.8+boomLen), 0.05, matD); scene.add(groups.crane); } // 施工电梯(人货梯):附壁于塔柱外侧,双导轨架 + 吊笼 + 附墙 + 天轮 function buildLift(towerZ){ groups.lift = groups.lift || new THREE.Group(); var mat = new THREE.MeshPhongMaterial({ color:0x4db8a0, emissive:0x123a30 }); // 青绿 var matR = new THREE.MeshPhongMaterial({ color:0x3a8f7c, emissive:0x0e2a24 }); // 深青 var X = -15, Z = towerZ + 1.6, H = 141; function bar3(x1,y1,z1, x2,y2,z2, r, mat){ var dx=x2-x1, dy=y2-y1, dz=z2-z1; var len = Math.sqrt(dx*dx+dy*dy+dz*dz); if(len < 0.5) return; var m = new THREE.Mesh(new THREE.CylinderGeometry(r, r, len, 6), mat); m.position.set((x1+x2)/2, (y1+y2)/2, (z1+z2)/2); m.quaternion.setFromUnitVectors(new THREE.Vector3(0,1,0), new THREE.Vector3(dx,dy,dz).normalize()); groups.lift.add(m); } // 双导轨立柱(沿 X 向间距 0.6m) [X-0.3, X+0.3].forEach(function(rx){ var m = new THREE.Mesh(new THREE.CylinderGeometry(0.09, 0.09, H, 6), mat); m.position.set(rx, H/2, Z); groups.lift.add(m); }); // 横档每4m for(var y=4; y<H; y+=4){ bar3(X-0.3, y, Z, X+0.3, y, Z, 0.045, matR); } // 附墙杆(连至塔柱外侧 X=-12.25,每12m一道) for(var ay=12; ay<=132; ay+=12){ bar3(X+0.3, ay, Z, -12.25, ay, Z, 0.06, matR); bar3(X+0.3, ay, Z, -12.25, ay+3, Z, 0.04, matR); } // 吊笼(运行在 y=95 示意) var cage = new THREE.Mesh(new THREE.BoxGeometry(1.15, 2.5, 1.55), mat); cage.position.set(X, 95, Z); groups.lift.add(cage); var ce = new THREE.LineSegments(new THREE.EdgesGeometry(cage.geometry), new THREE.LineBasicMaterial({ color:0x1d5c4c })); ce.position.copy(cage.position); groups.lift.add(ce); // 顶部天轮 var wheel = new THREE.Mesh(new THREE.CylinderGeometry(0.35, 0.35, 0.2, 10), matR); wheel.rotation.z = Math.PI/2; wheel.position.set(X, H+0.7, Z); groups.lift.add(wheel); // 底部基础 var base = new THREE.Mesh(new THREE.BoxGeometry(1.8, 0.4, 1.8), matR); base.position.set(X, 0.2, Z); groups.lift.add(base); scene.add(groups.lift); } // 混凝土泵管:塔柱附壁竖管(供索塔混凝土)+ 梁面水平管(供主梁挂篮浇筑) function buildPump(towerZ, dir){ groups.pump = groups.pump || new THREE.Group(); var matP = new THREE.MeshPhongMaterial({ color:0xd43a2f, emissive:0x3a0e0a }); // 红 var matF = new THREE.MeshPhongMaterial({ color:0x8a2218, emissive:0x2a0a06 }); // 法兰 深红 var X = 13.5, Z = towerZ + 2.3, H = 140; // 竖直主管(附壁于塔柱外侧 X=13.5) var pipe = new THREE.Mesh(new THREE.CylinderGeometry(0.09, 0.09, H, 8), matP); pipe.position.set(X, H/2, Z); groups.pump.add(pipe); // 法兰卡箍每10m for(var y=0; y<=H; y+=10){ var f = new THREE.Mesh(new THREE.CylinderGeometry(0.135, 0.135, 0.07, 8), matF); f.position.set(X, y, Z); groups.pump.add(f); } // 底部水平引入段 + 弯头(地面泵站来管) var hp = new THREE.Mesh(new THREE.CylinderGeometry(0.09, 0.09, 5, 8), matP); hp.rotation.z = Math.PI/2; hp.position.set(X-2.5, 0.4, Z); groups.pump.add(hp); var elbow = new THREE.Mesh(new THREE.SphereGeometry(0.14, 8, 8), matP); elbow.position.set(X, 0.55, Z); groups.pump.add(elbow); // 梁面水平段(沿 0号块/悬浇段顶面 y=43.2 向主跨延伸,至挂篮浇筑区) var hlen = 24, hz = towerZ + dir*(2.3 + hlen/2); var dp = new THREE.Mesh(new THREE.CylinderGeometry(0.09, 0.09, hlen, 8), matP); dp.rotation.x = Math.PI/2; dp.position.set(12.0, 43.2, hz); groups.pump.add(dp); scene.add(groups.pump); } // 液压爬模(索塔施工模板体系):紧贴塔肢外圈 4 面板 + 顶部操作平台 + 液压爬升缸 function buildForm(legX, towerZ){ groups.form = groups.form || new THREE.Group(); var matP = new THREE.MeshPhongMaterial({ color:0xc8a04e, emissive:0x3a2c0e }); // 模板 黄褐 var matW = new THREE.MeshPhongMaterial({ color:0x8f9aad, emissive:0x28303c }); // 平台 灰蓝 var matH = new THREE.MeshPhongMaterial({ color:0xa8822f, emissive:0x2a2008 }); // 液压缸 深棕 var y0 = 56, y1 = 62; // 前后面板(X 向宽 4.4m,塔肢3.5m 外扩 0.9m) [towerZ-1.78, towerZ+1.78].forEach(function(z){ var f = new THREE.Mesh(new THREE.BoxGeometry(4.4, 6, 0.14), matP); f.position.set(legX, (y0+y1)/2, z); groups.form.add(f); var fe = new THREE.LineSegments(new THREE.EdgesGeometry(f.geometry), new THREE.LineBasicMaterial({ color:0x5c4a1e })); fe.position.copy(f.position); groups.form.add(fe); }); // 左右面板(Z 向宽 3.56m) [legX-1.78, legX+1.78].forEach(function(x){ var f = new THREE.Mesh(new THREE.BoxGeometry(0.14, 6, 3.56), matP); f.position.set(x, (y0+y1)/2, towerZ); groups.form.add(f); var fe = new THREE.LineSegments(new THREE.EdgesGeometry(f.geometry), new THREE.LineBasicMaterial({ color:0x5c4a1e })); fe.position.copy(f.position); groups.form.add(fe); }); // 顶部操作平台(外挑一圈) var plat = new THREE.Mesh(new THREE.BoxGeometry(6.0, 0.12, 5.0), matW); plat.position.set(legX, y1+0.26, towerZ); groups.form.add(plat); // 平台护栏 [[-2.7,-2.3],[2.7,-2.3],[-2.7,2.3],[2.7,2.3]].forEach(function(c){ var rail = new THREE.Mesh(new THREE.CylinderGeometry(0.04, 0.04, 1.0, 6), matW); rail.position.set(legX+c[0], y1+0.8, towerZ+c[1]); groups.form.add(rail); }); // 液压爬升缸(四角短竖杆) [[-1.9,-1.9],[1.9,-1.9],[-1.9,1.9],[1.9,1.9]].forEach(function(c){ var cyl = new THREE.Mesh(new THREE.CylinderGeometry(0.07, 0.07, 5.6, 6), matH); cyl.position.set(legX+c[0], (y0+y1)/2, towerZ+c[1]); groups.form.add(cyl); }); scene.add(groups.form); } // ================== V13 施工措施设备:塔顶缆索吊机 / 混凝土拌合站+泵站 ================== // 塔顶缆索吊机:无水山区大峡谷 → 不设栈桥,以塔顶缆索吊为主吊运手段 // 两塔顶间张拉主索(跨中垂度 f≈18m),起重小车(跑车)沿索横移吊装;塔顶索鞍桁架;两端背索锚固于地锚 function buildCableCrane(){ groups.cablecrane = new THREE.Group(); var matM = new THREE.MeshPhongMaterial({ color:0xff7f2a, emissive:0x6a2c05 }); // 主索/吊绳 亮橙 var matD = new THREE.MeshPhongMaterial({ color:0xd9681e, emissive:0x50240a }); // 深橙(小车/索鞍) var matB = new THREE.MeshPhongMaterial({ color:0x8f6fc7, emissive:0x2e1c4a }); // 背索 紫 var matC = new THREE.MeshPhongMaterial({ color:0xe8a63c, emissive:0x4a3208 }); // 吊装构件 金黄 function bar3(x1,y1,z1, x2,y2,z2, r, mat){ var dx=x2-x1, dy=y2-y1, dz=z2-z1; var len = Math.sqrt(dx*dx+dy*dy+dz*dz); if(len < 0.5) return; var m = new THREE.Mesh(new THREE.CylinderGeometry(r, r, len, 6), mat); m.position.set((x1+x2)/2, (y1+y2)/2, (z1+z2)/2); m.quaternion.setFromUnitVectors(new THREE.Vector3(0,1,0), new THREE.Vector3(dx,dy,dz).normalize()); groups.cablecrane.add(m); } var topY = 141.5; // 索鞍顶高程(塔顶140m 之上) var z1 = 0, z2 = 214, L = z2 - z1, f = 18; // 主索跨中垂度 // ① 主索(承重索):两端塔顶高、跨中下垂(抛物线垂度 f=18m),用分段折线模拟(每段约7m) var segs = Math.round(L / 7); for(var i=0; i<segs; i++){ var za = z1 + L*i/segs, zb = z1 + L*(i+1)/segs; var ya = topY - 4*f*(za-z1)*(z2-za)/(L*L); var yb = topY - 4*f*(zb-z1)*(z2-zb)/(L*L); bar3(0, ya, za, 0, yb, zb, 0.11, matM); } // ② 塔顶索鞍桁架(横跨两塔肢,X 从 -10.5 到 +10.5,高 y=140~143) [-10.5, 10.5].forEach(function(legX){ var sadd = new THREE.Mesh(new THREE.BoxGeometry(1.0, 3.0, 2.4), matD); sadd.position.set(legX, 141.5, z1); groups.cablecrane.add(sadd); var sadd2 = sadd.clone(); sadd2.position.z = z2; groups.cablecrane.add(sadd2); // 索鞍支承斜撑(塔肢顶→索鞍底) bar3(legX, 138.5, z1, legX + (legX>0?1:-1)*0.9, 142.2, z1, 0.09, matD); bar3(legX, 138.5, z2, legX + (legX>0?1:-1)*0.9, 142.2, z2, 0.09, matD); }); // 横向连接桁架(两索鞍之间,索塔顶部) bar3(-10.5, 141.5, z1, 10.5, 141.5, z1, 0.08, matD); bar3(-10.5, 141.5, z2, 10.5, 141.5, z2, 0.08, matD); bar3(-10.5, 140.6, z1, 10.5, 142.4, z1, 0.06, matD); bar3(10.5, 140.6, z1, -10.5, 142.4, z1, 0.06, matD); bar3(-10.5, 140.6, z2, 10.5, 142.4, z2, 0.06, matD); bar3(10.5, 140.6, z2, -10.5, 142.4, z2, 0.06, matD); // ③ 起重小车(跑车,位于主跨中 Z=107,挂在主索上) var cz = 107, cy = topY - 4*f*(cz-z1)*(z2-cz)/(L*L); var car = new THREE.Mesh(new THREE.BoxGeometry(1.6, 0.7, 2.4), matD); car.position.set(0, cy - 0.35, cz); groups.cablecrane.add(car); // 小车行走轮(两个,骑在主索上) [[-0.55, -0.8], [0.55, -0.8], [-0.55, 0.8], [0.55, 0.8]].forEach(function(w){ var wheel = new THREE.Mesh(new THREE.CylinderGeometry(0.32, 0.32, 0.22, 10), matM); wheel.rotation.x = Math.PI/2; wheel.position.set(w[0], cy - 0.62, cz + w[1]); groups.cablecrane.add(wheel); }); // 吊绳(小车→吊钩,下放至桥面附近)+吊装构件(钢筋笼示意) bar3(0, cy - 0.7, cz, 0, 38.5, cz, 0.05, matM); var hook = new THREE.Mesh(new THREE.ConeGeometry(0.3, 0.9, 8), matM); hook.rotation.x = Math.PI; hook.position.set(0, 38.2, cz); groups.cablecrane.add(hook); var load = new THREE.Mesh(new THREE.BoxGeometry(2.6, 1.6, 6.0), matC); load.position.set(0, 37.0, cz); groups.cablecrane.add(load); // 钢筋笼外轮廓线 var le = new THREE.LineSegments(new THREE.EdgesGeometry(load.geometry), new THREE.LineBasicMaterial({ color:0x7a4a0a })); le.position.copy(load.position); groups.cablecrane.add(le); // ④ 背索(主索两端经塔顶索鞍锚固于两岸地锚) [-121, 335].forEach(function(az){ bar3(0, topY, az > 100 ? z2 : z1, 0, 3, az, 0.09, matB); bar3(0, topY, az > 100 ? z2 : z1, -14, 3, az, 0.06, matB); bar3(0, topY, az > 100 ? z2 : z1, 14, 3, az, 0.06, matB); // 地锚块 var anc = new THREE.Mesh(new THREE.BoxGeometry(6, 2.4, 4), new THREE.MeshPhongMaterial({ color:0x7d8a99 })); anc.position.set(0, 1.2, az); groups.cablecrane.add(anc); var ac = new THREE.Mesh(new THREE.BoxGeometry(6, 2.4, 4), new THREE.MeshBasicMaterial({ color:0x000000, wireframe:true })); ac.position.set(0, 1.2, az); groups.cablecrane.add(ac); }); // ⑤ 牵引索(主索旁的工作索,示意:两塔顶间略平行细线) bar3(-0.8, topY-0.8, z1, -0.8, topY-0.8, z2, 0.04, matD); scene.add(groups.cablecrane); } // 混凝土拌合站 + 泵站:全桥泵送施工,平均运距3km → 峡谷左岸设场站,泵管沿便道接至桥位 function buildPlant(){ groups.plant = new THREE.Group(); var matB = new THREE.MeshPhongMaterial({ color:0x5f8fa8, emissive:0x1c3a4a }); // 搅拌楼主体 青蓝 var matS = new THREE.MeshPhongMaterial({ color:0x8a97a5, emissive:0x2e3640 }); // 筒仓 灰蓝 var matR = new THREE.MeshPhongMaterial({ color:0xd43a2f, emissive:0x3a0e0a }); // 泵车 红 var matG = new THREE.MeshPhongMaterial({ color:0xc8a86a, emissive:0x4a3a1a }); // 骨料 沙黄 var matY = new THREE.MeshPhongMaterial({ color:0xf2c14e, emissive:0x5c4408 }); // 皮带机 金黄 var matD = new THREE.MeshPhongMaterial({ color:0xd43a2f, emissive:0x3a0e0a }); // 泵送管线 红 var PX = -46, PZ = -172; // 左岸场站位置(桥左端 Z=-121 外约 51m) function box(w, h, d, x, y, z, mat){ var m = new THREE.Mesh(new THREE.BoxGeometry(w, h, d), mat); m.position.set(x, y, z); groups.plant.add(m); return m; } // ① 搅拌楼(HZS120 双机):4 立柱 + 主体箱体 + 顶部配料斗 + 出料口 var MLX = PX, MLZ = PZ + 8; [[-3.2,-2.2],[3.2,-2.2],[-3.2,2.2],[3.2,2.2]].forEach(function(c){ var col = new THREE.Mesh(new THREE.CylinderGeometry(0.22, 0.22, 8, 8), matS); col.position.set(MLX+c[0], 4, MLZ+c[1]); groups.plant.add(col); }); box(7.4, 5.2, 5.4, MLX, 10.6, MLZ, matB); box(7.4, 5.2, 5.4, MLX, 10.6, MLZ, new THREE.MeshBasicMaterial({ color:0x000000, wireframe:true })); // 顶部配料斗(倒锥体,开口朝上) var hopper = new THREE.Mesh(new THREE.ConeGeometry(1.6, 1.8, 8), matB); hopper.rotation.x = Math.PI; hopper.position.set(MLX, 14.4, MLZ); groups.plant.add(hopper); // 出料斗(下方锥斗,伸向泵车) var out = new THREE.Mesh(new THREE.ConeGeometry(0.9, 1.4, 8), matB); out.position.set(MLX, 6.7, MLZ); groups.plant.add(out); // ② 粉料筒仓 ×4(水泥×2 + 粉煤灰×2,高12m) [-6.5, -2.2, 2.2, 6.5].forEach(function(dx, i){ var sx = PX + dx, sz = PZ - 9; var silo = new THREE.Mesh(new THREE.CylinderGeometry(1.5, 1.5, 10, 12), matS); silo.position.set(sx, 5, sz); groups.plant.add(silo); var cone = new THREE.Mesh(new THREE.ConeGeometry(1.5, 2.2, 12), matS); cone.position.set(sx, 11.1, sz); groups.plant.add(cone); var leg = new THREE.Mesh(new THREE.CylinderGeometry(0.12, 0.12, 0.8, 6), matS); leg.position.set(sx, 0.4, sz); groups.plant.add(leg); }); // ③ 骨料仓(砂/碎石 3 堆,半锥形) [[-8.5, -2.2], [-2.8, -2.2], [2.9, -2.2]].forEach(function(g){ var pile = new THREE.Mesh(new THREE.ConeGeometry(2.4, 1.7, 8), matG); pile.position.set(PX+g[0], 0.85, PZ+g[1]); groups.plant.add(pile); }); // ④ 斜皮带输送机(骨料仓→搅拌楼顶) var belt = new THREE.Mesh(new THREE.CylinderGeometry(0.3, 0.3, 16, 8), matY); belt.rotation.x = 0.30; belt.position.set(PX - 5.5, 6.6, PZ + 1.6); groups.plant.add(belt); // ⑤ 操作室 / 配电房 box(4.5, 2.4, 3.0, PX + 9, 1.2, PZ + 6, new THREE.MeshPhongMaterial({ color:0xa9b6c2, emissive:0x3a444e })); // ⑥ 泵站(HBT90 拖泵 ×2,紧邻出料斗) var pz = PZ + 13; [-1.5, 1.5].forEach(function(dx){ box(2.8, 1.7, 5.6, PX + dx, 1.15, pz, matR); // 泵车料斗(开口朝上,接收搅拌楼混凝土) var tl = new THREE.Mesh(new THREE.ConeGeometry(0.7, 1.0, 8), matR); tl.rotation.x = Math.PI; tl.position.set(PX + dx, 2.5, pz); groups.plant.add(tl); // 出料软管 var hose = new THREE.Mesh(new THREE.CylinderGeometry(0.09, 0.09, 2.2, 6), matR); hose.rotation.z = Math.PI/2; hose.position.set(PX + dx + 1.4, 1.7, pz + 3.4); groups.plant.add(hose); }); // 泵站雨棚 box(7.6, 0.12, 7.4, PX, 3.4, pz, matS); [[-3.6, -3.4], [3.6, -3.4], [-3.6, 3.4], [3.6, 3.4]].forEach(function(c){ var pole = new THREE.Mesh(new THREE.CylinderGeometry(0.08, 0.08, 3.4, 6), matS); pole.position.set(PX+c[0], 1.7, pz+c[1]); groups.plant.add(pole); }); // ⑦ 泵送管线(泵站→桥位:沿便道地面管线,接入塔1泵管底部 X=13.5, y=0.4, Z=2.3) function line(x1, y1, z1, x2, y2, z2, r){ var dx=x2-x1, dy=y2-y1, dz=z2-z1; var len = Math.sqrt(dx*dx+dy*dy+dz*dz); if(len < 0.5) return; var m = new THREE.Mesh(new THREE.CylinderGeometry(r, r, len, 6), matD); m.position.set((x1+x2)/2, (y1+y2)/2, (z1+z2)/2); m.quaternion.setFromUnitVectors(new THREE.Vector3(0,1,0), new THREE.Vector3(dx,dy,dz).normalize()); groups.plant.add(m); } // 泵站出口 → 桥左端(Z=-121)→ 沿地面至塔1竖管接入点(Z=2.3, X=13.5) line(PX, 0.5, pz, 13.5, 0.5, -121, 0.05); // 沿便道泵送 line(13.5, 0.5, -121, 13.5, 0.5, 2.3, 0.05); // 桥台/边坡段 // 场站与桥位间运距示意虚线(3km → 图上标注) var dpts = []; for(var t=0; t<=1.001; t+=0.05){ dpts.push(new THREE.Vector3(PX + t*(13.5-PX), 0.9, pz + t*(2.3-pz))); } var dl = new THREE.Line( new THREE.BufferGeometry().setFromPoints(dpts), new THREE.LineBasicMaterial({ color:0xd43a2f, transparent:true, opacity:0.35 }) ); groups.plant.add(dl); scene.add(groups.plant); } function buildCables(){ groups.cables = new THREE.Group(); var mat = new THREE.MeshPhongMaterial({ color:0x9aa4b0, transparent:true, opacity:0.5 }); function cable(x1, y1, z1, x2, y2, z2){ var v = new THREE.Vector3(x2 - x1, y2 - y1, z2 - z1); var len = v.length(); var mid = new THREE.Vector3((x1+x2)/2, (y1+y2)/2, (z1+z2)/2); var mesh = new THREE.Mesh(new THREE.CylinderGeometry(0.09, 0.09, len, 6), mat); mesh.position.copy(mid); mesh.quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), v.clone().normalize()); groups.cables.add(mesh); } // 塔1(Z=0):向两侧各 12 根(锚固点 z=±(9+9i),i=0..11 → ±9~±108) [-1, 1].forEach(function(sx){ [-1, 1].forEach(function(sz){ for (var i = 0; i < 12; i++){ var z = 9 + i * 9; cable(sx * 10.5, 136.5, 0, sx * 10.5, 42.9, sz * z); } }); }); // 塔2(Z=214):向两侧各 12 根(主跨侧 205~106,边跨侧 223~322) [-1, 1].forEach(function(sx){ [-1, 1].forEach(function(sz){ for (var j = 0; j < 12; j++){ var z = 9 + j * 9; cable(sx * 10.5, 136.5, 214, sx * 10.5, 42.9, 214 + sz * z); } }); }); scene.add(groups.cables); } function buildLabels(){ groups.labels = new THREE.Group(); function roundRect(ctx, x, y, w, h, r){ ctx.beginPath(); ctx.moveTo(x + r, y); ctx.arcTo(x + w, y, x + w, y + h, r); ctx.arcTo(x + w, y + h, x, y + h, r); ctx.arcTo(x, y + h, x, y, r); ctx.arcTo(x, y, x + w, y, r); ctx.closePath(); } function label(text, x, y, z, scale){ var c = document.createElement('canvas'); c.width = 512; c.height = 128; var ctx = c.getContext('2d'); ctx.fillStyle = 'rgba(35,50,70,0.78)'; roundRect(ctx, 6, 10, 500, 108, 22); ctx.fill(); ctx.font = 'bold 46px "Microsoft YaHei","PingFang SC",sans-serif'; ctx.fillStyle = '#ffffff'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(text, 256, 66); var tex = new THREE.CanvasTexture(c); var sp = new THREE.Sprite(new THREE.SpriteMaterial({ map:tex, transparent:true, depthTest:false })); sp.position.set(x, y, z); var s = scale || 16; sp.scale.set(s, s * 0.25, 1); groups.labels.add(sp); return sp; } function dimLine(a, b, labelText, lx, ly, lz, scale){ var geo = new THREE.BufferGeometry().setFromPoints([a, b]); var ln = new THREE.Line(geo, new THREE.LineBasicMaterial({ color:0x33475e })); groups.labels.add(ln); if (labelText) label(labelText, lx, ly, lz, scale); } function tick(p, dx, dz){ var geo = new THREE.BufferGeometry().setFromPoints([ new THREE.Vector3(p.x - dx, p.y, p.z - dz), new THREE.Vector3(p.x + dx, p.y, p.z + dz) ]); groups.labels.add(new THREE.Line(geo, new THREE.LineBasicMaterial({ color:0x33475e }))); } // 结构名称标签 label('索塔1 H=140m', -15, 148, 0, 18); label('劲性骨架(塔肢内)', 11.2, 126, -4, 12); label('锚固区骨架加密段 95~140m(平联5m/道)', 15, 118, -4, 11); label('6m节段分缝·节点板+M20螺栓', 15, 34, 4, 11); label('下横梁', 0, 32.5, 7.5, 13); label('塔1 0号块 20m', 0, 47.6, -13, 14); label('贝雷梁平台 2m', 7.8, 42.8, 8.5, 11); label('钢管桩 Φ60cm×40m', 8.8, 21, 10.8, 13); label('塔肢投影 · 禁布桩', -15, 2.2, 4, 12); label('挂篮(示意)', 0, 51.5, 17.5, 11); label('塔吊 H≈150m(附壁式)', 16, 165, 4, 12); label('施工电梯(附壁)', -16.5, 153, 8, 11); label('混凝土泵管', 13.5, 148, 8, 10); label('液压爬模(爬升平台)', -10.5, 67.5, 5, 11); label('塔顶缆索吊机(主索+跑车)', 0, 150, 132, 12); label('混凝土拌合站 / 泵站', -46, 20, -172, 12); label('泵送管线 · 平均运距≈3km', 26, 6, -60, 11); label('斜拉索(双索面)', 15, 105, 0, 13); label('峡谷地面(支架基础面)', 0, 2.2, -34, 14); // 塔1 边跨现浇段标签 label('边跨现浇段 13m', 0, 47.8, -126, 13); label('过渡墩', -6, 45.5, -122.5, 11); label('过渡墩投影 · 禁布桩', -7, 2.2, -122.5, 10); label('边跨合拢段 2m', 0, 47.2, -107, 10); label('中跨合拢段 2m', 0, 47.2, 107, 10); label('边跨桩 3排×5根', 10.5, 21, -114, 11); label('0号块桩 4排×5根(20根)', 11, 21, 0, 11); label('边跨悬浇段 16段×6m', 0, 47.8, -62, 12); label('中跨悬浇段 16段×6m', 0, 47.8, 62, 12); label('主跨悬浇段(塔2侧)16段×6m', 0, 47.8, 158, 11); // 塔2 结构标签 label('索塔2 H=140m', 15, 148, 214, 18); label('塔2 0号块 20m', 0, 47.6, 201, 14); label('塔2 0号块桩 4排×5根(20根)', 11, 21, 214, 11); label('塔2边跨悬浇段 16段×6m', 0, 47.8, 270, 11); label('塔2边跨合拢段 2m', 0, 47.2, 321, 10); label('塔2边跨现浇段 13m', 0, 47.8, 331, 11); label('塔2过渡墩', -6, 45.5, 336, 11); label('塔2边跨桩 3排×5根', 10.5, 21, 328, 11); label('塔2边跨现浇段投影 · 禁布桩', 7, 2.2, 337, 10); // 40m 支架高 dimLine(new THREE.Vector3(8.9, 0, 9.8), new THREE.Vector3(8.9, 40, 9.8), '40m', 8.9, 20, 12.2, 10); tick(new THREE.Vector3(8.9, 0, 9.8), 0.5, 0); tick(new THREE.Vector3(8.9, 40, 9.8), 0.5, 0); // 20m 0号块长 dimLine(new THREE.Vector3(-1.2, 46.8, -10), new THREE.Vector3(-1.2, 46.8, 10), '20m', -1.2, 48.6, 0, 10); tick(new THREE.Vector3(-1.2, 46.8, -10), 0, 0.5); tick(new THREE.Vector3(-1.2, 46.8, 10), 0, 0.5); // 24.5m 桥宽 dimLine(new THREE.Vector3(-12.25, 43, 11.2), new THREE.Vector3(12.25, 43, 11.2), '24.5m', 0, 44.8, 11.2, 10); tick(new THREE.Vector3(-12.25, 43, 11.2), 0.5, 0); tick(new THREE.Vector3(12.25, 43, 11.2), 0.5, 0); // 140m 塔高 dimLine(new THREE.Vector3(-13.8, 0, -3.5), new THREE.Vector3(-13.8, 139.5, -3.5), '140m', -13.8, 70, -6.5, 10); tick(new THREE.Vector3(-13.8, 0, -3.5), 0.5, 0); tick(new THREE.Vector3(-13.8, 139.5, -3.5), 0.5, 0); // 塔肢中心距 dimLine(new THREE.Vector3(-10.5, 0.8, 5.5), new THREE.Vector3(10.5, 0.8, 5.5), '塔肢中心距 21m', 0, 3, 8, 11); // 贝雷梁 2m dimLine(new THREE.Vector3(5, 38, 9.3), new THREE.Vector3(5, 40, 9.3), '2m', 5, 41.2, 9.3, 8); // 边跨现浇段 13m dimLine(new THREE.Vector3(-1.2, 46.8, -121), new THREE.Vector3(-1.2, 46.8, -108), '13m', -1.2, 48.6, -114.5, 10); tick(new THREE.Vector3(-1.2, 46.8, -121), 0, 0.5); tick(new THREE.Vector3(-1.2, 46.8, -108), 0, 0.5); // 边跨桩排距示意(3排) dimLine(new THREE.Vector3(9.5, 0.8, -118.5), new THREE.Vector3(9.5, 0.8, -109.5), '排距4.5m×2', 9.5, 3.2, -114, 9); // 0号块桩横向5根间距示意 dimLine(new THREE.Vector3(-5.5, 0.8, -11), new THREE.Vector3(5.5, 0.8, -11), '横向5根 · 间距2.75m', 0, 3.2, -11, 9); scene.add(groups.labels); } function setGroupOpacity(grp, op){ grp.traverse(function(o){ if (o.isMesh && o.material){ o.material.transparent = (op < 1); o.material.opacity = op; o.material.depthWrite = (op >= 1); o.material.needsUpdate = true; } }); } function bindUI(){ document.getElementById('chk-rotate').onchange = function(e){ controls.autoRotate = e.target.checked; }; document.getElementById('chk-cables').onchange = function(e){ groups.cables.visible = e.target.checked; }; document.getElementById('chk-cant').onchange = function(e){ groups.cant.visible = e.target.checked; }; document.getElementById('chk-labels').onchange = function(e){ groups.labels.visible = e.target.checked; }; document.getElementById('chk-nogo').onchange = function(e){ groups.nogo.visible = e.target.checked; }; document.getElementById('chk-seg').onchange = function(e){ groups.seg.visible = e.target.checked; groups.closure.visible = e.target.checked; groups.segLong.visible = e.target.checked && document.getElementById('chk-seg-long').checked; groups.segTrans.visible = e.target.checked && document.getElementById('chk-seg-trans').checked; groups.segVert.visible = e.target.checked && document.getElementById('chk-seg-vert').checked; }; document.getElementById('chk-seg-long').onchange = function(e){ groups.segLong.visible = e.target.checked && document.getElementById('chk-seg').checked; }; document.getElementById('chk-seg-trans').onchange = function(e){ groups.segTrans.visible = e.target.checked && document.getElementById('chk-seg').checked; }; document.getElementById('chk-seg-vert').onchange = function(e){ groups.segVert.visible = e.target.checked && document.getElementById('chk-seg').checked; }; document.getElementById('chk-tower').onchange = function(e){ setGroupOpacity(groups.tower, e.target.checked ? 0.22 : 1); }; document.getElementById('chk-brace').onchange = function(e){ groups.bracing.visible = e.target.checked; }; // 劲性骨架:勾选 → 骨架可见 + 塔柱联动半透明(透视内部桁架);取消 → 恢复实心 document.getElementById('chk-frame').onchange = function(e){ var on = e.target.checked; groups.frame.visible = on; var tw = document.getElementById('chk-tower'); if(on){ tw.checked = true; setGroupOpacity(groups.tower, 0.22); } else { tw.checked = false; setGroupOpacity(groups.tower, 1); } }; // 节段分缝(节点板+螺栓):勾选时若骨架被隐藏则联动显示骨架 document.getElementById('chk-joint').onchange = function(e){ var on = e.target.checked; groups.frameJoints.visible = on; if(on && !document.getElementById('chk-frame').checked){ document.getElementById('chk-frame').checked = true; groups.frame.visible = true; document.getElementById('chk-tower').checked = true; setGroupOpacity(groups.tower, 0.22); } }; document.getElementById('chk-crane').onchange = function(e){ groups.crane.visible = e.target.checked; }; document.getElementById('chk-lift').onchange = function(e){ groups.lift.visible = e.target.checked; }; document.getElementById('chk-pump').onchange = function(e){ groups.pump.visible = e.target.checked; }; document.getElementById('chk-form').onchange = function(e){ groups.form.visible = e.target.checked; }; document.getElementById('chk-cablecrane').onchange = function(e){ groups.cablecrane.visible = e.target.checked; }; document.getElementById('chk-plant').onchange = function(e){ groups.plant.visible = e.target.checked; }; // 初始同步:骨架默认显示 → 塔柱联动半透明 setGroupOpacity(groups.tower, 0.22); var views = { '整体': [[280, 190, 450], [0, 55, 107]], '正面': [[0, 90, 560], [0, 50, 107]], '侧面': [[540, 95, 0], [0, 50, 107]], '俯视': [[0, 440, 5], [0, 0, 107]], '近景': [[60, 28, 62], [0, 25, 0]], '边跨近景': [[72, 26, -104], [0, 24, -114]], '边跨合拢': [[0, 40, -70], [0, 42, -107]], '中跨合拢': [[0, 40, 145], [0, 42, 107]], '塔2近景': [[260, 26, 176], [0, 25, 214]], '塔吊近景': [[42, 120, 64], [15, 88, 10]], '缆索吊近景': [[26, 105, 78], [0, 60, 107]], '拌合站近景': [[-80, 26, -138], [-46, 6, -172]], '横断面': [[0, 44, 36], [0, 42, 0]] }; document.querySelectorAll('.views button').forEach(function(b){ b.onclick = function(){ var v = views[b.dataset.v]; if (b.dataset.v === '横断面') setCrossSection(true); else setCrossSection(false); moveCamera(new THREE.Vector3(v[0][0], v[0][1], v[0][2]), new THREE.Vector3(v[1][0], v[1][1], v[1][2])); }; }); document.getElementById('xs-close').onclick = function(){ setCrossSection(false); var v = views['整体']; moveCamera(new THREE.Vector3(v[0][0], v[0][1], v[0][2]), new THREE.Vector3(v[1][0], v[1][1], v[1][2])); }; } var _clip = null; var _xsState = { cant:null, labels:null, rotate:null, crane:null, lift:null, pump:null, form:null, cablecrane:null, plant:null }; var _xsHide = ['cant','crane','lift','pump','form','cablecrane','plant']; // 在塔中心 Z=0.05 处剖切,露出横断面:切掉 Z>0.05 的主梁/塔/悬浇段/合拢段 function setCrossSection(on){ var p = document.getElementById('xsect'); var rk = document.getElementById('chk-rotate'); if (on){ if (!_clip) _clip = new THREE.Plane(new THREE.Vector3(0, 0, -1), 0.05); ['tower','girder','side','seg','segLong','segTrans','segVert','closure','frame','frameJoints', 'crane','lift','pump','form'].forEach(function(k){ groups[k].traverse(function(o){ if (o.material){ if (o.material._saveClip === undefined) o.material._saveClip = o.material.clippingPlanes; o.material.clippingPlanes = [_clip]; } }); }); if (_xsState.rotate === null) _xsState.rotate = rk ? rk.checked : true; _xsHide.forEach(function(k){ if (_xsState[k] === null) _xsState[k] = groups[k].visible; groups[k].visible = false; // 挂篮/塔吊/电梯/泵管/爬模挡横断面视线,临时隐藏 }); groups.labels.visible = false; // 3D 标注同样遮挡,由 2D 面板承担标注 controls.autoRotate = false; if (rk) rk.checked = false; if (p) p.style.display = 'block'; } else { Object.keys(groups).forEach(function(k){ if (!groups[k]) return; groups[k].traverse(function(o){ if (o.material){ if (o.material._saveClip !== undefined){ o.material.clippingPlanes = o.material._saveClip; } else { o.material.clippingPlanes = null; } } }); }); _xsHide.forEach(function(k){ if (_xsState[k] !== null){ groups[k].visible = _xsState[k]; _xsState[k] = null; } }); if (_xsState.labels !== null){ groups.labels.visible = _xsState.labels; _xsState.labels = null; } if (_xsState.rotate !== null){ controls.autoRotate = _xsState.rotate; if (rk) rk.checked = _xsState.rotate; _xsState.rotate = null; } if (p) p.style.display = 'none'; } } function moveCamera(pos, target){ var start = camera.position.clone(); var startT = controls.target.clone(); var t0 = performance.now(); function anim(now){ var t = Math.min(1, (now - t0) / 900); var e = t * t * (3 - 2 * t); camera.position.lerpVectors(start, pos, e); controls.target.lerpVectors(startT, target, e); controls.update(); if (t < 1) requestAnimationFrame(anim); } requestAnimationFrame(anim); } function animate(){ requestAnimationFrame(animate); controls.update(); renderer.render(scene, camera); } boot();})();</script></body></html>