You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
9.1 KiB
232 lines
9.1 KiB
|
5 days ago
|
#ifndef BUSBAR_SEGMENT_HPP
|
||
|
|
#define BUSBAR_SEGMENT_HPP
|
||
|
|
|
||
|
|
#include "point.hpp"
|
||
|
|
#include "vector3.hpp"
|
||
|
|
#include "busbar_types.hpp"
|
||
|
|
#include <vector>
|
||
|
|
#include <memory>
|
||
|
|
|
||
|
|
constexpr float kBendLengthCostFactor = 1.25f;
|
||
|
|
|
||
|
|
struct OccupiedVoxelInfo {
|
||
|
|
Point point;
|
||
|
|
Vector3 tangent;
|
||
|
|
Vector3 normal;
|
||
|
|
int j_layer = 0; // cross-section position in normal direction (lower_t = bottom)
|
||
|
|
};
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// BusbarSegment 基类
|
||
|
|
// ============================================================================
|
||
|
|
class BusbarSegment {
|
||
|
|
protected:
|
||
|
|
SegmentType type_;
|
||
|
|
Point start_pos_;
|
||
|
|
Vector3 start_normal_;
|
||
|
|
Point end_pos_;
|
||
|
|
Vector3 end_normal_;
|
||
|
|
float width_;
|
||
|
|
float thickness_;
|
||
|
|
|
||
|
|
public:
|
||
|
|
BusbarSegment(SegmentType type,
|
||
|
|
const Point& start, const Vector3& start_normal,
|
||
|
|
const Point& end, const Vector3& end_normal,
|
||
|
|
float width, float thickness)
|
||
|
|
: type_(type), start_pos_(start), start_normal_(start_normal),
|
||
|
|
end_pos_(end), end_normal_(end_normal),
|
||
|
|
width_(width), thickness_(thickness) {}
|
||
|
|
|
||
|
|
virtual ~BusbarSegment() = default;
|
||
|
|
|
||
|
|
// 纯虚函数
|
||
|
|
virtual std::vector<OccupiedVoxelInfo> getOccupiedVoxels() const = 0;
|
||
|
|
virtual float getLength() const = 0;
|
||
|
|
|
||
|
|
// 弯段返回角度,直段返回0
|
||
|
|
virtual float getBendAngle() const { return 0.0f; }
|
||
|
|
|
||
|
|
virtual float getCost() const { return getLength(); }
|
||
|
|
virtual Vector3 getStartTangent() const = 0;
|
||
|
|
virtual Vector3 getEndTangent() const = 0;
|
||
|
|
|
||
|
|
// 访问器
|
||
|
|
SegmentType type() const { return type_; }
|
||
|
|
Point startPos() const { return start_pos_; }
|
||
|
|
Point endPos() const { return end_pos_; }
|
||
|
|
Vector3 startNormal() const { return start_normal_; }
|
||
|
|
Vector3 endNormal() const { return end_normal_; }
|
||
|
|
float width() const { return width_; }
|
||
|
|
float thickness() const { return thickness_; }
|
||
|
|
};
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// StraightSegment (直段)
|
||
|
|
// ============================================================================
|
||
|
|
class StraightSegment : public BusbarSegment {
|
||
|
|
private:
|
||
|
|
Vector3 tangent_; // 存储切向,避免从坐标计算导致的精度问题
|
||
|
|
|
||
|
|
public:
|
||
|
|
StraightSegment(const Point& start, const Vector3& start_normal,
|
||
|
|
const Point& end, const Vector3& end_normal,
|
||
|
|
float width, float thickness)
|
||
|
|
: BusbarSegment(SegmentType::STRAIGHT, start, start_normal,
|
||
|
|
end, end_normal, width, thickness),
|
||
|
|
tangent_((end.toVector3() - start.toVector3()).normalized()) {}
|
||
|
|
|
||
|
|
// 带切向的构造函数
|
||
|
|
StraightSegment(const Point& start, const Vector3& start_normal,
|
||
|
|
const Point& end, const Vector3& end_normal,
|
||
|
|
float width, float thickness,
|
||
|
|
const Vector3& tangent)
|
||
|
|
: BusbarSegment(SegmentType::STRAIGHT, start, start_normal,
|
||
|
|
end, end_normal, width, thickness),
|
||
|
|
tangent_(tangent) {}
|
||
|
|
|
||
|
|
std::vector<OccupiedVoxelInfo> getOccupiedVoxels() const override;
|
||
|
|
float getLength() const override;
|
||
|
|
Vector3 getStartTangent() const override { return tangent_; }
|
||
|
|
Vector3 getEndTangent() const override { return tangent_; }
|
||
|
|
Vector3 tangent() const { return tangent_; }
|
||
|
|
};
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// FlatBendSegment (平弯段)
|
||
|
|
// - 从水平方向弯向垂直方向(或反向)
|
||
|
|
// - 固定90度弯曲
|
||
|
|
// - 弯曲半径 = f * H
|
||
|
|
// - 法向改变90度
|
||
|
|
// - 会导致Z轴变化
|
||
|
|
// ============================================================================
|
||
|
|
class FlatBendSegment : public BusbarSegment {
|
||
|
|
private:
|
||
|
|
Point center_; // 圆心位置
|
||
|
|
float radius_; // 弯曲半径
|
||
|
|
bool upward_; // true=向上弯, false=向下弯
|
||
|
|
|
||
|
|
public:
|
||
|
|
FlatBendSegment(const Point& start, const Vector3& start_normal,
|
||
|
|
const Point& end, const Vector3& end_normal,
|
||
|
|
float width, float thickness,
|
||
|
|
const Point& center, float radius, bool upward)
|
||
|
|
: BusbarSegment(SegmentType::FLAT_BEND, start, start_normal,
|
||
|
|
end, end_normal, width, thickness),
|
||
|
|
center_(center), radius_(radius), upward_(upward) {}
|
||
|
|
|
||
|
|
std::vector<OccupiedVoxelInfo> getOccupiedVoxels() const override;
|
||
|
|
float getCost() const override { return getLength() * kBendLengthCostFactor; }
|
||
|
|
float getLength() const override { return radius_ * M_PI / 2.0f; } // 90度弧长
|
||
|
|
Vector3 getStartTangent() const override;
|
||
|
|
Vector3 getEndTangent() const override;
|
||
|
|
float getBendAngle() const override { return M_PI / 2.0f; }
|
||
|
|
Point center() const { return center_; }
|
||
|
|
float radius() const { return radius_; }
|
||
|
|
bool isUpward() const { return upward_; }
|
||
|
|
};
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// VerticalBendSegment (立弯段)
|
||
|
|
// - 在水平面内弯曲
|
||
|
|
// - Z轴不变(或变化很小)
|
||
|
|
// - 弯曲半径 = v * W
|
||
|
|
// - 法向保持不变(始终垂直)
|
||
|
|
// - 类似贴在地上的圆弧
|
||
|
|
// ============================================================================
|
||
|
|
class VerticalBendSegment : public BusbarSegment {
|
||
|
|
private:
|
||
|
|
Point center_; // 圆心位置,Z坐标与起点相同
|
||
|
|
float radius_; // 弯曲半径
|
||
|
|
float angle_; // 弯曲角度(弧度),可以是各种角度
|
||
|
|
|
||
|
|
public:
|
||
|
|
VerticalBendSegment(const Point& start, const Vector3& start_normal,
|
||
|
|
const Point& end, const Vector3& end_normal,
|
||
|
|
float width, float thickness,
|
||
|
|
const Point& center, float radius, float angle)
|
||
|
|
: BusbarSegment(SegmentType::VERTICAL_BEND, start, start_normal,
|
||
|
|
end, end_normal, width, thickness),
|
||
|
|
center_(center), radius_(radius), angle_(angle) {}
|
||
|
|
|
||
|
|
std::vector<OccupiedVoxelInfo> getOccupiedVoxels() const override;
|
||
|
|
float getCost() const override { return getLength() * kBendLengthCostFactor; }
|
||
|
|
float getLength() const override { return radius_ * std::abs(angle_); }
|
||
|
|
Vector3 getStartTangent() const override;
|
||
|
|
Vector3 getEndTangent() const override;
|
||
|
|
float getBendAngle() const override { return angle_; }
|
||
|
|
Point center() const { return center_; }
|
||
|
|
float radius() const { return radius_; }
|
||
|
|
float angle() const { return angle_; }
|
||
|
|
};
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// TwistSegment (扭转段)
|
||
|
|
// - 沿长度方向扭转
|
||
|
|
// - 法向旋转90度
|
||
|
|
// - 扭转长度 = t * W
|
||
|
|
// ============================================================================
|
||
|
|
class TwistSegment : public BusbarSegment {
|
||
|
|
private:
|
||
|
|
float twist_angle_; // 扭转角度(弧度),目前固定90度
|
||
|
|
|
||
|
|
public:
|
||
|
|
TwistSegment(const Point& start, const Vector3& start_normal,
|
||
|
|
const Point& end, const Vector3& end_normal,
|
||
|
|
float width, float thickness,
|
||
|
|
float twist_angle)
|
||
|
|
: BusbarSegment(SegmentType::TWIST, start, start_normal,
|
||
|
|
end, end_normal, width, thickness),
|
||
|
|
twist_angle_(twist_angle) {}
|
||
|
|
|
||
|
|
std::vector<OccupiedVoxelInfo> getOccupiedVoxels() const override;
|
||
|
|
float getCost() const override { return getLength() * kBendLengthCostFactor; }
|
||
|
|
float getLength() const override;
|
||
|
|
Vector3 getStartTangent() const override;
|
||
|
|
Vector3 getEndTangent() const override;
|
||
|
|
|
||
|
|
float twistAngle() const { return twist_angle_; }
|
||
|
|
};
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Bend45Segment (折叠弯段)
|
||
|
|
// - 在水平面内转弯,Z轴有高度变化
|
||
|
|
// - 法向保持不变或旋转
|
||
|
|
// ============================================================================
|
||
|
|
class Bend45Segment : public BusbarSegment {
|
||
|
|
private:
|
||
|
|
Point center_; // 圆心在水平面的投影坐标
|
||
|
|
float radius_; // 弯曲半径 = b * W
|
||
|
|
float bend_angle_; // 水平转角(弧度)
|
||
|
|
bool is_upward_; // true = 向上偏移, false = 向下偏移
|
||
|
|
float z_offset_; // Z轴偏移量 = 2bH + H
|
||
|
|
|
||
|
|
public:
|
||
|
|
Bend45Segment(const Point& start, const Vector3& start_normal,
|
||
|
|
const Point& end, const Vector3& end_normal,
|
||
|
|
float width, float thickness,
|
||
|
|
const Point& center, float radius,
|
||
|
|
float bend_angle, bool is_upward)
|
||
|
|
: BusbarSegment(SegmentType::BEND_45, start, start_normal,
|
||
|
|
end, end_normal, width, thickness),
|
||
|
|
center_(center), radius_(radius),
|
||
|
|
bend_angle_(bend_angle), is_upward_(is_upward){
|
||
|
|
z_offset_ = (end.toVector3() - start.toVector3()).dot(start_normal);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::vector<OccupiedVoxelInfo> getOccupiedVoxels() const override;
|
||
|
|
float getCost() const override { return getLength() * kBendLengthCostFactor; }
|
||
|
|
float getLength() const override {
|
||
|
|
// 弧长 + Z轴偏移距离的估算
|
||
|
|
return radius_ * std::abs(bend_angle_) + std::abs(z_offset_);
|
||
|
|
}
|
||
|
|
Vector3 getStartTangent() const override;
|
||
|
|
Vector3 getEndTangent() const override;
|
||
|
|
float getBendAngle() const override { return bend_angle_; }
|
||
|
|
Point center() const { return center_; }
|
||
|
|
float radius() const { return radius_; }
|
||
|
|
bool isUpward() const { return is_upward_; }
|
||
|
|
};
|
||
|
|
|
||
|
|
#endif
|