use crate::beach_line as vb;
use crate::extended_scalar::extended_exp_fpt as ef;
#[cfg(feature = "console_debug")]
use crate::tln;
use crate::{BvError, GrowingVob, VobU32};
use ordered_float::OrderedFloat;
use std::cmp::Ordering;
use std::collections::BTreeSet;
use std::fmt;
use std::rc::Rc;
#[derive(Copy, Clone)]
pub struct CircleEventIndex(pub u32);
#[allow(dead_code)]
impl CircleEventIndex {
#[inline(always)]
fn increment(&mut self) {
self.0 += 1;
}
pub fn usize(self) -> usize {
self.0 as usize
}
pub fn u32(self) -> u32 {
self.0
}
}
impl fmt::Display for CircleEventIndex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Debug for CircleEventIndex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "CircleEventIndex({})", self.0)
}
}
#[derive(Clone)]
pub struct CircleEvent {
index_: Option<CircleEventIndex>, center_x_: f64,
center_y_: f64,
lower_x_: f64,
beach_line_index_: Option<vb::BeachLineIndex>, is_site_point_: bool,
}
impl fmt::Debug for CircleEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"CE(x:{:.12},y:{:.12},lx:{:.12})",
self.center_x_, self.center_y_, self.lower_x_,
)
}
}
impl PartialEq for CircleEvent {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
self.center_x_ == other.center_x_
&& self.center_y_ == other.center_y_
&& self.lower_x_ == other.lower_x_
}
}
impl Eq for CircleEvent {}
impl PartialOrd for CircleEvent {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for CircleEvent {
#[inline(always)]
fn cmp(&self, other: &Self) -> Ordering {
match OrderedFloat(self.lower_x_).cmp(&OrderedFloat(other.lower_x_)) {
Ordering::Less => Ordering::Less,
Ordering::Greater => Ordering::Greater,
_ => match OrderedFloat(self.center_y_).cmp(&OrderedFloat(other.center_y_)) {
Ordering::Less => Ordering::Less,
Ordering::Greater => Ordering::Greater,
Ordering::Equal => {
if let (Some(self_index), Some(other_index)) = (self.index_, other.index_) {
#[cfg(feature = "console_debug")]
println!(
"ce_id: {}.cmp({}) {:?}",
self_index.0,
other_index.0,
self_index.0.cmp(&other_index.0).reverse()
);
self_index.0.cmp(&other_index.0).reverse()
} else {
debug_assert!(false);
Ordering::Greater
}
}
},
}
}
}
impl CircleEvent {
pub(crate) fn new(bech_line_index: vb::BeachLineIndex) -> CircleEvent {
Self {
center_x_: 0_f64,
center_y_: 0_f64,
lower_x_: 0_f64,
beach_line_index_: Some(bech_line_index),
index_: None,
is_site_point_: false,
}
}
#[inline]
pub(crate) fn set_3_ext(
&mut self,
x: ef::ExtendedExponentFpt,
y: ef::ExtendedExponentFpt,
lower_x: ef::ExtendedExponentFpt,
) {
self.set_3(x.d(), y.d(), lower_x.d());
}
pub(crate) fn get_index(&self) -> Option<CircleEventIndex> {
self.index_
}
pub(crate) fn set_index(&mut self, index: CircleEventIndex) {
self.index_ = Some(index);
}
#[allow(dead_code)]
pub(crate) fn x(&self) -> f64 {
self.center_x_
}
pub(crate) fn x_as_xf(&self) -> ef::ExtendedExponentFpt {
ef::ExtendedExponentFpt::from(self.center_x_)
}
pub(crate) fn set_x(&mut self, x: f64) -> &mut Self {
self.center_x_ = x;
self
}
pub(crate) fn y(&self) -> f64 {
self.center_y_
}
#[allow(dead_code)]
pub(crate) fn y_as_ext(&self) -> ef::ExtendedExponentFpt {
ef::ExtendedExponentFpt::from(self.center_y_)
}
pub(crate) fn set_y(&mut self, y: f64) -> &mut Self {
self.center_y_ = y;
self
}
#[inline(always)]
pub(crate) fn lower_x(&self) -> f64 {
self.lower_x_
}
#[inline(always)]
pub(crate) fn set_lower_x(&mut self, x: f64) -> &mut Self {
self.lower_x_ = x;
self
}
#[allow(dead_code)]
#[inline(always)]
pub(crate) fn lower_y(&self) -> f64 {
self.center_y_
}
#[inline(always)]
pub(crate) fn set_3(&mut self, x: f64, y: f64, lower_x: f64) {
let _ = self.set_x(x);
let _ = self.set_y(y);
let _ = self.set_lower_x(lower_x);
}
#[inline(always)]
pub(crate) fn is_site_point(&self) -> bool {
self.is_site_point_
}
#[inline(always)]
pub(crate) fn set_is_site_point(&mut self) {
self.is_site_point_ = true
}
#[cfg(any(feature = "ce_corruption_check", feature = "console_debug"))]
#[allow(dead_code)]
pub fn dbg(&self) {
println!("[{},{}]", self.x(), self.y());
}
#[inline]
pub(crate) fn set_x_xf(&mut self, x: ef::ExtendedExponentFpt) {
let _ = self.set_x(x.d());
}
#[inline]
pub(crate) fn set_y_xf(&mut self, y: ef::ExtendedExponentFpt) {
let _ = self.set_y(y.d());
}
#[inline]
pub(crate) fn set_lower_x_xf(&mut self, x: ef::ExtendedExponentFpt) {
let _ = self.set_lower_x(x.d());
}
#[inline]
pub(crate) fn beach_line_index(&self) -> Option<vb::BeachLineIndex> {
self.beach_line_index_
}
}
pub(crate) struct CircleEventQueue {
ce_by_order_: BTreeSet<Rc<CircleEvent>>,
ce_by_id_: rustc_hash::FxHashMap<u32, Rc<CircleEvent>>,
c_list_next_free_index_: CircleEventIndex,
inactive_circle_ids_: VobU32, }
impl Default for CircleEventQueue {
fn default() -> CircleEventQueue {
Self {
ce_by_order_: BTreeSet::new(),
ce_by_id_: rustc_hash::FxHashMap::default(),
c_list_next_free_index_: CircleEventIndex(0),
inactive_circle_ids_: VobU32::fill(128),
}
}
}
impl CircleEventQueue {
#[inline]
pub(crate) fn is_empty(&self) -> bool {
self.ce_by_order_.is_empty()
}
#[inline(always)]
pub(crate) fn peek(&self) -> Option<&Rc<CircleEvent>> {
self.ce_by_order_.first()
}
#[cfg(feature = "ce_corruption_check")]
pub(crate) fn ce_corruption_check(&self) {
if self.ce_by_order_.len() >= 2 {
let mut iter = self.ce_by_order_.iter();
let first_ce = iter.next().unwrap();
let second_ce = iter.next().unwrap();
if first_ce.cmp(second_ce) != Ordering::Less {
println!("*************************************************");
println!("topmost CE could just as well been the second CE.");
println!("topmost CE :{:?}", first_ce);
println!("second CE :{:?}", second_ce);
}
}
}
#[inline(always)]
fn pop_first(&mut self) -> Option<Rc<CircleEvent>> {
self.ce_by_order_.pop_first()
}
pub(crate) fn pop_inactive_at_top(&mut self) -> Result<(), BvError> {
while !self.is_empty() {
if let Some(peek) = self.peek() {
if let Some(peek) = peek.get_index() {
if !self.is_active(peek) {
self.pop_and_destroy()?;
continue;
}
} else {
return Err(BvError::InternalError(format!(
"Circle event had no id {}:{}",
file!(),
line!()
)));
}
}
break;
}
debug_assert!({
if self.ce_by_id_.len() != self.ce_by_order_.len() {
return Err(BvError::InternalError(format!(
"The two circle event lists should always be of the same size. {}:{}",
file!(),
line!()
)));
};
true
});
Ok(())
}
pub(crate) fn pop_and_destroy(&mut self) -> Result<(), BvError> {
if let Some(circle) = self.pop_first() {
if let Some(circle_id) = circle.index_ {
let _ = self.ce_by_id_.remove(&circle_id.0);
self.inactive_circle_ids_.set_grow(circle_id.usize(), true);
} else {
return Err(BvError::InternalError(format!(
"circle event lists corruption, circle event id {:?} not found {}:{}",
circle.index_,
file!(),
line!()
)));
}
}
debug_assert!({
if self.ce_by_id_.len() != self.ce_by_order_.len() {
return Err(BvError::InternalError(format!(
"The two circle event lists should always be of the same size. {}:{}",
file!(),
line!()
)));
};
true
});
Ok(())
}
#[allow(dead_code)]
pub(crate) fn clear(&mut self) {
self.ce_by_order_.clear();
self.ce_by_id_.clear();
self.inactive_circle_ids_ = {
let mut cids = VobU32::fill(512);
cids.resize(512, false);
cids
}
}
pub(crate) fn associate_and_push(&mut self, mut ce: CircleEvent) -> CircleEventIndex {
let circle_event_id = self.c_list_next_free_index_;
ce.set_index(circle_event_id);
let rc_ce = Rc::new(ce);
let _ = self.ce_by_id_.insert(circle_event_id.0, Rc::clone(&rc_ce));
let _ = self.ce_by_order_.insert(rc_ce);
self.c_list_next_free_index_.increment();
circle_event_id
}
#[inline(always)]
pub(crate) fn is_active(&self, circle_event_id: CircleEventIndex) -> bool {
!self.inactive_circle_ids_.get_f(circle_event_id.usize())
}
pub(crate) fn deactivate(&mut self, circle_event_id: Option<CircleEventIndex>) {
#[cfg(not(feature = "console_debug"))]
if let Some(circle_event_id) = circle_event_id {
self.inactive_circle_ids_
.set_grow(circle_event_id.usize(), true);
}
#[cfg(feature = "console_debug")]
if let Some(circle_event_id) = circle_event_id {
if !self.inactive_circle_ids_.get_f(circle_event_id.usize()) {
if self.ce_by_id_.contains_key(&circle_event_id.0) {
tln!("deactivate {:?}", self.ce_by_id_[&circle_event_id.0]);
} else {
tln!("circle {} not present", circle_event_id);
}
self.inactive_circle_ids_
.set_grow(circle_event_id.usize(), true);
}
}
}
pub(crate) fn top(&self) -> Result<Option<&Rc<CircleEvent>>, BvError> {
let c = self.peek();
if let Some(cc) = c {
let id = cc.index_.unwrap();
if !self.is_active(id) {
return Err(BvError::InternalError(format!(
"Tried to use an inactive circle event {}, {}:{}",
id.0,
file!(),
line!()
)));
}
}
Ok(c)
}
#[cfg(feature = "console_debug")]
pub(crate) fn dbg_ce(&self, cei: CircleEventIndex) {
if let Some(ce) = self.ce_by_id_.get(&cei.0) {
print!("{:?}", ce);
} else {
print!("{}: not found", cei);
}
}
#[allow(dead_code)]
#[cfg(any(test, feature = "console_debug"))]
pub(crate) fn len(&self) -> usize {
self.ce_by_order_.len()
}
}