Box2D Get Bounding Box of a Body

获取Box2D中已创建体的边界框
本文解答了如何在Box2D中获取已创建并正在世界中交互的体的边界框的问题,通过迭代体的所有碰撞形状来生成新的AABB。

转载自:http://gamedev.stackexchange.com/questions/1366/box2d-get-bounding-box-of-a-body

问题:

In Box2D, I was curious if it's possible to get a bounding box of a body already created in the world.

So basically, the Body is created, it's interacting with the world and such. And I needed that Body's bounding box. Is it possible?

答案:

In Box2D, bodies don't have bounding boxes associated with them, fixture do.

So you need to iterate over all the fixtures and generate a new AABB. Something like this:

b2AABB aabb; aabb.lowerBound = b2Vec2(FLT_MAX,FLT_MAX); aabb.upperBound = b2Vec2(-FLT_MAX,-FLT_MAX); b2Fixture* fixture = body->GetFixtureList(); while (fixture != NULL) { aabb.Combine(aabb, fixture->GetAABB()); fixture = fixture->GetNext(); }

后端,import re import json from flask import Flask, request, jsonify, send_file from io import BytesIO from moxing import mox app = Flask(name) 提取 box 和 ref 的正则表达式 BOX_PATTERN = re.compile(r" ParseError: KaTeX parse error: Undefined control sequence: \[ at position 1: \̲[̲(.*?) ]“) REF_PATTERN = re.compile(r”(.*?)") def parse_boxes_and_refs(text): boxes = [] for box_match in BOX_PATTERN.finditer(text): box_str = box_match.group(1) coords = [int(x.strip()) for x in box_str.split(“,”)] # coords: [x_min, y_min, x_max, y_max] boxes.append({ “coords”: coords }) for ref_match in REF_PATTERN.finditer(text): label = ref_match.group(1) boxes[-1][“label”] = label # 将 label 添加到最后一个 box 中 return boxes @app.route(“/jsonl”, methods=[“GET”]) def get_jsonl(): bucket = request.args.get(“bucket”) file_path = request.args.get(“file”) if not bucket or not file_path: return jsonify({“error”: “Missing bucket or file”}), 400 try: full_path = f"obs://{bucket}/{file_path}" with mox.file.File(full_path, 'r') as f: lines = f.read().splitlines() data = [] for line in lines: item = json.loads(line) parsed_item = { "src": item["image"], "width": item["width"], "height": item["height"], "conversation": [], "boxes": [] } for msg in item["conversations"]: parsed_msg = { "from": msg["from"], "value": msg["value"] } parsed_item["conversation"].append(parsed_msg) # 提取 box 和 ref boxes = parse_boxes_and_refs(msg["value"]) if boxes: parsed_item["boxes"].extend(boxes) data.append(parsed_item) return jsonify(data) except Exception as e: return jsonify({"error": str(e)}), 500 @app.route(“/image”, methods=[“GET”]) def get_image(): bucket = request.args.get(“bucket”) path = request.args.get(“path”) if not bucket or not path: return jsonify({“error”: “Missing bucket or image path”}), 400 try: full_path = f"obs://{bucket}/{path}" if not mox.file.exists(full_path): return jsonify({"error": "Image not found"}), 404 with mox.file.File(full_path, 'rb') as f: img_data = f.read() return send_file(BytesIO(img_data), mimetype="image/jpeg") except Exception as e: return jsonify({"error": str(e)}), 500 前端const canvas = document.getElementById(“imageCanvas”); const ctx = canvas.getContext(“2d”); const conversationDiv = document.getElementById(“conversation”); function displaySingleImageDetection(item) { const imagePath = item.src; // 清空画布 ctx.clearRect(0, 0, canvas.width, canvas.height); // 创建图片对象 const img = new Image(); img.crossOrigin = “Anonymous”; img.src = /image?bucket=${bucketSelect.value}&path=${imagePath}; img.onload = () => { // 设置 canvas 大小为图片大小 canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); // 绘制图片 // 绘制 bounding boxes if (item.boxes && item.boxes.length > 0) { item.boxes.forEach(box => { const [x_min, y_min, x_max, y_max] = box.coords; const label = box.label; // 绘制矩形框 ctx.strokeStyle = "red"; ctx.lineWidth = 2; ctx.strokeRect(x_min, y_min, x_max - x_min, y_max - y_min); // 绘制标签文本 ctx.fillStyle = "red"; ctx.font = "16px Arial"; ctx.fillText(label, x_min + 5, y_min + 20); }); } }; // 更新对话框内容 conversationDiv.innerHTML = “”; item.conversation.forEach(msg => { const div = document.createElement(“div”); div.className = "message " + (msg.from === “human” ? “human” : “gpt”); div.textContent = ${msg.from}: ${msg.value.replace(/\n/g, '')}; conversationDiv.appendChild(div); }); } 现在希望再get_jsonl环节只读文件每一行,get_image环节根据索引读相应行数据处理数据,读图片展示图片和对话,前端中还有上一张下账的功能,
最新发布
08-12
后端import re import json from flask import Flask, request, jsonify, send_file from io import BytesIO from moxing import mox app = Flask(__name__) # 提取 box 和 ref 的正则表达式 BOX_PATTERN = re.compile(r"<box>\[\[(.*?)\]\]</box>") REF_PATTERN = re.compile(r"<ref>(.*?)</ref>") def parse_boxes_and_refs(text): boxes = [] for box_match in BOX_PATTERN.finditer(text): box_str = box_match.group(1) coords = [int(x.strip()) for x in box_str.split(",")] # coords: [x_min, y_min, x_max, y_max] boxes.append({ "coords": coords }) for ref_match in REF_PATTERN.finditer(text): label = ref_match.group(1) boxes[-1]["label"] = label # 将 label 添加到最后一个 box 中 return boxes @app.route("/jsonl", methods=["GET"]) def get_jsonl(): bucket = request.args.get("bucket") file_path = request.args.get("file") if not bucket or not file_path: return jsonify({"error": "Missing bucket or file"}), 400 try: full_path = f"obs://{bucket}/{file_path}" with mox.file.File(full_path, 'r') as f: lines = f.read().splitlines() data = [] for line in lines: item = json.loads(line) parsed_item = { "src": item["image"], "width": item["width"], "height": item["height"], "conversation": [], "boxes": [] } for msg in item["conversations"]: parsed_msg = { "from": msg["from"], "value": msg["value"] } parsed_item["conversation"].append(parsed_msg) # 提取 box 和 ref boxes = parse_boxes_and_refs(msg["value"]) if boxes: parsed_item["boxes"].extend(boxes) data.append(parsed_item) return jsonify(data) except Exception as e: return jsonify({"error": str(e)}), 500 @app.route("/image", methods=["GET"]) def get_image(): bucket = request.args.get("bucket") path = request.args.get("path") if not bucket or not path: return jsonify({"error": "Missing bucket or image path"}), 400 try: full_path = f"obs://{bucket}/{path}" if not mox.file.exists(full_path): return jsonify({"error": "Image not found"}), 404 with mox.file.File(full_path, 'rb') as f: img_data = f.read() return send_file(BytesIO(img_data), mimetype="image/jpeg") except Exception as e: return jsonify({"error": str(e)}), 500 前端const canvas = document.getElementById("imageCanvas"); const ctx = canvas.getContext("2d"); const conversationDiv = document.getElementById("conversation"); function displaySingleImageDetection(item) { const imagePath = item.src; // 清空画布 ctx.clearRect(0, 0, canvas.width, canvas.height); // 创建图片对象 const img = new Image(); img.crossOrigin = "Anonymous"; img.src = `/image?bucket=${bucketSelect.value}&path=${imagePath}`; img.onload = () => { // 设置 canvas 大小为图片大小 canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); // 绘制图片 // 绘制 bounding boxes if (item.boxes && item.boxes.length > 0) { item.boxes.forEach(box => { const [x_min, y_min, x_max, y_max] = box.coords; const label = box.label; // 绘制矩形框 ctx.strokeStyle = "red"; ctx.lineWidth = 2; ctx.strokeRect(x_min, y_min, x_max - x_min, y_max - y_min); // 绘制标签文本 ctx.fillStyle = "red"; ctx.font = "16px Arial"; ctx.fillText(label, x_min + 5, y_min + 20); }); } }; // 更新对话框内容 conversationDiv.innerHTML = ""; item.conversation.forEach(msg => { const div = document.createElement("div"); div.className = "message " + (msg.from === "human" ? "human" : "gpt"); div.textContent = `${msg.from}: ${msg.value.replace(/\n/g, '')}`; conversationDiv.appendChild(div); }); } 报错Uncaught (in promise) TypeError: Cannot read properties of null (reading 'getContext') at displaySingleImageDetection ((index):341:26) at (index):325:15
08-08
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值