使用Math.Atan2后出现错误,感觉是内存错误

本文介绍了一种用于寻找并构建多边形的C#算法。该算法通过分割线段来查找交点,并利用这些交点构建多边形。在实现过程中遇到了Debug与Release模式下结果不同的问题,最终通过替代Math.Atan2方法解决了这一问题。

 

      发现过程:如上代码在Debug和Release下执行程序时,出来的结果不一样(Bebug下找到6个,Release下找到4个),由于代码中并没有使用不安全代码,所以怀疑是Math.Atan2的问题,于是在代码483行加入代码 File.AppendAllText("Azimuth.txt", azimuth.ToString() + Environment.NewLine);想打印出Release时计算出来的角度,但是一加这行代码后,结果却莫名其妙的正确了。后来由于考虑到实现中实际只需要按方向做角度排序,并不需要算出较精确的角度,所以在代码208行用了一个其他的方法绕过了Math.Atan2的使用,至此代码不管在Debug下还是在Release下都能正常出结果了。

        因为以前只有在c++中出现过这种问题,是因为指针使用不当,出现的内存问题,所以这边只能怀疑是Math.Atan2的方法有较隐蔽的内存错误,而Math.Atan2这个方法微软也确实是调用了它的底层库,不知其具体实现。也请各位大侠指点

 

ps:

1.这条大虾请无视,Debug下F5还是Ctrl+F5没关系,但Release必须Ctrl+F5或者运行编译后的exe才算执行程序,才能看到差异

2.我同事的机器和我自己家里的机器都会出这问题,但我自己公司的机器确没有这问题,所以我这不能保证这个问题一定能在你的机器上出现

 

s.width) p.vx *= -1; if(p.y < 0 || p.y > canvas.height) p.vy *= -1; // ===== 插入边界碰撞分裂逻辑 ===== (在边界反弹代码之后) if ((p.x < 0 || p.x > canvas.width || p.y < 0 || p.y > canvas.height) && performance.now() > p.splitCooldown & p.splitCount < p.maxSplitTimes) { // 生成两个新粒子 for(let i=0; i<2; i++) { const angle = Math.random() * Math.PI * 2; const newParticle = new WaveParticle(p.x, p.y); newParticle.maxSplitTimes = 3; newParticle.splitCooldown = performance.now() + 5000; newParticle.vx = p.vx * 0.8 + Math.cos(angle) * 2; newParticle.vy = p.vy * 0.8 + Math.sin(angle) * 2; particles.push(newParticle); } p.splitCount++; p.splitCooldown = performance.now() + 5000; } // 能量衰减 p.vx *= (1 - DAMPING); p.vy *= (1 - DAMPING); // 更新位置 p.x += p.vx; p.y += p.vy; // 粒子间碰撞检测 particles.forEach(other => { if(p === other) return; const dx = other.x - p.x; const dy = other.y - p.y; const dist = Math.sqrt(dx*dx + dy*dy); if(dist < REPULSE_RADIUS) { // 排斥力计算 const force = (REPULSE_RADIUS - dist) / REPULSE_RADIUS; const angle = Math.atan2(dy, dx); p.vx -= Math.cos(angle) * force * 0.5; p.vy -= Math.sin(angle) * force * 0.5; // ===== 插入碰撞分裂逻辑 ===== (在现有碰撞检测循环内) if(dist < p.radius * 2 && performance.now() > p.splitCooldown & p.splitCount < p.maxSplitTimes) { // 生成两个新粒子 for(let i=0; i<2; i++) { const angle = Math.random() * Math.PI * 2; const newParticle = new WaveParticle(p.x, p.y); // 继承属性修改 newParticle.maxSplitTimes = 3; // 子代最大分裂次数 newParticle.splitCooldown = performance.now() + 5000; // 5秒冷却 newParticle.vx = p.vx * 0.8 + Math.cos(angle) * 2; newParticle.vy = p.vy * 0.8 + Math.sin(angle) * 2; particles.push(newParticle); } // 更新母体状态 p.splitCount++; p.splitCooldown = performance.now() + 500; } } }); }); } // ===== 渲染绘制 ===== function draw() { ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; ctx.fillRect(0, 0, canvas.width, canvas.height); particles.forEach(p => { ctx.beginPath(); ctx.arc(p.x, p.y, p.radius, 0, Math.PI*2); ctx.fillStyle = ; ctx.fill(); }); }rgba(0, 150, 255, ${p.life}) // ===== 动画循环 ===== function animate() { updateParticles()的 draw(); requestAnimationFrame(动画); } animate()的; </script>粒子数量检测的代码,粒子总数量不能超过500,超过清除最早的粒子,添加进这个代码里,其余代码不动,然后把完整发给我,
03-30
父组件要在地图子组件画两条线,首先是特勤线路的线路 async handleTaskInfo(row) { try { const params = { id: row.id, }; const res = await getTqInfoApiBusiness(params); const dataPoints = res.data.xlData.map(item => ([ Number(item.longitude), Number(item.latitude) ])); this.$refs.mineMapRef.drawRoute(dataPoints); this.$refs.mineMapRef.addRouteMarker(dataPoints[0], "end"); this.$refs.mineMapRef.addRouteMarker(dataPoints[dataPoints.length - 1], "start"); console.log(dataPoints, '获取特勤线路详细信息成功'); } catch (error) { console.log("获取特勤线路详细信息失败", error); } },然后根据车载信息拿到的每一条坐标点,在这个线路基础上绘制新路线,并且添加一个车辆的图标实时更新 // 特勤路线演习 handlestartTq(type) { this.deviceArray = [] console.log(this.deviceArray, 'aaaaaaaaaaaa'); console.log("type:", type, "deviceArray:", this.deviceArray); this.isStartTq = type this.handlesHeadTq() }, // 特勤路线演习-头车 async handlesHeadTq() { console.log("deviceArray:", this.deviceArray); await this.$nextTick(); const dataPoints = this.deviceArray.map(item => ([ Number(item.longitude), Number(item.latitude) ])); this.$refs.mineMapRef.updateVehiclePosition(dataPoints[dataPoints.length - 1]) },子组件代码如下,怎么优化效果,让他符合整个流程 // 绘制车辆 drawRoute(points) { // 历史路线图层 this.mapObj.addSource('history-route', { type: 'geojson', data: points }); this.mapObj.addLayer({ id: 'history-route-layer', type: 'line', source: 'history-route', paint: { 'line-color': '#45CCDA', 'line-width': 4, 'line-opacity': 0.7 } }); // 实时路线图层(覆盖在历史路线上方) this.mapObj.addSource('realtime-route', { type: 'geojson', data: this.createLineGeoJSON([]) }); this.mapObj.addLayer({ id: 'realtime-route-layer', type: 'line', source: 'realtime-route', paint: { 'line-color': '#FFFC00', 'line-width': 4, 'line-opacity': 0.9 } }, 'history-route-layer'); // 确保实时路线在历史路线上方 }, // 创建车辆图标 initCarMarker() { const el = document.createElement('div'); el.className = 'car-marker'; el.style.backgroundImage = 'url(/images/car.png)'; // 替换为实际车辆图标路径 el.style.width = '32px'; el.style.height = '32px'; el.style.backgroundSize = '100%'; this.carMarker = new minemap.Marker({ element: el, rotationAlignment: 'map', // 方向随地图旋转 anchor: 'center' // 中心点定位 }).setLngLat([0, 0]).addTo(this.mapObj); }, // 暴露给父组件的方法 // 子组件方法(增量更新) updateVehiclePosition(newPoint) { // 更新车辆图标位置 this.carMarker.setLngLat(newPoint); // 更新实时路线(增量) if (this.realtimeRouteSource) { const currentData = this.realtimeRouteSource.getData(); const currentCoords = currentData.features[0].geometry.coordinates; const updatedCoords = [...currentCoords, newPoint]; this.realtimeRouteSource.setData(this.createLineString(updatedCoords)); } // 视角跟随 this.mapObj.flyTo({ center: newPoint }); } , // 增量更新路线(核心优化) updateRouteGeoJSON(newPoint) { // 获取现有路线数据 const currentData = this.realtimeRouteSource.getData(); const currentCoords = currentData.features[0].geometry.coordinates; // 添加新点 const updatedCoords = [...currentCoords, newPoint]; // 高效更新数据源 this.realtimeRouteSource.setData({ type: 'Feature', geometry: { type: 'LineString', coordinates: updatedCoords } }); }, // 移动车辆图标(带方向计算) moveCarMarker(newPosition) { if (!this.carMarker) return; // 计算行驶方向(需要至少两个点) if (this.routes.realtime.length > 1) { const prevPoint = this.routes.realtime[this.routes.realtime.length - 2]; const bearing = this.calculateBearing(prevPoint, newPosition); this.carMarker.setRotation(bearing); } // 更新位置 this.carMarker.setLngLat(newPosition); }, // 计算两点间方向角(单位:度) calculateBearing(start, end) { const startLng = start[0] * Math.PI / 180; const startLat = start[1] * Math.PI / 180; const endLng = end[0] * Math.PI / 180; const endLat = end[1] * Math.PI / 180; const y = Math.sin(endLng - startLng) * Math.cos(endLat); const x = Math.cos(startLat) * Math.sin(endLat) - Math.sin(startLat) * Math.cos(endLat) * Math.cos(endLng - startLng); return Math.atan2(y, x) * 180 / Math.PI; }, // 更新单个路线图层 updateRouteLayer(sourceId, coordinates) { if (coordinates.length < 2) return; const source = this.mapObj.getSource(sourceId); if (source) { source.setData(this.createLineString(coordinates)); } }, // 创建LineString GeoJSON createLineString(coordinates) { return { type: 'Feature', geometry: { type: 'LineString', coordinates: coordinates } }; },
最新发布
07-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰风漫天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值