如何在平截头体上剪切线段?

时间:2008-09-16 22:15:58

标签: math clipping

给定两个向量 A B ,它们形成线段 L = A-B。 此外,假设视锥体 F 由其左,右,底,顶,近和远平面定义。

如何对 F 剪辑 L

也就是说,测试一个交叉点哪里出现交叉点? (请记住,如果一条线段与一个平截头体相交,如果它与一个角落的两边相交,则该线段可以更多。)

如果可能,请提供一个代码示例(C ++或Python首选)。

3 个答案:

答案 0 :(得分:4)

我现在不想为此编写代码,但如果我正确理解“frustum”,则以下内容应该有效。

  1. 将线与所有给定的平面相交
  2. 如果你有两个十字路口,那就完成了。
  3. 如果只有一个交点计算前平面并相交。
  4. 如果您仍然只有一个交点计算背板并相交。
  5. 但我可能完全被误解了。在这种情况下,请详细说明:)

答案 1 :(得分:1)

除了上面提到的Corporal Touchy,你还需要know how to intersect a line segment with a plane。在该页面的描述中,u表示行的参数化定义中的参数。首先,使用所描述的两种方法之一计算u。如果u的值落在0.0到1.0的范围内,则平面会将线段剪切到线段的某个位置。将你回到你的线方程中可以得到交点出现的点。

另一种方法是找到每个点到飞机的directed distance。如果一个点的距离是正的而另一个是负的,则它们位于平面的相对侧。然后你知道哪个点在你的平截头体之外(根据你的飞机法线指向哪个方向)。使用这种方法,通过基于有向距离的比率进行线性插值,可以更快地找到交点。例如。如果一个点的距离是+12而另一个是-12,你知道平面将这个段切成两半,你的u参数是0.5。

希望这有帮助。

答案 2 :(得分:1)

首先extract the planes from your view matrix

然后使用你的点来定义一个向量,将min / max定义为(0,1),然后在平面上迭代并将它们与段相交,更新最小值/最大值,如果func parseWithIndexes(p *parser) (map[*Node][2]int, error) { // Iterate until EOF. Any other error will cause an early return. var err error var globalBufDif int var prevEndBuf int var tokenIndex [2]int tokenMap := make(map[*Node][2]int) for err != io.EOF { // CDATA sections are allowed only in foreign content. n := p.oe.top() p.tokenizer.AllowCDATA(n != nil && n.Namespace != "") t := p.top().FirstChild for { if t != nil && t.NextSibling != nil { t = t.NextSibling } else { break } } tokenMap[t] = tokenIndex if prevEndBuf > p.tokenizer.data.end { globalBufDif += prevEndBuf } prevEndBuf = p.tokenizer.data.end // Read and parse the next token. p.tokenizer.Next() tokenIndex = [2]int{p.tokenizer.data.start + globalBufDif, p.tokenizer.data.end + globalBufDif} p.tok = p.tokenizer.Token() if p.tok.Type == ErrorToken { err = p.tokenizer.Err() if err != nil && err != io.EOF { return tokenMap, err } } p.parseCurrentToken() } return tokenMap, nil } // ParseFragmentWithIndexes parses a fragment of HTML and returns the nodes // that were found. If the fragment is the InnerHTML for an existing element, // pass that element in context. func ParseFragmentWithIndexes(r io.Reader, context *Node) ([]*Node, map[*Node][2]int, error) { contextTag := "" if context != nil { if context.Type != ElementNode { return nil, nil, errors.New("html: ParseFragment of non-element Node") } // The next check isn't just context.DataAtom.String() == context.Data because // it is valid to pass an element whose tag isn't a known atom. For example, // DataAtom == 0 and Data = "tagfromthefuture" is perfectly consistent. if context.DataAtom != a.Lookup([]byte(context.Data)) { return nil, nil, fmt.Errorf("html: inconsistent Node: DataAtom=%q, Data=%q", context.DataAtom, context.Data) } contextTag = context.DataAtom.String() } p := &parser{ tokenizer: NewTokenizerFragment(r, contextTag), doc: &Node{ Type: DocumentNode, }, scripting: true, fragment: true, context: context, } root := &Node{ Type: ElementNode, DataAtom: a.Html, Data: a.Html.String(), } p.doc.AppendChild(root) p.oe = nodeStack{root} p.resetInsertionMode() for n := context; n != nil; n = n.Parent { if n.Type == ElementNode && n.DataAtom == a.Form { p.form = n break } } tokenMap, err := parseWithIndexes(p) if err != nil { return nil, nil, err } parent := p.doc if context != nil { parent = root } var result []*Node for c := parent.FirstChild; c != nil; { next := c.NextSibling parent.RemoveChild(c) result = append(result, c) c = next } return result, tokenMap, nil } 则提前退出

这是一个纯Python函数的例子,没有外部代码。

min > max