manimgeo.components.circle.adapter 源代码

from __future__ import annotations

from ...math import (
    circumcenter,
    inscribed,
    inverse_circle,
    plane_get_ABCD, # 新增
)
from ..base import GeometryAdapter
from .args import *
from pydantic import Field
from typing import cast
import numpy as np

[文档] class CircleAdapter(GeometryAdapter[CircleConstructArgs]): center: np.ndarray = Field(default=np.zeros(3), description="计算圆心坐标", init=False) radius: Number = Field(default=0.0, description="计算圆半径", init=False) normal: np.ndarray = Field(default=np.array([0.0, 0.0, 1.0]), description="计算圆所在平面的法向量", init=False) # 新增 area: Number = Field(default=0.0, description="计算圆面积", init=False) circumference: Number = Field(default=0.0, description="计算圆周长", init=False) def __call__(self): """根据 self.args 执行具体计算""" match self.construct_type: case "CNR": args = cast(CNRArgs, self.args) self.center = args.center.coord.copy() self.radius = args.radius self.normal = args.normal.vec / np.linalg.norm(args.normal.vec) # 归一化 case "PR": args = cast(PRArgs, self.args) self.center = args.center.coord.copy() self.radius = args.radius if args.normal: self.normal = args.normal.vec / np.linalg.norm(args.normal.vec) else: self.normal = np.array([0.0, 0.0, 1.0]) # 默认 XY 平面 case "PP": args = cast(PPArgs, self.args) self.center = args.center.coord.copy() self.radius = np.linalg.norm(args.point.coord - args.center.coord) # type: ignore if args.normal: self.normal = args.normal.vec / np.linalg.norm(args.normal.vec) else: self.normal = np.array([0.0, 0.0, 1.0]) # 默认 XY 平面 case "L": args = cast(LArgs, self.args) start = args.radius_segment.start.copy() end = args.radius_segment.end.copy() self.center = start self.radius = np.linalg.norm(end - start) # type: ignore if args.normal: self.normal = args.normal.vec / np.linalg.norm(args.normal.vec) else: self.normal = np.array([0.0, 0.0, 1.0]) # 默认 XY 平面 case "PPP": args = cast(PPPArgs, self.args) self.radius, self.center = circumcenter( args.point1.coord, args.point2.coord, args.point3.coord ) A, B, C = plane_get_ABCD(args.point1.coord, args.point2.coord, args.point3.coord) normal_vec = np.array([A, B, C]) self.normal = normal_vec / np.linalg.norm(normal_vec) # 归一化 case "TranslationCirV": args = cast(TranslationCirVArgs, self.args) self.center = args.circle.center + args.vector.vec self.radius = args.circle.radius self.normal = args.circle.normal # 继承原圆法向量 case "InverseCirCir": args = cast(InverseCirCirArgs, self.args) self.center, self.radius, self.normal = inverse_circle( # 修改 args.circle.center, args.circle.radius, args.circle.normal, # 修改 args.base_circle.center, args.base_circle.radius, args.base_circle.normal # 修改 ) case "InscribePPP": args = cast(InscribePPPArgs, self.args) self.radius, self.center = inscribed(args.point1.coord, args.point2.coord, args.point3.coord) A, B, C = plane_get_ABCD(args.point1.coord, args.point2.coord, args.point3.coord) normal_vec = np.array([A, B, C]) self.normal = normal_vec / np.linalg.norm(normal_vec) # 归一化 case _: raise NotImplementedError(f"Invalid constructing method: {self.construct_type}") self.area = np.pi * self.radius ** 2 self.circumference = 2 * np.pi * self.radius