fn cross_section(&self, slice: &Hyperplane<f64>) -> Self {
        if self.rank() < 4 {
            unreachable!();
        }

        let mut vertices = Vec::new();
        let mut ranks = Vec::with_capacity(self.rank());

        // We map all indices of k-elements in the original polytope to the
        // indices of the new (k-1)-elements resulting from taking their
        // intersections with the slicing hyperplane.
        let mut hash_element = HashMap::new();

        // Determines the vertices of the cross-section.
        for (idx, edge) in self[2].iter().enumerate() {
            let segment = Segment(&self.vertices[edge.subs[0]], &self.vertices[edge.subs[1]]);

            // If we got ourselves a new vertex:
            if let Some(p) = slice.intersect(segment) {
                hash_element.insert(idx, vertices.len());
                vertices.push(p);
            }
        }

        let vertex_count = vertices.len();

        // The slice does not intersect the polytope.
        if vertex_count == 0 {
            return Self::nullitope();
        }

        ranks.push(SubelementList::min());
        ranks.push(SubelementList::vertices(vertex_count));

        // Takes care of building everything else.
        for r in 3..self.rank() {
            let mut new_hash_element = HashMap::new();
            let mut new_els = SubelementList::new();

            for (idx, el) in self[r].iter().enumerate() {
                let mut new_subs = Subelements::new();
                for sub in &el.subs {
                    if let Some(&v) = hash_element.get(sub) {
                        new_subs.push(v);
                    }
                }

                // If we got ourselves a new edge:
                if !new_subs.is_empty() {
                    new_hash_element.insert(idx, new_els.len());
                    new_els.push(new_subs);
                }
            }

            ranks.push(new_els);
            hash_element = new_hash_element;
        }

        // Adds a maximal element manually.
        ranks.push(SubelementList::max(ranks.last().unwrap().len()));

        // Splits compounds of dyads.
        let (first, last) = ranks.split_at_mut(3);

        if let (Some(edges), Some(faces)) = (first.last_mut(), last.first_mut()) {
            // Keeps track of the indices of our new edges.
            let mut edge_num = edges.len();
            let mut new_edges = SubelementList::new();

            // The superelements of all edges.
            let mut edge_sups = Vec::new();
            for _ in 0..edge_num {
                edge_sups.push(Superelements::new());
            }

            for (idx, face) in faces.iter().enumerate() {
                for &sub in face {
                    edge_sups[sub].push(idx);
                }
            }

            for (edge_idx, subs) in edges.iter_mut().enumerate() {
                debug_assert_eq!(
                    subs.len() % 2,
                    0,
                    "A line should always intersect a polygon an even amount of times!"
                );
                let comps = subs.len() / 2;

                if comps > 1 {
                    // Sorts the component's vertices lexicographically.
                    subs.sort_unstable_by_key(|&x| PointOrd::new(vertices[x].clone()));

                    // Splits the edge, adds the new split edges as subelements
                    // to the edge's superelements.
                    for _ in 1..comps {
                        let v0 = subs.pop().unwrap();
                        let v1 = subs.pop().unwrap();
                        new_edges.push(vec![v0, v1].into());

                        for &sup in &edge_sups[edge_idx] {
                            faces[sup].push(edge_num);
                        }

                        edge_num += 1;
                    }
                }
            }

            // Adds the new edges.
            edges.append(&mut new_edges);
        }

        // Builds the polytope.
        // TODO: no need for ranks, just use the builder directly.
        let mut builder = AbstractBuilder::new();
        for subelements in ranks {
            builder.push(subelements);
        }

        // Safety: TODO shit, this one's complicated... I'll come back to it.
        unsafe {
            let mut abs = builder.build();
            abs.untangle_faces();
            Self::new(vertices, abs)
        }
    }
/// Takes the cross-section of a polytope through a given hyperplane.
///
/// # Todo
/// We should make this function take a general [`Subspace`] instead.
Takes the cross-section of a polytope through a given hyperplane.
Takes the cross - section of a polytope through a given hyperplane .
fn cross_section(&self, slice: &Hyperplane<f64>) -> Self {
        if self.rank() < 4 {
            unreachable!();
        }
        let mut vertices = Vec::new();
        let mut ranks = Vec::with_capacity(self.rank());
        // We map all indices of k-elements in the original polytope to the
        // indices of the new (k-1)-elements resulting from taking their
        // intersections with the slicing hyperplane.
        let mut hash_element = HashMap::new();
        // Determines the vertices of the cross-section.
        for (idx, edge) in self[2].iter().enumerate() {
            let segment = Segment(&self.vertices[edge.subs[0]], &self.vertices[edge.subs[1]]);
            // If we got ourselves a new vertex:
            if let Some(p) = slice.intersect(segment) {
                hash_element.insert(idx, vertices.len());
                vertices.push(p);
            }
        }
        let vertex_count = vertices.len();
        // The slice does not intersect the polytope.
        if vertex_count == 0 {
            return Self::nullitope();
        }
        ranks.push(SubelementList::min());
        ranks.push(SubelementList::vertices(vertex_count));
        // Takes care of building everything else.
        for r in 3..self.rank() {
            let mut new_hash_element = HashMap::new();
            let mut new_els = SubelementList::new();
            for (idx, el) in self[r].iter().enumerate() {
                let mut new_subs = Subelements::new();
                for sub in &el.subs {
                    if let Some(&v) = hash_element.get(sub) {
                        new_subs.push(v);
                    }
                }
                // If we got ourselves a new edge:
                if !new_subs.is_empty() {
                    new_hash_element.insert(idx, new_els.len());
                    new_els.push(new_subs);
                }
            }
            ranks.push(new_els);
            hash_element = new_hash_element;
        }
        // Adds a maximal element manually.
        ranks.push(SubelementList::max(ranks.last().unwrap().len()));
        // Splits compounds of dyads.
        let (first, last) = ranks.split_at_mut(3);
        if let (Some(edges), Some(faces)) = (first.last_mut(), last.first_mut()) {
            // Keeps track of the indices of our new edges.
            let mut edge_num = edges.len();
            let mut new_edges = SubelementList::new();
            // The superelements of all edges.
            let mut edge_sups = Vec::new();
            for _ in 0..edge_num {
                edge_sups.push(Superelements::new());
            }
            for (idx, face) in faces.iter().enumerate() {
                for &sub in face {
                    edge_sups[sub].push(idx);
                }
            }
            for (edge_idx, subs) in edges.iter_mut().enumerate() {
                debug_assert_eq!(
                    subs.len() % 2,
                    0,
                    "A line should always intersect a polygon an even amount of times!"
                );
                let comps = subs.len() / 2;
                if comps > 1 {
                    // Sorts the component's vertices lexicographically.
                    subs.sort_unstable_by_key(|&x| PointOrd::new(vertices[x].clone()));
                    // Splits the edge, adds the new split edges as subelements
                    // to the edge's superelements.
                    for _ in 1..comps {
                        let v0 = subs.pop().unwrap();
                        let v1 = subs.pop().unwrap();
                        new_edges.push(vec![v0, v1].into());
                        for &sup in &edge_sups[edge_idx] {
                            faces[sup].push(edge_num);
                        }
                        edge_num += 1;
                    }
                }
            }
            // Adds the new edges.
            edges.append(&mut new_edges);
        }
        // Builds the polytope.
        // TODO: no need for ranks, just use the builder directly.
        let mut builder = AbstractBuilder::new();
        for subelements in ranks {
            builder.push(subelements);
        }
        // Safety: TODO shit, this one's complicated... I'll come back to it.
        unsafe {
            let mut abs = builder.build();
            abs.untangle_faces();
            Self::new(vertices, abs)
        }
    }
fn cross_section ( & self , slice : & Hyperplane < f64 > ) -> Self { if self . rank ( ) < 4 { unreachable ! ( ) ; } let mut vertices = Vec :: new ( ) ; let mut ranks = Vec :: with_capacity ( self . rank ( ) ) ; // We map all indices of k-elements in the original polytope to the // indices of the new (k-1)-elements resulting from taking their // intersections with the slicing hyperplane. let mut hash_element = HashMap :: new ( ) ; // Determines the vertices of the cross-section. for ( idx , edge ) in self [ 2 ] . iter ( ) . enumerate ( ) { let segment = Segment ( & self . vertices [ edge . subs [ 0 ] ] , & self . vertices [ edge . subs [ 1 ] ] ) ; // If we got ourselves a new vertex: if let Some ( p ) = slice . intersect ( segment ) { hash_element . insert ( idx , vertices . len ( ) ) ; vertices . push ( p ) ; } } let vertex_count = vertices . len ( ) ; // The slice does not intersect the polytope. if vertex_count == 0 { return Self :: nullitope ( ) ; } ranks . push ( SubelementList :: min ( ) ) ; ranks . push ( SubelementList :: vertices ( vertex_count ) ) ; // Takes care of building everything else. for r in 3 .. self . rank ( ) { let mut new_hash_element = HashMap :: new ( ) ; let mut new_els = SubelementList :: new ( ) ; for ( idx , el ) in self [ r ] . iter ( ) . enumerate ( ) { let mut new_subs = Subelements :: new ( ) ; for sub in & el . subs { if let Some ( & v ) = hash_element . get ( sub ) { new_subs . push ( v ) ; } } // If we got ourselves a new edge: if ! new_subs . is_empty ( ) { new_hash_element . insert ( idx , new_els . len ( ) ) ; new_els . push ( new_subs ) ; } } ranks . push ( new_els ) ; hash_element = new_hash_element ; } // Adds a maximal element manually. ranks . push ( SubelementList :: max ( ranks . last ( ) . unwrap ( ) . len ( ) ) ) ; // Splits compounds of dyads. let ( first , last ) = ranks . split_at_mut ( 3 ) ; if let ( Some ( edges ) , Some ( faces ) ) = ( first . last_mut ( ) , last . first_mut ( ) ) { // Keeps track of the indices of our new edges. let mut edge_num = edges . len ( ) ; let mut new_edges = SubelementList :: new ( ) ; // The superelements of all edges. let mut edge_sups = Vec :: new ( ) ; for _ in 0 .. edge_num { edge_sups . push ( Superelements :: new ( ) ) ; } for ( idx , face ) in faces . iter ( ) . enumerate ( ) { for & sub in face { edge_sups [ sub ] . push ( idx ) ; } } for ( edge_idx , subs ) in edges . iter_mut ( ) . enumerate ( ) { debug_assert_eq ! ( subs len ( ) 2 0 " " ) ; let comps = subs . len ( ) / 2 ; if comps > 1 { // Sorts the component's vertices lexicographically. subs . sort_unstable_by_key ( | & x | PointOrd :: new ( vertices [ x ] . clone ( ) ) ) ; // Splits the edge, adds the new split edges as subelements // to the edge's superelements. for _ in 1 .. comps { let v0 = subs . pop ( ) . unwrap ( ) ; let v1 = subs . pop ( ) . unwrap ( ) ; new_edges . push ( vec ! [ v0 v1 ] . into ( ) ) ; for & sup in & edge_sups [ edge_idx ] { faces [ sup ] . push ( edge_num ) ; } edge_num += 1 ; } } } // Adds the new edges. edges . append ( & mut new_edges ) ; } // Builds the polytope. // TODO: no need for ranks, just use the builder directly. let mut builder = AbstractBuilder :: new ( ) ; for subelements in ranks { builder . push ( subelements ) ; } // Safety: TODO shit, this one's complicated... I'll come back to it. unsafe { let mut abs = builder . build ( ) ; abs . untangle_faces ( ) ; Self :: new ( vertices , abs ) } }
Takes the cross-section of a polytope through a given hyperplane.
Takes the cross - section of a polytope through a given hyperplane .
&self
slice
&Hyperplane<f64>
todo
We should make this function take a general [`Subspace`] instead.
We should make this function take a general [ ` Subspace ` ] instead .