Source code for Geometry3D.geometry.segment

# -*- coding: utf-8 -*-
"""Segment Module"""
from .body import GeoBody
from .point import Point
from .plane import Plane
from ..utils.vector import Vector
from .line import Line
from ..utils.constant import get_eps
from ..utils.logger import get_main_logger
import math
import copy
[docs]class Segment(GeoBody): """ **Input:** - Segment(Point,Point) - Segment(Point,Vector) """ class_level = 3 # the class level of Segment def __init__(self,a,b): a = copy.deepcopy(a) b = copy.deepcopy(b) if isinstance(a,Point) and isinstance(b,Point): if a == b: raise ValueError("Cannot initialize a Segment with two identical Points") self.line = Line(a,b) self.start_point = a self.end_point = b elif isinstance(a,Point) and isinstance(b,Vector): if b.length() < get_eps(): raise ValueError("Cannot initialize a Segment with the length of Vector is 0") self.line = Line(a,b) self.start_point = a self.end_point = Point(a.pv() + b) else: raise ValueError('Cannot create segment with type:%s and %s' % (type(a),type(b))) def __eq__(self,other): return ((self.start_point == other.start_point and self.end_point == other.end_point) or (self.end_point == other.start_point and self.start_point == other.end_point)) def __repr__(self): return "Segment({}, {})".format(self.start_point, self.end_point) def __contains__(self, other): """Checks if a point lies on a segment""" if isinstance(other,Point): r1 = other in self.line v = Vector(self.start_point,self.end_point) v1 = Vector(self.start_point,other) if v1.length() < get_eps(): return True else: reletive_length = v1 * v / (v.length()) / (v.length()) return r1 and (reletive_length > -get_eps()) and (reletive_length < 1 + get_eps()) # r1 = point in self.line # r2 = point.x >= (min(self.start_point.x,self.end_point.x) - get_eps()) # r3 = point.x <= (max(self.start_point.x,self.end_point.x) + get_eps()) elif isinstance(other,Segment): return (other.start_point in self) and (other.end_point in self) else: get_main_logger().warning("Calling type {} in type {} which is always False".format(type(other),type(self))) return False
[docs] def in_(self,other): """other can be plane or line""" if isinstance(other,Line): return (self.start_point in other) and (self.end_point in other) elif isinstance(other,Plane): return (self.start_point in other) and (self.end_point in other) else: return NotImplementedError("")
def __hash__(self): """return the hash value of the segment""" return hash(("Segment", hash(self.start_point) + hash(self.end_point), hash(self.start_point) * hash(self.end_point) )) def __getitem__(self,idx): """return the i point of the segment""" return (self.start_point,self.end_point)[idx] def __setitem__(self,idx,value): """set the i point of the segment""" if idx == 0: self.start_point = value elif idx == 1: self.end_point = value else: raise IndexError("Index out of range")
[docs] def move(self, v): """Return the Segment that you get when you move self by vector v, self is also moved""" if isinstance(v,Vector): self.start_point.move(v) self.end_point.move(v) return Segment(self.start_point,self.end_point) else: raise NotImplementedError("The second parameter for move function must be Vector")
[docs] def parametric(self): """Returns (start_point, end_point) so that you can build the information for the segment """ return (self.start_point, self.end_point)
[docs] def length(self): """retutn the length of the segment""" return self.start_point.distance(self.end_point)
__all__ = ("Segment",)